ANN: Fixed name detection bug in presence of "The".
[utils.git] / bkselect.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <unistd.h>
4 #include <errno.h>
5 #include <dirent.h>
6 #include <string.h>
7 #include <sys/stat.h>
8 #include <sys/xattr.h>
9
10 int printsize = 0;
11 int printnames = 1;
12 long long tsize = 0;
13
14 int bkselect(char *path, int s)
15 {
16     DIR *d;
17     int r;
18     struct dirent *de;
19     struct stat sb;
20     char *pb;
21     char ab[16];
22     int pbl, pl, al;
23     
24     al = sizeof(ab) - 1;
25     if((al = getxattr(path, "user.bkselect", ab, sizeof(ab))) < 0) {
26         if(errno == ENODATA) {
27         } else if(errno == EPERM) {
28             /* Ignore for now because of weird effects... */
29         } else if(errno == E2BIG) {
30             fprintf(stderr, "warning: bad bkselect value on %s", path);
31         } else {
32             perror(path);
33             return(1);
34         }
35     } else {
36         ab[al] = 0;
37         if(!strcmp(ab, "y")) {
38             s = 1;
39         } else if(!strcmp(ab, "n")) {
40             s = 0;
41         } else {
42             fprintf(stderr, "warning: bad bkselect value on %s", path);
43         }
44     }
45     
46     if((d = opendir(path)) == NULL) {
47         perror(path);
48         return(1);
49     }
50     
51     r = 0;
52     pl = strlen(path);
53     pb = malloc(pbl = pl + 2);
54     strcpy(pb, path);
55     pb[pl] = '/';
56     while((de = readdir(d)) != NULL) {
57         if(!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
58             continue;
59         if(strlen(de->d_name) + pl + 2 > pbl) {
60             pbl = strlen(de->d_name) + pl + 2;
61             pb = realloc(pb, pbl);
62         }
63         strcpy(pb + pl + 1, de->d_name);
64         if(lstat(pb, &sb)) {
65             perror(pb);
66             continue;
67         }
68         if(S_ISDIR(sb.st_mode)) {
69             if(bkselect(pb, s))
70                 r = 1;
71         } else if(S_ISREG(sb.st_mode) || S_ISLNK(sb.st_mode)) {
72             if(s) {
73                 if(printnames)
74                     printf("%s\n", pb);
75                 tsize += sb.st_size;
76             }
77         }
78     }
79     
80     closedir(d);
81     return(r);
82 }
83
84 void usage(void)
85 {
86     fprintf(stderr, "usage: bkselect [-hsqo] [path...]\n");
87 }
88
89 int main(int argc, char **argv)
90 {
91     int c, i, r, s;
92     
93     s = 1;
94     while((c = getopt(argc, argv, "hsqo")) >= 0) {
95         switch(c) {
96         case 's':
97             printsize = 1;
98             break;
99         case 'q':
100             printnames = 0;
101             break;
102         case 'o':
103             s = 0;
104             break;
105         case 'h':
106         default:
107             usage();
108             exit((c == 'h')?0:1);
109         }
110     }
111     if(argc - optind < 1) {
112         r = bkselect(".", s);
113     } else {
114         r = 0;
115         for(i = optind; i < argc; i++) {
116             if(bkselect(argv[i], s))
117                 r = 1;
118         }
119     }
120     if(printsize)
121         printf("%lli\n", tsize);
122     return(r);
123 }