您的位置:首页 > 编程语言

Unix环境编程-文件和目录

2012-08-31 13:30 134 查看
一、打开/关闭文件

1

名称:

open

目标:

打开一个文件。

头文件:

#include <sys/types.h>

#include <sys/stat.h>

#include < fcntl.h>

函数原形:

int open(const char * pathname,int flags);

int open(const char * pathname,int flags,mode_t mode);

参数:

pathname 文件名

flags 打开模式

返回值:

-1 遇到错误

int 打开成功,返回文件描述符。

要打开一个文件,必须指定文件名和打开模式,有3种打开模式:只读,只写,可读可写,分别对应于O_RDONLY,O_WRONLY,O_RDWR,这在头文件/usr/include/fcntl.h中有定义。

打开文件是内核提供的服务,如果在打开过程中内核检测到任何错误,这个系统调用就会返回-1。错误的类型是各种各样的,如:要打开的文件不存在。即使文件存在可能因为权限不够而无法打开,在open的联机帮助中列出了各种可能的错误,大家可以看看。

UNIX允许一个文件被多个进程访问,也就是说当一个文件被一个进程打开后,这个文件还可以被其它进程打开。

如果文件被顺利打开, 内核会返回一个正整数的值,这个数值就叫文件描述符,文件描述符是是一个简单的整数,用以标明每一个被进程所打开的文件,描述符0代表标准输出,对应的宏是STDOUT_FILENO, 描述符1代表标准输入,对应的宏为STDIN_FILENO,描述符2代表标准错误输出,对应的宏为STDERR_FILENO, 系统给进程分配描述符都是从3开始的,如果同时打开好几个文件,它们所对应的的文件描述符是不同的,如果一个文件打开多次,对应的文件描述符也不相同。必须通过文件描述符对文件操作。下面的程序可以证明这一点。

Open 函数的第二个功能是创建一个新文件并把它打开,其中有几个宏定义对于着flags参数:

O_CREAT 如果打开文件不存在open就创建一个文件。

O_TRUNC 如果打开的文件已经存在open就把原文件清空,长度置为0。

所有我们利用open(pathname, O_WRONLY| O_CREAT| O_TRUNC,0777);

下面是一个例子

/*1_2.c*/

#include <unistd.h>

#include <sys/stat.h>

#include <sys/fcntl.h>

#include <stdio.h>

char buf[]=”abcdefg”;

int main(int argc,char *argv[ ])

{

int fd;

if((fd=open(argv[1],O_RDWR|O_CREAT|O_TRUNC,0777))==-1)

perror (“error”);

if(write(fd,buf,7)!=7)

perror(“error”);

if(read(fd,buf,sizeof(buf))<0)

perror (“error”);

printf(“%s\n”,buf);:

}

2.

名称:

close

目标:

关闭一个文件。

头文件:

#include < unistd.h>

函数原形:

int close(int fd)

参数:

fd 文件描述符

返回值:

-1 遇到错误

int 关闭成功,返回文件描述符。

Close这个系统调用会关闭进程和文件fd之间的连接,如果关闭过程中出现错误,close返回-1,如:fd所指的文件并不存在。关闭成功则返回文件描述符。

3.

名称:

creat

目标:

创建/重写一个文件

头文件:

#include <sys/types.h>

#include <stat.h>

#include < fcntl.h>

函数原形:

int creat(const char *pathname,mode_t mode)

参数:

pathname 文件名

mode 访问模式

返回值:

-1 遇到错误

    \

fd 创建成功,返回文件描述符

creat告诉内核创建一个名为filename的文件,如果这个文件不存在,就创建它,如果已经存在,就把它的内容清空,把文件的长度设为0。

如果内核成功地创建了文件,那么文件的许可位(permission bits)被设置为由第二个参数mode所指定的值.如:

fd=creat(“addressbook”,0644);

创建一个名为addressbook的文件,如果文件不存在,那么文件的许可位被设为 rw-r-r—.

如果文件已存在它的内容会被清空。任一情况下,fd都会是指向addressbook的文件描述符。

二、文件的读取和写入

4.

名称:

read

目标:

把数据读到缓冲区。

头文件:

#include < unistd.h>

函数原形:

ssize_t read(int fd, void *buf, size_t count)

参数:

fd 文件描述符

buf 用来存放数据的目的缓冲区

count 要读取的字节数

返回值:

-1 遇到错误

numread 成功关闭,返回所读取的字节数目。

read这个系统调用请求内核从fd所指定的文件中读取qty字节的数据,存放到buf所指定的内存空间中,内核如果成功地读取了数据,就返回所读取的字节数目。否则返回-1。

当文件的字节数没有你想要的那么多时,read就会判断下一个数值是不是’\0’,如果是就停止读取,然后退出。numread返回的是’\0’之前的字节数,也就是是原文件的字节数而不是你想读的字节数。

5.

名称:

write

目标:

将内存中的数据写入文件。

头文件:

#include < unistd.h>

函数原形:

size_t write(int fd, const void *buf, size_t count)

参数:

fd 文件描述符

buf 内存数据

count 要写的字节数

返回值:

-1 遇到错误

Num written 成功写入,返回写入的字节数目。

在实际的写入过程中,可能会出现写入的字节数少于所要求的。这可能有两个原因,第一是有的系统对文件的最大尺寸有限制,第二是磁盘空间接近满了。在上述两种情况下内核都会尽力把数据往文件中写,并将实际写入的字节数返回,所以调用write后都必须检查返回值是否与要写入的相同,如果不同就要采取相应的措施。

学完上面几个系统调用,我们就可以自己编写的cp命令了。它的基本思路是从原文件读取数据写入缓冲,再将缓冲的数据写入目标文件。

/*1_3.c*/

#include <stdio.h>

#include <unistd.h>

#include <fcntl.h>

#include <stdlib.h>

#define BUFFERSIZE 4096

#define COPYMODE 0644

void oops(char *s1,char *s2);

main(int argc,char *argv[])

{

int in_fd,out_fd,n_chars;

char buf[BUFFERSIZE];

if(argc!=3)

{

fprintf(stderr,”usage:%s source destination\n”,*argv);

exit(1);

}

if((in_fd=open(argv[1],O_RDONLY))==-1)

oops(“Cannot open”,argv[1]);

if((out_fd=creat(argv[2], COPYMODE))==-1)

oops(“Cannot creat”,argv[2]);

while((n_chars=read(in_fd,buf,BUFFERSIZE))>0)

{

if(write(out_fd,buf,n_chars)!=n_chars)

oops(“Write error to”,argv[2]);

}

if(n_chars==-1)

opps(“Read error form”,argv[1]);

if(close(in_fd)==-1||close(out_fd)==-1)

oops(“Error clising files”);

}

void oops(char *s1,char *s2)

{

fprintf(stderr,”Error:%s”,s1);

perror(s2);

exit(1);

}

三、文件描述符操作函数

6.

名称::

lseek

目标:

使指针指向文件中的指定位置。

头文件:

#include <sys/types.h>

#include <unistd.h>

函数原形:

off_t lseek(int fildes,off_t offset,int whence)

参数:

fildes 文件描述符

offset 移动的距离

wence SEEK_SET=>文件的开始

SEEK_CUR=>当前位子

SEEK_END=>文件结束

返回值:

-1 遇到错误

Ildpos 指针变化前的位子

lseek改变文件描述符所关联的指针的位置,新的位置由offset和wence来指定,wence是基准位置,基准位子可以是文件的开始(0)、当前位子(1)或文件的结束(2)。 offset是从基准位子开始的偏移量。若wence为SEEK_SET,该文件的偏移设置为距文件开始处offset个字节数。若wence是SEEK_CUR,该文件的偏移设置为其当前值加offset, offset可为正或负。若wence是SEEK_END,该文件的偏移设置为文件长度加offset,
offset可为正或负。

lseek(fd,0,SEEK_END);

