背景知识
文件系统是操作系统中负责存取和管理信息的模块,它用统一的方式管理用户和系统信息的存储、检索、更新、共享和保护,并为用户提供一整套方便有效的文件使用和操作方法。文件这一术语不但反映了用户概念中的逻辑结构,而且和存放它的辅助存储器(也称文件存储器)的存储结构紧密相关。所以,同一个文件必须从逻辑文件和物理文件两个侧面来观察它。
对于用户来说,可按自己的愿望并遵循文件系统的规则来定义文件信息的逻辑结构,由文件系统提供“按名存取”来实现对用户文件信息的存储和检索。可见,使用者在处理他的信息时,只需关心所执行的文件操作及文件的逻辑结构,而不必涉及存储结构。但对文件系统本身来说,必须采用特定的数据结构和有效算法,实现文件的逻辑结构到存储结构的映射,实现对文件存储空间和用户信息的管理,提供多种存取方法。例如,用户希望与具体的存储硬件无关,使用路径名、文件名、文件内位移就可以进行数据(字节、字段或记录)的读、写、改、删操作;而作为实现这些功能的文件系统来说,它的工作与存储硬件紧密相关,是根据用户的文件操作请求,转化为对设备(磁盘)上的信息按照所在的位置(设备号、柱面号、磁道号和物理块号)进行寻址、读写和控制。所以,文件系统的功能就是要在逻辑文件与物理文件、逻辑地址与物理地址、逻辑结构与物理结构、逻辑操作与物理操作之间实现转换,保证存取速度快、存储空间利用率高、数据可共享、安全可靠性好。
文件系统的基本功能之一是负责文件目录的建立、维护和检索,要求编排的目录便于查找、防止冲突,目录的检索方便迅速。由于文件目录也需要永久保存,所以,把文件目录也组织成文件存放在磁盘上称目录文件。有了文件目录后,就可实现文件的“按名存取”。当用户要求存取某个文件时,系统查找文件目录并比较文件名就可找到所寻文件的文件控制块(文件目录项)。然后,再通过文件目录项指出文件的文件信息相对位置或文件信息首块物理位置等就能依次存取文件信息。
1、获取文件的user、group、others访问权限
任务描述:
- 输入文件名,分别打印该文件的user、group、others的访问权限,以rwx和数字的方式打印
相关知识:
- 通过访问struct stat结构体中的st_mode成员,可以获取文件访问权限
- 获取文件属性int stat(const char *restrict pathname,struct stat *restrict buf)
pathname:文件的绝对路径名,buf:存有文件属性的stat结构体
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; //文件所有者 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; //文件内容对应的块数量 };
- user、group、others的读/写/执行9个权限在st_mode中各占一个bit位,如果bit位值为1,就表示文件具有该权限,如果为0,则表示文件不具有该权限。
- 使用st_mode & S_IRUSR 可以获得文件的用户是否具有读的权限位,如果该位为1,则该文件可以被所属用户进行读取,否则不能被读取。
main.c:
#include<stdio.h> #include<stdlib.h> #include<sys/stat.h> #include<unistd.h> struct stat buf; int main(int argc,char *argv[]) { int i; if(argc!=2){ perror("argc error\n"); exit(1); } if(stat(argv[1],&buf)!=0){ perror("stat error\n"); exit(1); } if(buf.st_mode&S_IRUSR) printf("user read\n"); if(buf.st_mode&S_IWUSR) printf("user write\n"); if(buf.st_mode&S_IXUSR) printf("user chmod\n"); if(buf.st_mode&S_IRGRP) printf("group read\n"); if(buf.st_mode&S_IWGRP) printf("group write\n"); if(buf.st_mode&S_IXGRP) printf("group chmod\n"); if(buf.st_mode&S_IROTH) printf("other read\n"); if(buf.st_mode&S_IWOTH) printf("other write\n"); if(buf.st_mode&S_IXOTH) printf("other chmod\n"); printf("======================\n"); for(i=2;i>=0;i--){ if(buf.st_mode&1<<(i*3+2))//依次取权限位的8\5\2的mode printf("r"); else printf("-"); if(buf.st_mode&1<<(i*3+1))//依次取权限位的7\4\1的mode printf("w"); else printf("-"); if(buf.st_mode&1<<(i*3+0))//依次取权限位的6\3\0的mode printf("x"); else printf("-"); } printf("\n"); printf("======================\n"); printf("The file authority is %o\n",buf.st_mode&0777); return 0; }
2、关闭文件的group的写权限和other的写权限
任务描述:
- 输入文件名,打印输出该文件初始的group和others权限,以及关闭写权限后的group和others权限
相关知识:
- stat获取文件权限,chmod关闭group和others的写权限
- int chmod(const char *path,mode_t mode),chmod()会依照参数mode权限来更改参数path指定文件的权限
- S_ISUID 04000 文件的(set user-id on execution)位
S_ISGID 02000 文件的(set group-id on execution)位
S_ISVTX 01000 文件的sticky位
S_IRUSR(S_IREAD) 00400 文件所有者具可读取权限
S_IWUSR(S_IWRITE)00200 文件所有者具可写入权限
S_IXUSR(S_IEXEC) 00100 文件所有者具可执行权限
S_IRGRP 00040 用户组具可读取权限
S_IWGRP 00020 用户组具可写入权限
S_IXGRP 00010 用户组具可执行权限
S_IROTH 00004 其他用户具可读取权限
S_IWOTH 00002 其他用户具可写入权限
S_IXOTH 00001 其他用户具可执行权限 - 要关闭某个权限位,只需对该权限位取反,然后与文件原来的权限位进行&操作即可。
main.c:
#include<stdio.h> #include<stdlib.h> #include<sys/stat.h> #include<sys/types.h> #include<unistd.h> struct stat buf; int main(int argc,char *argv[]) { int i; if(argc!=2){ perror("argc error\n"); exit(1); } if(stat(argv[1],&buf)!=0){ perror("stat error\n"); exit(1); } for(i=2;i>=0;i--){ if(buf.st_mode&1<<(i*3+2)) printf("r"); else printf("-"); if(buf.st_mode&1<<(i*3+1)) printf("w"); else printf("-"); if(buf.st_mode&1<<(i*3+0)) printf("x"); else printf("-"); } printf("\n"); printf("The file authority is:%o\n",buf.st_mode&0777); printf("after chmod\n"); chmod(argv[1],buf.st_mode&=~S_IWGRP);//group可写取反就是关闭写权限 chmod(argv[1],buf.st_mode&=~S_IWOTH);//others可写取反就是关闭写权限 /*由于文件权限已经更改,所以需要重新获取文件属性*/ if(stat(argv[1],&buf)!=0){ perror("stat error\n"); exit(1); } for(i=2;i>=0;i--){ if(buf.st_mode&1<<(i*3+2)) printf("r"); else printf("-"); if(buf.st_mode&1<<(i*3+1)) printf("w"); else printf("-"); if(buf.st_mode&1<<(i*3+0)) printf("x"); else printf("-"); } printf("\n"); printf("The file authority is:%o\n",buf.st_mode&0777); return 0; }
3、设置文件的访问权限为rw-r--r--
任务描述:
- 输入文件名,打印输出该文件初始权限,以及修改为rw-r--r--后的权限
相关知识:
- 使用chmod设置文件的多个权限位,对这些权限位进行按位或操作即可
main.c:
#include<stdio.h> #include<stdlib.h> #include<sys/stat.h> #include<sys/types.h> #include<unistd.h> struct stat buf; int main(int argc,char *argv[]) { int i; if(argc!=2){ perror("argc error\n"); exit(1); } if(stat(argv[1],&buf)!=0){ perror("stat error\n"); exit(1); } for(i=2;i>=0;i--){ if(buf.st_mode&1<<(i*3+2)) printf("r"); else printf("-"); if(buf.st_mode&1<<(i*3+1)) printf("w"); else printf("-"); if(buf.st_mode&1<<(i*3+0)) printf("x"); else printf("-"); } printf("\n"); printf("The file authority is:%o\n",buf.st_mode&0777); printf("after chmod\n"); chmod(argv[1],buf.st_mode&=S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); if(stat(argv[1],&buf)!=0){ perror("stat error\n"); exit(1); } for(i=2;i>=0;i--){ if(buf.st_mode&1<<(i*3+2)) printf("r"); else printf("-"); if(buf.st_mode&1<<(i*3+1)) printf("w"); else printf("-"); if(buf.st_mode&1<<(i*3+0)) printf("x"); else printf("-"); } printf("\n"); printf("The file authority is:%o\n",buf.st_mode&0777); return 0; }
4、获取文件属性
任务描述:
- 输入文件名,打印输出该文件用户id,组id,大小、最后访问时间、最后修改时间
相关知识:
- 使用stat函数和stat结构体获取文件属性
main.c:
#include<stdio.h> #include<sys/stat.h> #include<unistd.h> #include<stdlib.h> #include<time.h> struct stat buf; int main(int argc,char *argv[]) { if(argc!=2){ perror("argc error\n"); exit(1); } if(stat(argv[1],&buf)!=0){ perror("stat error\n"); exit(1); } printf("user id is :%d\n",buf.st_uid); printf("group id is :%d\n",buf.st_gid); printf("file size is:%d\n",(int)buf.st_size); printf("last access time is:%s",ctime(&buf.st_atime)); printf("lase modify time is:%s",ctime(&buf.st_mtime)); return 0; }
5、修改文件的组id
任务描述:
- 输入文件名和新的组id,打印输出该文件原有组id和新的组id
相关知识:
int chown(const char *pathname, uid_t owner, gid_t group):改变文件的所有者的用户ID
参数pathname表示文件的路径。
参数owner表示新的所有者用户的ID。
参数group表示新的组ID。
参数owner的值为-1时,文件的所有者ID不发生变化,同样的道理对于组ID也是一样的。
更改文件的所有者是一项需要谨慎处理的操作,因为可能会导致安全问题。因此并不是所有的用户都可以修改文件的所有者ID的。如果需要修改一个文件的所有者ID和组ID,该用户必须是根用户,或者修改文件的进程的有效用户ID等于该文件的ID,也就是说修改必须经过文件所有者授权。
main.c:
#include<stdio.h> #include<sys/stat.h> #include<unistd.h> #include<stdlib.h> #include<time.h> struct stat buf; int main(int argc,char *argv[]) { if(argc!=3){ perror("argc error\n"); exit(1); } if(stat(argv[1],&buf)!=0){ perror("stat error\n"); exit(1); } printf("old group id is :%d\n",buf.st_gid); /*参数owner设置为-1表示文件所有者ID/组ID不发生变化*/ if(chown(argv[1],-1,atoi(argv[2]))!=0){ perror("chowm error\n"); exit(1); } if(stat(argv[1],&buf)!=0){ perror("stat error\n"); exit(1); } printf("new group id is :%d\n",buf.st_gid); return 0; }
6、修改文件的访问时间和修改时间为当前时间
任务描述:
- 输入文件名,输出处理前文件的最后访问/修改时间和处理后的最后访问/修改时间
相关知识:
- int utime(const char * pathname, const struct utimbuf * times):修改文件访问时间
pathname:要修改的文件的路径名称
times: 结构体struct utimbuf变量。
struct utimbuf结构体如下:
struct utimbuf{
time_t actime;
time_t modtime;
}
actime表示文件访问时间,modtime表示文件修改时间。
当times是空指针时,文件的访问时间和修改时间都被设置为当前时间。
main.c:
#include<stdio.h> #include<sys/stat.h> #include<unistd.h> #include<stdlib.h> #include<time.h> struct stat buf; int main(int argc,char *argv[]) { if(argc!=2){ perror("argc error\n"); exit(1); } if(stat(argv[1],&buf)!=0){ perror("stat error\n"); exit(1); } printf("last access time is:%s",ctime(&buf.st_atime)); printf("lase modify time is:%s",ctime(&buf.st_mtime)); if(utime(argv[1],NULL)!=0){ perror("utime error\n"); exit(1); } if(stat(argv[1],&buf)!=0){ perror("stat error\n"); exit(1); } printf("after utime\n"); printf("last access time is:%s",ctime(&buf.st_atime)); printf("lase modify time is:%s",ctime(&buf.st_mtime)); return 0; }