1. access系统调用
access系统调用用于检测所指定的文件访问权限,原型如下:
4. mkdir、rmdir系统调用
mkdir、rmdir系统调用同命令mkdir、rmdir类似,用于创建、删除一个目录,原型如下:
5. remove函数
remove函数用于删除一个文件或目录,同rm命令类似,原型如下:
6. opendir、readdir、closedir函数
opendir函数用于打开一个目录,原型如下:
而readdir函数用于读取一个目录,原型如下:
再来看看readdir返回值struct dirent,结构体定义如下:
closedir函数用于关闭"directory stream",原型如下:
好吧,来看一个实例,将一个目录中的所有文件列举出来:
st_mode:文件的类型与权限,st_mode总共16位,其中高4位为文件的类型,可以通过宏S_ISREG()、S_ISDIR()等相关宏来判断是普通文件、目录文件等。而低12位则是文件权限位,这里只要知道低9位就是我们常见的例如777就可以了。
st_uid:文件所属用户的id。
st_gid:文件所属组的id。
st_size:文件大小。
st_atime:对应文件的最后访问时间。
st_mtime:对应文件的最后修改时间。
st_ctime:对应文件的状态发生改变时间。
好了,了解了这些,来看一个实例:
2. 改变文件属主
可以通过chown、fchown系统调用来改变文件属主,原型如下:
3. 改变文件权限
改变文件权限可以通过chmod、fchmod系统调用,原型如下:
4. 关于umask
先来看一段代码:
umask用于open、mkdir这类系统调用创建文件或目录的权限掩码,用于屏蔽一些权限位,权限计算公式如下:
(mode & ~umask & 0777)
通常umask默认值为0022,其含义是对于同组或其他用户,应屏蔽写权限。假设调用mkdir创建一个目录,其mode为0777,那么创建的目录权限实际为0755。
可以通过umask()系统调用来改变这个掩码值,原型如下:
access系统调用用于检测所指定的文件访问权限,原型如下:
#include <unistd.h>
int access(const char *pathname, int mode);
代码示例如下:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
if (access(argv[1], F_OK))
printf("No such file or directory!\n");
else
printf("%s\n", argv[1]);
return 0;
}
其中F_OK用于测试这个文件或目录是否存在,其它mode常量还有R_OK、W_OK、X_OK,分别对应读权限,写权限和可执行权限。access系统调用检测成功的话返回0,否则返回-1,而这些mode常量可以通过或运算形成位掩码,只要其中一项检测没有成功返回值都为-1。
2. link、unlink系统调用
link、unlink系统调用用于创建和删除硬链接,原型如下:
#include <unistd.h>
int link(const char *oldpath, const char *newpath);
int unlink(const char *pathname);
link系统调用中的oldpath是一个已经存在的文件名,而newpath将是要创建硬链接的文件名,如果newpath存在,则不会将其覆盖。
3. rename系统调用
reanme系统有点类似于mv命令,用于重命名一个文件或移动一个文件,原型如下:
#include <stdio.h>
int rename(const char *oldpath, const char *newpath);
4. mkdir、rmdir系统调用
mkdir、rmdir系统调用同命令mkdir、rmdir类似,用于创建、删除一个目录,原型如下:
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int mkdir(const char *pathname, mode_t mode);
int rmdir(const char *pathname);
5. remove函数
remove函数用于删除一个文件或目录,同rm命令类似,原型如下:
#include <stdio.h>
int remove(const char *pathname);
6. opendir、readdir、closedir函数
opendir函数用于打开一个目录,原型如下:
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
opendir返回值是一个DIR类型的指针,即所谓的"directory stream",供后续函数使用。
而readdir函数用于读取一个目录,原型如下:
#include <dirent.h>
struct dirent *readdir(DIR *dirp);
其中的dirp指针即是opendir的返回值,每调用一次readdir函数,dirp指针将指向下一个待读取的"directory entry",如果已经读取到"directory stream"的末尾或者出错,将返回一个NULL指针。
再来看看readdir返回值struct dirent,结构体定义如下:
struct dirent {
ino_t d_ino; /* inode number */
off_t d_off; /* offset to the next dirent */
unsigned short d_reclen; /* length of this record */
unsigned char d_type; /* type of file; not supported
by all file system types */
char d_name[256]; /* filename */
};
closedir函数用于关闭"directory stream",原型如下:
#include <sys/types.h>
#include <dirent.h>
int closedir(DIR *dirp);
好吧,来看一个实例,将一个目录中的所有文件列举出来:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
int main(int argc, char *argv[])
{
DIR *dir;
struct dirent *dp;
dir = opendir(argv[1]);
if (dir == NULL) {
perror("opendir error");
return -1;
}
for (;;) {
dp = readdir(dir);
if (dp == NULL)
break;
if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
continue; /* skip . and .. */
printf("%s\n", dp->d_name);
}
closedir(dir);
return 0;
}
//2015.08.13 补
1. stat相关系统调用
stat()、lstat()、fstat()系统调用用于获取文件相关信息,原型如下:
#include <sys/stat.h>
int stat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);
int lstat(const char *path, struct stat *buf);
其中stat根据文件名来获取文件相关信息。
lstat与stat类似,区别在于如果文件属于符号链接,那么所获取的信息是符号链接本身,而不是符号链接所指向的文件。
fstat则是根据一个打开文件的文件描述符来获取文件相关信息。
而上述系统调用都会将所获取的文件信息存储在struct stat指针所指向的缓冲区中,struct stat类型定义如下:
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for file system I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};
这里只针对部分成员加以描述。
st_mode:文件的类型与权限,st_mode总共16位,其中高4位为文件的类型,可以通过宏S_ISREG()、S_ISDIR()等相关宏来判断是普通文件、目录文件等。而低12位则是文件权限位,这里只要知道低9位就是我们常见的例如777就可以了。
st_uid:文件所属用户的id。
st_gid:文件所属组的id。
st_size:文件大小。
st_atime:对应文件的最后访问时间。
st_mtime:对应文件的最后修改时间。
st_ctime:对应文件的状态发生改变时间。
好了,了解了这些,来看一个实例:
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <time.h>
int main(int argc, char *argv[])
{
struct stat sb;
if (stat(argv[1], &sb) < 0) {
perror("stat");
exit(EXIT_FAILURE);
}
printf( "mode \t\t%o\n"
"uid \t\t%d\n"
"gid \t\t%d\n"
"size \t\t%d\n"
"blocksize \t%d\n"
"blocks \t\t%d\n" , sb.st_mode, sb.st_uid, sb.st_gid,
(int)sb.st_size, (int)sb.st_blksize, (int)sb.st_blocks);
printf( "atime \t\t%s", ctime(&sb.st_atime));
printf( "mtime \t\t%s", ctime(&sb.st_mtime));
printf( "ctime \t\t%s", ctime(&sb.st_ctime));
exit(EXIT_SUCCESS);
}
2. 改变文件属主
可以通过chown、fchown系统调用来改变文件属主,原型如下:
#include <unistd.h>
int chown(const char *path, uid_t owner, gid_t group);
int fchown(int fd, uid_t owner, gid_t group);
3. 改变文件权限
改变文件权限可以通过chmod、fchmod系统调用,原型如下:
#include <sys/stat.h>
int chmod(const char *path, mode_t mode);
int fchmod(int fd, mode_t mode);
4. 关于umask
先来看一段代码:
#include <stdio.h>
#include <sys/stat.h>
int main(int argc, char *argv[])
{
if (mkdir(argv[1],
(S_IRWXU | S_IRWXG | S_IRWXO) /*0777*/) < 0) {
perror("mkdir");
}
return 0;
}
这段代码是新建一个目录,目录的权限是0777,但是呢,代码执行之后,结果并不是所预期的那样,创建的目录权限为0775,这是什么原因呢,那就是同这里的umask有关。
umask用于open、mkdir这类系统调用创建文件或目录的权限掩码,用于屏蔽一些权限位,权限计算公式如下:
(mode & ~umask & 0777)
通常umask默认值为0022,其含义是对于同组或其他用户,应屏蔽写权限。假设调用mkdir创建一个目录,其mode为0777,那么创建的目录权限实际为0755。
可以通过umask()系统调用来改变这个掩码值,原型如下:
#include <sys/stat.h>
mode_t umask(mode_t mask);
对于上面代码只需要作出如下修改,创建的目录权限就是我们想要的0777,代码如下:
#include <stdio.h>
#include <sys/stat.h>
int main(int argc, char *argv[])
{
umask(0);
if (mkdir(argv[1],
(S_IRWXU | S_IRWXG | S_IRWXO) /*0777*/) < 0) {
perror("mkdir");
}
return 0;
}
那么我想获取系统默认的掩码值,怎么获取呢?可以通过下面的方式:
mode_t getumask(void)
{
mode_t mask = umask( 0 );
umask(mask);
return mask;
}
使用umask系统调用会返回之前的掩码值,那么调用getumask一下,当前我的系统掩码值为0002,所以最终创建的目录权限为0775,这就能理解为什么指定0777权限而得到0775权限的原因了。
参考教程:The Linux Programming Interface - A Linux and UNIX System Programming Handbook.pdf