文件位偏移量可以大于文件的当前长度,在这种情况下,对该文件的下一次写将延长该文件,并在文件中构成一个空洞,这一点是允许的。位于文件中没有写过的字节都被读为0。

下面是一个例子:

/*1_4.c*/

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <unistd.h>

#include <stdlib.h>

char buf1[]=”abcdefg”;

char buf2[]=”ABCDEFG”;

int main(void)

{

int fd;

if((fd=creat(“file.hole”,0644))==-1)

printf(“creat error”);

if(write(fd,buf1,7)!=7)

printf (“buf1 write error”);

if(lseek(fd,40,SEEK_SET)==-1)

printf (“lseek error”);

if(write(fd,buf2,7)!=7)

printf (“buf2 write error”);

exit(0);

}

7.

名称::

dup/dup2

目标:

复制一个现存的文件描述符.

头文件:

#include <unistd.h>

函数原形:

int dup(int oldfd)

int dup2(int oldfd,int newfd)

参数:

oldfd 原有文件描述符

newfd 新的文件描述符

返回值:

-1 遇到错误

int 新文件描述符

  
系统调用dup是用来复制一个文件描述符,也就是将进程u区的文件描述符表中的一项复制一份,使得这两项同时指向系统稳健表的同一表项。
  系统调用dup复制由参数oldfd指定的文件描述到进程文件描述符表的第一个空表项处。而系统调用dup2复制由参数oldfd指定的文件描述到参数newfd指定的文件描述符表项处。老的文件描述符和新复制的文件描述符可以互换使用。它们共享锁、文件指针和文件状态。例如,对其中一个文件描述符使用系统调用lseek修改文件指针的位置,对另一文件描述符来说文件指针也改变了,其实我们了解了内核的工作原理,这一点很容易理解。因为我们知道,文件指针是放在系统文件表中的。但这两个文件描述符具有不同的close-on-exec标志,因为该标志是存放在文件描述符表中的。
  该调用成功时,返回值为新的描述符;错误时,返回-1,并设置相应的错误代码errno:

EBADF:参数oldfd不是一个已经打开的文件描述符;或者参数newfd超出允许的文件描述符的取值范围。
EMFILE:进程打开的文件描述符数量已经到达最大值,但仍然企图打开新的文件描述符。

  下面我们来看一个简单的例子。在这个例子中,我们将标准输出(文件描述符为1)关闭,并将一个打开了普通文件“output”的文件描述符复制到标准输出上,因为刚关闭了文件描述符1,所以,文件描述符表的第一个空表项是1。所以,程序以后的printf等向标准输出写的内容都写到了文件中。
利用这个功能我们可以把输出/输入重定向到文件中。下面是一个例子。

/*1_5.c*/

#include <stdio.h>

#include <unistd.h>

#include <systypes.h>

#include <sys/stat.h>

#include <string.h>

#include <errno.h>

#include <fcntl.h>

main(int argc,char *argv[])

{

int fd;

if ((fd=open(argv[1],O_CREAT|O_RDWR,0644))==-1)

printf("cannot open output file ");

close(1); /* 关闭标准输出 */

if(dup(fd)==-1); /* 复制fd到文件描述符1上 */

 perror(“error”);
close(fd); /* 即时关闭不用的文件描述符是一个好习惯 */

printf("This line will write to file ");

}
  该程序执行过程的屏幕拷贝:
[wap@wapgw /tmp]$ gcc -o 1_5 1_5.c

[wap@wapgw /tmp]$ ./1_5 test1

[wap@wapgw /tmp]$ more test1

This line will write to file

dup2的功能和dup基本相同,只不过是dup2复制oldfd到newfd上。下面是用dup2实现同样的例子。

/*1_6.c*/

#include <stdio.h>

#include <unistd.h>

#include <systypes.h>

#include <sys/stat.h>

#include <string.h>

#include <errno.h>

#include <fcntl.h>

main(int argc,char *argv[])

