Initial commit.
[dus.git] / dus.c
1
2 /*************************************************************************/
3 /* START_IP_HEADER                                                       */
4 /*                                                                       */
5 /* This program is free software: you can redistribute it and/or modify  */
6 /* it under the terms of the version 3 of the GNU General Public License */
7 /* as published by the Free Software Foundation.                         */
8 /*                                                                       */
9 /* This program is distributed in the hope that it will be useful, but   */
10 /* WITHOUT ANY WARRANTY; without even the implied warranty of            */
11 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      */
12 /* General Public License for more details.                              */
13 /*                                                                       */
14 /* You should have received a copy of the GNU General Public License     */
15 /* along with this program. If not, see <http://www.gnu.org/licenses/>.  */
16 /*                                                                       */
17 /* Written by and Copyright (C) Francois Fleuret                         */
18 /* Contact <francois.fleuret@idiap.ch> for comments & bug reports        */
19 /*                                                                       */
20 /* END_IP_HEADER                                                         */
21 /*************************************************************************/
22
23 #define _BSD_SOURCE
24
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <dirent.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <unistd.h>
31 #include <errno.h>
32 #include <string.h>
33
34 struct file_with_size {
35   char *filename;
36   size_t size;
37   struct file_with_size *next;
38 };
39
40 size_t file_or_dir_size(char *name) {
41   DIR *dir;
42   struct dirent *dir_e;
43   struct stat dummy;
44   size_t result;
45   char subname[1024];
46
47   result = 0;
48
49   if(lstat(name, &dummy) != 0) {
50     printf("Can not stat %s (%s).\n", name, strerror(errno));
51     exit (1);
52   }
53
54   if(S_ISLNK(dummy.st_mode)) {
55     return 0;
56   }
57
58   dir = opendir(name);
59
60   if(dir) {
61     while((dir_e = readdir(dir))) {
62       if(strcmp(dir_e->d_name, ".") &&
63          strcmp(dir_e->d_name, "..")) {
64         sprintf(subname, "%s/%s", name, dir_e->d_name);
65         result += file_or_dir_size(subname);
66       }
67     }
68     closedir(dir);
69   } else {
70     if(S_ISREG(dummy.st_mode)) {
71       result += dummy.st_size;
72     }
73   }
74
75   return result;
76 }
77
78 struct file_with_size *create(char *name, struct file_with_size *current) {
79   struct file_with_size *result;
80   result = malloc(sizeof(struct file_with_size));
81   result->filename = strdup(name);
82   result->size = file_or_dir_size(name);
83   result->next = current;
84   return result;
85 }
86
87 int main(int argc, char **argv) {
88   int k;
89   struct file_with_size *root;
90
91   root = 0;
92   for(k = 1; k < argc; k++) {
93     root = create(argv[k], root);
94   }
95
96   while(root) {
97     printf("%u %s\n",
98            root->size,
99            root->filename);
100     root = root->next;
101   }
102
103   exit(0);
104 }