version 1.5, 1996/09/02 16:04:09 |
version 1.6, 1996/11/30 21:08:53 |
|
|
/* $OpenBSD$ */ |
/* $OpenBSD$ */ |
/* $NetBSD: dir.c,v 1.11 1996/08/13 16:42:02 christos Exp $ */ |
/* $NetBSD: dir.c,v 1.12 1996/11/06 17:59:04 christos Exp $ */ |
|
|
/* |
/* |
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California. |
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California. |
|
|
|
|
#ifndef lint |
#ifndef lint |
#if 0 |
#if 0 |
static char sccsid[] = "@(#)dir.c 5.6 (Berkeley) 12/28/90"; |
static char sccsid[] = "@(#)dir.c 8.2 (Berkeley) 1/2/94"; |
#else |
#else |
static char rcsid[] = "$OpenBSD$"; |
static char rcsid[] = "$OpenBSD$"; |
#endif |
#endif |
|
|
dirSearchPath = Lst_Init (FALSE); |
dirSearchPath = Lst_Init (FALSE); |
openDirectories = Lst_Init (FALSE); |
openDirectories = Lst_Init (FALSE); |
Hash_InitTable(&mtimes, 0); |
Hash_InitTable(&mtimes, 0); |
|
|
/* |
/* |
* Since the Path structure is placed on both openDirectories and |
* Since the Path structure is placed on both openDirectories and |
* the path we give Dir_AddDir (which in this case is openDirectories), |
* the path we give Dir_AddDir (which in this case is openDirectories), |
|
|
char *name; /* name to check */ |
char *name; /* name to check */ |
{ |
{ |
register char *cp; |
register char *cp; |
|
|
for (cp = name; *cp; cp++) { |
for (cp = name; *cp; cp++) { |
switch(*cp) { |
switch(*cp) { |
case '{': |
case '{': |
|
|
Path *p; /* Directory to search */ |
Path *p; /* Directory to search */ |
Lst expansions; /* Place to store the results */ |
Lst expansions; /* Place to store the results */ |
{ |
{ |
Hash_Search search; /* Index into the directory's table */ |
Hash_Search search; /* Index into the directory's table */ |
Hash_Entry *entry; /* Current entry in the table */ |
Hash_Entry *entry; /* Current entry in the table */ |
Boolean isDot; /* TRUE if the directory being searched is . */ |
Boolean isDot; /* TRUE if the directory being searched is . */ |
|
|
isDot = (*p->name == '.' && p->name[1] == '\0'); |
isDot = (*p->name == '.' && p->name[1] == '\0'); |
|
|
for (entry = Hash_EnumFirst(&p->files, &search); |
for (entry = Hash_EnumFirst(&p->files, &search); |
entry != (Hash_Entry *)NULL; |
entry != (Hash_Entry *)NULL; |
entry = Hash_EnumNext(&search)) |
entry = Hash_EnumNext(&search)) |
|
|
if (DEBUG(DIR)) { |
if (DEBUG(DIR)) { |
printf("expanding \"%s\"...", word); |
printf("expanding \"%s\"...", word); |
} |
} |
|
|
cp = strchr(word, '{'); |
cp = strchr(word, '{'); |
if (cp) { |
if (cp) { |
DirExpandCurly(word, cp, path, expansions); |
DirExpandCurly(word, cp, path, expansions); |
|
|
* First the files in dot |
* First the files in dot |
*/ |
*/ |
DirMatchFiles(word, dot, expansions); |
DirMatchFiles(word, dot, expansions); |
|
|
/* |
/* |
* Then the files in every other directory on the path. |
* Then the files in every other directory on the path. |
*/ |
*/ |
|
|
Boolean hasSlash; /* true if 'name' contains a / */ |
Boolean hasSlash; /* true if 'name' contains a / */ |
struct stat stb; /* Buffer for stat, if necessary */ |
struct stat stb; /* Buffer for stat, if necessary */ |
Hash_Entry *entry; /* Entry for mtimes table */ |
Hash_Entry *entry; /* Entry for mtimes table */ |
|
|
/* |
/* |
* Find the final component of the name and note whether it has a |
* Find the final component of the name and note whether it has a |
* slash in it (the name, I mean) |
* slash in it (the name, I mean) |
|
|
hasSlash = FALSE; |
hasSlash = FALSE; |
cp = name; |
cp = name; |
} |
} |
|
|
if (DEBUG(DIR)) { |
if (DEBUG(DIR)) { |
printf("Searching for %s...", name); |
printf("Searching for %s...", name); |
} |
} |
|
|
dot->hits += 1; |
dot->hits += 1; |
return (estrdup (name)); |
return (estrdup (name)); |
} |
} |
|
|
if (Lst_Open (path) == FAILURE) { |
if (Lst_Open (path) == FAILURE) { |
if (DEBUG(DIR)) { |
if (DEBUG(DIR)) { |
printf("couldn't open path, file not found\n"); |
printf("couldn't open path, file not found\n"); |
|
|
misses += 1; |
misses += 1; |
return ((char *) NULL); |
return ((char *) NULL); |
} |
} |
|
|
/* |
/* |
* We look through all the directories on the path seeking one which |
* We look through all the directories on the path seeking one which |
* contains the final component of the given name and whose final |
* contains the final component of the given name and whose final |
|
|
} |
} |
} |
} |
} |
} |
|
|
/* |
/* |
* We didn't find the file on any existing members of the directory. |
* We didn't find the file on any existing members of the directory. |
* If the name doesn't contain a slash, that means it doesn't exist. |
* If the name doesn't contain a slash, that means it doesn't exist. |
|
|
misses += 1; |
misses += 1; |
return ((char *) NULL); |
return ((char *) NULL); |
} |
} |
|
|
if (*name != '/') { |
if (*name != '/') { |
Boolean checkedDot = FALSE; |
Boolean checkedDot = FALSE; |
|
|
if (DEBUG(DIR)) { |
if (DEBUG(DIR)) { |
printf("failed. Trying subdirectories..."); |
printf("failed. Trying subdirectories..."); |
} |
} |
|
|
if (DEBUG(DIR)) { |
if (DEBUG(DIR)) { |
printf("checking %s...", file); |
printf("checking %s...", file); |
} |
} |
|
|
|
|
if (stat (file, &stb) == 0) { |
if (stat (file, &stb) == 0) { |
if (DEBUG(DIR)) { |
if (DEBUG(DIR)) { |
printf("got it.\n"); |
printf("got it.\n"); |
} |
} |
|
|
Lst_Close (path); |
Lst_Close (path); |
|
|
/* |
/* |
* We've found another directory to search. We know there's |
* We've found another directory to search. We know there's |
* a slash in 'file' because we put one there. We nuke it after |
* a slash in 'file' because we put one there. We nuke it after |
|
|
*cp = '\0'; |
*cp = '\0'; |
Dir_AddDir (path, file); |
Dir_AddDir (path, file); |
*cp = '/'; |
*cp = '/'; |
|
|
/* |
/* |
* Save the modification time so if it's needed, we don't have |
* Save the modification time so if it's needed, we don't have |
* to fetch it again. |
* to fetch it again. |
|
|
free (file); |
free (file); |
} |
} |
} |
} |
|
|
if (DEBUG(DIR)) { |
if (DEBUG(DIR)) { |
printf("failed. "); |
printf("failed. "); |
} |
} |
|
|
return(NULL); |
return(NULL); |
} |
} |
} |
} |
|
|
/* |
/* |
* Didn't find it that way, either. Sigh. Phase 3. Add its directory |
* Didn't find it that way, either. Sigh. Phase 3. Add its directory |
* onto the search path in any case, just in case, then look for the |
* onto the search path in any case, just in case, then look for the |
|
|
cp[-1] = '\0'; |
cp[-1] = '\0'; |
Dir_AddDir (path, name); |
Dir_AddDir (path, name); |
cp[-1] = '/'; |
cp[-1] = '/'; |
|
|
bigmisses += 1; |
bigmisses += 1; |
ln = Lst_Last (path); |
ln = Lst_Last (path); |
if (ln == NILLNODE) { |
if (ln == NILLNODE) { |
|
|
} else { |
} else { |
p = (Path *) Lst_Datum (ln); |
p = (Path *) Lst_Datum (ln); |
} |
} |
|
|
if (Hash_FindEntry (&p->files, cp) != (Hash_Entry *)NULL) { |
if (Hash_FindEntry (&p->files, cp) != (Hash_Entry *)NULL) { |
return (estrdup (name)); |
return (estrdup (name)); |
} else { |
} else { |
|
|
if (DEBUG(DIR)) { |
if (DEBUG(DIR)) { |
printf("Looking for \"%s\"...", name); |
printf("Looking for \"%s\"...", name); |
} |
} |
|
|
bigmisses += 1; |
bigmisses += 1; |
entry = Hash_FindEntry(&mtimes, name); |
entry = Hash_FindEntry(&mtimes, name); |
if (entry != (Hash_Entry *)NULL) { |
if (entry != (Hash_Entry *)NULL) { |
|
|
* Dir_MTime -- |
* Dir_MTime -- |
* Find the modification time of the file described by gn along the |
* Find the modification time of the file described by gn along the |
* search path dirSearchPath. |
* search path dirSearchPath. |
* |
* |
* Results: |
* Results: |
* The modification time or 0 if it doesn't exist |
* The modification time or 0 if it doesn't exist |
* |
* |
|
|
char *fullName; /* the full pathname of name */ |
char *fullName; /* the full pathname of name */ |
struct stat stb; /* buffer for finding the mod time */ |
struct stat stb; /* buffer for finding the mod time */ |
Hash_Entry *entry; |
Hash_Entry *entry; |
|
|
if (gn->type & OP_ARCHV) { |
if (gn->type & OP_ARCHV) { |
return Arch_MTime (gn); |
return Arch_MTime (gn); |
} else if (gn->path == (char *)NULL) { |
} else if (gn->path == (char *)NULL) { |
|
|
} else { |
} else { |
fullName = gn->path; |
fullName = gn->path; |
} |
} |
|
|
if (fullName == (char *)NULL) { |
if (fullName == (char *)NULL) { |
fullName = estrdup(gn->name); |
fullName = estrdup(gn->name); |
} |
} |
|
|
if (fullName && gn->path == (char *)NULL) { |
if (fullName && gn->path == (char *)NULL) { |
gn->path = fullName; |
gn->path = fullName; |
} |
} |
|
|
gn->mtime = stb.st_mtime; |
gn->mtime = stb.st_mtime; |
return (gn->mtime); |
return (gn->mtime); |
} |
} |
|
|
* none |
* none |
* |
* |
* Side Effects: |
* Side Effects: |
* A structure is added to the list and the directory is |
* A structure is added to the list and the directory is |
* read and hashed. |
* read and hashed. |
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
*/ |
*/ |
|
|
register Path *p; /* pointer to new Path structure */ |
register Path *p; /* pointer to new Path structure */ |
DIR *d; /* for reading directory */ |
DIR *d; /* for reading directory */ |
register struct dirent *dp; /* entry in directory */ |
register struct dirent *dp; /* entry in directory */ |
|
|
ln = Lst_Find (openDirectories, (ClientData)name, DirFindName); |
ln = Lst_Find (openDirectories, (ClientData)name, DirFindName); |
if (ln != NILLNODE) { |
if (ln != NILLNODE) { |
p = (Path *)Lst_Datum (ln); |
p = (Path *)Lst_Datum (ln); |
|
|
printf("Caching %s...", name); |
printf("Caching %s...", name); |
fflush(stdout); |
fflush(stdout); |
} |
} |
|
|
if ((d = opendir (name)) != (DIR *) NULL) { |
if ((d = opendir (name)) != (DIR *) NULL) { |
p = (Path *) emalloc (sizeof (Path)); |
p = (Path *) emalloc (sizeof (Path)); |
p->name = estrdup (name); |
p->name = estrdup (name); |
p->hits = 0; |
p->hits = 0; |
p->refCount = 1; |
p->refCount = 1; |
Hash_InitTable (&p->files, -1); |
Hash_InitTable (&p->files, -1); |
|
|
/* |
/* |
* Skip the first two entries -- these will *always* be . and .. |
* Skip the first two entries -- these will *always* be . and .. |
*/ |
*/ |
(void)readdir(d); |
(void)readdir(d); |
(void)readdir(d); |
(void)readdir(d); |
|
|
while ((dp = readdir (d)) != (struct dirent *) NULL) { |
while ((dp = readdir (d)) != (struct dirent *) NULL) { |
#if defined(sun) && defined(d_ino) /* d_ino is a sunos4 #define for d_fileno */ |
#if defined(sun) && defined(d_ino) /* d_ino is a sunos4 #define for d_fileno */ |
/* |
/* |
|
|
char *tstr; /* the current directory preceded by 'flag' */ |
char *tstr; /* the current directory preceded by 'flag' */ |
LstNode ln; /* the node of the current directory */ |
LstNode ln; /* the node of the current directory */ |
Path *p; /* the structure describing the current directory */ |
Path *p; /* the structure describing the current directory */ |
|
|
str = estrdup (""); |
str = estrdup (""); |
|
|
if (Lst_Open (path) == SUCCESS) { |
if (Lst_Open (path) == SUCCESS) { |
while ((ln = Lst_Next (path)) != NILLNODE) { |
while ((ln = Lst_Next (path)) != NILLNODE) { |
p = (Path *) Lst_Datum (ln); |
p = (Path *) Lst_Datum (ln); |
|
|
} |
} |
Lst_Close (path); |
Lst_Close (path); |
} |
} |
|
|
return (str); |
return (str); |
} |
} |
|
|
|
|
Dir_Destroy((ClientData) p); |
Dir_Destroy((ClientData) p); |
} |
} |
} |
} |
|
|
|
|
|
|
/*- |
/*- |
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
* Dir_Concat -- |
* Dir_Concat -- |
|
|
{ |
{ |
LstNode ln; |
LstNode ln; |
Path *p; |
Path *p; |
|
|
printf ("#*** Directory Cache:\n"); |
printf ("#*** Directory Cache:\n"); |
printf ("# Stats: %d hits %d misses %d near misses %d losers (%d%%)\n", |
printf ("# Stats: %d hits %d misses %d near misses %d losers (%d%%)\n", |
hits, misses, nearmisses, bigmisses, |
hits, misses, nearmisses, bigmisses, |
|
|
static int DirPrintDir (p, dummy) |
static int DirPrintDir (p, dummy) |
ClientData p; |
ClientData p; |
ClientData dummy; |
ClientData dummy; |
{ |
{ |
printf ("%s ", ((Path *) p)->name); |
printf ("%s ", ((Path *) p)->name); |
return (dummy ? 0 : 0); |
return (dummy ? 0 : 0); |
} |
} |