Added an S_ISDIR check before opendir() to work on hfsplus volumes (?)
[dus.git] / dus.c
diff --git a/dus.c b/dus.c
index d4ca191..03bd980 100644 (file)
--- a/dus.c
+++ b/dus.c
@@ -22,7 +22,7 @@
  *
  */
 
-#define VERSION_NUMBER "1.1"
+#define VERSION_NUMBER "1.2"
 
 #define _BSD_SOURCE
 
@@ -85,7 +85,7 @@ int ignore_entry(const char *name) {
   return
     strcmp(name, ".") == 0 ||
     strcmp(name, "..") == 0 ||
-    (ignore_dotfiles && name[0] == '.'  && name[1] != '/');
+    (ignore_dotfiles && name[0] == '.' && name[1] != '/');
 }
 
 size_sum_t entry_size(const char *name) {
@@ -106,20 +106,22 @@ size_sum_t entry_size(const char *name) {
     return 0;
   }
 
-  dir = opendir(name);
-
-  if(dir) {
-    while((dir_e = readdir(dir))) {
-      if(!ignore_entry(dir_e->d_name)) {
-        snprintf(subname, PATH_MAX, "%s/%s", name, dir_e->d_name);
-        result += entry_size(subname);
+  if(S_ISDIR(dummy.st_mode)) {
+    dir = opendir(name);
+    if(dir) {
+      while((dir_e = readdir(dir))) {
+        if(!ignore_entry(dir_e->d_name)) {
+          snprintf(subname, PATH_MAX, "%s/%s", name, dir_e->d_name);
+          result += entry_size(subname);
+        }
       }
+      closedir(dir);
+    } else {
+      fprintf(stderr, "Can not open directory %s: %s\n", name, strerror(errno));
+      exit(EXIT_FAILURE);
     }
-    closedir(dir);
-  } else {
-    if(S_ISREG(dummy.st_mode)) {
-      result += dummy.st_size;
-    }
+  } else if(S_ISREG(dummy.st_mode)) {
+    result += dummy.st_size;
   }
 
   return result;
@@ -167,6 +169,26 @@ struct entry_node *push_entry(char *name, struct entry_node *head) {
   return result;
 }
 
+struct entry_node *push_dir_content(char *name, struct entry_node *head) {
+  char subname[PATH_MAX];
+  DIR *dir;
+  struct dirent *dir_e;
+  dir = opendir(name);
+  if(dir) {
+    while((dir_e = readdir(dir))) {
+      if(!ignore_entry(dir_e->d_name)) {
+        snprintf(subname, PATH_MAX, "%s/%s", name, dir_e->d_name);
+        head = push_entry(subname, head);
+      }
+    }
+    closedir(dir);
+  } else {
+    fprintf(stderr, "Can not open directory %s: %s\n", name, strerror(errno));
+    exit (EXIT_FAILURE);
+  }
+  return head;
+}
+
 void destroy_entry_list(struct entry_node *node) {
   struct entry_node *next;
   while(node) {
@@ -204,7 +226,8 @@ int compare_files(const void *x1, const void *x2) {
   }
 }
 
-void raw_print(char *buffer, size_t buffer_size, char *filename,  size_sum_t size) {
+void raw_print(char *buffer, size_t buffer_size,
+               char *filename,  size_sum_t size) {
   char *a, *b, *c, u;
 
   b = buffer;
@@ -230,7 +253,8 @@ void raw_print(char *buffer, size_t buffer_size, char *filename,  size_sum_t siz
   snprintf(b, buffer_size - (b - buffer), "%s\n", filename);
 }
 
-void fancy_print(char *buffer, size_t buffer_size, char *filename, size_sum_t size) {
+void fancy_print(char *buffer, size_t buffer_size,
+                 char *filename, size_sum_t size) {
   if(size < 1024) {
     snprintf(buffer,
              buffer_size,
@@ -337,7 +361,7 @@ void print_sorted(struct entry_node *root, int width, int height) {
 void usage(FILE *out) {
   fprintf(out, "Usage: dus [OPTION]... [FILE]...\n");
   fprintf(out, "Version %s (%s)\n", VERSION_NUMBER, UNAME);
-  fprintf(out, "List files and directories sorted according to their size or content size. Take the content of the current directory as argument if none is provided.\n");
+  fprintf(out, "Lists files and directories according to their size. The sizes are computed by summing recursively exact file sizes through directories. If a given directory has its name appended with '/', it is not listed, but the elements it contains are. If no files or directories are provided as arguments, the current directory is used as default.\n");
   fprintf(out, "\n");
   /*            01234567890123456789012345678901234567890123456789012345678901234567890123456789*/
   fprintf(out, "   -d, --ignore-dots          ignore files and directories starting with a '.'\n");
@@ -374,7 +398,7 @@ static struct option long_options[] = {
 };
 
 int main(int argc, char **argv) {
-  int c;
+  int c, l;
   struct entry_node *root;
   struct winsize win;
 
@@ -428,23 +452,16 @@ int main(int argc, char **argv) {
 
   if (optind < argc) {
     while (optind < argc) {
-      root = push_entry(argv[optind++], root);
-    }
-  } else {
-    DIR *dir;
-    struct dirent *dir_e;
-    dir = opendir(".");
-    if(dir) {
-      while((dir_e = readdir(dir))) {
-        if(!ignore_entry(dir_e->d_name)) {
-          root = push_entry(dir_e->d_name, root);
-        }
+      l = strlen(argv[optind]);
+      if(l > 0 && argv[optind][l - 1] == '/') {
+        argv[optind][l - 1] = '\0';
+        root = push_dir_content(argv[optind++], root);
+      } else {
+        root = push_entry(argv[optind++], root);
       }
-      closedir(dir);
-    } else {
-      fprintf(stderr, "Can not open ./: %s\n", strerror(errno));
-      exit (EXIT_FAILURE);
     }
+  } else {
+    root = push_dir_content(".", root);
   }
 
   if(isatty(STDOUT_FILENO) &&