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