• Home
  • Raw
  • Download

Lines Matching +full:- +full:execdir

1 /* find.c - Search directories for matching files.
11 USE_FIND(NEWTOY(find, "?^HL[-HL]", TOYFLAG_USR|TOYFLAG_BIN))
17 usage: find [-HL] [DIR...] [<options>]
20 Default: search ".", match all, -print matches.
22 -H Follow command line symlinks -L Follow all symlinks
25 -name PATTERN filename with wildcards (-iname case insensitive)
26 -path PATTERN path name with wildcards (-ipath case insensitive)
27 -user UNAME belongs to user UNAME -nouser user ID not known
28 -group GROUP belongs to group GROUP -nogroup group ID not known
29 -perm [-/]MODE permissions (-=min /=any) -prune ignore dir contents
30 -size N[c] 512 byte blocks (c=bytes) -xdev only this filesystem
31 -links N hardlink count -atime N[u] accessed N units ago
32 -ctime N[u] created N units ago -mtime N[u] modified N units ago
33 -newer FILE newer mtime than FILE -mindepth N at least N dirs down
34 -depth ignore contents of dir -maxdepth N at most N dirs down
35 -inum N inode number N -empty empty files and dirs
36 -type [bcdflps] type is (block, char, dir, file, symlink, pipe, socket)
37 -true always true -false always false
38 -context PATTERN security context
39 -newerXY FILE X=acm time > FILE's Y=acm time (Y=t: FILE is literal time)
41 Numbers N may be prefixed by a - (less than) or + (greater than). Units for
42 -Xtime are d (days, default), h (hours), m (minutes), or s (seconds).
45 !, -a, -o, ( ) not, and, or, group expressions
48 -print Print match with newline -print0 Print match with null
49 -exec Run command with path -execdir Run command in file's dir
50 -ok Ask before exec -okdir Ask before execdir
51 -delete Remove matching file/dir -printf FORMAT Print using format string
56 -printf FORMAT characters are \ escapes and:
84 // None of this can go in TT because you can have more than one -exec
90 struct execdir_data exec, *execdir; member
93 // Perform pending -exec (if any)
96 struct execdir_data *bb = aa->execdir ? aa->execdir : &aa->exec; in flush_exec()
100 if (!bb->namecount) return 0; in flush_exec()
102 dlist_terminate(bb->names); in flush_exec()
104 // switch to directory for -execdir, or back to top if we have an -execdir in flush_exec()
105 // _and_ a normal -exec, or are at top of tree in -execdir in flush_exec()
106 if (TT.topdir != -1) { in flush_exec()
107 if (aa->dir && new && new->parent) { in flush_exec()
109 rc = fchdir(new->parent->dirfd); in flush_exec()
112 perror_msg_raw(revert ? new->name : "."); in flush_exec()
118 // execdir: accumulated execs in this directory's children. in flush_exec()
119 newargs = xmalloc(sizeof(char *)*(aa->arglen+bb->namecount+1)); in flush_exec()
120 if (aa->curly < 0) { in flush_exec()
121 memcpy(newargs, aa->argstart, sizeof(char *)*aa->arglen); in flush_exec()
122 newargs[aa->arglen] = 0; in flush_exec()
124 int pos = aa->curly, rest = aa->arglen - aa->curly; in flush_exec()
128 memcpy(newargs, aa->argstart, sizeof(char *)*pos); in flush_exec()
129 for (dl = bb->names; dl; dl = dl->next) newargs[pos++] = dl->data; in flush_exec()
130 rest = aa->arglen - aa->curly - 1; in flush_exec()
131 memcpy(newargs+pos, aa->argstart+aa->curly+1, sizeof(char *)*rest); in flush_exec()
137 llist_traverse(bb->names, llist_free_double); in flush_exec()
138 bb->names = 0; in flush_exec()
139 bb->namecount = 0; in flush_exec()
152 if (*str == '+' || *str == '-') sign = *(str++); in compare_numsign()
153 else if (!isdigit(*str)) error_exit("%s not [+-]N", str); in compare_numsign()
155 if (units && isdigit(str[strlen(str)-1])) myval *= units; in compare_numsign()
158 if (sign == '-') return val < myval; in compare_numsign()
170 // Descend or ascend -execdir + directory level
171 static void execdir(struct dirtree *new, int flush) in execdir() function
177 if (new && TT.topdir == -1) return; in execdir()
179 for (dl = TT.argdata; dl; dl = dl->next) { in execdir()
180 if (dl->prev != (void *)1) continue; in execdir()
182 if (!aa->plus || (new && !aa->dir)) continue; in execdir()
186 // Flush pending "-execdir +" instances for this dir in execdir()
187 // or flush everything for -exec at top in execdir()
190 // pop per-directory struct in execdir()
191 if ((bb = aa->execdir)) { in execdir()
192 aa->execdir = bb->next; in execdir()
195 } else if (aa->dir) { in execdir()
197 // Push new per-directory struct for -execdir/okdir + codepath. (Can't in execdir()
198 // use new->extra because command line may have multiple -execdir) in execdir()
200 bb->next = aa->execdir; in execdir()
201 aa->execdir = bb; in execdir()
218 // skip . and .. below topdir, handle -xdev and -depth in do_find()
221 if (new->again&2) { in do_find()
222 if (!new->parent || errno != ENOENT) { in do_find()
228 if (new->parent) { in do_find()
230 if (TT.xdev && new->st.st_dev != new->parent->st.st_dev) recurse = 0; in do_find()
231 } else TT.start = new->name; in do_find()
233 if (S_ISDIR(new->st.st_mode)) { in do_find()
235 if (!new->again) { in do_find()
238 for (n = new->parent; n; n = n->parent) { in do_find()
239 if (n->st.st_ino==new->st.st_ino && n->st.st_dev==new->st.st_dev) { in do_find()
248 execdir(new, 0); in do_find()
254 execdir(new, 1); in do_find()
265 // print: saw one of print/ok/exec, no need for default -print in do_find()
273 if (*s != '-') { in do_find()
291 if (--pcount < 0) goto error; in do_find()
306 test = !unlinkat(dirtree_parentfd(new), new->name, in do_find()
307 S_ISDIR(new->st.st_mode) ? AT_REMOVEDIR : 0); in do_find()
334 if (S_ISDIR(new->st.st_mode)) { in do_find()
335 int fd = openat(dirtree_parentfd(new), new->name, O_RDONLY); in do_find()
339 while ((de = readdir(dfd)) && isdotdot(de->d_name)); in do_find()
343 } else if (S_ISREG(new->st.st_mode)) { in do_find()
344 if (new->st.st_size) test = 0; in do_find()
348 if (check) if (bufgetpwuid(new->st.st_uid)) test = 0; in do_find()
350 if (check) if (bufgetgrgid(new->st.st_gid)) test = 0; in do_find()
352 if (check && S_ISDIR(new->st.st_mode) && !TT.depth) recurse = 0; in do_find()
361 char *arg = ss[1], *path = 0, *name = new ? new->name : arg; in do_find()
368 else arg = ((struct double_list *)llist_pop(&argdata))->data; in do_find()
381 if (lsm_get_context(path, &context) != -1) { in do_find()
390 int match_min = *m == '-', in do_find()
393 m2 = new->st.st_mode & 07777; in do_find()
403 if (i<0) error_exit("bad -type '%c'", *ss[1]); in do_find()
404 if ((new->st.st_mode & S_IFMT) != types[i]) test = 0; in do_find()
412 time_t thyme = (int []){new->st.st_atime, new->st.st_ctime, in do_find()
413 new->st.st_mtime}[stridx("acm", *s)]; in do_find()
416 if (len && -1!=(uu = stridx("dhms",tolower(copy[len-1])))) { in do_find()
418 copy[--len] = 0; in do_find()
421 test = compare_numsign(TT.now - thyme, units, copy); in do_find()
425 if (check) test = compare_numsign(new->st.st_size, 512, ss[1]); in do_find()
427 if (check) test = compare_numsign(new->st.st_nlink, 0, ss[1]); in do_find()
429 if (check) test = compare_numsign(new->st.st_ino, 0, ss[1]); in do_find()
435 while ((dt = dt->parent)) i++; in do_find()
470 udl->u.tm = *(struct timespec *)(((char *)&st) in do_find()
475 xparsedate(ss[1], &(udl->u.tm.tv_sec), &nano, 1); in do_find()
476 udl->u.tm.tv_nsec = nano; in do_find()
478 } else if (*s == 'u') udl->u.uid = xgetuid(ss[1]); in do_find()
479 else udl->u.gid = xgetgid(ss[1]); in do_find()
484 if (*s == 'u') test = new->st.st_uid == udl->u.uid; in do_find()
485 else if (*s == 'g') test = new->st.st_gid == udl->u.gid; in do_find()
487 struct timespec *tm = (void *)(((char *)&new->st) in do_find()
491 else test = (tm->tv_sec == udl->u.tm.tv_sec) in do_find()
492 ? tm->tv_nsec > udl->u.tm.tv_nsec in do_find()
493 : tm->tv_sec > udl->u.tm.tv_sec; in do_find()
498 || !strcmp(s, "execdir") || !strcmp(s, "okdir")) in do_find()
508 // catch "-exec" with no args and "-exec \;" in do_find()
512 aa->argstart = ++ss; in do_find()
513 aa->curly = -1; in do_find()
515 // Record command line arguments to -exec in do_find()
519 aa->curly = len; in do_find()
521 aa->plus++; in do_find()
525 } else aa->argsize += sizeof(char *) + strlen(ss[len]) + 1; in do_find()
527 if (!ss[len]) error_exit("-exec without %s", in do_find()
528 aa->curly!=-1 ? "\\;" : "{}"); in do_find()
530 aa->arglen = len; in do_find()
531 aa->dir = !!strchr(s, 'd'); in do_find()
532 if (TT.topdir == -1) TT.topdir = xopenro("."); in do_find()
541 ss += aa->arglen + 1; in do_find()
545 name = aa->dir ? xstrdup(new->name) : dirtree_path(new, 0); in do_find()
555 // Add next name to list (global list without -dir, local with) in do_find()
556 bb = aa->execdir ? aa->execdir : &aa->exec; in do_find()
557 dlist_add(&bb->names, name); in do_find()
558 bb->namecount++; in do_find()
560 // -exec + collates and saves result in exitval in do_find()
561 if (aa->plus) { in do_find()
565 aa->prev = (void *)1; in do_find()
570 if ((aa->plus += sizeof(char *)+strlen(name)+1) > TT.max_bytes) { in do_find()
571 aa->plus = 1; in do_find()
594 while (*fmt>='0' && *fmt<='7' && n++<3) ch=(ch*8)+*(fmt++)-'0'; in do_find()
595 --fmt; in do_find()
601 fmt = next_printf(ff = fmt-1, 0); in do_find()
602 if ((len = fmt-ff)>28) error_exit("bad %.*s", len+1, ff); in do_find()
610 printf(next, (ch == 'i') ? (long long)new->st.st_ino in do_find()
611 : (long long)new->st.st_size); in do_find()
616 if (ch == 'G') next[len] = 'd', ll = new->st.st_gid; in do_find()
617 else if (ch == 'm') next[len] = 'o', ll = new->st.st_mode&~S_IFMT; in do_find()
618 else if (ch == 'U') next[len] = 'd', ll = new->st.st_uid; in do_find()
619 else if (ch == 'f') ll = (long)new->name; in do_find()
620 else if (ch == 'g') ll = (long)getgroupname(new->st.st_gid); in do_find()
621 else if (ch == 'u') ll = (long)getusername(new->st.st_uid); in do_find()
629 mode_to_string(new->st.st_mode, buf); in do_find()
638 if (*++fmt!='@') error_exit("bad -printf %%T: %%T%c", *fmt); in do_find()
639 sprintf(buf, "%ld.%ld", new->st.st_mtim.tv_sec, in do_find()
640 new->st.st_mtim.tv_nsec); in do_find()
645 ll = (lsm_get_context(path, &ff) != -1) ? (long)ff : (long)"?"; in do_find()
647 } else error_exit("bad -printf %%%c", ch); in do_find()
657 // pass first. Putting it here gets the error message (-unknown in do_find()
658 // vs -known noarg) right. in do_find()
659 if (!*++ss) error_exit("'%s' needs 1 arg", --s); in do_find()
671 if (S_ISDIR(new->st.st_mode)) execdir(new, 0); in do_find()
686 TT.topdir = -1; in find_main()
687 TT.max_bytes = sysconf(_SC_ARG_MAX) - environ_bytes(); in find_main()
691 if (strchr("-!(", *toys.optargs[len])) break; in find_main()
708 execdir(0, 1); in find_main()