+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <dirent.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <attr/xattr.h>
+#include <attr/attributes.h>
+
+int bkselect(char *path, int s)
+{
+ DIR *d;
+ int r;
+ struct dirent *de;
+ struct stat sb;
+ char *pb;
+ char ab[16];
+ int pbl, pl, al;
+
+ al = sizeof(ab) - 1;
+ if(attr_get(path, "bkselect", ab, &al, 0)) {
+ if(errno == ENOATTR) {
+ } else if(errno == EPERM) {
+ /* Ignore for now because of weird effects... */
+ } else if(errno == E2BIG) {
+ fprintf(stderr, "warning: bad bkselect value on %s", path);
+ } else {
+ perror(path);
+ return(1);
+ }
+ } else {
+ ab[al] = 0;
+ if(!strcmp(ab, "y")) {
+ s = 1;
+ } else if(!strcmp(ab, "n")) {
+ s = 0;
+ } else {
+ fprintf(stderr, "warning: bad bkselect value on %s", path);
+ }
+ }
+
+ if((d = opendir(path)) == NULL) {
+ perror(path);
+ return(1);
+ }
+
+ r = 0;
+ pl = strlen(path);
+ pb = malloc(pbl = pl + 2);
+ strcpy(pb, path);
+ pb[pl] = '/';
+ while((de = readdir(d)) != NULL) {
+ if(!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
+ continue;
+ if(strlen(de->d_name) + pl + 2 > pbl) {
+ pbl = strlen(de->d_name) + pl + 2;
+ pb = realloc(pb, pbl);
+ }
+ strcpy(pb + pl + 1, de->d_name);
+ if(lstat(pb, &sb)) {
+ perror(pb);
+ continue;
+ }
+ if(S_ISDIR(sb.st_mode)) {
+ if(bkselect(pb, s))
+ r = 1;
+ } else if(S_ISREG(sb.st_mode) || S_ISLNK(sb.st_mode)) {
+ if(s)
+ printf("%s\n", pb);
+ }
+ }
+
+ closedir(d);
+ return(r);
+}
+
+int main(int argc, char **argv)
+{
+ int i, r;
+
+ if(argc < 1) {
+ fprintf(stderr, "usage: bkselect path...\n");
+ exit(1);
+ }
+ r = 0;
+ for(i = 1; i < argc; i++) {
+ if(bkselect(argv[i], 0))
+ r = 1;
+ }
+ return(r);
+}