Fix select bug.
[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)) {
15f697c9 73 if(s) {
74 if(printnames)
75 printf("%s\n", pb);
76 tsize += sb.st_size;
77 }
1ba19398 78 }
79 }
80
81 closedir(d);
82 return(r);
83}
84
0b768200 85void usage(void)
86{
15f697c9 87 fprintf(stderr, "usage: bkselect [-hsqo] path...\n");
0b768200 88}
89
1ba19398 90int main(int argc, char **argv)
91{
15f697c9 92 int c, i, r, s;
1ba19398 93
15f697c9 94 s = 1;
95 while((c = getopt(argc, argv, "hsqo")) >= 0) {
0b768200 96 switch(c) {
97 case 's':
98 printsize = 1;
99 break;
100 case 'q':
101 printnames = 0;
102 break;
15f697c9 103 case 'o':
104 s = 0;
105 break;
0b768200 106 case 'h':
107 default:
108 usage();
109 exit((c == 'h')?0:1);
110 }
111 }
112 if(argc - optind < 1) {
113 usage();
1ba19398 114 exit(1);
115 }
116 r = 0;
0b768200 117 for(i = optind; i < argc; i++) {
15f697c9 118 if(bkselect(argv[i], s))
1ba19398 119 r = 1;
120 }
0b768200 121 if(printsize)
122 printf("%lli\n", tsize);
1ba19398 123 return(r);
124}