Day5
stat/fstat/lstat
#include <sys/stat.h>
- 用来获取文件的属性,
- 返回 0 成功, -1 失败
int stat(const char *path, struct stat *buf);
path
需要文件路径
int fstat(int fd, struct stat *buf);
fd
需要打开后的文件描述符
int lstat(const char *pathname, struct stat *buf);
stat/fstat 会跟踪链接目标,而lstat不跟踪链接目标
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* file type and mode */
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 filesystem I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
/* Since Linux 2.6, the kernel supports nanosecond
precision for the following timestamp fields.
For the details before Linux 2.6, see NOTES. */
struct timespec st_atim; /* time of last access */
struct timespec st_mtim; /* time of last modification */
struct timespec st_ctim; /* time of last status change */
#define st_atime st_atim.tv_sec /* Backward compatibility */
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec
};
S_ISREG(m) is it a regular file?
S_ISDIR(m) directory?
S_ISCHR(m) character device?
S_ISBLK(m) block device?
S_ISFIFO(m) FIFO (named pipe)?
S_ISLNK(m) symbolic link? (Not in POSIX.1-1996.)
S_ISSOCK(m) socket? (Not in POSIX.1-1996.)
S_IFMT 0170000 bit mask for the file type bit field
S_IFSOCK 0140000 socket
S_IFLNK 0120000 symbolic link
S_IFREG 0100000 regular file
S_IFBLK 0060000 block device
S_IFDIR 0040000 directory
S_IFCHR 0020000 character device
S_IFIFO 0010000 FIFO
S_ISUID 04000 set-user-ID bit
S_ISGID 02000 set-group-ID bit (see below)
S_ISVTX 01000 sticky bit (see below)
S_IRWXU 00700 owner has read, write, and execute permission
S_IRUSR 00400 owner has read permission
S_IWUSR 00200 owner has write permission
S_IXUSR 00100 owner has execute permission
S_IRWXG 00070 group has read, write, and execute permission
S_IRGRP 00040 group has read permission
S_IWGRP 00020 group has write permission
S_IXGRP 00010 group has execute permission
S_IRWXO 00007 others (not in group) have read, write, and
execute permission
S_IROTH 00004 others have read permission
S_IWOTH 00002 others have write permission
S_IXOTH 00001 others have execute permission
练习2:使用stat函数,获取文件的属性,显示出文件的类型和权限
homework
struct tm *localtime(const time_t *timep);
- 使用一个记录秒数据的
struct tm {
int tm_sec; /* Seconds (0-60) */
int tm_min; /* Minutes (0-59) */
int tm_hour; /* Hours (0-23) */
int tm_mday; /* Day of the month (1-31) */
int tm_mon; /* Month (0-11) */
int tm_year; /* Year - 1900 */
int tm_wday; /* Day of the week (0-6, Sunday = 0) */
int tm_yday; /* Day in the year (0-365, 1 Jan = 0) */
int tm_isdst; /* Daylight saving time */
};
练习3:获取文件的最后访问时间,最后修改时间,最后属性修改时间
homework
access
int access(const char *pathname, int mode);
- 测试当前用户对文件的访问权限
pathname
文件路径mode
F_OK
是否存在R_OK
是否有读权限W_OK
是否有写权限X_OK
是否有执行权限
- 返回值 0是 -1否
umask
mode_t umask(mode_t mask);
- 设置并获取权限屏蔽码,(给文件设置权限时,会受权限屏蔽码约束)功能与umask命令一样,一旦设置成功,新创建的文件解不会有mask中的权限
- 返回值 旧的权限屏蔽码
- 注意 该权限屏蔽码只对当前进程有效,进程结束后变成默认
chmod/fchmod
int chmod(const char *pathname, mode_t mode);
int fchmod(int fd, mode_t mode);
- 修改文件的权限
- 返回值 成功0 失败-1
- 注意 不受权限屏蔽码的约束
truncate/ftruncate
int truncate(const char *path, off_t length);
int ftruncate(int fd, off_t length);
- 修改文件的大小,如果文件的大小
- 返回 0 成功 -1 失败
link/unlink/remove/rename
int link(const char *oldpath, const char *newpath);
- 创建硬链接文件.硬链接指向的是文件的内存,因此当链接目标被删除后依然能访问文件内容
int unlink(const char *pathname);
- 删除硬链接文件
- 注意 普通文件就是硬链接数量为1的文件,当把一个文件的硬链接数删除到0时,这个文件就被删除了
int remove(const char *pathname);
- 删除文件,该函数时标准库中的删除文件函数,底层调用了unlink系统调用
int rename(const char *oldpath, const char *newpath);
- 文件重命名
symlink/readlink
int symlink(const char *target, const char *linkpath);
- 创建软连接(目录文件只能创建软连接)
oldpath
链接目标newpath
链接文件- 返回 0 成功 -1 失败
ssize_t readlink(const char *pathname, char *buf, size_t bufsiz);
- 读取软链接文件的内容而非链接目标(open打开软连接文件是打开目标文件)
path
链接文件的路径buf
读取数据存储位置bufsiz
读取多少个字节- 成功读取的字节数
mkdir/rmdir
- 返回值 0 成功 -1 失败
int mkdir(const char *pathname, mode_t mode);
- 创建目录,目录一定要有执行权限,否则无法进入
int rmdir(const char *pathname);
- 删除空目录,非空无法删除
chdir/fchdir/getcwd
char *getcwd(char *buf, size_t size);
- 获取当前进程的工作目录,工作目录是指当不加路径信息时,创建/打开是从哪个目录下查找工作目录默认是程序所在的目录
int chdir(const char *path);
- 修改进程的工作目录
- 返回值 0 成功 -1 失败
int fchdir(int fd);
- 修改进程的工作目录
- fd 被open打开的目录文件的fd
- 返回值 0 成功 -1 失败
opendir/fdopendir/closedir/readdir/rewinddir/telldir/seekdir
DIR *opendir(const char *name);
- 打开一个目录流
- 返回值 目录流(链表)
DIR *fdopendir(int fd);
- 使用文件描述符获取目录流,fd必须是目标文件的
struct dirent *readdir(DIR *dirp);
- 从目录流中读取一个文件结点的信息
struct dirent {
ino_t d_ino; /* Inode number */
off_t d_off; /* Not an offset; see below */
unsigned short d_reclen; /* Length of this record */
unsigned char d_type; /* Type of file; not supported
by all filesystem types */
char d_name[256]; /* Null-terminated filename */
};
d_type:
DT_BLK This is a block device.
DT_CHR This is a character device.
DT_DIR This is a directory.
DT_FIFO This is a named pipe (FIFO).
DT_LNK This is a symbolic link.
DT_REG This is a regular file.
DT_SOCK This is a UNIX domain socket.
DT_UNKNOWN The file type could not be determined.
int closedir(DIR *dirp);
- 关闭目录流
void rewinddir(DIR *dirp);
- 把文件目录流的位置指针调整到开头
long telldir(DIR *dirp);
- 获取当前目录流的位置指针在第几个文件结点
void seekdir(DIR *dirp, long offset);
- 调整当前目录流的位置指针
offset
只能是telldir的返回值
作业1 实现
ls -l
的功能
homework
struct passwd *getpwnam(const char *name);
- 根据用户id获取用户名
struct group *getgrgid(gid_t gid);
- 根据组id获取组名
作业2 实现
rm -rf
功能(删除非空目录)
homework
/* Inode number */
off_t d_off; /* Not an offset; see below */
unsigned short d_reclen; /* Length of this record */
unsigned char d_type; /* Type of file; not supported
by all filesystem types */
char d_name[256]; /* Null-terminated filename */
};
d_type:
DT_BLK This is a block device.
DT_CHR This is a character device.
DT_DIR This is a directory.
DT_FIFO This is a named pipe (FIFO).
DT_LNK This is a symbolic link.
DT_REG This is a regular file.
DT_SOCK This is a UNIX domain socket.
DT_UNKNOWN The file type could not be determined.
`int closedir(DIR *dirp);`
- 关闭目录流
`void rewinddir(DIR *dirp);`
- 把文件目录流的位置指针调整到开头
`long telldir(DIR *dirp);`
- 获取当前目录流的位置指针在第几个文件结点
`void seekdir(DIR *dirp, long offset);`
- 调整当前目录流的位置指针
- `offset` 只能是telldir的返回值
> 作业1 实现`ls -l`的功能
> [homework](./code/homework/ls.c)
> >`struct passwd *getpwnam(const char *name);`
> > - 根据用户id获取用户名
> >
> > `struct group *getgrgid(gid_t gid);`
> > - 根据组id获取组名
>
> 作业2 实现`rm -rf`功能(删除非空目录)
> [homework](./code/homework/rm.c)