Advertisement
Guest User

ls-lR-Program a-la ls -lR

a guest
Oct 17th, 2019
147
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.44 KB | None | 0 0
  1. #include <dirent.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <sys/stat.h>
  6. #include <time.h>
  7. #include <stdarg.h>
  8. #include <pwd.h>
  9. #include <grp.h>
  10.  
  11. const int FLAGS[9] = { S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP, S_IWGRP, S_IXGRP, S_IROTH, S_IWOTH, S_IXOTH };
  12.  
  13. const char SYMBOLS[9] = { 'r', 'w', 'x', 'r', 'w', 'x', 'r', 'w', 'x' };
  14.  
  15. const char WRONG_SYMBOL = '-';
  16.  
  17. void make_rights_formatted(int st_mode, char result[11]) {
  18.   result[10] = '\0';
  19.   result[0] = S_ISDIR(st_mode) ? 'd' : '-';
  20.   for (int i = 1; i < 10; i++)
  21.     if ((st_mode & FLAGS[i - 1]) == FLAGS[i - 1])
  22.       result[i] = SYMBOLS[i - 1];
  23.     else
  24.       result[i] = WRONG_SYMBOL;
  25. }
  26.  
  27. int max(int a, int b) {
  28.   return a >= b ? a : b;
  29. }
  30.  
  31. int visit_directory(char *dirname, char ***entries) {
  32.   DIR *dir = opendir(dirname);
  33.   if (dir == NULL) {
  34.     perror(dirname);
  35.     return -1;
  36.   }
  37.  
  38.   struct dirent *dir_entry;
  39.  
  40.   char *entry_name;
  41.   int entry_name_capacity = 20;
  42.  
  43.   entry_name = malloc(sizeof(char) * (entry_name_capacity + 1));
  44.  
  45.   int entries_size = 0;
  46.   int entries_capacity = 10;
  47.   *entries = realloc(*entries, sizeof(char *) * entries_capacity);
  48.  
  49.   while ((dir_entry = readdir(dir)) != NULL) {
  50.     if (strcmp(dir_entry->d_name, ".") == 0 || strcmp(dir_entry->d_name, "..") == 0) {
  51.       continue;
  52.     }
  53.     int name_size = strlen(dir_entry->d_name);
  54.     if (name_size < entry_name_capacity) {
  55.       entry_name_capacity = max(entry_name_capacity * 2, name_size);
  56.       entry_name = realloc(entry_name, sizeof(char) * (entry_name_capacity + 1));
  57.     }
  58.     sprintf(entry_name, "%s", dir_entry->d_name);
  59.  
  60.     char *new_entry = malloc(name_size);
  61.     memcpy(new_entry, entry_name, name_size);
  62.     new_entry[name_size] = '\0';
  63.  
  64.     if (entries_size == entries_capacity) {
  65.       entries_capacity *= 2;
  66.       *entries = realloc(*entries, sizeof(char *) * entries_capacity);
  67.     }
  68.     (*entries)[entries_size] = new_entry;
  69.     ++entries_size;
  70.   }
  71.  
  72.   closedir(dir);
  73.  
  74.   if (entries_size < entries_capacity) {
  75.     *entries = realloc(*entries, entries_size * sizeof(char *));
  76.   }
  77.  
  78.   return entries_size;
  79. }
  80.  
  81. int sprintf_to(int dest_cap, char **dest, char *format, ...) {
  82.   if (*dest == NULL || dest_cap == 0) {
  83.     *dest = realloc(*dest, sizeof(char) * 10);
  84.     dest_cap = 10;
  85.   }
  86.  
  87.   va_list args;
  88.   va_start(args, format);
  89.   int size = vsnprintf(*dest, dest_cap, format, args) + 1;
  90.  
  91.   if (size > dest_cap) {
  92.     *dest = realloc(*dest, sizeof(char) * size);
  93.     dest_cap = size;
  94.  
  95.     va_end(args);
  96.     va_start(args, format);
  97.     vsnprintf(*dest, size, format, args);
  98.   }
  99.  
  100.   va_end(args);
  101.   return dest_cap;
  102. }
  103.  
  104. static int str_compare(const void *a, const void *b) {
  105.   return strcmp(*(char * const *)a, *(char * const *)b);
  106. }
  107.  
  108. void ls(char *dirname) {
  109.   char **entries = NULL;
  110.   int entries_count;
  111.  
  112.   entries_count = visit_directory(dirname, &entries);
  113.  
  114.   qsort(entries, entries_count, sizeof(char *), str_compare);
  115.  
  116.   struct stat stat_buf;
  117.  
  118.   int path_cap = 20;
  119.   char *path = malloc(path_cap * sizeof(char));
  120.  
  121.   const int columns_count = 7;
  122.   char ***data;
  123.  
  124.   data = malloc(sizeof(char**) * entries_count);
  125.  
  126.   for (int i = 0; i < entries_count; i++) {
  127.     path_cap = sprintf_to(path_cap, &path, "%s/%s", dirname, entries[i]);
  128.  
  129.     if (stat(path, &stat_buf)) {
  130.       perror(path);
  131.       continue;
  132.     }
  133.  
  134.     char rights[10];
  135.     make_rights_formatted(stat_buf.st_mode, rights);
  136.  
  137.     char *access_time = ctime(&stat_buf.st_atime);
  138.     access_time[strlen(access_time) - 1] = '\0';
  139.  
  140.     data[i] = malloc(sizeof(char*) * columns_count);
  141.  
  142.     for (int j = 0; j < columns_count; j++) {
  143.       data[i][j] = NULL;
  144.     }
  145.  
  146.     struct passwd *owner_usr = getpwuid(stat_buf.st_uid);
  147.     struct group *owner_grp = getgrgid(stat_buf.st_gid);
  148.  
  149.     int off = 0;
  150.     sprintf_to(0, data[i] + off++, "%s", rights);
  151.     sprintf_to(0, data[i] + off++, "%d", stat_buf.st_nlink);
  152.     sprintf_to(0, data[i] + off++, "%s", owner_usr->pw_name);
  153.     sprintf_to(0, data[i] + off++, "%s", owner_grp->gr_name);
  154.     sprintf_to(0, data[i] + off++, "%lld", (long long)stat_buf.st_size);
  155.     sprintf_to(0, data[i] + off++, "%s", access_time);
  156.     sprintf_to(0, data[i] + off++, "%s", entries[i]);
  157.   }
  158.  
  159.   int col_max_len[columns_count];
  160.  
  161.   for (int i = 0; i < columns_count; i++) {
  162.     col_max_len[i] = 0;
  163.   }
  164.  
  165.   for (int j = 0; j < columns_count; j++) {
  166.     for (int i = 0; i < entries_count; i++) {
  167.       col_max_len[j] = max(col_max_len[j], strlen(data[i][j]));
  168.     }
  169.   }
  170.  
  171.   printf("%s:\n", dirname);
  172.   for (int i = 0; i < entries_count; i++) {
  173.     for (int j = 0; j < columns_count - 1; j++) {
  174.       printf("%*s ", col_max_len[j], data[i][j]);
  175.     }
  176.     printf("%s\n", data[i][columns_count - 1]);
  177.   }
  178.  
  179.   for (int i = 0; i < entries_count; i++) {
  180.     for (int j = 0; j < columns_count; j++) {
  181.       free(data[i][j]);
  182.     }
  183.     free(data[i]);
  184.   }
  185.   free(data);
  186.  
  187.   for (int i = 0; i < entries_count; i++) {
  188.     sprintf(path, "%s/%s", dirname, entries[i]);
  189.     if (stat(path, &stat_buf)) {
  190.       perror(path);
  191.       continue;
  192.     }
  193.     if (S_ISDIR(stat_buf.st_mode)) {
  194.       printf("\n");
  195.       ls(path);
  196.     }
  197.   }
  198.  
  199.   free(path);
  200.   for (int i = 0; i < entries_count; i++) {
  201.     free(entries[i]);
  202.   }
  203.   free(entries);
  204. }
  205.  
  206. int main(int argc, char **argv) {
  207.   char **max_dir = argv + argc;
  208.   for (char **dir = argv + 1; dir < max_dir; dir++) {
  209.     if (dir > argv + 1) {
  210.       printf("\n");
  211.     }
  212.     ls(*dir);
  213.   }
  214. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement