int ftw(const char *path, int (*fn)(const char *, const struct stat *, int), int nfds) { char * const paths[2] = { (char *)path, NULL }; FTSENT *cur; FTS *ftsp; int error = 0, fnflag, sverrno; /* XXX - nfds is currently unused */ if (nfds < 1 || nfds > OPEN_MAX) { errno = EINVAL; return (-1); } ftsp = fts_open(paths, FTS_LOGICAL | FTS_COMFOLLOW | FTS_NOCHDIR, NULL); if (ftsp == NULL) return (-1); while ((cur = fts_read(ftsp)) != NULL) { switch (cur->fts_info) { case FTS_D: fnflag = FTW_D; break; case FTS_DNR: fnflag = FTW_DNR; break; case FTS_DP: /* we only visit in preorder */ continue; case FTS_F: case FTS_DEFAULT: fnflag = FTW_F; break; case FTS_NS: case FTS_NSOK: case FTS_SLNONE: fnflag = FTW_NS; break; case FTS_SL: fnflag = FTW_SL; break; case FTS_DC: errno = ELOOP; /* FALLTHROUGH */ default: error = -1; goto done; } error = fn(cur->fts_path, cur->fts_statp, fnflag); if (error != 0) break; } done: sverrno = errno; if (fts_close(ftsp) != 0 && error == 0) error = -1; else errno = sverrno; return (error); }
static int remove_path(const char *path) { FTS *fts; FTSENT *ent; const char *argv[2] = { path, NULL }; int err; fts = fts_open((char *const *)argv, FTS_NOSTAT | FTS_PHYSICAL, NULL); if (!fts) return errno; for (;;) { ent = fts_read(fts); if (!ent) { err = errno; break; } err = remove_ent(ent); if (err) break; } fts_close(fts); return err; }
static int recurse(const char * path) { FTS *fts; FTSENT *ftsent; char * const apath[] = { strdup(path), NULL }; fts = fts_open(apath,FTS_NOCHDIR|FTS_NOSTAT|FTS_COMFOLLOW, NULL); if ( NULL == fts) { ERROR("fts_open(%s) failed", path); return EXIT_FAILURE; } while ((ftsent = fts_read(fts))) switch (ftsent->fts_info) { case FTS_F: if ( is_video(ftsent) ) if ( convert_video(ftsent) ) ERROR("conversion failed: %s", ftsent->fts_path); break; case FTS_SLNONE: case FTS_NS: case FTS_ERR: ERROR("fts_read: %s (%s)", ftsent->fts_path, strerror(errno)); default:(void)0; } fts_close(fts); free(apath[0]); return EXIT_SUCCESS; }
fs_entry* fsc_read(fscrawl_t f) { FTSENT *ent; if (!f) return NULL; for(;;) { ent = fts_read(f->fts); if (ent == NULL) { if (errno) { logerrno(LOG_DEBUG, "fsc_read", errno); continue; } break; } if (ent->fts_namelen > 0 && FTSENT_VALID_TYPE(ent)) return ftsentcpy(&f->ent, ent); if (ent->fts_info == FTS_ERR) logerrno(LOG_DEBUG, "fsc_read", ent->fts_errno); } return NULL; }
int onlp_file_find(char* root, char* fname, char** rpath) { FTS *fs; FTSENT *ent; char* argv[] = { NULL, NULL }; argv[0] = root; if ((fs = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_COMFOLLOW, NULL)) == NULL) { AIM_LOG_ERROR("fts_open(%s): %{errno}", argv[0], errno); return ONLP_STATUS_E_INTERNAL; } while ((ent = fts_read(fs)) != NULL) { switch (ent->fts_info) { case FTS_F: { if(!strcmp(fname, ent->fts_name)) { *rpath = realpath(ent->fts_path, NULL); fts_close(fs); return ONLP_STATUS_OK; } } break; } } fts_close(fs); return ONLP_STATUS_E_MISSING; }
S triefort_iter_next(ITER * const iter) { FTSENT * ent; while((ent = fts_read(iter->fts))) { switch(ent->fts_info) { case FTS_NS: case FTS_DNR: case FTS_ERR: fprintf(stderr, "%s: fts_read error: %s\n", ent->fts_accpath, strerror(ent->fts_errno)); break; case FTS_F: case FTS_DC: case FTS_DOT: case FTS_NSOK: case FTS_DP: case FTS_SL: case FTS_SLNONE: case FTS_DEFAULT: break; case FTS_D: // We've found a directory at our level. // TODO: probably more validation. Maybe? if (ent->fts_level == iter->fort->cfg.depth + 1) { iter->ent = ent; mk_hash_from_hex_str( iter->ent->fts_name, iter->hash, iter->fort->cfg.hash_len); return triefort_ok; } break; } } iter->ent = NULL; iter->done = true; return triefort_err_iterator_done; }
static int recursive_remove(const char * const path) { if (NULL == path) { return 0; } int e = 0; if (dir_exists(path)) { FTSENT * ent; const char * const ptrs[] = { path, 0 }; const int fts_options = FTS_NOCHDIR | FTS_PHYSICAL | FTS_XDEV; FTS * fts = fts_open((char * const *)ptrs, fts_options, NULL); while((ent = fts_read(fts)) && 0 == e) { switch(ent->fts_info) { case FTS_NS: case FTS_DNR: case FTS_ERR: fprintf(stderr, "%s: fts_read error: %s\n", ent->fts_accpath, strerror(ent->fts_errno)); e = ent->fts_errno; break; case FTS_D: case FTS_DC: case FTS_DOT: case FTS_NSOK: break; case FTS_DP: case FTS_F: case FTS_SL: case FTS_SLNONE: case FTS_DEFAULT: if (0 != remove(ent->fts_accpath)) { fprintf(stderr, "Unable to remove %s. %s\n", ent->fts_accpath, strerror(ent->fts_errno)); e = ent->fts_errno; } break; } } fts_close(fts); } return e; }
int traverse(char* const argv[], void (*process_file)(const char *path)) { FTS *ftsp = NULL; FTSENT *child = NULL; if ((ftsp = fts_open(argv, FTS_COMFOLLOW | FTS_NOCHDIR | FTS_XDEV, NULL)) == NULL) { warn("fts_open"); return -1; } while ((child = fts_read(ftsp)) != NULL) { if (errno != 0) { perror("fts_read"); } switch(child->fts_info) { case FTS_F : // printf("%d %s\t\t\t", child->fts_level, child->fts_name); process_file(child->fts_path); break; //case FTS_D : // printf("%d %s\n", child->fts_level, child->fts_path); // break; default : break; } } fts_close(ftsp); return 0; }
///////////////////////////////////////////////////////////// // Count the number of files for header length calculation ///////////////////////////////////////////////////////////// static int countFiles(char **source) { FTS *ftsp; FTSENT *p, *chp; int fts_options = FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOCHDIR; if ((ftsp = fts_open(source, fts_options, NULL)) == NULL) { warn("fts_open"); return -1; } /* Initialize ftsp with as many argv[] parts as possible. */ chp = fts_children(ftsp, 0); if (chp == NULL) { return 0; /* no files to traverse */ } while ((p = fts_read(ftsp)) != NULL) { switch (p->fts_info) { case FTS_F: if(strstr(p->fts_path, "DS_Store") == NULL) //wasn't a DS_Store file. { //increment the file count fileCountForHeader++; } break; default: break; } } fts_close(ftsp); return 0; }
static int remove_dir_recursively(char *dirname) { FTS *ftsp; FTSENT *p, *chp; int fts_options = FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOCHDIR; if ((ftsp = fts_open(&dirname, fts_options, NULL)) == NULL) { perror("fts_open"); return -1; } chp = fts_children(ftsp, 0); if (chp == NULL) { fts_close(ftsp); rmdir(dirname); return 0; } while ((p = fts_read(ftsp)) != NULL) { switch (p->fts_info) { case FTS_D: if (strcmp(dirname, p->fts_path)) { remove_dir_recursively(p->fts_path); rmdir(p->fts_path); } break; case FTS_F: unlink(p->fts_path); break; default: break; } } fts_close(ftsp); rmdir(dirname); return 0; }
int list_deleted_files(const char *path, size_t root_path_len, bool verbose) { // This WORKS with files and itself is listed. However, prefixs are WRONG! if (!verbose) { printf("Removed: %s/\n", &path[root_path_len]); return 0; } FTSENT *cur; char *paths[2] = {(char *) path, NULL }; FTS *ftsp = fts_open(paths, FTS_NOCHDIR | FTS_PHYSICAL, NULL); if (ftsp == NULL) { return -1; } int return_val = 0; while (((cur = fts_read(ftsp)) != NULL) && (return_val == 0)) { switch (cur->fts_info) { case FTS_D: break; // do nothing case FTS_DP: printf("Removed: %s/\n", &cur->fts_path[root_path_len]); break; case FTS_F: case FTS_SL: printf("Removed: %s\n", &cur->fts_path[root_path_len]); break; case FTS_DEFAULT: fprintf(stderr, "File %s is a special file (device or pipe). We cannot handle that.\n", cur->fts_path); return_val = -1; break; default: fprintf(stderr, "Error occured when opening %s.\n", cur->fts_path); return_val = -1; } } if (errno) { return_val = -1; } // if no error happened, fts_read will "sets the external variable errno to 0" according to the documentation return fts_close(ftsp) || return_val; }
/* this is used with -r to recursively descend directories */ static void handle_dir(char *dir) { char *path_argv[2]; FTS *fts; FTSENT *entry; path_argv[0] = dir; path_argv[1] = 0; fts = fts_open(path_argv, FTS_PHYSICAL | FTS_NOCHDIR, NULL); if (fts == NULL) { // warn("couldn't fts_open %s", dir); fprintf(stderr, "gzip: couldn't fts_open %s: %s\n", dir, strerror(errno)); return; } while ((entry = fts_read(fts))) { switch(entry->fts_info) { case FTS_D: case FTS_DP: continue; case FTS_DNR: case FTS_ERR: case FTS_NS: maybe_warn("%s", entry->fts_path); continue; case FTS_F: handle_file(entry->fts_path, entry->fts_statp); } } (void)fts_close(fts); }
int grep_tree(char **argv) { FTS *fts; FTSENT *p; int c, fts_flags; c = 0; fts_flags = FTS_PHYSICAL | FTS_NOSTAT | FTS_NOCHDIR; if (!(fts = fts_open(argv, fts_flags, NULL))) err(2, NULL); while ((p = fts_read(fts)) != NULL) { switch (p->fts_info) { case FTS_DNR: break; case FTS_ERR: file_err = 1; if(!sflag) warnx("%s: %s", p->fts_path, strerror(p->fts_errno)); break; case FTS_DP: break; default: c += procfile(p->fts_path); break; } } if (errno) err(2, "fts_read"); return c; }
void parse_summary_recursive(struct rmDsummary_set *dest, char *dirname, struct hash_table *categories) { FTS *hierarchy; FTSENT *entry; char *argv[] = {dirname, NULL}; hierarchy = fts_open(argv, FTS_PHYSICAL, NULL); if(!hierarchy) fatal("fts_open error: %s\n", strerror(errno)); struct rmDsummary *s; while( (entry = fts_read(hierarchy)) ) if( S_ISREG(entry->fts_statp->st_mode) && strstr(entry->fts_name, RULE_SUFFIX) ) //bug: no links { FILE *stream; stream = fopen(entry->fts_accpath, "r"); if(!stream) fatal("Cannot open resources summary file: %s : %s\n", entry->fts_accpath, strerror(errno)); while((s = parse_summary(stream, entry->fts_path, categories))) list_push_tail(dest->summaries, s); fclose(stream); } fts_close(hierarchy); }
static void notice_cgroups_in_hierarchy (CockpitSamples *samples, const gchar *prefix, void (* collect) (CockpitSamples *, const gchar *, const gchar *)) { const gchar *paths[] = { prefix, NULL }; gsize prefix_len; FTSENT *ent; FTS *fs; prefix_len = strlen (prefix); fs = fts_open ((gchar **)paths, FTS_NOCHDIR | FTS_COMFOLLOW, NULL); if (fs) { while((ent = fts_read (fs)) != NULL) { if (ent->fts_info == FTS_D) { const char *f = ent->fts_path + prefix_len; if (*f == '/') f++; collect (samples, ent->fts_path, f); } } fts_close (fs); } }
int16_t chown_recursive(char * const path, uid_t uid, uid_t gid) { // See man fts(3) for these. Modify these to do what you want: int fts_options = FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV | FTS_SEEDOT ; // fts_open requires a null-terminated array of paths. // We only have one path. char* paths[2] ; paths[0] = path ; paths[1] = NULL ; FTS* ftsp = fts_open(paths, fts_options, NULL) ; if (ftsp == NULL) { return -2 ; } FTSENT* ftsPointer = 0 ; while ((ftsPointer = fts_read(ftsp)) != NULL) { /* This will execute once for each item in the tree. According to the man page fts(3): "directories are visited two distinguishable times; in pre-order (before any of their descendants are visited) and in post-order (after all of their descendants have been visited)" But if I replace chown() below with a printf(), it only logs once for each directory, in pre-order. Example: Doing /Users/jk/Desktop/OW5/. Doing /Users/jk/Desktop/OW5/.. Doing /Users/jk/Desktop/OW5/BkmxTemp/. Doing /Users/jk/Desktop/OW5/BkmxTemp/.. Doing /Users/jk/Desktop/OW5/BkmxTemp/placesNo1Dump.txt Doing /Users/jk/Desktop/OW5/BkmxTemp/placesOk1Dump.txt Apparently a "visit" does not mean "returned by ftsPointer->fts_info" */ int result ; switch (ftsPointer->fts_info) { // List here the file types you want to be chown-ed. // We want all types. case FTS_F: // regular file case FTS_D: // directory case FTS_DOT: // system dot file, i.e. '.' or '..' case FTS_SL: // symbolic link result = chown(ftsPointer->fts_path, uid, gid) ; if (result != 0) { // chown only returns either 0 or -1. // Must be -1 here. return result ; } break ; default: printf("Internal Error 524-0192 unknown type %d\n", ftsPointer->fts_info) ; break; } } fts_close(ftsp) ; return 0 ; }
/* this is used with -r to recursively descend directories */ static void handle_dir(char *dir) { char *path_argv[2]; FTS *fts; FTSENT *entry; path_argv[0] = dir; path_argv[1] = 0; fts = fts_open(path_argv, FTS_PHYSICAL, NULL); if (fts == NULL) { warn("couldn't fts_open %s", dir); return; } while ((entry = fts_read(fts))) { switch(entry->fts_info) { case FTS_D: case FTS_DP: continue; case FTS_DNR: case FTS_ERR: case FTS_NS: maybe_warn("%s", entry->fts_path); continue; case FTS_F: handle_file(entry->fts_name, entry->fts_statp); } } (void)fts_close(fts); }
int traverse(const char *lower_root, const char *upper_root, bool verbose, FILE* script_stream, TRAVERSE_CALLBACK callback_d, TRAVERSE_CALLBACK callback_dp, TRAVERSE_CALLBACK callback_f, TRAVERSE_CALLBACK callback_sl, TRAVERSE_CALLBACK callback_whiteout,void *extra) { // returns 0 on success FTSENT *cur; char *paths[2] = {(char *) upper_root, NULL }; char lower_path[PATH_MAX]; strcpy(lower_path, lower_root); size_t upper_root_len = strlen(upper_root); size_t lower_root_len = strlen(lower_root); FTS *ftsp = fts_open(paths, FTS_NOCHDIR | FTS_PHYSICAL, NULL); if (ftsp == NULL) { return -1; } int return_val = 0; while (((cur = fts_read(ftsp)) != NULL) && (return_val == 0)) { TRAVERSE_CALLBACK callback = NULL; switch (cur->fts_info) { case FTS_D: callback = callback_d; break; case FTS_DP: callback = callback_dp; break; case FTS_F: callback = callback_f; break; case FTS_SL: callback = callback_sl; break; case FTS_DEFAULT: if (is_whiteout(cur->fts_statp)) { callback = callback_whiteout; } else { return_val = -1; fprintf(stderr, "File %s is a special file (device or pipe). We cannot handle that.\n", cur->fts_path); } break; default: return_val = -1; fprintf(stderr, "Error occured when opening %s.\n", cur->fts_path); } if (callback != NULL) { int fts_instr = 0; struct stat lower_status; bool lower_exist = true; strcpy(&lower_path[lower_root_len], &(cur->fts_path[upper_root_len])); if (lstat(lower_path, &lower_status) != 0) { if (errno == ENOENT || errno == ENOTDIR) { // the corresponding lower file (or its ancestor) does not exist at all lower_exist = false; } else { // stat failed for some unknown reason fprintf(stderr, "Failed to stat %s.\n", lower_path); return_val = -1; break; // do not call callback in this case } } return_val = callback(lower_path, cur->fts_path, lower_root_len, lower_exist ? &lower_status : NULL, cur->fts_statp, verbose, script_stream, &fts_instr,extra); // return_val must previously be 0 if (fts_instr) { fts_set(ftsp, cur, fts_instr); } } } if (errno) { return_val = -1; } // if no error happened, fts_read will "sets the external variable errno to 0" according to the documentation return fts_close(ftsp) || return_val; }
struct list *parse_summary_recursive(char *dirname) { FTS *hierarchy; FTSENT *entry; char *argv[] = {dirname, NULL}; struct list *summaries = list_create(0); hierarchy = fts_open(argv, FTS_PHYSICAL, NULL); if(!hierarchy) fatal("fts_open error: %s\n", strerror(errno)); struct summary *s; while( (entry = fts_read(hierarchy)) ) if( strstr(entry->fts_name, RULE_SUFFIX) ) { s = parse_summary_file(entry->fts_accpath); list_push_head(summaries, (void *) s); } fts_close(hierarchy); return summaries; }
/* Tell fts not to traverse into the hierarchy at ENT. */ static void fts_skip_tree (FTS *fts, FTSENT *ent) { fts_set (fts, ent, FTS_SKIP); /* Ensure that we do not process ENT a second time. */ ignore_value (fts_read (fts)); }
int rm_dir(char *path) { FTS *fts; FTSENT *p; static char *fpath[] = { NULL, NULL }; fpath[0] = path; if ((fts = fts_open(fpath, FTS_PHYSICAL, NULL)) == NULL) { warn("fts_open %s", path); return (1); } while ((p = fts_read(fts)) != NULL) { switch (p->fts_info) { case FTS_DP: case FTS_DNR: if (rmdir(p->fts_accpath) == -1) warn("rmdir %s", p->fts_accpath); break; case FTS_F: if (unlink(p->fts_accpath) == -1) warn("unlink %s", p->fts_accpath); break; case FTS_D: case FTS_DOT: default: continue; } } fts_close(fts); return (0); }
bool Path::rmdir(const Path& dir) { if (!dir.isDir()) return false; // hva slags drittapi er dette? char* const dirs[2] = { const_cast<char*>(dir.constData()), 0 }; FTS* fdir = fts_open(dirs, FTS_NOCHDIR, 0); if (!fdir) return false; FTSENT *node; while ((node = fts_read(fdir))) { if (node->fts_level > 0 && node->fts_name[0] == '.') { fts_set(fdir, node, FTS_SKIP); } else { switch (ftsType(node->fts_info)) { case File: unlink(node->fts_path); break; case Directory: ::rmdir(node->fts_path); break; default: break; } } } fts_close(fdir); return true; }
FTSENT *__sf_fts_read(FTS *ftsp) { if (tt_rand_u32() % 2) { return NULL; } else { return fts_read(ftsp); } }
int FDirectory::AddDirectory(const char *dirpath) { char *argv [2] = { NULL, NULL }; argv[0] = new char[strlen(dirpath)+1]; strcpy(argv[0], dirpath); FTS *fts; FTSENT *ent; int count = 0; fts = fts_open(argv, FTS_LOGICAL, NULL); if (fts == NULL) { Printf("Failed to start directory traversal: %s\n", strerror(errno)); return 0; } const size_t namepos = strlen(Filename); FString pathfix; while ((ent = fts_read(fts)) != NULL) { if (ent->fts_info == FTS_D && ent->fts_name[0] == '.') { // Skip hidden directories. (Prevents SVN bookkeeping // info from being included.) fts_set(fts, ent, FTS_SKIP); } if (ent->fts_info == FTS_D && ent->fts_level == 0) { continue; } if (ent->fts_info != FTS_F) { // We're only interested in remembering files. continue; } // Some implementations add an extra separator between // root of the hierarchy and entity's path. // It needs to be removed in order to resolve // lumps' relative paths properly. const char* path = ent->fts_path; if ('/' == path[namepos]) { pathfix = FString(path, namepos); pathfix.AppendCStrPart(&path[namepos + 1], ent->fts_pathlen - namepos - 1); path = pathfix.GetChars(); } AddEntry(path, ent->fts_statp->st_size); count++; } fts_close(fts); delete[] argv[0]; return count; }
bool hardened_shadow_remove_dir_contents(const char *path) { bool result = true; /* Note: nftw-based code would be possibly simpler, * but it wouldn't be possible to have as detailed error messages. */ FTS *fts_handle = NULL; char *fts_argv[] = { strdup(path), NULL }; /* Make sure strdup above succeeded. */ if (!fts_argv[0]) { result = false; goto out; } fts_handle = fts_open(fts_argv, FTS_PHYSICAL | FTS_NOSTAT, NULL); if (!fts_handle) { warn("fts_open"); result = false; goto out; } FTSENT *fts_entry; while ((fts_entry = fts_read(fts_handle))) { switch (fts_entry->fts_info) { case FTS_DNR: case FTS_NS: /* Warn about the problem, but continue deleting files. */ warnx("%s: %s", fts_entry->fts_path, strerror(fts_entry->fts_errno)); result = false; break; case FTS_ERR: /* We consider this a fatal error, i.e. abort processing now. */ warnx("%s: %s", fts_entry->fts_path, strerror(fts_entry->fts_errno)); result = false; goto out; case FTS_D: break; case FTS_DP: if (fts_entry->fts_level > 0 && rmdir(fts_entry->fts_accpath) != 0) { warn("%s", fts_entry->fts_accpath); result = false; } break; default: if (fts_entry->fts_level > 0 && unlink(fts_entry->fts_accpath) != 0) { warn("%s", fts_entry->fts_accpath); result = false; } break; } } out: if (fts_handle) fts_close(fts_handle); free(fts_argv[0]); return result; }
Error PathMan::read_dir(const char * path) { uint32_t len = strlen(path); char word[len+1]; memcpy(word, path, len); word[len ] = 0; char * ppath[] = {word, 0}; LookUp lu = lookup("/"), flu; if (lu.err) return lu.err; FTSENT *node; FTS *tree = fts_open(ppath, FTS_NOCHDIR, 0); if (!tree) return FAILURE; { size_t len; while ((node = fts_read(tree))) { char word[node->fts_pathlen + 3]; if (node->fts_info & FTS_F) { mkword(node, word, len); flu = add_file(word, 0); if (flu.err) goto fout; flu.file->offset = 0; flu.file->size = node->fts_statp->st_size; } else if (node->fts_info & FTS_D) { mkword(node, word, len); if (len > 1) { if (word[len - 1] != '/') { word[len++] = '/'; } word[len] = 0; lu = add_dir(word, 0); if (lu.err) goto dout; } } } fts_close(tree); } return SUCCESS; fout: fts_close(tree); return flu.err; dout: fts_close(tree); return lu.err; }
/* * Traverse() walks the logical directory structure specified by the argv list * in the order specified by the mastercmp() comparison function. During the * traversal it passes linked lists of structures to display() which represent * a superset (may be exact set) of the files to be displayed. */ static void traverse(int argc, char *argv[], int options) { FTS *ftsp; FTSENT *p, *chp; int ch_options; if ((ftsp = fts_open(argv, options, f_nosort ? NULL : mastercmp)) == NULL) err(EXIT_FAILURE, NULL); display(NULL, fts_children(ftsp, 0)); if (f_listdir) return; /* * If not recursing down this tree and don't need stat info, just get * the names. */ ch_options = !f_recursive && options & FTS_NOSTAT ? FTS_NAMEONLY : 0; while ((p = fts_read(ftsp)) != NULL) switch (p->fts_info) { case FTS_DC: warnx("%s: directory causes a cycle", p->fts_name); break; case FTS_DNR: case FTS_ERR: warnx("%s: %s", p->fts_name, strerror(p->fts_errno)); rval = EXIT_FAILURE; break; case FTS_D: if (p->fts_level != FTS_ROOTLEVEL && p->fts_name[0] == '.' && !f_listdot) break; /* * If already output something, put out a newline as * a separator. If multiple arguments, precede each * directory with its name. */ if (output) (void)printf("\n%s:\n", p->fts_path); else if (argc > 1) { (void)printf("%s:\n", p->fts_path); output = 1; } chp = fts_children(ftsp, ch_options); display(p, chp); if (!f_recursive && chp != NULL) (void)fts_set(ftsp, p, FTS_SKIP); break; } if (errno) err(EXIT_FAILURE, "fts_read"); }
/* * Print all files in the directory tree that match the glob pattern. * Example: pmatch("/usr/src", "*.c"); */ void pmatch(char *dir, const char *pattern) { FTS *tree; FTSENT *f; char *argv[] = { dir, NULL }; /* * FTS_LOGICAL follows symbolic links, including links to other * directories. It detects cycles, so we never have an infinite * loop. FTS_NOSTAT is because we never use f->statp. It uses * our entcmp() to sort files by name. */ tree = fts_open(argv, FTS_LOGICAL | FTS_NOSTAT, entcmp); if (tree == NULL) err(1, "fts_open"); /* * Iterate files in tree. This iteration always skips * "." and ".." because we never use FTS_SEEDOT. */ while ((f = fts_read(tree))) { switch (f->fts_info) { case FTS_DNR: /* Cannot read directory */ case FTS_ERR: /* Miscellaneous error */ case FTS_NS: /* stat() error */ /* Show error, then continue to next files. */ warn("%s", f->fts_path); continue; case FTS_DP: /* Ignore post-order visit to directory. */ continue; } /* * Check if name matches pattern. If so, then print * path. This check uses FNM_PERIOD, so "*.c" will not * match ".invisible.c". */ if (fnmatch(pattern, f->fts_name, FNM_PERIOD) == 0) puts(f->fts_path); /* * A cycle happens when a symbolic link (or perhaps a * hard link) puts a directory inside itself. Tell user * when this happens. */ if (f->fts_info == FTS_DC) warnx("%s: cycle in directory tree", f->fts_path); } /* fts_read() sets errno = 0 unless it has error. */ if (errno != 0) err(1, "fts_read"); if (fts_close(tree) < 0) err(1, "fts_close"); }
/* This function takes three parameters: PATH of an existing file system object. A RECURSE boolean which if the file system object is a directory, will call restorecon_private on every file system object in the directory. A LOCAL boolean that indicates whether the function should set object labels to the default for the local process, or use system wide settings. Returns false on failure. errno will be set appropriately. */ bool restorecon (char const *path, bool recurse, bool local) { char *newpath = NULL; FTS *fts; bool ok = true; if (! IS_ABSOLUTE_FILE_NAME (path) && ! local) { /* Generate absolute path as required by subsequent matchpathcon(), with libselinux < 2.1.5 2011-0826. Also generating the absolute path before the fts walk, will generate absolute paths in the fts entries, which may be quicker to process in any case. */ newpath = canonicalize_filename_mode (path, CAN_MISSING); if (! newpath) error (EXIT_FAILURE, errno, _("error canonicalizing %s"), quote (path)); } const char *ftspath[2] = { newpath ? newpath : path, NULL }; if (! recurse) { ok = restorecon_private (*ftspath, local) != -1; free (newpath); return ok; } fts = xfts_open ((char *const *) ftspath, FTS_PHYSICAL, NULL); while (1) { FTSENT *ent; ent = fts_read (fts); if (ent == NULL) { if (errno != 0) { error (0, errno, _("fts_read failed")); ok = false; } break; } ok &= restorecon_private (fts->fts_path, local) != -1; } if (fts_close (fts) != 0) { error (0, errno, _("fts_close failed")); ok = false; } free (newpath); return ok; }
int _rm(char const* path) { FTS* tree; FTSENT* cur = NULL; char* paths[2]; paths[0] = (char*)path; paths[1] = NULL; tree = fts_open(paths, FTS_COMFOLLOW | FTS_NOCHDIR, NULL); if (tree != NULL) { while ((cur = fts_read(tree)) != NULL) { switch (cur->fts_info) { case FTS_NS: case FTS_DNR: case FTS_ERR: fprintf(stderr, "Error: %s: fts_read error: %s\n", cur->fts_accpath, strerror(cur->fts_errno)); return 1; case FTS_DC: case FTS_DOT: case FTS_NSOK: /* Not reached unless FTS_LOGICAL, FTS_SEEDOT, or FTS_NOSTAT were */ /* passed to fts_open() */ break; case FTS_D: /* Do nothing. Need depth-first search, so directories are deleted */ /* in FTS_DP */ break; case FTS_DP: case FTS_F: case FTS_SL: case FTS_SLNONE: case FTS_DEFAULT: if (remove(cur->fts_accpath) < 0) { fprintf(stderr, "Error: %s: Failed to remove: %s\n", strerror(errno), cur->fts_path); return 1; } break; } } fts_close(tree); return 0; } return 1; }