二、文件属性 int stat(const char *path, struct stat *buf); 功能:根据文件的路径获取文件的属性 buf:存储文件属性的结构体指针,是一个输出型参数 int fstat(int fd, struct stat *buf); 功能:根据文件描述符获取文件的属性 int lstat(const char *path, struct stat *buf); 功能:获取软连接文件的文件属性 struct stat { dev_t st_dev; // 设备ID ino_t st_ino; // inode 编号 mode_t st_mode; // 文件的类型和权限 * nlink_t st_nlink; // 硬链接数 uid_t st_uid; // 用户ID gid_t st_gid; // 组ID dev_t st_rdev; // 特殊设备ID号 off_t st_size; // 总字节数 * blksize_t st_blksize; // IO块字节数 blkcnt_t st_blocks; // 占用512字节块数 time_t st_atime; // 最后访问时间 time_t st_mtime; // 最后内容修改时间 * time_t st_ctime; // 最后状态修改时间 }; 在POSIX中,对于st_mode 有以下宏可以判断文件属于哪个类型: S_ISREG(m) 检查是否是普通文件 S_ISDIR(m) 目录文件 S_ISCHR(m) 字符设备文件 S_ISBLK(m) 块设备文件 S_ISFIFO(m) 管道文件 S_ISLNK(m) 软连接文件 S_ISSOCK(m) Socket文件 使用st_mode 与下面掩码进行处理(&),能获取文件的类型和权限: S_IFMT 0170000 获取文件类型的掩码 S_IFSOCK 0140000 socket文件 S_IFLNK 0120000 软链接文件 S_IFREG 0100000 普通文件 S_IFBLK 0060000 块设备文件 S_IFDIR 0040000 目录文件 S_IFCHR 0020000 字符设备文件 S_IFIFO 0010000 管道文件 S_ISUID 0004000 设置用户ID S_ISGID 0002000 设置组ID S_ISVTX 0001000 粘着位。如果一个可执行程序文件的这一位被设置了,程序第一次运行完之后,程序的正文部分的一个副本仍被保存在交换区(程序的正文部分是机器指令) S_IRWXU 00700 用户权限掩码 S_IRUSR 00400 用户读权限 S_IWUSR 00200 用户写权限 S_IXUSR 00100 用户执行权限 S_IRWXG 00070 组权限掩码 S_IRGRP 00040 组读权限 S_IWGRP 00020 组写权限 S_IXGRP 00010 组执行权限 S_IRWXO 00007 其它用户权限掩码 S_IROTH 00004 其它用户读权限 S_IWOTH 00002 其它用户写权限 S_IXOTH 00001 其它用户执行权限 三、文件的权限 int access(const char *pathname, int mode); 功能:测试当前用户对文件有哪些权限 pathname:文件路径 mode:想要测试的权限 F_OK 文件是否存在 R_OK 读权限 W_OK 写权限 X_OK 执行权限 返回值:存在则返回0,不存在返回-1 注意:如果文件不存在,测试RWX权限也会返回-1 int chmod(const char *path, mode_t mode); 功能:根据文件路径修改文件权限 path:文件路径 mode:由三位的八进制数组成的权限码 0644 普通文件 0755 执行文件 0755 目录文件 int fchmod(int fd, mode_t mode); 功能:根据文件描述符修改文件权限 权限屏蔽码: 如果我们不让新创建的文件具有某些权限,可以通过设置权限屏蔽码进行过滤 通过命令 umask 查看当前终端的权限屏蔽码 通过命令 umask 0xxx 可以修改当前终端的权限屏蔽码 注意:权限屏蔽码对于chmod/fchmod 函数和命令无效 mode_t umask(mode_t mask); 功能:设置当前进程的权限屏蔽码 mask:想要设置的权限屏蔽码 返回值:返回旧的权限屏蔽码 注意:该函数的设置只对当前进程有效,进程结束后就失效了 四、修改文件大小 int truncate(const char *path, off_t length); 功能:根据文件路径修改文件的大小 length:想要修改成的字节数大小 int ftruncate(int fd, off_t length); 功能:根据文件描述符修改文件大小 练习1:实现一个函数,可以删除文件的第[n,m)个字节 1 2 3 4 5 6 7 8 9 10 11 12 int del_file(const char* path,size_t n,size_t m); 五、删除和重命名 int remove(const char *pathname); 功能:标准库中的删除文件函数,底层调用unlink int unlink(const char *pathname); (最后一个硬链接才有效) 功能:删除文件 系统函数 int rename(const char *oldpath, const char *newpath); 功能:重命名文件 六、链接文件 Linux的文件系统会把分区主要分为两大部分: inode 信息块:默认128b 记录了文件的权限、大小、所有者、修改时间等信息,以及对应的block的位置信息。 block 块:默认4k 记录了文件名和真正的数据信息 每个文件必须拥有唯一一个inode以为若干个block,读取文件时,需要借助目录的block中记录的文件名找到该文件的inode号,继而通过inode读取到该文件的block 什么是软硬链接文件? 硬链接:硬链接文件没有自己的inode和block,只是在不同目录下复制了一份源文件的inode信息,可以通过inode访问到源文件的同一份block 软连接:软连接文件会建立自己的新的inode和block,而软连接文件的block中存储的是源文件的文件名和inode号 区别: 1、如果修改硬链接文件内容,源文件以及其它的硬链接文件也会被修改,软链接不会 2、删除源文件,只是删除了源文件的inode,block不会清理 3、删除源文件,硬链接文件不受影响,但软链接文件无法访问源文件 4、当硬链接数被删除为0时,文件才算是被真正的删除了 5、软链接可以连接目录,硬链接不可以 6、软链接可以跨文件系统,硬链接不行 int link(const char *oldpath, const char *newpath); 功能:创建硬链接文件 int symlink(const char *oldpath, const char *newpath); 功能:创建软链接文件 ssize_t readlink(const char *path, char *buf, size_t bufsiz); 功能:读取软链接文件数据,而非链接目标数据,读取的其实是链接的路径 buf:是一个输入型参数,获取链接路径 bufsize:获取的字节数 七、目录操作 int mkdir(const char *pathname, mode_t mode); 功能:创建目录 mode:目录的权限,注意必须要有执行权限,否则无法进入 int rmdir(const char *pathname); 功能:删除空目录 int chdir(const char *path); 功能:进入某个目录,相当于cd命令 char *getcwd(char *buf, size_t size); 功能:获取当前工作目录,相当于pwd命令 DIR *opendir(const char *name); 功能:打开目录文件,返回一个目录流 name:选择要打开的目录 struct dirent *readdir(DIR *dirp); 功能:从目录流中读取一条记录 struct dirent { ino_t d_ino; // i节点号 off_t d_off; // 下一条条目的偏移值 unsigned short d_reclen; // 当前条目的长度 unsigned char d_type; // 文件类型 DT_BLK 块设备文件 DT_CHR 字符设备文件 DT_DIR 目录文件 DT_FIFO 管道文件 DT_LNK 软链接文件 DT_REG 普通文 DT_SOCK socket文件 DT_UNKNOWN 未知类型 char d_name[256]; // 文件名 }; int closedir(DIR *dirp); 功能:关闭一个目录流 void seekdir(DIR *dirp, long loc); 功能:设置目录流的位置指针,用于随机读取 void rewinddir(DIR *dirp); 功能:设置目录流的位置指针到开头 long telldir(DIR *dirp); 功能:获取当前目录流的位置指针位置 作业: 1、实现 ls -l 功能 2、实现rm -rf功能