cryke

my ls

Oct 17th, 2020 (edited)
752
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <dirent.h>
  4. #include <sys/stat.h>
  5. #include <time.h>
  6. #include <string.h>
  7. #include <pwd.h>
  8. #include <grp.h>
  9.  
  10. #define COL_USER    0
  11. #define COL_GRP     1
  12. #define COL_NLINKS  2
  13. #define COL_SZ      3
  14. #define NUM_COLS    4
  15.  
  16. unsigned int col_width[NUM_COLS];
  17. char format[256];
  18.  
  19. typedef char TFilename[256];
  20.  
  21. void prepare_fmt()
  22. {
  23.     sprintf(format, "%%s %%%dlu %%%ds %%%ds %%%dd %%s %%s\n", col_width[COL_NLINKS], col_width[COL_USER], col_width[COL_GRP], col_width[COL_SZ]);
  24. }
  25.  
  26. void measure_columns(const char* f_name, const char* full_path)
  27. {
  28.     struct stat st;
  29.  
  30.     if (stat(full_path, &st) == 0)
  31.     {
  32.         char time_str[20];
  33.         strftime(time_str, 20, "%F %R", (localtime(&st.st_ctime)));
  34.  
  35.         struct passwd *pw = getpwuid(st.st_uid);
  36.         struct group *grp = getgrgid(st.st_gid);
  37.  
  38.         unsigned int user_len = strlen(pw->pw_name);
  39.         unsigned int grp_len = strlen(grp->gr_name);
  40.  
  41.         if (user_len > col_width[COL_USER])
  42.             col_width[COL_USER] = user_len;
  43.  
  44.         if (grp_len > col_width[COL_GRP])
  45.             col_width[COL_GRP] = grp_len;
  46.  
  47.         unsigned int size_len;
  48.         unsigned int links_len;
  49.         unsigned int div;
  50.         links_len = 2;
  51.         for (div = 10; div != 1000000; div *= 10, links_len++)
  52.         {
  53.             if (st.st_nlink / div == 0) break;
  54.         }
  55.  
  56.         if (links_len > col_width[COL_NLINKS])
  57.             col_width[COL_NLINKS] = links_len;
  58.  
  59.         size_len = 2;
  60.         for (div = 10; div != 1000000000; div *= 10, size_len++)
  61.         {
  62.             if (st.st_size / div == 0) break;
  63.         }
  64.  
  65.         if (size_len > col_width[COL_SZ])
  66.             col_width[COL_SZ] = size_len;
  67.  
  68.     }
  69.     else
  70.     {
  71.         printf("Error: problem with stat()\n");
  72.     }
  73. }
  74.  
  75. void show_info(const char* f_name, const char* full_path)
  76. {
  77.     char mod_val[11] = {0};
  78.     struct stat st;
  79.  
  80.     if (stat(full_path, &st) == 0)
  81.     {
  82.         mode_t perm = st.st_mode;
  83.         mod_val[0] = ' ';
  84.  
  85.         if (S_ISDIR(st.st_mode))
  86.         {
  87.             mod_val[0] = 'd';
  88.         }
  89.         else if (S_ISREG(st.st_mode))
  90.         {
  91.             mod_val[0] = ' ';
  92.         }
  93.         else if (S_ISLNK(st.st_mode))
  94.         {
  95.             mod_val[0] = 'l';
  96.         }
  97.  
  98.         mod_val[1] = (perm & S_IRUSR) ? 'r' : '-';
  99.         mod_val[2] = (perm & S_IWUSR) ? 'w' : '-';
  100.         mod_val[3] = (perm & S_IXUSR) ? 'x' : '-';
  101.         mod_val[4] = (perm & S_IRGRP) ? 'r' : '-';
  102.         mod_val[5] = (perm & S_IWGRP) ? 'w' : '-';
  103.         mod_val[6] = (perm & S_IXGRP) ? 'x' : '-';
  104.         mod_val[7] = (perm & S_IROTH) ? 'r' : '-';
  105.         mod_val[8] = (perm & S_IWOTH) ? 'w' : '-';
  106.         mod_val[9] = (perm & S_IXOTH) ? 'x' : '-';
  107.         mod_val[10] = '\0';
  108.  
  109.         char time_str[20];
  110.         strftime(time_str, 20, "%F %R", (localtime(&st.st_ctime)));
  111.  
  112.         struct passwd *pw = getpwuid(st.st_uid);
  113.         struct group *grp = getgrgid(st.st_gid);
  114.  
  115.         printf(format,
  116.                 mod_val,
  117.                 st.st_nlink,
  118.                 pw->pw_name,
  119.                 grp->gr_name,
  120.                 st.st_size,
  121.                 time_str,
  122.                 f_name);
  123.     }
  124.     else
  125.     {
  126.         printf("Error: problem with stat()\n");
  127.     }
  128.  
  129. }
  130.  
  131. int cmpfunc(const void* a, const void* b)
  132. {
  133.     char *la, *lb;
  134.     la = (char*)a;
  135.     lb = (char*)b;
  136.     return strcmp(la, lb);
  137. }
  138.  
  139. void process_dir(const char * d_name)
  140. {
  141.     DIR *folder;
  142.     struct dirent *entry;
  143.     unsigned int num = 0;
  144.     unsigned int num_entries = 0;
  145.     TFilename *filenames;
  146.  
  147.     folder = opendir(d_name);
  148.     if (!folder)
  149.     {
  150.         perror("Unable to read directory");
  151.         perror(d_name);
  152.         return ;
  153.     }
  154.  
  155.     while ((entry = readdir(folder)))
  156.     {
  157.         if (!strcmp(entry->d_name, ".")) continue;
  158.         if (!strcmp(entry->d_name, "..")) continue;
  159.         num_entries++;
  160.     }
  161.     closedir(folder);
  162.  
  163.     if (!num_entries) return;
  164.  
  165.     folder = opendir(d_name);
  166.     if (!folder)
  167.     {
  168.         perror("Unable to read directory");
  169.         perror(d_name);
  170.         return ;
  171.     }
  172.  
  173.     filenames = calloc(num_entries, sizeof(TFilename));
  174.  
  175.     if(filenames)
  176.     {
  177.         while ((entry = readdir(folder)) && (num < num_entries))
  178.         {
  179.             if (!strcmp(entry->d_name, ".")) continue;
  180.             if (!strcmp(entry->d_name, "..")) continue;
  181.  
  182.             strcpy(filenames[num], entry->d_name);
  183.             num++;
  184.         }
  185.  
  186.         qsort(filenames, num, sizeof(TFilename), cmpfunc);
  187.  
  188.         printf("Total: %d\n", num);
  189.         for (int i=0; i<num; ++i)
  190.         {
  191.             char path[256];
  192.             strcpy(path, d_name);
  193.             strcat(path, "/");
  194.             strcat(path, filenames[i]);
  195.             measure_columns(filenames[i], path);
  196.         }
  197.  
  198.         prepare_fmt();
  199.  
  200.         for (int i=0; i<num; ++i)
  201.         {
  202.             char path[256];
  203.             strcpy(path, d_name);
  204.             strcat(path, "/");
  205.             strcat(path, filenames[i]);
  206.             show_info(filenames[i], path);
  207.         }
  208.         free(filenames);
  209.     }
  210.     closedir(folder);
  211. }
  212.  
  213. int main(int argc, char* argv[])
  214. {
  215.     if (argc > 1)
  216.     {
  217.         for (int i = 1; i < argc; i++)
  218.         {
  219.             char* arg = argv[i];
  220.             struct stat st;
  221.  
  222.             if (stat(arg, &st) == 0)
  223.             {
  224.                 if (S_ISDIR(st.st_mode))
  225.                 {
  226.                     printf("%s:\n", arg);
  227.                     process_dir(arg);
  228.                     printf("\n");
  229.                 }
  230.                 else
  231.                 {
  232.                     measure_columns(arg, arg);
  233.                     prepare_fmt();
  234.                     show_info(arg, arg);
  235.                 }
  236.             }
  237.         }
  238.     }
  239.  
  240.     else
  241.     {
  242.         process_dir(".");
  243.     }
  244.     return 0;
  245. }
  246.  
  247.  
RAW Paste Data