{

int fd;

if((fd=open(argv[1],O_WRONLY|O_CREAT,0644))==-1)

perror(“error”);

close(1);

if(dup2(fd,1)==-1)

perror(“error”);

close(fd);

printf(“This line will write to file \n”);

close(fd);

}

利用这两个函数我们可以实现管道的功能,有关管道的内容将在后面介绍。

8.

名称::

fcntl

目标:

改变已经打开文件的性质。

头文件:

#include <unistd.h>

#include <sys/types.h>

#include <fcntl.h>

函数原形:

int fcntl(int fd,int cmd);

int fcntl(int fd,int cmd,long arg);

int fcntl(int fd,int cmd,struct flock *lock);

参数:

fd 文件描述符

cmd 功能描述位

返回值:

-1 遇到错误

V-node

int 依赖于cmd
fcntl函数有5种功能:

1 复制一个现存的文件描述符(cmd=F_DUPFD)

2 获得/设置文件描述符标记(cmd=F_GETFD或F_SETFD)

3 获得/设置文件状态标志(cmd=F_GETFL或F_SETFL)

4 获得/设置异步I/O所有权(cmd=F_GETOWN 或F_SETOWN)

5 获得/设置记录锁(cmd=F_GRTLK,F_SETLK或F_SETLKW)

fcntl的功能之一是重复文件描述字。

fcntl (FileDescriptor, F_DUPFD, 0)等价于Dup(FileDescriptor)

close (New); fcntl(Old, F_DUPFD, New)等价于dup2 (Old,New)

fcntl的功能之二获得/设置文件描述符标记。

获得文件描述标记fcntl (FileDescriptor, F_GETFD)

设置文件描述标记fcntl(FileDescriptor, F_SETFD, flags)

fcntl的功能之三获得/设置文件状态标签,文件状态标签分为3类它们是文件访问方式、打开时标志和I/O操作方式。

一、目录的打开和关闭

1.

名称:

opendir

目标:

打开一个目录。

头文件:

#include <sys/types.h>

#include < dirent.h>

函数原形:

DIR *opendir(const char *name)

参数:

name 目录名

返回值:

NULL 遇到错误

DIR * 打开成功

opendir用于打开一个目录,其功能和open相似。只不过open用于打开一个文件,而opendir用于打开一个目录。如果opendir可以成功打开一个目录,它就返回一个指向目录的指针,我们可以通过opendir的联机帮助知道这些内容。

首先在命令提示符后面键入[root@LINUX root]#man –k opendir来查找和opendir相关的联机帮助。我们可以得到以下内容:

opendir (3) -open a directory

这正是我们想要的。

然后我们可以键入[root@LINUX root]#man 3 opendir 来查看opendir[3]的联机帮助。

在帮助文档中我们可以看到这样一段话:

The opendir() function opens a directory stream correspondig to the directory name,and returns a pointer to the directory stream. The stream is positioned at the first entry in the directory.

The opendir() function rerurns a poin to the directory stream or NULL if an error occurred.

这些正是我们要找的信息. 除了这些信息我们还可以从帮助中获取诸如函数头文件,函数功能,函数原形,返回值,出错处理,相关函数等信息。大家试着用同样的方法来学习这些相关函数,达到举一返三的目的。

2.

名称:

closedir

目标:

关闭一个目录.

头文件:

#include <sys/types.h>

#include < dirent.h>

函数原形:

int closedir(DIR *dir)

参数:

dir 指向目录的指针

返回值:

-1 遇到错误

0 打开成功,返回指向目录的指针。

二、目录的读取

3

名称:

readdir

目标:

读取目录内容。

头文件:

#include <unistd.h>

#include <lixux/dirent.h>

#include < linux/unistd.h>

函数原形:

int readdir(unsigned int fd ,struct dirent *dirp,unsigned int count)

参数:

fd 文件描述符

dirp 用于存放读入数据的数组

count

返回值:

-1 遇到错误

0 打开成功

同样readdir的功能也和read相似,用于读取目录中内容。其实用open,read,close等函数也可以对目录目录操作的,但不是一个好的办法,因为Linux支持多种的目录类型,如Apple,HFS,ISO9600,VFAY,NFS,如果用read来读,需要了解这些不同类型目录各自的结构细节。

