一、打开/关闭文件
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:
下面我们来看一个简单的例子。在这个例子中,我们将标准输出(文件描述符为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[])
close(fd); /* 即时关闭不用的文件描述符是一个好习惯 */ 该程序执行过程的屏幕拷贝:
[wap@wapgw /tmp]$ gcc -o 1_5 1_5.c |
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 遇到错误
|
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。