apue学习之文件IO第二部分
学习apue课程已经有一个多月了,有很多知识点需要自己去总结:
下面是主要的几个函数的介绍:
1-stat()函数是获得文件的主要信息。在linux当中主要以一个结构体来保存文件的信息,其中每一个字段都代表着文件的一个信息量:
struct stat { dev_t st_dev; /* ID of device containing file */ ino_t st_ino; /* inode number */ mode_t st_mode; /* protection */ /*文件的权限状态值,是一个数值*/ 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 file system I/O */ blkcnt_t st_blocks; /* number of 512B blocks allocated */ time_t st_atime; /* time of last access */ time_t st_mtime; /* time of last modification */ time_t st_ctime; /* time of last status change */ /* 最后一次修改的状态*/ };
在使用这个结构体的时候我们会用到许多的宏定义,比如st_mode的值要做一些判断。详细的介绍请参照man手册对此函数的定义。
stat()函数:
stat, fstat, lstat - get file status #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> int stat(const char *path, struct stat *buf); int fstat(int fd, struct stat *buf); int lstat(const char *path, struct stat *buf); //主要使用stat()函数
2-opendir
opendir, fdopendir - open a directory #include <sys/types.h> #include <dirent.h> DIR *opendir(const char *name); DIR *fdopendir(int fd);
打开一个目录,返回一个文件指针,DIR *dir ; 返回的结果记录着目录的信息,一般和readdir搭配使用做为其参数。
3-readdir
NAME readdir, readdir_r - read a directory //读取一个目录 SYNOPSIS #include <dirent.h> struct dirent *readdir(DIR *dirp);
int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
读取一个目录,每次只能读一个目录的信息,readdir()参数为opendir返回的文件指针DIR* dir ,返回值为一个结构体struct dirent *指针类型。
这个结构体如下:
主要包括着目录的信息:
linux当中一切都为文件,那么目录也是属于一种文件,所以stat对其也是适用的。
struct dirent { ino_t d_ino; /* inode number */ off_t d_off; /* offset to the next dirent */ unsigned short d_reclen; /* length of this record */ unsigned char d_type; /* type of file; not supported by all file system types */ char d_name[256]; /* filename */ };
在stat结构体当中有两个字段,一个是st_uid , 一个是st_gid 两个变量都是数值类型,要获得具体的所属用户的名字和所属组的名字,则需要使用getpwuid()和getgrgid()这两个函数。
getpwnam, getpwnam_r, getpwuid, getpwuid_r - get password file entry #include <sys/types.h> #include <pwd.h> struct passwd *getpwnam(const char *name); struct passwd *getpwuid(uid_t uid); int getpwnam_r(const char *name, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result); int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result);
这组函数和getpwuid()所实现的功能都是类似的。
这里面有一个结构体struct passwd:
struct passwd { char *pw_name; /* username */ char *pw_passwd; /* user password */ uid_t pw_uid; /* user ID */ gid_t pw_gid; /* group ID */ char *pw_gecos; /* user information */ char *pw_dir; /* home directory */ char *pw_shell; /* shell program */ };
这样就可以得到此用户的所有信息。包括用户密码。
还有一个函数和他类似:getgrgid()
NAME getgrnam, getgrnam_r, getgrgid, getgrgid_r - get group file entry SYNOPSIS #include <sys/types.h> #include <grp.h> struct group *getgrnam(const char *name); struct group *getgrgid(gid_t gid); int getgrnam_r(const char *name, struct group *grp, char *buf, size_t buflen, struct group **result); int getgrgid_r(gid_t gid, struct group *grp, char *buf, size_t buflen, struct group **result);
返回的是一个struct group
struct group { char *gr_name; /* group name */ char *gr_passwd; /* group password */ gid_t gr_gid; /* group ID */ char **gr_mem; /* group members */ };
现在我们来实现一个在linux下面常用的一个功能:
即:ls -l -i
大家都知道ls 是显示所有当前目录下的所有文件的信息,包括目录。所以我们要打开的目录就是openddir(".");然后读取其信息,并对其分解。
1 #include <time.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <unistd.h> 5 #include <sys/types.h> 6 #include <sys/stat.h> 7 #include <string.h> 8 #include <dirent.h> 9 #include <pwd.h> 10 #include <grp.h> 11 12 void get_type( int ); 13 void get_mode( int ); 14 15 int main() 16 { 17 DIR * dir ; 18 dir = opendir("."); 19 if( dir == NULL ) 20 { 21 perror("opendir"); 22 exit(1); 23 } 24 struct dirent *cur ; 25 while( ( cur = readdir( dir ) ) != NULL ) 26 { 27 struct stat st ; 28 /* get states of file from d_name */ 29 int ret = stat( cur->d_name , &st ); 30 if( ret == -1 ) 31 { 32 perror("stat"); 33 exit(1); 34 } 35 printf("%ld " , st.st_ino ); 36 get_type( st.st_mode ); 37 get_mode( st.st_mode ); 38 /* getpwuid getgrgid*/ 39 /* get namenam and group name through the st_uid and st_gid */ 40 struct passwd * pwd = getpwuid( st.st_uid ); 41 printf("%s " , pwd->pw_name ); 42 // printf("%s " , pwd->pw_passwd ); 43 // printf("%s " , pwd->pw_gecos ); 44 struct group *grp = getgrgid( st.st_gid ); 45 printf("%s " , grp->gr_name ); 46 printf("%ld\t" , st.st_size ); 47 /* ctime */ 48 char *time = ctime( &st.st_ctime ); 49 printf("%.12s " , time+4 ); 50 printf("%s " , cur->d_name ); 51 printf("\n"); 52 } 53 return 0; 54 } 55 56 /* get the type of current files */ 57 void get_type( int m ) 58 { 59 if( S_ISREG(m)) 60 printf("-"); 61 else if( S_ISDIR(m)) 62 printf("d"); 63 else if( S_ISCHR(m)) 64 printf("c"); 65 else if( S_ISBLK(m)) 66 printf("b"); 67 else if( S_ISFIFO(m)) 68 printf("p"); 69 else if( S_ISLNK(m)) 70 printf("l"); 71 else //if( S_ISSOCK(m)) 72 printf("s"); 73 } 74 75 /* get the modition of current files */ 76 void get_mode( int m ) 77 { 78 char str[10]; 79 memset( str , '-' , 10 ); // littal bug 80 str[9] = '\0'; 81 /* onwer user's mode */ 82 if( ( m&S_IRUSR ) == S_IRUSR ) 83 str[0] = 'r'; 84 if( ( m&S_IWUSR ) == S_IWUSR ) 85 str[1] = 'w'; 86 if( ( m&S_IXUSR ) == S_IXUSR ) 87 str[2] = 'x'; 88 /* group user's mode */ 89 if( ( m&S_IRGRP) == S_IRGRP ) 90 str[3] = 'r'; 91 if( ( m&S_IWGRP) == S_IWGRP ) 92 str[4] = 'w'; 93 if( ( m&S_IXGRP) == S_IXGRP ) 94 str[5] = 'x'; 95 /* other user's mode */ 96 97 if( (m&S_IROTH) == S_IROTH ) 98 str[6] = 'r'; 99 if( (m&S_IWOTH) == S_IWOTH ) 100 str[7] = 'w'; 101 if( (m&S_IXOTH) == S_IXOTH ) 102 str[8] = 'x'; 103 printf("%s " , str ); 104 } 105
以上代码我在使用memset()的时候第二个参数报错了,后来找了半天的原因,原来是因为使用‘-’这个字符覆盖数组的时候我弄成了“-”这是字符串,对应的ASCII的值是不一样的。这个例子的关键是如何实现权限的打印。通过stat结构体的中的st_mode 并对其判断。