利用这些函数我们可以编写不加参数的ls 命令,下面是代码。
/*2_1.c*/

#include < dirent.h>
#include <stdio.h>
#include <sys/types.h>

void show_dir(char dirname[]);

main(int ac,char *av[])
{
if(ac==1)
show_dir(“.”); / *读当前目录*/
else
while(--ac)
{
printf(“%s:\n”,*++av);
show_dir(*av); /*读指定目录*/
}
}

void show_dir(char dirname[])
{
DIR *dir_ptr; /*定义目录类型的指针*/
struct dirent *direntp; /*定义用于读目录的缓冲区*/

if((dir_ptr=opendir(dirname))==NULL)
printf(“Can’t open!”);
else
{
while((direntp=readdir(dir_ptr))!=NULL)
printf(“%s\n”,direntp->d_name);
closedir(dir_ptr);
}
}

三、目录的创建和删除

4.

名称:

mkdir

目标:

创建目录

头文件:

#include < sys/stat.h>

#include <sys/types.h>

函数原形:

int result=mkdir(char *pathname,mode_t mode)

参数:

pathname 新建目录名

mode 权限位的掩码

返回值:

-1 遇到错误

0 成功创建

/*2_2.c*/

#include <unistd.h>

#include <sys/types.h>

main(int argc,char *argv[])

{

int result;

if(argc!=2)

printf(“please input a direction.”);

if((result=mkdir(argv[1]))==-1)

perror(“error”);

}

5.

名称:

rmdir

目标:

删除一个目录,此目录必须为空

头文件:

#include <unistd.h>

函数原形:

int result=rmdir(const char *path);

参数:

path 目录名

返回值:

-1 遇到错误

0 成功删除

四、文件的链接

6.

名称:

link

目标:

创建一个文件的新链接

头文件:

#include < unistd.h>

函数原形:

int link(const char *oldpath,const char *newpath);

参数:

oldpath 原始链接名称

newpath 新建链接名称

返回值:

-1 遇到错误

0 成功创建

实例:

/*2_3.c*/

#include <unistd.h>

main(int argc,char *argv[])

{

int result;

if(argc!=3)

printf(“please input two file!”);

if((result=link(argv[1],argv[2]))==-1)

perror(“error”);

}

7.

名称:

unlink

目标:

删除一个链接

头文件:

#include <unistd.h>

函数原形:

int unlink(const char *pathname);

参数:

pathname 目录名

返回值:

-1 遇到错误

0 成功删除

8.

名称:

rename

目标:

重命名或删除一个链接

头文件:

#include < stdio.h>

函数原形:

int rename(const char* foldoath, const char* newpath);

参数:

oldpath 原始连接名称

newpath 新建连接名称

返回值:

-1 遇到错误

0 成功返回

/*2_5.c*/

#include <stdio.h>

#include <unistd.h>

main(int argc,char *argv[])

{

int result;

if(argc!=3)

printf(“please input two link!”);

if((result=tename(argv[1].argv[2]))==-1)

perror(“error”);

}

9.

名称:

symlink

目标:

创建符号连接文件

头文件:

#include <unistd.h>

函数原形:

int symlink(const char *oldpath,const char *newpath);

参数:

oldpath 原文件名

newpath 新连接名

返回值:

-1 遇到错误

0 成功返回

下面是例子:

#include <unistd.h>

main(int argc,char *argv[])

{

if(symlink(argv[1],argv[2])<0)

perror(“error”);

}

10.

名称:

chdir/fchdir

目标:

改变所调用进程的当前目录

头文件:

#include < unistd.h>

函数原形:

int chdir(const char *path);

int fchdir(int fd);

参数:

path 要达到的目录

fd 文件描述符

返回值:

-1 遇到错误

0 成功改变

六、文件的属性

11

名称:

stat/fstat/lstat

目标:

得到文件的属性。

头文件:

