#include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <dirent.h>
 #include <time.h>
 #include <errno.h>
 #include <pwd.h>
 #define len 32
 int main(int argc, char const *argv[]) {
     if(argc != 2) {
         printf("Usage: %s [OPTION]\n", argv[0]);
         goto err;
     }
     time_t t;
     time(&t);
     char uid_n[10];
     char gid[10];
     uid_t uid;
     char level[9];
     struct passwd *pwd;
     unsigned char symbol;
     int total = 0;
     DIR *file = NULL;
     struct dirent *dir = NULL;
     struct stat st;
     file = opendir(argv[1]);
     if(file == NULL) {
         printf("Line %d occurs %d error\n", __LINE__,errno);
         goto err;
     }
     /*this step is needed,it'll fail on function stat as its path is not clear*/
     if(-1 == chdir(argv[1])) {
         printf("Line %d occurs %d error\n", __LINE__,errno);
         goto err;
     }
     while ((dir = readdir(file)) != NULL) {
        if(-1 == (stat(dir->d_name, &st))) {
             printf("Line %d occurs %d error\n", __LINE__,errno);
             goto err;
         }
         #if 0 /*another way to check the file type*/
         if(S_ISDIR(st.st_mode))
             printf("d");
         else if(S_ISREG(st.st_mode))
             printf("-");
         else if(S_ISCHR(st.st_mode))
             printf("c");
         else if(S_ISBLK(st.st_mode))
             printf("b");
         else if(S_ISFIFO(st.st_mode))
             printf("p");
         else if(S_ISLNK(st.st_mode))
             printf("l");
         else if(S_ISSOCK(st.st_mode))
             printf("s");
         else
             printf("?");
         /*also can be written like this*/
         switch(st.st_mode & S_IFMT)
         {
             case S_IFDIR:
                 printf("d");
                 break;
             case S_IFREG:
                 printf("-");
                 break;
             case S_IFCHR:
                 printf("c");
                 break;
             case S_IFBLK:
                 printf("b");
                 break;
             case S_IFIFO:
                 printf("p");
                 break;
             case S_IFLNK:
                 printf("l");
                 break;
             case S_IFSOCK:
                 printf("s");
                 break;
             default:
                 printf("?");
                 break;
         #endif
         total += st.st_blocks;
         switch (dir->d_type) {
             case DT_DIR:     symbol = 'd'; break;
             case DT_REG:     symbol = '-'; break;
             case DT_BLK:     symbol = 'b'; break;
             case DT_LNK:     symbol = 'l'; break;
             case DT_FIFO:    symbol = 'p'; break;
             case DT_SOCK:    symbol = 's'; break;
             case DT_UNKNOWN: symbol = '?'; break;
             default: printf("error happens\n");break;
         }
uid = getuid();
        pwd = getpwuid(uid);
         if( NULL == pwd ) {
             printf("Line %d:%d\n",__LINE__,errno);
             goto err;
         }
         if(st.st_uid == getuid() || st.st_gid == getgid()) {
             strcpy(uid_n,pwd->pw_name);
             strcpy(gid,uid_n);
         }
         else{
             strcpy(uid_n,"root");
             strcpy(gid,uid_n);
         }
         /*文件所有者权限*/
         if(st.st_mode & S_IRUSR)
             level[0] = 'r';
         else
             level[0] = '-';
          if(st.st_mode & S_IWUSR)
             level[1] = 'w';
         else
             level[1] = '-';
          if(st.st_mode & S_IXUSR)
             level[2] = 'x';
         else
             level[2] = '-';
         /*用户组权限*/
          if(st.st_mode & S_IRGRP)
             level[3] = 'r';
         else
             level[3] = '-';
          if(st.st_mode & S_IWGRP)
             level[4] = 'w';
         else
             level[4] = '-';
          if(st.st_mode & S_IXGRP)
             level[5] = 'x';
         else
             level[5] = '-';
         /*其他用户权限*/
          if(st.st_mode & S_IROTH)
             level[6] = 'r';
         else
             level[6] = '-';
          if(st.st_mode & S_IWOTH)
             level[7] = 'w';
         else
             level[7] = '-';
          if(st.st_mode & S_IXOTH)
             level[8] = 'x';
         else
             level[8] = '-';
    
         printf("%c",symbol);
         printf("%s",level);
         printf("%4u\t",st.st_nlink); /*在ac上运行需要用%u*/
         printf("%s",uid_n);
         printf("\t");
         printf("%s",gid);
         printf("%8lld\t",st.st_size); /*在ac上运行需要用%lld*/
         printf("%24.24s ",ctime(&st.st_mtime));
         printf("%s",dir->d_name);
         printf("\t");
        //printf("\n");
         printf("\n");
        if(NULL == dir && errno == 0)
             break;
         if(NULL == dir && errno != 0) {
             printf("Line %d occurs %d error\n", __LINE__,errno);
            goto err;
         }
     }
printf("total %d\n",total/2); //getconf PAGESIZE可以查看块的大小
closedir(file);
 err:
   exit(1);
return 0;
 }










