int trap_ReadDirectory(lua_State *s) { directory_t *dir; direntry_t *ent; const char *path; int i; trap_args(s, "ReadDirectory", "s", &path); path = datapath(path); dir = OPENDIR(path); if (dir == NULL) FATAL("Failed to open directory: %s", path); lua_newtable(s); i = 1; for (ent = READDIR(dir); ent != NULL; ent = READDIR(dir)) { path = DIRENT_NAME(ent); if (strcmp(path, ".") == 0) continue; if (strcmp(path, "..") == 0) continue; lua_pushstring(s, va("%d", i)); lua_pushstring(s, DIRENT_NAME(ent)); lua_settable(s, -3); ++i; } CLOSEDIR(dir); return 1; }
static int max_backup_version (const char *file, const char *dir) { DIR *dirp; struct dirent *dp; int highest_version; int this_version; size_t file_name_length; dirp = opendir (dir); if (!dirp) return 0; highest_version = 0; file_name_length = strlen (file); while ((dp = readdir (dirp)) != 0) { if (!REAL_DIR_ENTRY (dp) || NLENGTH (dp) < file_name_length + 4) continue; this_version = version_number (file, dp->d_name, file_name_length); if (this_version > highest_version) highest_version = this_version; } if (CLOSEDIR (dirp)) return 0; return highest_version; }
char * savedir (const char *dir) { DIR *dirp; struct dirent *dp; char *name_space; size_t allocated = NAME_SIZE_DEFAULT; size_t used = 0; int save_errno; dirp = opendir (dir); if (dirp == NULL) return NULL; name_space = xmalloc (allocated); errno = 0; while ((dp = readdir (dirp)) != NULL) { /* Skip "", ".", and "..". "" is returned by at least one buggy implementation: Solaris 2.4 readdir on NFS filesystems. */ char const *entry = dp->d_name; if (entry[entry[0] != '.' ? 0 : entry[1] != '.' ? 1 : 2] != '\0') { size_t entry_size = strlen (entry) + 1; if (used + entry_size < used) xalloc_die (); if (allocated <= used + entry_size) { do { if (2 * allocated < allocated) xalloc_die (); allocated *= 2; } while (allocated <= used + entry_size); name_space = xrealloc (name_space, allocated); } memcpy (name_space + used, entry, entry_size); used += entry_size; } } name_space[used] = '\0'; save_errno = errno; if (CLOSEDIR (dirp) != 0) save_errno = errno; if (save_errno != 0) { free (name_space); errno = save_errno; return NULL; } return name_space; }
/* the rest of the pattern segments */ #endif /* ANSI_PROTOTYPES */ { char *saved_end = path_end; /* saved to be resored */ char *pat; /* current pattern segment */ struct stat st; /* to check if file exists */ #ifdef GLOBDEBUG ffprintf(STDDBG,"do_glob: path = '%s', pat = '%s'\n", main_path, *gpat ); #endif for ( ; (pat = *gpat) != 0 && no_glob(pat); gpat++ ) { #ifdef GLOBDEBUG ffprintf(STDDBG,"no_glob: path = '%s', pat = '%s'\n", main_path, pat ); #endif *path_end = '/'; (void)strcpy(path_end+1, pat); path_end += strlen(pat) + 1; if (GLOBSTAT(main_path, &st) != 0 ) { *saved_end = '\0'; return; } } if (pat) matchdir(path_end, gpat); else add_name(); *saved_end = '\0'; return; } static void #ifndef ANSI_PROTOTYPES matchdir(path_end, gpat) char *path_end; /* ptr to end of main_path */ char **gpat; /* the rest of the pattern segments */ #else /* ANSI_PROTOTYPES */ matchdir(char *path_end, char **gpat) /* ptr to end of main_path */ /* the rest of the pattern segments */ #endif /* ANSI_PROTOTYPES */ { char *x; /* scratch */ VOIDDIR *dirp; /* for directory reading */ VOIDDIRENT *dp; /* directory entry */ struct stat st; /* to determine files type */ #ifdef GLOBDEBUG ffprintf(STDDBG,"matchdir: path = '%s', pat = '%s'\n", main_path, *gpat ); #endif if ((dirp = OPENDIR(main_path)) == NULL) return; *path_end = '/'; while ((dp = READDIR(dirp)) != NULL) { char *dirname; x = dirname = GETNAME(dp); /* was dp->d_name */ if (*x == '.' && (*++x == '\0' || (*x == '.' && *++x == '\0'))) continue; if (*dirname == '.' && **gpat != '.') continue; (void)strcpy(path_end + 1, dirname); if (glob_match(*gpat, dirname)) { /* this is a match */ if ( *(gpat+1) == 0 ) { /* and it is the last */ add_name(); /* so eat it */ continue; } if (GLOBSTAT(main_path, &st) == 0 /* else not the last */ && (st.st_mode & S_IFMT) == S_IFDIR) do_glob(path_end + strlen(dirname) + 1, gpat + 1); } } (void)CLOSEDIR(dirp); *path_end = '\0'; }
void dir_srch (parse_blk *pfil) { struct stat statbuf; int stat_res; lv_val *dir1, *dir2, *tmp; mstr tn; short p2_len; char filb[MAX_FBUFF + 1], patb[sizeof(ptstr)], *c, *lastd, *top, *p2, *c1, ch; mval pat_mval, sub, compare; bool wildname, seen_wd; struct dirent *dent; DIR *dp; plength *plen; int closedir_res; op_kill(zsrch_dir1); op_kill(zsrch_dir2); if (!pfil->b_name) return; /* nothing to search for */ ESTABLISH(dir_ch); pat_mval.mvtype = MV_STR; pat_mval.str.addr = patb; /* patb should be sizeof(ptstr.buff) but instead is sizeof(ptstr) since the C compiler * complains about the former and the latter is just 4 bytes more */ pat_mval.str.len = 0; sub.mvtype = MV_STR; sub.str.len = 0; compare.mvtype = MV_STR; compare.str.len = 0; wildname = (pfil->fnb & F_WILD_NAME) != 0; dir1 = zsrch_dir1; dir2 = zsrch_dir2; if (pfil->fnb & F_WILD_DIR) { seen_wd = FALSE; for (c = pfil->l_dir, lastd = c, top = c + pfil->b_dir; c < top;) { ch = *c++; if (ch == '/') /* note the start of each directory segment */ { if (seen_wd) break; lastd = c; } if (ch == '?' || ch == '*') seen_wd = TRUE; } assert(c <= top); sub.str.addr = pfil->l_dir; sub.str.len = lastd - sub.str.addr; tmp = op_putindx(VARLSTCNT(2) dir1, &sub); tmp->v.mvtype = MV_STR; tmp->v.str.len = 0; for(;;) { tn.addr = lastd; /* wildcard segment */ tn.len = c - lastd - 1; lastd = c; genpat(&tn, &pat_mval); seen_wd = FALSE; p2 = c - 1; for (; c < top;) { ch = *c++; if (ch == '/') /* note the start of each directory segment */ { if (seen_wd) break; lastd = c; } if (ch == '?' || ch == '*') seen_wd = TRUE; } p2_len = lastd - p2; /* length of non-wild segment after wild section */ for (;;) { pop_top(dir1, &sub); /* get next item off the top */ if (!sub.str.len) break; memcpy(filb, sub.str.addr, sub.str.len); filb[sub.str.len] = 0; sub.str.addr = filb; dp = OPENDIR(filb); if (!dp) continue; while(READDIR(dp, dent)) { compare.str.addr = &dent->d_name[0]; compare.str.len = strlen(&dent->d_name[0]); assert(compare.str.len); if ( dent->d_name[0] == '.' && (compare.str.len == 1 || (compare.str.len == 2 && dent->d_name[1] == '.')) ) { continue; /* don't want to read . and .. */ } if (compare.str.len + sub.str.len + p2_len > MAX_FBUFF) continue; if (do_pattern(&compare, &pat_mval)) { /* got a hit */ if (stringpool.free + compare.str.len + sub.str.len + p2_len + 1 > stringpool.top) stp_gcol(compare.str.len + sub.str.len + p2_len + 1); /* concatenate directory and name */ c1 = (char *)stringpool.free; tn = sub.str; s2pool(&tn); tn = compare.str; s2pool(&tn); tn.addr = p2; tn.len = p2_len; s2pool(&tn); *stringpool.free++ = 0; compare.str.addr = c1; compare.str.len += sub.str.len + p2_len; STAT_FILE(compare.str.addr, &statbuf, stat_res); if (-1 == stat_res) continue; if (!(statbuf.st_mode & S_IFDIR)) continue; /* put in results tree */ tmp = op_putindx(VARLSTCNT(2) dir2, &compare); tmp->v.mvtype = MV_STR; tmp->v.str.len = 0; } } CLOSEDIR(dp, closedir_res); } tmp = dir1; dir1 = dir2; dir2 = tmp; if (c >= top) break; } } else { sub.str.addr = pfil->l_dir; sub.str.len = pfil->b_dir; tmp = op_putindx(VARLSTCNT(2) dir1, &sub); tmp->v.mvtype = MV_STR; tmp->v.str.len = 0; } if (wildname) { tn.addr = pfil->l_name; tn.len = pfil->b_name + pfil->b_ext; genpat(&tn, &pat_mval); } for (;;) { pop_top(dir1, &sub); /* get next item off the top */ if (!sub.str.len) break; if (wildname) { memcpy(filb, sub.str.addr, sub.str.len); filb[sub.str.len] = 0; sub.str.addr = filb; dp = OPENDIR(filb); if (!dp) continue; while(READDIR(dp, dent)) { compare.str.addr = &dent->d_name[0]; compare.str.len = strlen(&dent->d_name[0]); if ( dent->d_name[0] == '.' && (compare.str.len == 1 || (compare.str.len == 2 && dent->d_name[1] == '.'))) { continue; /* don't want to read . and .. */ } if (compare.str.len + sub.str.len > MAX_FBUFF) continue; if (do_pattern(&compare, &pat_mval)) { /* got a hit */ if (stringpool.free + compare.str.len + sub.str.len > stringpool.top) stp_gcol(compare.str.len + sub.str.len); /* concatenate directory and name */ c = (char *)stringpool.free; tn = sub.str; s2pool(&tn); tn = compare.str; s2pool(&tn); compare.str.addr = c; compare.str.len += sub.str.len; /* put in results tree */ tmp = op_putindx(VARLSTCNT(2) ind_var, &compare); tmp->v.mvtype = MV_STR; tmp->v.str.len = 0; plen = (plength *)&tmp->v.m[1]; plen->p.pblk.b_esl = compare.str.len; plen->p.pblk.b_dir = sub.str.len; for (c = &compare.str.addr[sub.str.len], c1 = top = &compare.str.addr[compare.str.len]; c < top; ) { if (*c++ != '.') break; } for (; c < top;) { if (*c++ == '.') c1 = c - 1; } plen->p.pblk.b_ext = top - c1; plen->p.pblk.b_name = plen->p.pblk.b_esl - plen->p.pblk.b_dir - plen->p.pblk.b_ext; } } CLOSEDIR(dp, closedir_res); } else { assert(pfil->fnb & F_WILD_DIR); compare.str.addr = pfil->l_name; compare.str.len = pfil->b_name + pfil->b_ext; if (compare.str.len + sub.str.len > MAX_FBUFF) continue; memcpy(filb, sub.str.addr, sub.str.len); filb[sub.str.len] = 0; sub.str.addr = filb; if (stringpool.free + compare.str.len + sub.str.len > stringpool.top) stp_gcol(compare.str.len + sub.str.len); /* concatenate directory and name */ c1 = (char *)stringpool.free; tn = sub.str; s2pool(&tn); tn = compare.str; s2pool(&tn); compare.str.addr = c1; compare.str.len += sub.str.len; /* put in results tree */ tmp = op_putindx(VARLSTCNT(2) ind_var, &compare); tmp->v.mvtype = MV_STR; tmp->v.str.len = 0; plen = (plength *)&tmp->v.m[1]; plen->p.pblk.b_esl = compare.str.len; plen->p.pblk.b_dir = sub.str.len; plen->p.pblk.b_name = pfil->b_name; plen->p.pblk.b_ext = pfil->b_ext; } } op_kill(zsrch_dir1); op_kill(zsrch_dir2); REVERT; }
static int thrashdir( char *sigdir) { DIR *dirp; DIR_BUF *dp; char *cwd; int safeguard, recurse; int c = 0, numentries, pick; struct stat st; sigfile[0] = '\0'; if ((dirp = opendir(CURRENTDIR)) == NULL) return 1; numentries = 0; while ((dp = readdir(dirp)) != NULL) numentries++; /* * consider "." and ".." non-entries * consider all entries starting with "." non-entries */ cwd = my_malloc(PATH_LEN); #ifndef M_AMIGA if (numentries < 3 || cwd == NULL) #else if (numentries == 0 || cwd == NULL) #endif /* !M_AMIGA */ { CLOSEDIR(dirp); return -1; } get_cwd(cwd); recurse = strcmp(cwd, sigdir); /* * If we are using the root sig directory, we don't want * to recurse, or else we might use a custom sig intended * for a specific newsgroup (and not this one). */ for (safeguard = 0, dp = NULL; safeguard < MAXLOOPS && dp == NULL; safeguard++) { #ifdef DEBUG if (debug == 2) error_message("sig loop=[%d] recurse=[%d]", safeguard, recurse); #endif /* DEBUG */ #ifdef HAVE_REWINDDIR rewinddir(dirp); #else CLOSEDIR(dirp); if ((dirp = opendir(CURRENTDIR)) == NULL) return 1; #endif /* HAVE_REWINDDIR */ pick = rand() % numentries + 1; while (--pick >= 0) { if ((dp = readdir(dirp)) == NULL) break; } if (dp != NULL) { /* if we could open the dir entry */ if (!strcmp(dp->d_name, CURRENTDIR) || (dp->d_name[0] == '.')) dp = NULL; else { /* if we have a non-dot entry */ if (stat(dp->d_name, &st) == -1) { CLOSEDIR(dirp); return 1; } if (S_ISDIR(st.st_mode)) { if (recurse) { /* * do subdirectories */ if ((my_chdir(dp->d_name) < 0) || ((c = thrashdir(sigdir)) == 1)) { CLOSEDIR(dirp); return 1; } if (c == -1) { /* * the one we picked was an * empty dir so try again. */ dp = NULL; my_chdir(cwd); } } else dp = NULL; } else { /* end dir; we have a file */ get_cwd(sigfile); strcat(sigfile, "/"); strcat(sigfile, dp->d_name); #ifdef DEBUG if (debug == 2) error_message("Found a file=[%s]", sigfile); #endif /* DEBUG */ } } } } free(cwd); #ifdef DEBUG if (debug == 2) error_message("return 0: sigfile=[%s]", sigfile); #endif /* DEBUG */ CLOSEDIR(dirp); return 0; }
static void process_dir (char *pathname, char *name, int pathlen, const struct stat *statp, char *parent) { int subdirs_left; /* Number of unexamined subdirs in PATHNAME. */ bool subdirs_unreliable; /* if true, cannot use dir link count as subdir limif (if false, it may STILL be unreliable) */ struct stat stat_buf; size_t dircount = 0u; DIR *dirp; if (statp->st_nlink < 2) { subdirs_unreliable = true; subdirs_left = 0; } else { subdirs_unreliable = false; /* not necessarily right */ subdirs_left = statp->st_nlink - 2; /* Account for name and ".". */ } errno = 0; dirp = opendir_safer (name); if (dirp == NULL) { assert (errno != 0); error (0, errno, "%s", safely_quote_err_filename (0, pathname)); state.exit_status = 1; } else { char *cur_path; /* Full path of each file to process. */ char *cur_name; /* Base name of each file to process. */ unsigned cur_path_size; /* Bytes allocated for `cur_path'. */ register unsigned file_len; /* Length of each path to process. */ register unsigned pathname_len; /* PATHLEN plus trailing '/'. */ bool did_stat = false; if (pathname[pathlen - 1] == '/') pathname_len = pathlen + 1; /* For '\0'; already have '/'. */ else pathname_len = pathlen + 2; /* For '/' and '\0'. */ cur_path_size = 0; cur_path = NULL; /* We're about to leave the directory. If there are any * -execdir argument lists which have been built but have not * yet been processed, do them now because they must be done in * the same directory. */ complete_pending_execdirs (); if (strcmp (name, ".")) { enum SafeChdirStatus status = safely_chdir (name, TraversingDown, &stat_buf, SymlinkHandleDefault, &did_stat); switch (status) { case SafeChdirOK: /* If there had been a change but wd_sanity_check() * accepted it, we need to accept that on the * way back up as well, so modify our record * of what we think we should see later. * If there was no change, the assignments are a no-op. * * However, before performing the assignment, we need to * check that we have the stat information. If O_NOFOLLOW * is available, safely_chdir() will not have needed to use * stat(), and so stat_buf will just contain random data. */ if (!did_stat) { /* If there is a link we need to follow it. Hence * the direct call to stat() not through (options.xstat) */ set_stat_placeholders (&stat_buf); if (0 != stat (".", &stat_buf)) break; /* skip the assignment. */ } dir_ids[dir_curr].dev = stat_buf.st_dev; dir_ids[dir_curr].ino = stat_buf.st_ino; break; case SafeChdirFailWouldBeUnableToReturn: error (0, errno, "."); state.exit_status = 1; break; case SafeChdirFailNonexistent: case SafeChdirFailDestUnreadable: case SafeChdirFailStat: case SafeChdirFailNotDir: case SafeChdirFailChdirFailed: error (0, errno, "%s", safely_quote_err_filename (0, pathname)); state.exit_status = 1; return; case SafeChdirFailSymlink: error (0, 0, _("warning: not following the symbolic link %s"), safely_quote_err_filename (0, pathname)); state.exit_status = 1; return; } } while (1) { const char *namep; mode_t mode = 0; const struct dirent *dp; /* We reset errno here to distinguish between end-of-directory and an error */ errno = 0; dp = readdir (dirp); if (NULL == dp) { if (errno) { /* an error occurred, but we are not yet at the end of the directory stream. */ error (0, errno, "%s", safely_quote_err_filename (0, pathname)); continue; } else { break; /* End of the directory stream. */ } } else { namep = dp->d_name; /* Skip "", ".", and "..". "" is returned by at least one buggy implementation: Solaris 2.4 readdir on NFS file systems. */ if (!namep[0] || (namep[0] == '.' && (namep[1] == 0 || (namep[1] == '.' && namep[2] == 0)))) continue; } #if defined HAVE_STRUCT_DIRENT_D_TYPE if (dp->d_type != DT_UNKNOWN) mode = type_to_mode (dp->d_type); #endif /* Append this directory entry's name to the path being searched. */ file_len = pathname_len + strlen (namep); if (file_len > cur_path_size) { while (file_len > cur_path_size) cur_path_size += 1024; free (cur_path); cur_path = xmalloc (cur_path_size); strcpy (cur_path, pathname); cur_path[pathname_len - 2] = '/'; } cur_name = cur_path + pathname_len - 1; strcpy (cur_name, namep); state.curdepth++; if (!options.no_leaf_check && !subdirs_unreliable) { if (mode && S_ISDIR(mode) && (subdirs_left == 0)) { /* This is a subdirectory, but the number of directories we * have found now exceeds the number we would expect given * the hard link count on the parent. This is likely to be * a bug in the file system driver (e.g. Linux's * /proc file system) or may just be a fact that the OS * doesn't really handle hard links with Unix semantics. * In the latter case, -noleaf should be used routinely. */ error (0, 0, _("WARNING: Hard link count is wrong for %s (saw only st_nlink=%" PRIuMAX " but we already saw %" PRIuMAX " subdirectories): this may be a bug in your file system driver. Automatically turning on find's -noleaf option. Earlier results may have failed to include directories that should have been searched."), safely_quote_err_filename(0, pathname), (uintmax_t) statp->st_nlink, (uintmax_t) dircount); state.exit_status = 1; /* We know the result is wrong, now */ options.no_leaf_check = true; /* Don't make same mistake again */ subdirs_unreliable = 1; subdirs_left = 1; /* band-aid for this iteration. */ } /* Normal case optimization. On normal Unix file systems, a directory that has no subdirectories has two links: its name, and ".". Any additional links are to the ".." entries of its subdirectories. Once we have processed as many subdirectories as there are additional links, we know that the rest of the entries are non-directories -- in other words, leaf files. */ { int count; count = process_path (cur_path, cur_name, subdirs_left == 0, pathname, mode, D_INO(dp)); subdirs_left -= count; dircount += count; } } else { /* There might be weird (e.g., CD-ROM or MS-DOS) file systems mounted, which don't have Unix-like directory link counts. */ process_path (cur_path, cur_name, false, pathname, mode, D_INO(dp)); } state.curdepth--; } /* We're about to leave the directory. If there are any * -execdir argument lists which have been built but have not * yet been processed, do them now because they must be done in * the same directory. */ complete_pending_execdirs (); if (strcmp (name, ".")) { enum SafeChdirStatus status; /* We could go back and do the next command-line arg instead, maybe using longjmp. */ char const *dir; bool deref = following_links () ? true : false; if ( (state.curdepth>0) && !deref) dir = ".."; else { chdir_back (); dir = parent; } did_stat = false; status = safely_chdir (dir, TraversingUp, &stat_buf, SymlinkHandleDefault, &did_stat); switch (status) { case SafeChdirOK: break; case SafeChdirFailWouldBeUnableToReturn: error (EXIT_FAILURE, errno, "."); return; case SafeChdirFailNonexistent: case SafeChdirFailDestUnreadable: case SafeChdirFailStat: case SafeChdirFailSymlink: case SafeChdirFailNotDir: case SafeChdirFailChdirFailed: error (EXIT_FAILURE, errno, "%s", safely_quote_err_filename (0, pathname)); return; } } free (cur_path); CLOSEDIR (dirp); } if (subdirs_unreliable) { /* Make sure we hasn't used the variable subdirs_left if we knew * we shouldn't do so. */ assert (0 == subdirs_left || options.no_leaf_check); } }
static char * old_savedirinfo (const char *dir, struct savedir_extrainfo **extra) { DIR *dirp; struct dirent *dp; char *name_space; size_t namebuf_allocated = 0u, namebuf_used = 0u; #if defined(HAVE_STRUCT_DIRENT_D_TYPE) && defined(USE_STRUCT_DIRENT_D_TYPE) size_t extra_allocated = 0u, extra_used = 0u; struct savedir_extrainfo *info = NULL; #endif int save_errno; if (extra) *extra = NULL; dirp = opendir (dir); if (dirp == NULL) return NULL; errno = 0; name_space = NULL; while ((dp = readdir (dirp)) != NULL) { /* Skip "", ".", and "..". "" is returned by at least one buggy implementation: Solaris 2.4 readdir on NFS file systems. */ char const *entry = dp->d_name; if (entry[entry[0] != '.' ? 0 : entry[1] != '.' ? 1 : 2] != '\0') { /* Remember the name. */ size_t entry_size = strlen (entry) + 1; name_space = extendbuf(name_space, namebuf_used+entry_size, &namebuf_allocated); memcpy (name_space + namebuf_used, entry, entry_size); namebuf_used += entry_size; #if defined(HAVE_STRUCT_DIRENT_D_TYPE) && defined(USE_STRUCT_DIRENT_D_TYPE) /* Remember the type. */ if (extra) { info = extendbuf(info, (extra_used+1) * sizeof(struct savedir_dirinfo), &extra_allocated); info[extra_used].type_info = type_to_mode(dp->d_type); ++extra_used; } #endif } } name_space = extendbuf(name_space, namebuf_used+1, &namebuf_allocated); name_space[namebuf_used] = '\0'; save_errno = errno; if (CLOSEDIR (dirp) != 0) save_errno = errno; if (save_errno != 0) { free (name_space); errno = save_errno; return NULL; } #if defined(HAVE_STRUCT_DIRENT_D_TYPE) && defined(USE_STRUCT_DIRENT_D_TYPE) if (extra && info) *extra = info; #endif return name_space; }
struct savedir_dirinfo * xsavedir(const char *dir, int flags) { DIR *dirp; struct dirent *dp; struct savedir_dirinfo *result = NULL; struct new_savedir_direntry_internal *internal; size_t namebuf_allocated = 0u, namebuf_used = 0u; size_t entrybuf_allocated = 0u; int save_errno; dirp = opendir (dir); if (dirp == NULL) return NULL; errno = 0; result = xmalloc(sizeof(*result)); result->buffer = NULL; result->size = 0u; result->entries = NULL; internal = NULL; while ((dp = readdir (dirp)) != NULL) { /* Skip "", ".", and "..". "" is returned by at least one buggy implementation: Solaris 2.4 readdir on NFS file systems. */ char const *entry = dp->d_name; if (entry[entry[0] != '.' ? 0 : entry[1] != '.' ? 1 : 2] != '\0') { /* Remember the name. */ size_t entry_size = strlen (entry) + 1; result->buffer = extendbuf(result->buffer, namebuf_used+entry_size, &namebuf_allocated); memcpy ((result->buffer) + namebuf_used, entry, entry_size); /* Remember the other stuff. */ internal = extendbuf(internal, (1+result->size)*sizeof(*internal), &entrybuf_allocated); internal[result->size].flags = 0; #if defined(HAVE_STRUCT_DIRENT_D_TYPE) && defined(USE_STRUCT_DIRENT_D_TYPE) internal[result->size].type_info = type_to_mode(dp->d_type); if (dp->d_type != DT_UNKNOWN) internal[result->size].flags |= SavedirHaveFileType; #else internal[result->size].type_info = 0; #endif internal[result->size].buffer_offset = namebuf_used; /* Prepare for the next iteration */ ++(result->size); namebuf_used += entry_size; } } result->buffer = extendbuf(result->buffer, namebuf_used+1, &namebuf_allocated); result->buffer[namebuf_used] = '\0'; /* convert the result to its externally-usable form. */ result->entries = convertentries(result, internal); free(internal); internal = NULL; if (flags & SavedirSort) { qsort(result->entries, result->size, sizeof(*result->entries), savedir_cmp); } save_errno = errno; if (CLOSEDIR (dirp) != 0) save_errno = errno; if (save_errno != 0) { free (result->buffer); free (result); errno = save_errno; return NULL; } return result; }
char * savedir (const char *dir, off_t name_size) { DIR *dirp; struct dirent *dp; char *name_space; char *namep; dirp = opendir (dir); if (dirp == NULL) return NULL; /* Be sure name_size is at least `1' so there's room for the final NUL byte. */ if (name_size <= 0) name_size = 1; name_space = (char *) malloc (name_size); if (name_space == NULL) { closedir (dirp); return NULL; } namep = name_space; while ((dp = readdir (dirp)) != NULL) { /* Skip "." and ".." (some NFS filesystems' directories lack them). */ if (dp->d_name[0] != '.' || (dp->d_name[1] != '\0' && (dp->d_name[1] != '.' || dp->d_name[2] != '\0'))) { off_t size_needed = (namep - name_space) + NAMLEN (dp) + 2; if (size_needed > name_size) { char *new_name_space; while (size_needed > name_size) name_size += 1024; new_name_space = realloc (name_space, name_size); if (new_name_space == NULL) { closedir (dirp); return NULL; } namep += new_name_space - name_space; name_space = new_name_space; } namep = stpcpy (namep, dp->d_name) + 1; } } *namep = '\0'; if (CLOSEDIR (dirp)) { free (name_space); return NULL; } return name_space; }
void dir_srch(parse_blk *pfil) { struct stat statbuf; int stat_res; lv_val *dir1, *dir2, *tmp; mstr tn; short p2_len; char filb[MAX_FBUFF + 1], patb[SIZEOF(ptstr)], *c, *lastd, *top, *p2, *c1, ch; mval pat_mval, sub, compare; boolean_t wildname, seen_wd; struct dirent *dent; DIR *dp; plength *plen; int closedir_res; DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; op_kill(TREF(zsearch_dir1)); op_kill(TREF(zsearch_dir2)); if (!pfil->b_name) return; /* nothing to search for */ ESTABLISH(dir_ch); pat_mval.mvtype = MV_STR; pat_mval.str.addr = patb; /* patb should be SIZEOF(ptstr.buff) but instead is SIZEOF(ptstr) since the C compiler * complains about the former and the latter is just 4 bytes more */ pat_mval.str.len = 0; sub.mvtype = MV_STR; sub.str.len = 0; compare.mvtype = MV_STR; compare.str.len = 0; wildname = (pfil->fnb & F_WILD_NAME) != 0; dir1 = TREF(zsearch_dir1); dir2 = TREF(zsearch_dir2); if (pfil->fnb & F_WILD_DIR) { seen_wd = FALSE; for (c = pfil->l_dir, lastd = c, top = c + pfil->b_dir; c < top;) { ch = *c++; if (ch == '/') /* note the start of each directory segment */ { if (seen_wd) break; lastd = c; } if (ch == '?' || ch == '*') seen_wd = TRUE; } assert(c <= top); sub.str.addr = pfil->l_dir; sub.str.len = INTCAST(lastd - sub.str.addr); tmp = op_putindx(VARLSTCNT(2) dir1, &sub); tmp->v.mvtype = MV_STR; tmp->v.str.len = 0; for (;;) { tn.addr = lastd; /* wildcard segment */ tn.len = INTCAST(c - lastd - 1); lastd = c; genpat(&tn, &pat_mval); seen_wd = FALSE; p2 = c - 1; for (; c < top;) { ch = *c++; if (ch == '/') /* note the start of each directory segment */ { if (seen_wd) break; lastd = c; } if (ch == '?' || ch == '*') seen_wd = TRUE; } p2_len = lastd - p2; /* length of non-wild segment after wild section */ for (;;) { pop_top(dir1, &sub); /* get next item off the top */ if (!sub.str.len) break; memcpy(filb, sub.str.addr, sub.str.len); filb[sub.str.len] = 0; sub.str.addr = filb; dp = OPENDIR(filb); if (!dp) continue; while (READDIR(dp, dent)) { compare.str.addr = &dent->d_name[0]; compare.str.len = STRLEN(&dent->d_name[0]); UNICODE_ONLY( if (gtm_utf8_mode) compare.mvtype &= ~MV_UTF_LEN; /* to force "char_len" to be recomputed * in do_pattern */ ) assert(compare.str.len); if (('.' == dent->d_name[0]) && ((1 == compare.str.len) || ((2 == compare.str.len) && ('.' == dent->d_name[1])))) continue; /* don't want to read . and .. */ if (compare.str.len + sub.str.len + p2_len > MAX_FBUFF) continue; if (do_pattern(&compare, &pat_mval)) { /* got a hit */ ENSURE_STP_FREE_SPACE(compare.str.len + sub.str.len + p2_len + 1); /* concatenate directory and name */ c1 = (char *)stringpool.free; tn = sub.str; s2pool(&tn); tn = compare.str; s2pool(&tn); tn.addr = p2; tn.len = p2_len; s2pool(&tn); *stringpool.free++ = 0; compare.str.addr = c1; compare.str.len += sub.str.len + p2_len; STAT_FILE(compare.str.addr, &statbuf, stat_res); if (-1 == stat_res) continue; if (!(statbuf.st_mode & S_IFDIR)) continue; /* put in results tree */ tmp = op_putindx(VARLSTCNT(2) dir2, &compare); tmp->v.mvtype = MV_STR; tmp->v.str.len = 0; } } CLOSEDIR(dp, closedir_res); } tmp = dir1; dir1 = dir2; dir2 = tmp; if (c >= top) break; }