zoukankan      html  css  js  c++  java
  • UNIXLINUX编程实践教程>第三章>实例代码注解>ls2

    一 问题

      对ls1的功能进行扩展,以达到类似ll命令的功能。

    二 分析

      在ls1中,我们利用readdir()函数和dirent结构体来获得目标文件夹内的文件名(dirent->d_name)。
      现在我们借助函数stat()和结构体stat以及上面得到的文件名来获得该目录内文件的详细信息(参看后面的“相关函数与结构体”部分)。

    三 实现

    1 头文件

    #include<stdio.h>
    #include<sys/types.h>
    #include<dirent.h>
    #include<sys/stat.h>
    #include<string.h>

    2 相关函数声明

    void do_ls(char dirname[]);
    void dostat(char *filename);
    void show_file_info(char *filename,struct stat *info_p);
    void mode_to_letters(int mode,char str[]);
    char *uid_to_name(uid_t uid);
    char *gid_to_name(gid_t gid);

    3 主函数

    获得目录的路径,并将该路径传递给do_ls()函数

    main(int ac,char *av[])
    {
        if(ac == 1)
        {
            do_ls(".");
        }
        else
        {
            while(--ac)
            {
                printf("%s:\n",*++av);
                /* 传递目录路径到do_ls函数 */
                do_ls(*av);
            }
        }
    }

    4 do_ls()函数

    结合opendir()函数和readdir()函数,通过目录的路径获得该目录内各文件或文件夹的名称,并将该名称传递给dostat()函数

    void do_ls(char dirname[])
    {
        DIR *dir_ptr;
        struct dirent *direntp;
        /* 使用opendir()函数“打开”目录,返回指向该目录的指针 */
        if((dir_ptr = opendir(dirname))==NULL)
        {
            fprintf(stderr,"ls2:cannot open %s\n",dirname);
        }
        else
        {
            /* 使用readdir()函数读取指针指向的目录,获得dirent结构体 */
            while((direntp = readdir(dir_ptr))!=NULL)
            {
                /* 通过dirent结构体获得文件名,并将文件名传递给dostat()函数 */
                dostat(direntp->d_name);
            }
            closedir(dir_ptr);
        }
    }

    5 dostat()函数

    使用stat()函数,通过文件或文件夹的名称获得保存了该文件信息的stat结构体,将该结构体传递给show_file_info()函数

    void dostat(char *filename)
    {
        struct stat info;
        /* 使用stat()函数,通过文件名获得stat结构体info */
        if(stat(filename,&info) == -1)
        {
            perror(filename);
        }
        else
        {
            /* 将stat结构体传递给show_file_info()函数 */
            show_file_info(filename,&info);
        }
    }

    6 show_file_info()函数

    将stat结构体中的各项参数分别解析并输出到标准输出

    void show_file_info(char *filename,struct stat *info_p)
    {
        /* 各解析函数声明 */
        char *uid_to_name(),*ctime(),*gid_to_name(),*filemode();
        void mode_to_letters();
        char modestr[11];
    
        /* 解析并输出文件的mode信息 */
        mode_to_letters(info_p->st_mode,modestr);
        printf("%s",modestr);
        /* 文件连接数 */
        printf("%4d",(int)info_p->st_nlink);
        /* 通过uid获得对应的用户名 */
        printf("%-8s",uid_to_name(info_p->st_uid));
        /* 通过gid获得对应的组名 */
        printf("%-8s",gid_to_name(info_p->st_gid));
        /* 文件大小 */
        printf("%8ld",(long)info_p->st_size);
        /* 最近一次修改时间 */
        printf("%.12s",4+ctime(&info_p->st_mtime));
        /* 文件名 */
        printf("%s\n",filename);
    }

     7 mode_to_letters()函数

    将传递进来的mode参数解析成string格式

    void mode_to_letters(int mode,char str[])
    {
        strcpy(str,"----------");
        
        if(S_ISDIR(mode)) str[0] = 'd';
        if(S_ISCHR(mode)) str[0] = 'c';
        if(S_ISBLK(mode)) str[0] = 'b';
    
        if(mode&S_IRUSR) str[1] = 'r';
        if(mode&S_IWUSR) str[2] = 'w';
        if(mode&S_IXUSR) str[3] = 'x';
    
        if(mode&S_IRGRP) str[4] = 'r';
        if(mode&S_IWGRP) str[5] = 'w';
        if(mode&S_IXGRP) str[6] = 'x';
    
        if(mode&S_IROTH) str[7] = 'r';
        if(mode&S_IWOTH) str[8] = 'w';
        if(mode&S_IXOTH) str[9] = 'x';
    }

    其中S_ISDIR、S_ISCHR、S_ISBLK等是宏,定义如下所示:

    #define S_ISFIFO(m) (((m)(0170000)) == (0010000))
    #define S_ISDIR(m) (((m)(0170000)) == (0040000))
    #define S_ISCHR(m) (((m)(0170000)) == (0020000))
    #define S_ISBLK(m) (((m)(0170000)) == (0060000))
    #define S_ISREG(m) (((m)(0170000)) == (0100000))

    8 uid_to_name()函数

    通过用户的uid,利用getpwuid()函数,将uid转换为用户名

    #include<pwd.h>
    char *uid_to_name(uid_t uid)
    {
        struct passwd *getpwuid(),*pw_ptr;
        static char numstr[10];
    
        if((pw_ptr = getpwuid(uid))==NULL)
        {
            sprintf(numstr,"%d",uid);
            return number;
        }
        else
        {
            return pw_ptr->pw_name;
        }
    }

    9 gid_to_name()函数

    通过用户的gid,利用getgrgid()函数,将gid转换为组名

    #include<grp.h>
    char *gid_to_name(gid_t gid)
    {
        struct group *getgrgid(),*grp_ptr;
        static char numstr[10];
    
        if((grp_ptr = getgrgid(gid))==NULL)
        {
            sprintf(numstr,"%d",gid);
            return numstr;
        }
        else
        {
            return grp_ptr->gr_name;
        }
    }

    相关函数与结构体

    1 stat()函数
    通过文件名获取文件信息,并保存在stat结构体中
    头文件:#include <sys/stat.h>  #include <unistd.h>
    函数原型 int stat(const char *file_name, struct stat *buf)
    参数    file_name 指向文件名的指针
          buf 指向stat结构体的指针
    返回值   0 执行成功
          -1 执行失败,错误代码存于ermo中

    2 stat结构体
    头文件:#include<sys/stat.h>
    struct stat
    {
      mode_t st_mode; //文件对应的模式,文件,目录等
      ino_t st_ino; //i-node节点号
      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; //文件内容对应的块数量

    }

    3 ctime()函数
    把日期和时间转换为字符串
    头文件:#include <cstdio>  #include <ctime>
    函数原型 char *ctime(const time_t *time)
    参数    time time_t格式的时间
    返回值   char * 字符串格式的时间

    4 getpwuid()函数
    通过用户的uid查找用户的相关信息,并以passwd结构体返回其数据
    头文件:#include <sys/types.h>  #include <pwd.h>
    函数原型 struct passwd *getpwuid(uid_t uid)
    参数    uid 用户的uid
    返回值   passwd结构体 uid对应的用户信息
          空指针 出错

    5 passwd结构体
    struct passwd
    {
      char * pw_name; /* Username, POSIX.1 */
      char * pw_passwd; /* Password */
      __uid_t pw_uid; /* User ID, POSIX.1 */
      __gid_t pw_gid; /* Group ID, POSIX.1 */
      char * pw_gecos; /* Real Name or Comment field */
      char * pw_dir; /* Home directory, POSIX.1 */
      char * pw_shell; /* Shell Program, POSIX.1 */
      char *pw_class;
      time_t pw_change;
      time_t pw_expire;
    }

    6 getgrgid()函数
    通过gid,找到该组的相关信息,并以group结构体返回其信息
    头文件:#include<grp.h>  #include<sys/types.h>
    函数原型 strcut group * getgrgid(gid_t gid)
    参数    gid
    返回值   group结构体 正常
          NULL 无数据或发生错误

    7 group结构体
    struct group
    {
      char *gr_name; /*组名称*/
      char *gr_passwd; /* 组密码*/
      gid_t gr_gid; /*组识别码*/
      char **gr_mem; /*组成员账号*/
    }

  • 相关阅读:
    获取最近6个月的年月(yyyyMM,不包括当月)
    checkbox与<c:forEach>在开发中遇到的问题记录
    MyBatis开发-->增删改
    MyBatis开发-->接口方式编程
    MyBatis开发-->入门
    android-async-http框架之与网络进行数据交互
    android-async-http框架之与服务器进行数据交互
    jQuery截取{}里的字符串及获取json里的值
    SSH整合之三:添加Hibernate环境且使之与Spring进行整合
    angular源码剖析之Provider系列--QProvider
  • 原文地址:https://www.cnblogs.com/cation/p/2875311.html
Copyright © 2011-2022 走看看