本文章将描述文件系统的其他特性和文件的性质。
1 stat、fstat、和lstat函数
获取文件的信息结构
#include <sys/stat.h>
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);
//若成功返回0,失败返回-1
stat函数获取与此命名文件有关的信息结构
fstat函数获取在描述符filedes上打开的文件的有关的信息
lstat与stat类似,但是当命名文件是一个符号链接的时候,lstat返回此符号连接的信息,而不是此符号连接所指向的文件的信息
以下是stat结构体的结构
struct stat {
mode_t st_mode; // 文件类型和权限
ino_t st_ino; // 文件的inode号
dev_t st_dev; // 设备号
dev_t st_rdev; // 特殊设备文件号
nlink_t st_nlink; // 链接数
uid_t st_uid; // 用户ID号
gid_t st_gid; // 用户属组ID号
off_t st_size; // 普通文件对应的文件字节数
time_t st_atime; // 文件最后被访问的时间
time_t st_mtime; // 文件最后被修改的时间
time_t st_ctime; // 文件状态最后被修改的时间
blksize_t st_blksize; // 文件内容对应的块大小
blkcnt_t st_blocks; // 文件内容对应的块数量
};
2 文件类型
文件类型包括以下几种:
(1)普通文件:最常见的类型,包含了某种形式的数据。
(2)目录文件:包含了其他文件的名字以及指向与这些文件有关的信息的指针。
(3)块特殊文件:这种类型的文件可以提供对设备带缓冲的访问(磁盘)。
(4)字符特殊文件:这种类型的文件提供对设备不带缓冲的访问。
(5)FIFO:这种类型的文件用于进程间通信,有时将其称为命名管道。
(6)套接字:这种类型的文件用于进程间的网络通信。
(7)符号链接:这种文件类型指向一个文件。
文件类型的信息保存在stat结构体的st_mode中,可以通过以下宏确定文件的类型
S_ISREG() //普通文件
S_ISDIR() //目录文件
S_ISCHR() //字符特殊文件
S_ISBLK() //块特殊文件
S_ISFIFO() //管道或FIFO
S_ISLNK() //符号链接
S_ISSOCK() //套接字
POSIX.1允许实现进程间对象(IPC)。以下宏可以确定IPC对象的类型,这些宏的参数是指向stat结构的指针
S_TYPEISMQ //消息队列
S_TYPEISSEM //信号量
S_TYPEISSHM //共享存储对象
3 用户ID和组ID
一个进程通常包含多个ID
实际用户ID和实际组ID标识我们究竟是谁,这两个字段在登录的时候取自口令文件中的登录项。
有效用户ID、有效组ID以及附加组ID决定了我们的文件访问权限。
保存的设置用户ID和保存的组ID在执行一个程序时包含了有效用户ID和组有效组ID的副本。
在stat函数中,设置用户ID位及设置组ID位都包含在st_mode值中。可以用S_ISUID()和S_ISGID()来测试。
2.4 文件的访问权限
所有的文件类型的文件都有访问权限(access Permission)
每个文件都有9个访问权限
S_IRUSR //用户-读
S_IWUSR //用户-写
S_IXUSR //用户-执行
S_IRGRP //组-读
S_IWGRP //组-写
S_IXGRP //组-执行
S_IROTH //其他-读
S_IWOTH //其他-写
S_IXOTH //其他-执行
我们用名字打开任一类型的文件时,对该名字中包含的每一个目录,包括它可能隐含的当前工作目录都应具有执行权限。
这就是为什么对于目录其执行权限位常被称为搜索位的原因。
进程在每次打开,创建和删除一个文件的时候,内核就进行文件访问权限的测试:
1.若进程的有效用户ID是0,则允许访问。
2.若进程的有效用户ID等于文件的所有者ID,那么,若所有者适当的访问权限位被设置,则允许访问,否则拒绝访问。
3.若进程的有效组ID或进程的附加组ID之一等于文件的组ID,那么,若所有者适当的访问权限位被设置,则允许访问,否则拒绝访问。
4.若其他用户适当的访问权限位被设置,则允许访问,否则拒绝访问。
5 access函数
按实际的用户ID和实际组ID进行访问权限测试
#include <unistd.h>
int access(const char *pathname, int mode);
//成功返回0,失败返回-1
6 umask函数
为进程设置文件模式创建屏蔽字
#include <sys/stat.h>
mode_t umask(mode_t cmask);
//返回以前的文件模式创建屏蔽字,没有出错返回
cmask是9个访问权限位
7 chmod和fchmod函数
改变文件的访问权限
#include <sys/stat.h>
int chmod(const char *pathname, mode_t mode);
int fchmod(int filedes, mode_t mode);
//成功返回0,失败返回-1
8 粘住位
S_ISVTX位在早期的UNIX尚未使用分页技术的早期版本中,被该位被称之为粘住位,当程序运行结束的时候,
其程序的正文部分的一个副本仍被保存在交换区内,下一次执行该程序的时候,可以较快的装入内存。
现今的粘住位称为保存正文位,如果对一个目录设置了粘住位,则只有满足以下条件之一,才可将其删除:
1.拥有此文件
2.拥有此目录
3.是超级用户
9 chown、fchown和lchown
用于更改文件的用户ID和组ID
#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);
//成功返回0,失败返回-1
10 文件长度
在unix环境下,文件长度只是文件的一个属性,并不表征占用多少磁盘空间
stat结构成员st_size表示以字节文单位的文件长度,此字段只针对与普通文件,目录文件和符号链接有意义。
11 文件截短
在文件尾端处截去一些数据以缩短文件。
#include <unistd.h>
int truncate(const char *pathname, off_t length);
int ftruncate(int filedes, off_t length);
//成功返回0,失败返回-1
以上两个函数是把现有的文件截短为length字节。
12 link、unlink、remove和rename
#include <unistd.h>
int link(const char *existingpath, const char *newpath);
//创建一个指向现有文件的链接
int unlink(const char *pathname);
//删除一个现有的目录项
int remove(const char *pathname);
//解除对一个文件或目录的链接
int rename(const char *oldname, const char *newname);
//对文件或目录改名
13 symlink和readlink函数
操作符号链接
#include <unistd.h>
int symlink(const char *actualpath, const char *sympath);
//创建一个符号链接
ssize_t readlink(const char * restrict pathname, char * restrict buf, size_t bufsize);
//读取一个符号链接
14 文件的时间
对每个文件保持三个时间字段
st_atime //文件数据的最后访问时间(read)
st_mtime //文件数据的最后修改时间(write)
st_ctime //i节点状态的最后更改时间(chmod, chown)
unix不记录文件的创建时间
15 utime函数
修改一个文件的访问和修改时间
#include <utime.h>
int utime(const char *pathname, const struct utimbuf *time);
struct utimbuf{
time_t actime;
time_t modtime;
};
16 mkdir和rmdir函数
创建和删除目录
#include <sys/stat.h>
int mkdir(const char * pathname, mode_t mode);
int rmdir(const char * pathname);//只能删除空目录,目录中只包括.和..
17 读目录
#include <dirent.h>
DIR *opendir(const char *pathname);
//成功返回指针,失败返回NULL
struct dirent *readdir(DIR *dp);
//成功返回指针,若在目录结尾或者出错返回NULL
void rewinddir(DIR *dp);
int closedir(DIR *dp);
//成功返回0,失败返回-1
long telldir(DIR *dp);
//返回与dp关联的目录中的当前位置
void seekdir(DIR *dp, long loc);
struct dirent {
ino_t d_ino;
char d_name[NAME_MAX + 1];
};
18 chdir、fchdir和getcwd
更改当前工作目录
#include <unistd.h>
int chdir(const char *pathname);
int fchdir(int filedes);
//成功返回0, 失败返回-1
获取当前工作目录的完整的绝对路径名
#include <unistd.h>
char * getcwd(char *buf, size_t size);
//成功返回buf, 失败返回NULL
1 stat、fstat、和lstat函数
获取文件的信息结构
#include <sys/stat.h>
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);
//若成功返回0,失败返回-1
stat函数获取与此命名文件有关的信息结构
fstat函数获取在描述符filedes上打开的文件的有关的信息
lstat与stat类似,但是当命名文件是一个符号链接的时候,lstat返回此符号连接的信息,而不是此符号连接所指向的文件的信息
以下是stat结构体的结构
struct stat {
mode_t st_mode; // 文件类型和权限
ino_t st_ino; // 文件的inode号
dev_t st_dev; // 设备号
dev_t st_rdev; // 特殊设备文件号
nlink_t st_nlink; // 链接数
uid_t st_uid; // 用户ID号
gid_t st_gid; // 用户属组ID号
off_t st_size; // 普通文件对应的文件字节数
time_t st_atime; // 文件最后被访问的时间
time_t st_mtime; // 文件最后被修改的时间
time_t st_ctime; // 文件状态最后被修改的时间
blksize_t st_blksize; // 文件内容对应的块大小
blkcnt_t st_blocks; // 文件内容对应的块数量
};
2 文件类型
文件类型包括以下几种:
(1)普通文件:最常见的类型,包含了某种形式的数据。
(2)目录文件:包含了其他文件的名字以及指向与这些文件有关的信息的指针。
(3)块特殊文件:这种类型的文件可以提供对设备带缓冲的访问(磁盘)。
(4)字符特殊文件:这种类型的文件提供对设备不带缓冲的访问。
(5)FIFO:这种类型的文件用于进程间通信,有时将其称为命名管道。
(6)套接字:这种类型的文件用于进程间的网络通信。
(7)符号链接:这种文件类型指向一个文件。
文件类型的信息保存在stat结构体的st_mode中,可以通过以下宏确定文件的类型
S_ISREG() //普通文件
S_ISDIR() //目录文件
S_ISCHR() //字符特殊文件
S_ISBLK() //块特殊文件
S_ISFIFO() //管道或FIFO
S_ISLNK() //符号链接
S_ISSOCK() //套接字
POSIX.1允许实现进程间对象(IPC)。以下宏可以确定IPC对象的类型,这些宏的参数是指向stat结构的指针
S_TYPEISMQ //消息队列
S_TYPEISSEM //信号量
S_TYPEISSHM //共享存储对象
3 用户ID和组ID
一个进程通常包含多个ID
实际用户ID和实际组ID标识我们究竟是谁,这两个字段在登录的时候取自口令文件中的登录项。
有效用户ID、有效组ID以及附加组ID决定了我们的文件访问权限。
保存的设置用户ID和保存的组ID在执行一个程序时包含了有效用户ID和组有效组ID的副本。
在stat函数中,设置用户ID位及设置组ID位都包含在st_mode值中。可以用S_ISUID()和S_ISGID()来测试。
2.4 文件的访问权限
所有的文件类型的文件都有访问权限(access Permission)
每个文件都有9个访问权限
S_IRUSR //用户-读
S_IWUSR //用户-写
S_IXUSR //用户-执行
S_IRGRP //组-读
S_IWGRP //组-写
S_IXGRP //组-执行
S_IROTH //其他-读
S_IWOTH //其他-写
S_IXOTH //其他-执行
我们用名字打开任一类型的文件时,对该名字中包含的每一个目录,包括它可能隐含的当前工作目录都应具有执行权限。
这就是为什么对于目录其执行权限位常被称为搜索位的原因。
进程在每次打开,创建和删除一个文件的时候,内核就进行文件访问权限的测试:
1.若进程的有效用户ID是0,则允许访问。
2.若进程的有效用户ID等于文件的所有者ID,那么,若所有者适当的访问权限位被设置,则允许访问,否则拒绝访问。
3.若进程的有效组ID或进程的附加组ID之一等于文件的组ID,那么,若所有者适当的访问权限位被设置,则允许访问,否则拒绝访问。
4.若其他用户适当的访问权限位被设置,则允许访问,否则拒绝访问。
5 access函数
按实际的用户ID和实际组ID进行访问权限测试
#include <unistd.h>
int access(const char *pathname, int mode);
//成功返回0,失败返回-1
6 umask函数
为进程设置文件模式创建屏蔽字
#include <sys/stat.h>
mode_t umask(mode_t cmask);
//返回以前的文件模式创建屏蔽字,没有出错返回
cmask是9个访问权限位
7 chmod和fchmod函数
改变文件的访问权限
#include <sys/stat.h>
int chmod(const char *pathname, mode_t mode);
int fchmod(int filedes, mode_t mode);
//成功返回0,失败返回-1
8 粘住位
S_ISVTX位在早期的UNIX尚未使用分页技术的早期版本中,被该位被称之为粘住位,当程序运行结束的时候,
其程序的正文部分的一个副本仍被保存在交换区内,下一次执行该程序的时候,可以较快的装入内存。
现今的粘住位称为保存正文位,如果对一个目录设置了粘住位,则只有满足以下条件之一,才可将其删除:
1.拥有此文件
2.拥有此目录
3.是超级用户
9 chown、fchown和lchown
用于更改文件的用户ID和组ID
#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);
//成功返回0,失败返回-1
10 文件长度
在unix环境下,文件长度只是文件的一个属性,并不表征占用多少磁盘空间
stat结构成员st_size表示以字节文单位的文件长度,此字段只针对与普通文件,目录文件和符号链接有意义。
11 文件截短
在文件尾端处截去一些数据以缩短文件。
#include <unistd.h>
int truncate(const char *pathname, off_t length);
int ftruncate(int filedes, off_t length);
//成功返回0,失败返回-1
以上两个函数是把现有的文件截短为length字节。
12 link、unlink、remove和rename
#include <unistd.h>
int link(const char *existingpath, const char *newpath);
//创建一个指向现有文件的链接
int unlink(const char *pathname);
//删除一个现有的目录项
int remove(const char *pathname);
//解除对一个文件或目录的链接
int rename(const char *oldname, const char *newname);
//对文件或目录改名
13 symlink和readlink函数
操作符号链接
#include <unistd.h>
int symlink(const char *actualpath, const char *sympath);
//创建一个符号链接
ssize_t readlink(const char * restrict pathname, char * restrict buf, size_t bufsize);
//读取一个符号链接
14 文件的时间
对每个文件保持三个时间字段
st_atime //文件数据的最后访问时间(read)
st_mtime //文件数据的最后修改时间(write)
st_ctime //i节点状态的最后更改时间(chmod, chown)
unix不记录文件的创建时间
15 utime函数
修改一个文件的访问和修改时间
#include <utime.h>
int utime(const char *pathname, const struct utimbuf *time);
struct utimbuf{
time_t actime;
time_t modtime;
};
16 mkdir和rmdir函数
创建和删除目录
#include <sys/stat.h>
int mkdir(const char * pathname, mode_t mode);
int rmdir(const char * pathname);//只能删除空目录,目录中只包括.和..
17 读目录
#include <dirent.h>
DIR *opendir(const char *pathname);
//成功返回指针,失败返回NULL
struct dirent *readdir(DIR *dp);
//成功返回指针,若在目录结尾或者出错返回NULL
void rewinddir(DIR *dp);
int closedir(DIR *dp);
//成功返回0,失败返回-1
long telldir(DIR *dp);
//返回与dp关联的目录中的当前位置
void seekdir(DIR *dp, long loc);
struct dirent {
ino_t d_ino;
char d_name[NAME_MAX + 1];
};
18 chdir、fchdir和getcwd
更改当前工作目录
#include <unistd.h>
int chdir(const char *pathname);
int fchdir(int filedes);
//成功返回0, 失败返回-1
获取当前工作目录的完整的绝对路径名
#include <unistd.h>
char * getcwd(char *buf, size_t size);
//成功返回buf, 失败返回NULL