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