📄 dir.c
字号:
} else#endif /* The directory has been all read in. */ return 0; } while ((d = readdir (dir->dirstream)) != 0) { /* Enter the file in the hash table. */ register unsigned int newhash = 0; unsigned int len; register unsigned int i; if (!REAL_DIR_ENTRY (d)) continue; len = NAMLEN (d); for (i = 0; i < len; ++i) HASHI (newhash, d->d_name[i]); newhash %= DIRFILE_BUCKETS;#ifdef WINDOWS32 /* * If re-reading a directory, check that this file isn't already * in the cache. */ if (rehash) { for (df = dir->files[newhash]; df != 0; df = df->next) if (streq(df->name, d->d_name)) break; } else df = 0; /* * If re-reading a directory, don't cache files that have * already been discovered. */ if (!df) {#endif df = (struct dirfile *) xmalloc (sizeof (struct dirfile)); df->next = dir->files[newhash]; dir->files[newhash] = df; df->name = savestring (d->d_name, len); df->impossible = 0;#ifdef WINDOWS32 }#endif /* Check if the name matches the one we're searching for. */ if (filename != 0 && newhash == hash && strieq (d->d_name, filename)) { return 1; } } /* If the directory has been completely read in, close the stream and reset the pointer to nil. */ if (d == 0) { --open_directories; closedir (dir->dirstream); dir->dirstream = 0; } return 0;}/* Return 1 if the name FILENAME in directory DIRNAME is entered in the dir hash table. FILENAME must contain no slashes. */intdir_file_exists_p (dirname, filename) register char *dirname; register char *filename;{ return dir_contents_file_exists_p (find_directory (dirname)->contents, filename);}/* Return 1 if the file named NAME exists. */intfile_exists_p (name) register char *name;{ char *dirend; char *dirname; char *slash;#ifndef NO_ARCHIVES if (ar_name (name)) return ar_member_date (name) != (time_t) -1;#endif#ifdef VMS dirend = rindex (name, ']'); dirend++; if (dirend == (char *)1) return dir_file_exists_p ("[]", name);#else /* !VMS */ dirend = rindex (name, '/');#if defined (WINDOWS32) || defined (__MSDOS__) /* Forward and backslashes might be mixed. We need the rightmost one. */ { char *bslash = rindex(name, '\\'); if (!dirend || bslash > dirend) dirend = bslash; /* The case of "d:file". */ if (!dirend && name[0] && name[1] == ':') dirend = name + 1; }#endif /* WINDOWS32 || __MSDOS__ */ if (dirend == 0)#ifndef _AMIGA return dir_file_exists_p (".", name);#else /* !VMS && !AMIGA */ return dir_file_exists_p ("", name);#endif /* AMIGA */#endif /* VMS */ slash = dirend; if (dirend == name) dirname = "/"; else {#if defined (WINDOWS32) || defined (__MSDOS__) /* d:/ and d: are *very* different... */ if (dirend < name + 3 && name[1] == ':' && (*dirend == '/' || *dirend == '\\' || *dirend == ':')) dirend++;#endif dirname = (char *) alloca (dirend - name + 1); bcopy (name, dirname, dirend - name); dirname[dirend - name] = '\0'; } return dir_file_exists_p (dirname, slash + 1);}/* Mark FILENAME as `impossible' for `file_impossible_p'. This means an attempt has been made to search for FILENAME as an intermediate file, and it has failed. */voidfile_impossible (filename) register char *filename;{ char *dirend; register char *p = filename; register unsigned int hash; register struct directory *dir; register struct dirfile *new;#ifdef VMS dirend = rindex (p, ']'); dirend++; if (dirend == (char *)1) dir = find_directory ("[]");#else dirend = rindex (p, '/');#if defined (WINDOWS32) || defined (__MSDOS__) /* Forward and backslashes might be mixed. We need the rightmost one. */ { char *bslash = rindex(p, '\\'); if (!dirend || bslash > dirend) dirend = bslash; /* The case of "d:file". */ if (!dirend && p[0] && p[1] == ':') dirend = p + 1; }#endif /* WINDOWS32 or __MSDOS__ */ if (dirend == 0)#ifdef _AMIGA dir = find_directory ("");#else /* !VMS && !AMIGA */ dir = find_directory (".");#endif /* AMIGA */#endif /* VMS */ else { char *dirname; char *slash = dirend; if (dirend == p) dirname = "/"; else {#if defined (WINDOWS32) || defined (__MSDOS__) /* d:/ and d: are *very* different... */ if (dirend < p + 3 && p[1] == ':' && (*dirend == '/' || *dirend == '\\' || *dirend == ':')) dirend++;#endif dirname = (char *) alloca (dirend - p + 1); bcopy (p, dirname, dirend - p); dirname[dirend - p] = '\0'; } dir = find_directory (dirname); filename = p = slash + 1; } for (hash = 0; *p != '\0'; ++p) HASHI (hash, *p); hash %= DIRFILE_BUCKETS; if (dir->contents == 0) { /* The directory could not be stat'd. We allocate a contents structure for it, but leave it out of the contents hash table. */ dir->contents = (struct directory_contents *) xmalloc (sizeof (struct directory_contents));#ifdef WINDOWS32 dir->contents->path_key = NULL; dir->contents->mtime = 0;#else /* WINDOWS32 */#ifdef VMS dir->contents->dev = 0; dir->contents->ino[0] = dir->contents->ino[1] = dir->contents->ino[2] = 0;#else dir->contents->dev = dir->contents->ino = 0;#endif#endif /* WINDOWS32 */ dir->contents->files = 0; dir->contents->dirstream = 0; } if (dir->contents->files == 0) { /* The directory was not opened; we must allocate the hash buckets. */ dir->contents->files = (struct dirfile **) xmalloc (sizeof (struct dirfile) * DIRFILE_BUCKETS); bzero ((char *) dir->contents->files, sizeof (struct dirfile) * DIRFILE_BUCKETS); } /* Make a new entry and put it in the table. */ new = (struct dirfile *) xmalloc (sizeof (struct dirfile)); new->next = dir->contents->files[hash]; dir->contents->files[hash] = new; new->name = xstrdup (filename); new->impossible = 1;}/* Return nonzero if FILENAME has been marked impossible. */intfile_impossible_p (filename) char *filename;{ char *dirend; register char *p = filename; register unsigned int hash; register struct directory_contents *dir; register struct dirfile *next;#ifdef VMS dirend = rindex (filename, ']'); if (dirend == 0) dir = find_directory ("[]")->contents;#else dirend = rindex (filename, '/');#if defined (WINDOWS32) || defined (__MSDOS__) /* Forward and backslashes might be mixed. We need the rightmost one. */ { char *bslash = rindex(filename, '\\'); if (!dirend || bslash > dirend) dirend = bslash; /* The case of "d:file". */ if (!dirend && filename[0] && filename[1] == ':') dirend = filename + 1; }#endif /* WINDOWS32 || __MSDOS__ */ if (dirend == 0)#ifdef _AMIGA dir = find_directory ("")->contents;#else /* !VMS && !AMIGA */ dir = find_directory (".")->contents;#endif /* AMIGA */#endif /* VMS */ else { char *dirname; char *slash = dirend; if (dirend == filename) dirname = "/"; else {#if defined (WINDOWS32) || defined (__MSDOS__) /* d:/ and d: are *very* different... */ if (dirend < filename + 3 && filename[1] == ':' && (*dirend == '/' || *dirend == '\\' || *dirend == ':')) dirend++;#endif dirname = (char *) alloca (dirend - filename + 1); bcopy (p, dirname, dirend - p); dirname[dirend - p] = '\0'; } dir = find_directory (dirname)->contents; p = filename = slash + 1; } if (dir == 0 || dir->files == 0) /* There are no files entered for this directory. */ return 0;#ifdef __MSDOS__ p = filename = dosify (p);#endif#ifdef HAVE_CASE_INSENSITIVE_FS p = filename = downcase (p);#endif#ifdef VMS p = filename = vmsify (p, 1);#endif for (hash = 0; *p != '\0'; ++p) HASH (hash, *p); hash %= DIRFILE_BUCKETS; for (next = dir->files[hash]; next != 0; next = next->next) if (strieq (filename, next->name)) return next->impossible; return 0;}/* Return the already allocated name in the directory hash table that matches DIR. */char *dir_name (dir) char *dir;{ return find_directory (dir)->name;}/* Print the data base of directories. */voidprint_dir_data_base (){ register unsigned int i, dirs, files, impossible; register struct directory *dir; puts (_("\n# Directories\n")); dirs = files = impossible = 0; for (i = 0; i < DIRECTORY_BUCKETS; ++i) for (dir = directories[i]; dir != 0; dir = dir->next) { ++dirs; if (dir->contents == 0) printf (_("# %s: could not be stat'd.\n"), dir->name); else if (dir->contents->files == 0)#ifdef WINDOWS32 printf (_("# %s (key %s, mtime %d): could not be opened.\n"), dir->name, dir->contents->path_key,dir->contents->mtime);#else /* WINDOWS32 */#ifdef VMS printf (_("# %s (device %d, inode [%d,%d,%d]): could not be opened.\n"), dir->name, dir->contents->dev, dir->contents->ino[0], dir->contents->ino[1], dir->contents->ino[2]);#else printf (_("# %s (device %ld, inode %ld): could not be opened.\n"), dir->name, (long int) dir->contents->dev, (long int) dir->contents->ino);#endif#endif /* WINDOWS32 */ else { register unsigned int f = 0, im = 0; register unsigned int j; register struct dirfile *df; for (j = 0; j < DIRFILE_BUCKETS; ++j) for (df = dir->contents->files[j]; df != 0; df = df->next) if (df->impossible) ++im; else ++f;#ifdef WINDOWS32 printf (_("# %s (key %s, mtime %d): "), dir->name, dir->contents->path_key, dir->contents->mtime);#else /* WINDOWS32 */#ifdef VMS printf (_("# %s (device %d, inode [%d,%d,%d]): "), dir->name, dir->contents->dev, dir->contents->ino[0], dir->contents->ino[1], dir->contents->ino[2]);#else printf (_("# %s (device %ld, inode %ld): "), dir->name, (long)dir->contents->dev, (long)dir->contents->ino);#endif#endif /* WINDOWS32 */ if (f == 0) fputs (_("No"), stdout); else printf ("%u", f); fputs (_(" files, "), stdout); if (im == 0) fputs (_("no"), stdout); else printf ("%u", im); fputs (_(" impossibilities"), stdout); if (dir->contents->dirstream == 0) puts ("."); else puts (_(" so far.")); files += f; impossible += im; } } fputs ("\n# ", stdout); if (files == 0) fputs (_("No"), stdout); else printf ("%u", files); fputs (_(" files, "), stdout); if (impossible == 0) fputs (_("no"), stdout); else printf ("%u", impossible); printf (_(" impossibilities in %u directories.\n"), dirs);}/* Hooks for globbing. */#include <glob.h>/* Structure describing state of iterating through a directory hash table. */struct dirstream { struct directory_contents *contents; /* The directory being read. */ unsigned int bucket; /* Current hash bucket. */ struct dirfile *elt; /* Current elt in bucket. */ };/* Forward declarations. */static __ptr_t open_dirstream PARAMS ((const char *));static struct dirent *read_dirstream PARAMS ((__ptr_t));static __ptr_topen_dirstream (directory) const char *directory;{ struct dirstream *new; struct directory *dir = find_directory ((char *)directory); if (dir->contents == 0 || dir->contents->files == 0) /* DIR->contents is nil if the directory could not be stat'd. DIR->contents->files is nil if it could not be opened. */ return 0; /* Read all the contents of the directory now. There is no benefit in being lazy, since glob will want to see every file anyway. */ (void) dir_contents_file_exists_p (dir->contents, (char *) 0); new = (struct dirstream *) xmalloc (sizeof (struct dirstream)); new->contents = dir->contents; new->bucket = 0; new->elt = new->contents->files[0]; return (__ptr_t) new;}static struct dirent *read_dirstream (stream) __ptr_t stream;{ struct dirstream *const ds = (struct dirstream *) stream; register struct dirfile *df; static char *buf; static unsigned int bufsz; while (ds->bucket < DIRFILE_BUCKETS) { while ((df = ds->elt) != 0) { ds->elt = df->next; if (!df->impossible) { /* The glob interface wants a `struct dirent', so mock one up. */ struct dirent *d; unsigned int len = strlen (df->name) + 1; if (sizeof *d - sizeof d->d_name + len > bufsz) { if (buf != 0) free (buf); bufsz *= 2; if (sizeof *d - sizeof d->d_name + len > bufsz) bufsz = sizeof *d - sizeof d->d_name + len; buf = xmalloc (bufsz); } d = (struct dirent *) buf; FAKE_DIR_ENTRY (d);#ifdef _DIRENT_HAVE_D_NAMLEN d->d_namlen = len - 1;#endif memcpy (d->d_name, df->name, len); return d; } } if (++ds->bucket == DIRFILE_BUCKETS) break; ds->elt = ds->contents->files[ds->bucket]; } return 0;}static voidansi_free(p) void *p;{ if (p) free(p);}voiddir_setup_glob (gl) glob_t *gl;{#ifndef VMS extern int stat ();#endif /* Bogus sunos4 compiler complains (!) about & before functions. */ gl->gl_opendir = open_dirstream; gl->gl_readdir = read_dirstream; gl->gl_closedir = ansi_free; gl->gl_stat = stat; /* We don't bother setting gl_lstat, since glob never calls it. The slot is only there for compatibility with 4.4 BSD. */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -