sys/stat.h头文件解析
** 目录:**
- stat结构体
struct stat
{
unsigned long st_dev; //设备号(文件系统)
unsigned long st_ino; //inode节点号
unsigned int st_mode; //文件类型和权限信息
unsigned int st_nlink; //文件的符号链接数
uid_t st_uid; //用户ID
gid_t st_gid; //组ID
unsigned long st_rdev; //设备号用于特殊文件
unsigned long __pad1;
long st_size; //文件的大小(以字节为单位)
int st_blksize; //best I/O block size
int __pad2;
long st_blocks; //文件内容对应的块大小
long st_atime; //文件内容对应的块数量
unsigned long st_atime_nsec;
long st_mtime; //文件最后被访问的时间
unsigned long st_mtime_nsec;
long st_ctime; //文件内容最后被修改的时间
unsigned long st_ctime_nsec;
unsigned int __unused4; //未使用4,预留位
unsigned int __unused5;
}
st_mode 定义了下列数种情况: S_IFMT 0170000 文件类型的位遮罩 S_IFSOCK 0140000 scoket S_IFLNK 0120000 符号连接 S_IFREG 0100000 一般文件 S_IFBLK 0060000 区块装置 S_IFDIR 0040000 目录 S_IFCHR 0020000 字符装置 S_IFIFO 0010000 先进先出(命名管道) 和文件权限标识
主要函数
代码语言:javascript复制extern int chmod(const char*, mode_t);
extern int fchmod(int, mode_t);
extern int mkdir(const char*, mode_t);
extern int fstat(int, struct stat*);
extern int fstat64(int, struct stat64*);
extern int fstatat(int, const char*, struct stat*, int);
extern int fstatat64(int, const char*, struct stat64*, int);
extern int lstat(const char*, struct stat*);
extern int lstat64(const char*, struct stat64*);
extern int stat(const char*, struct stat*);
extern int stat64(const char*, struct stat64*);
extern int mknod(const char*, mode_t, dev_t);
extern mode_t umask(mode_t);
1. chmod()
函数定义:
代码语言:javascript复制int chmod(const char *path, mode_t mode);
int fchmod(int fd, mode_t mode);
int fchmodat(int fd, const char *pathname, mode_t mode, int flag);
函数说明:
chmod()会依参数mode 权限来更改参数path 指定文件的权限。 fchmod()会依参数mode 权限来更改参数fd 所指文件的权限。参数fd 为已打开文件的文件描述符。参数mode 和chmod ()函数一致。 fchmodat函数与chmod函数在下面两种情况下是相同的:
- pathname参数为绝对路径
- fd参数取值为AT_FDCWD而pathname参数为相对路径
否则,fchmodat计算相对于打开目录(由fd参数指向)的pathname。flag参数可以用于改变fchmodat的行为,当设置了AT_SYMLINK_NOFOLLOW标志时,fchmodat并不会跟随符号链接。
返回值:
权限改变成功则返回0, 失败返回-1, 错误原因存于errno
参数 mode 有下列数种组合:
规律: S_I固定前缀 位标识 位标识: SUID=set uid (设置uid位) SGID=set gid (设置gid位) SVTX 粘滞位 R读,W写,X可执行,USR用户,GRP组,OTH其他 使用RWXU表示用户(取首字母其他同理)读写执行权限 使用RUSR表示用户读权限,其他同理
S_ISUID 04000 文件的 (set user-id on execution)位 S_ISGID 02000 文件的 (set group-id on execution)位 S_ISVTX 01000 文件的sticky 位 S_IRWXU 00700 文件所有者拥有读写和执行操作权限 S_IRUSR 00400 文件所有者具可读取权限 S_IRGRP 00040 用户组具可读取权限 S_IROTH 00004 其他用户具可读取权限 S_IRWXG 00070 用户组拥有读写和执行操作权限 S_IRWXO 00007 其他用户拥有读写和执行操作权限 S_IWGRP 00020 用户组具可写入权限 S_IWOTH 00002 其他用户具可写入权限 S_IWUSR 00200 文件所有者具可写入权限 S_IXGRP 00010 用户组具可执行权限 S_IXOTH 00001 其他用户具可执行权限 S_IXUSR 00100 文件所有者具可执行权限
权限值 00000含义:首位0为前缀表示八进制,第二位为特殊权限(suid,sgid等),第三位之后分别为用户位,用户组位,其他用户位,
数字表示:读权限值位1,写2,执行4,将多种权限值相加后得到组合权限。
9位字母表示:-------- 用户---,组---,其他---,r--读,-w-写,--x执行, 00755权限表示:rwxr-xr-x
错误代码:
EPERM 进程的有效用户识别码与欲修改权限的文件拥有者不同, 而且也不具root 权限. EACCESS 参数path 所指定的文件无法存取. EROFS 欲写入权限的文件存在于只读文件系统内. EFAULT 参数path 指针超出可存取内存空间. EINVAL 参数mode 不正确 ENAMETOOLONG 参数path 太长 ENOENT 指定的文件不存在 ENOTDIR 参数path 路径并非一目录 ENOMEM 核心内存不足 ELOOP 参数path 有过多符号连接问题. EIO I/O 存取错误
示例代码
代码语言:javascript复制#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
int DtoO(int mode)//转换为8进制
{
int tmp = 0;
if(mode == 0)
return 0;
tmp = DtoO(mode/8)*10 mode%8;
return tmp;
}
int main(int argc, char *argv[])
{
unsigned int mode = 0;
char cmode[8] = {0};
if(argc < 3)
{
fprintf(stderr, "Usage: %s mode filenamen", argv[0]);
exit(EXIT_FAILURE);
}
sprintf(cmode,"0%s",argv[1]);
mode = (unsigned int)atoi(argv[1]);
return 0;
}
2. mkdir()
函数定义:
代码语言:javascript复制int mkdir(const char *pathname, mode_t mode);
int mkdirat(int fd, const char *pathname, mode_t mode);
函数说明:
mkdir()函数以mode方式创建一个以参数pathname命名的目录,mode定义新创建目录的权限。 mkdirat()函数和mkdir()唯一区别:前者是在fd文件描述指示的路径下建立还该目录即使用绝对路径。 获取fd目录文件描述符,需要使用dirfd(DIR *dp)函数;参数dp为目录指针,需要opendir(const char *str)函数打开str所指路径。
返回值:
若目录创建成功,则返回0;否则返回-1,并将错误记录到全局变量errno中。
示例代码
代码语言:javascript复制#include <sys/stat.h>
int main(char argc, char *argv[])
{
int ok = 0;
if((ok=mkdir(argv[1],0755)) != 0)
{
perror("mkdir %s", argv[1]);
}
return 0;
}
注意事项
如果你希望创建一个755或更高的权限的目录。
需要先调用umask函数。
该函数原型:
mode_t umask(mode_t mask);
函数说明
umask()会将系统umask值设成参数mask&0777后的值,然后将先前的umask值返回。在使用open()建立新文件时,该参数mode并非真正建立文件的权限,而是(mode&~umask)的权限值。
例如,在建立文件时指定文件权限为0666,通常umask值默认为022,则该文件的真正权限则为0666&~022=0644,也就是rw-r--r--
返回值此调用不会有错误值返回。 返回值为原先系统的umask值。
因此,创建755的目录,需要先执行umask(0) 然后再调用mkdir函数。
3. stat()
函数定义
代码语言:javascript复制int stat(const char *restrict pathname,struct stat *restrict buf);
int fstat(int fields,struct stat *buf);
int lstat(const char *restrict pathname,struct stat *restrict buf);
int fstatat...
函数说明
给出一个文件(文件、文件夹),一旦给出pathname,stat函数就返回与此命名文件有关的信息结构,fstat函数获取已在描述符fields上打开文件的有关信息。lstat函数类似于stat.但是当命名的文件是一个符号链接时,lstat返回该符号链接的有关信息,而不是由该符号链接引用文件的信息。第二个参数buf是指针,它指向一个我们必须提供的结构,这些函数填写由buf指向的结构。该结构的实际定义可能随实现有所不同.
4. mknod()
用来创建文件的,其原型是:
代码语言:javascript复制int mknod(const char *path, mode_t mode, dev_t dev);
int mknodat(int fd, const char *path, mode_t mode, dev_t dev)
函数说明
第一个参数表示你要创建的文件的名称,第二个参数表示文件类型,第三个参数表示该文件对应的设备文件的设备号。只有当文件类型为 S_IFCHR 或 S_IFBLK 的时候该文件才有设备号,创建普通文件时传入0即可。
该函数最主要的用途就是创建FIFO文件,比如你的代码:
mknod(FIFO_FILE,S_IFIFO|0666,0); FIFO_FILE是一个字符指针,指向文件名,S_IFIFO表示要创建一个FIFO文件,0666表示该文件的权限是所有人可读可写,0表示该文件不是一个设备文件
其他函数
mkfifo
int mkfifo(const char*, mode_t); //创建命名管道
utimensat和futimens是以纳秒级的精度改变文件的时间戳
int utimensat(int dirfd, const char *pathname,const struct timespec times[2], int flags); int futimens(int fd, const struct timespec times[2]);