知识杂货铺

不卖切糕

View on GitHub
5 October 2017 14:59

《UNIX环境高级编程》 - File and Directory

by 宋强

stat, fstat和lstat函数

int stat(const char * restrict pathname, struct stat *restrict buf);
int fstat(int filedes, struct stat *buf);
int lstat(const char *restrict pathname, struct stat *restrict buf);

有关定义都定义在<sys/stat.h>头文件中。

stat函数用于返回文件相关的信息结构,fstat用于使用描述符货的文件,lstat和stat大部分功能相同,但是当要操作i的文件类型是一个符号链接时,他返回符号链接的信息,而不是符号链接所指向的文件的,也就是stat会返回符号链接所指向的最终文件的信息。

stat结构体的基础形式为:

struct stat{
    mode_t      st_mode;
    ino_t       st_ino;
    dev_t       st_dev;
    dev_t       st_rdev;
    nlink_t     st_nlink;
    uid_t       st_uid;
    gid_t       st_gid;
    off_t       st_size;
    time_t      st_atime;
    time_t      st_mtime;
    time_t      st_ctime;
    blksize_t   st_blksize;
    blkcnt_t    st_blocks;
};

UNIX总共包括七种文件类型:

在stat中使用以下几个宏判断文件类型:

文件类型
S_ISREG() 普通文件
S_ISDIR() 目录
S_ISCHR() 字符特殊文件
S_ISBLK() 块特殊文件
S_ISFIFO() FIFO文件
S_ISLNK() 符号链接
S_ISSOCK() 套接字

访问权限

关于用户权限的说明 p75

access

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

按照实际用户ID和组用户ID来对文件进行读写权限测试:

mode有以下四种属性:

mode 属性
R_OK 测试读权限
W_OK 测试写权限
X_OK 测试执行权限
F_OK 测试文件是否存在

umask

mode_t umask(mode_t cmask);

进程创建文件时,使用umask设置好的文件访问权限。

cmask是stat中定义的9个值:

cmask  
S_IRUSR 用户读
S_IWUSR 用户写
S_IXUSR 用户执行
S_IRGRP 组读
S_IWGRP 组写
S_IXGRP 组执行
S_IROTH 其他读
S_IWOTH 其他写
S_IXOTH 其他执行

chmod,fchmod

int chmod(const char *pathname, mode_t mode);
int fchmode(int filedes, mode_t mode);

这两个函数用于修改文件的访问权限,。

mode有15种选择:

mode 说明
S_ISUID 执行时设置用户ID
S_ISGID 执行时设置组ID
S_ISVTX 保存正文(粘住位)
S_IRWXU 用户(所有者)读写执行
S_IRUSR
S_IWUSR
S_IXUSR 执行
S_IRWXG 组读写执行
S_IRGRP
S_IWGRP
S_IXGRP 执行
S_IRWXO 其他用户读写执行
S_IROTH
S_IWOTH
S_IXOTH 执行

有关粘住位(sticky bit)的说明,详见p83。

chown,fchown,lchown

#include <unistd.h>
int chown(const char *pathname, uid_t owner, gid_t group);
int fchown(int filedes, uid_t owner, gid_t group);
int lchown(const char *pathname, uid_t owner, gid_t group);

如果owner或者group的值设置为-1,则不变。

超级用户或者拥有此文件或者当前进程拥有修改此文件权限的时候才可以修改。

truncate,ftruncate

#include <unistd.h>
int truncate(const char *pathname, off_t length);
int ftruncate(int filedes, off_t length);

这两个函数将文件缩短为length个字节,length之后的将不可以再访问,可以用于截短某个文件。

硬链接

link,unlink,remove,rename

#include <unistd.h>
int link(const char *existingpath, const char *newpath);
int unlink(const char *pathname);

link与unlink创建与删除链接。(本质是目录??这一节需要多对文件系统有所了解,p89)

这一节的链接指的是硬链接。

#include <stdio.h>
int remove(const char *pathname);
int rename(const char *oldname, const char *newname);

remove同样也可以用于解除一个对文件或者目录的链接。

rename用于对一个文件或者目录重命名。

符号链接

在使用路径文件名作为参数的一些文件操作函数里面,有些不支持符号链接,也就是使用符号链接作为参数时,操作的是符号链接本身,而不是其指向的文件,各个函数对符号链接的处理如下:

是否穿透到目标文件 函数
access
chdir
chmod
chown
creat
exec
lchown
link
lstat
open
opendir
pathconf
readlink
remove
rename
stat
truncate
unlink

有一个关于符号链接的经典错误,如果创建了不能打开的文件的符号链接,那么打开这个文件的时候就会提示不存在这个文件,让人感到迷惑:

$ln -s /no/such/file myfile
$cat myfile
>>cat: myfile: No such file or directory
#include <unistd.h>
int symlink(const char *actualpath, const char *sympath);
ssize_t readlink(const char* restrict pathname, char * restrict buf, size_t bufsize);

symlink用于创建一个符号链接,实际文件不要求一定存在。 readlink用于打开符号链接本身,并且返回链接中指向的实际文件的路径文件名字符串。

文件的时间

有关于各种函数修改i节点和文件内容实体是否修改相应的三种文件时间。p94

utime

#include <utime.h>
int utime(const char *pathname, const struct utimebuf *times);

用于修改文件的时间属性。

struct utimebuf{
    time_t  actime;
    time_t  modtime;
};

mkdir,rmdir

include <sys/stat.h>
int mkdir(const char * pathname, mode_t mode);

创建一个空目录,创建目录时必须至少给出一个执行权限,否则将无法进入。

#include <unistd.h>
int rmdir(const char * pathname);

满足删除条件时(链接数为0,打开他的进程的数目也为0等),执行此命令将删除这个目录。

chdir,fchdir,getpwd

#include <unistd.h>
int chdir(const char *pathname);
int fchdir(int filedes);
char *getcwd(char *buf, size_t size);

前两个用于切换目录,最后一个获取当前工作目录的绝对路径字符串,size是指定buf长度用的。

tags: UNIX