#include <sys/types.h>

#include <sys/stat.h>

#include <unistd.h>

函数原形:

int stat(const char *file_name,struct stat *buf)

int fstat(int filedes, struct stat *buf)

int lstat(const char *file_name,struct stat *buf)

参数:

file_name 文件名

filedes 文件描述符

buf 指向buffer的指针

返回值:

-1 遇到错误

0 成功返回

Stat把文件fname 的信息复制到指针bufp所指的结构中。Stat包括的信息有

st_mode 文件类型和许可权限

st_uid 用户所有者ID

st_gid 所属组ID

st_size 所占字节数

st_nlink 文件链接数

st_mtime 文件最后修改时间

st_atime 文件最后访问时间

st_actime 文件属性最后改变时间

下面的程序得到这些属性,并显示它们。

/*2_7.c*/

#include <stdio.h>

#include <sys/types.h>

#include <sys/stat.h>

int main(int ac, char *av[ ])

{

struct stat info;

if(ac>1)

if(stat(av[1],&info)!=-1)

{

show_stat_info(av[1],&info);

return 0;

}

else

perror(av[1]);

return 1;

}

show stat_info(char *fname,struct stat *buf)

{

printf(“mode : %o\n”,buf->st_mode); /*显示文件模式字段*/

printf(“links : %d\n”,buf->st_nlink); /*显示链接数*/

printf(“user : %d\n”,buf->st_uid); /*显示用户名ID*/

printf(“group : %d\n”,buf->st_gid); /*显示组ID*/

printf(“size : %d\n”,buf->st_size); /*显示文件大小*/

printf(“modtime : %d\n”,buf->st_mtime); /*显示文件的最后修改时间*/

printf(“name:%s\n”,fname);      /*显示文件名*/

}

fstat函数类似于stat,但是当命名的文件是一个符号连接时,lstat返回该符号连接的有关信息,而不是由该符号连接引用的文件的信息。

编译并运行fileinfo.c:

[root@LINUX root]#cc –o fileinfo fileinfo.c

[root@LINUX root]#./fileinfo fileinfo.c

mode:100664

links: 1

user:500

group:120

size:1106

modtime:965158604

name:fileinfo.c

这个程序就是ls –l 命令实现代码的一部分,但是会和ls –l的输出有些不同,比如说时间的表示,用户和组ID的表示,文件权限的表示。涉及到了Linux编码的问题,这里不作介绍,大家可以查阅相关质料。

七、文件的存取性和权限

12.

名称:

access

目标:

确定文件的可存取性

头文件:

#include < unistd.h>

函数原形:

int access(const char *pathname ,int mode);

参数:

pathname 文件名

mode 新的所有权和特殊属性。

返回值:

-1 遇到错误

0 成功返回

其中,mode是表4-5中所列常数的逐位或运算。

access函数的mode常数有:

R_OK 测试读许可权

W_OK 测试写许可权

X_OK 测试执行许可权

  F_OK 测试文件是否存在

当用open函数打开一个文件时,内核以进程的有效用户ID和有效组ID为基础执行其存取许可权测试。有时,进程也希望按区实际用户ID和实际组ID来测试其存取能力。例如当一个进程使用设置用户ID,或设置组ID特征作为另一个用户(或组)运行时,就可能需要。

access函数是按实际用户ID和实际组ID进行存取许可权测试的。下面是程序例子。

/*2_8.c*/

#include <stdio.h>

#include <fcntl.h>

#include <sys/types.h>

#include <unistd.h>

int main(int argc,char *argv[])

