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 并对其判断。

 

 

 

 

 

 

posted @ 2013-01-26 16:10  jamesduan  阅读(167)  评论(0编辑  收藏  举报