{

if(access(argv[1],R_OK)<0)

printf(“access error for %s\n”,argv[1];

else

printf(“read access OK\n”);

if(open(argv[1],O_RDONLY)<0)

printf(“open for reading OK\n”);

else

printf(“open for reading OK\n”);

}

13.

名称:

umask

目标:

为进程文件方式创建屏蔽字

头文件:

#include < sys/types.h>

#include <sys/stat.h>

函数原形:

mode_t umask(mode_t cmask);

参数:

cmask

返回值:

以前的文件方式创建屏蔽字

umask函数为进程设置文件方式创建屏蔽字,并返回以前的值。其中,参数cmask由下面9个常数逐为与构成。

S_IRUSR 用户-读

S_IWUSR 用户-写

S_IXUSR 用户-执行

S_IRGRP 组-读

S_IWGRP 组-写

S_IXGRP 组-执行

S_IROTH 其他-读

S_IWOTH 其他-写

S_IXOTH 其他-执行

在进程创建一个新文件或新目录时,就一定会使用文件方式创建屏蔽字。

下面是一个例子程序2_9.c创建两个文件,创建第一个时,umask值为0,创建第二个时,umask值禁止所有组和其他存取许可权。若运行此程序可得如下结果,从中可见存取许可权是如何设置的。

/*2_9.c*/

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <stdio.h>

int main(int argc,char *argv[])

{

umask(0);

if(creat(argv[1],S_IRUST|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)<0)

perror(“ERROR”);

umask(S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);

if(creat(argv[2],S_IRUST|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)<0)

perror(“ERROR”);

exit(0);

}

下面是执行:

#gcc –o 2_9 2_9.c

#./2_9 test1 test2

#ls –l test1 test2

-rw-rw-rw- 1 root root 0 sep 24 22:26 test1

-rw------- 1 root root 0 sep 24 22:26 test2

我们可以看到第二个文件的组成员和其他人的读写权限被屏蔽了。

14.

名称:

chmod/fchmod

目标:

修改文件的所有权限和特殊属性。

头文件:

#include < sys/types.h>

#include <sys/stat.h>

函数原形:

int chmod(const char *path,mode_t mode);

int fchmod(in fildes,mode_t mode);

参数:

path 文件名

mode 新的所有权和特殊属性。

fildes 文件描述符

返回值:

-1 遇到错误

0 成功返回

chmod函数在指定的文件上进行操作,而fchmod函数则对已打开的文件进行操作。

为了改变一个文件的许可权位,进程的有效用户ID必须等于文件的所有者,或者该进程必须具有超级用户许可权。

程序可以通过系统调用chmod来改变文件的所有权和特殊属性,如:

chmod(“/tmp/myfie”,04764);

chmod(“/tmp/myfie”,S_ISUID|S_IRWXU|S_IRGRP|S_IWGRP|S_IROTH);

上述两条指令的作用相同,第一条是八进制来表示,第二条是用<sys/stat.h>中定义的符号来表示。后者有明显的优点,当系统定义的许可位的值改变时,无需修改程序。

Chmod函数的mode常数如下:

宏表示 八进制表示 含义

S_ISUID 04000 执行时设置用户id

S_ISGID 02000 执行时设置组id

S_ISVTX 01000 保存正文

S_IRWXU 00700 用户(所有者)读、写和执行

S_IRUSR 00400 用户(所有者)读

S_IWUSR 00200 用户(所有者)写

S_IXUSR 00100 用户(所有者)执行

S_IRWXG 00070 组读、写和执行

S_IRGRP 00040 组读

S_IWGRP 00020 组写

S_IXGRP 00010 组执行

S_IRWXO 00007 其他读、写和执行

S_IROTH 00004 其他读

S_IWOTH 00002 其他写

S_IXOTH 00001 其他执行

八、文件所有者和组

15.

名称:

chown/fchown/lchown

目标:

修改文件所有者和组

头文件:

#include <sys/types.h>

#include < unistd.h>

函数原形:

int chown(const char *path,uid_t owner,gid_t group);

int fchown(int fd,uid_t owner,gid_t group);

int lchown(const char *path,uid_t owner,gid_t group);

参数:

path 文件名

fp 文件描述符

owner 新的文件所有者ID。

group 新的组ID。

返回值:

-1 遇到错误

0 成功返回

chown通过修改文件属性来修改文件所有者和组的ID。例如:

chown(“file1“,200,40);

将文件file1的用户ID改为200,组ID改为40。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: