⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dir.c

📁 DSP网络驱动开发_TMS3206
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Directory hashing for GNU Make.Copyright (C) 1988,89,91,92,93,94,95,96,97 Free Software Foundation, Inc.This file is part of GNU Make.GNU Make is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU Make is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU Make; see the file COPYING.  If not, write tothe Free Software Foundation, Inc., 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA.  */#include "make.h"#ifdef	HAVE_DIRENT_H# include <dirent.h># define NAMLEN(dirent) strlen((dirent)->d_name)#else# define dirent direct# define NAMLEN(dirent) (dirent)->d_namlen# ifdef HAVE_SYS_NDIR_H#  include <sys/ndir.h># endif# ifdef HAVE_SYS_DIR_H#  include <sys/dir.h># endif# ifdef HAVE_NDIR_H#  include <ndir.h># endif# ifdef HAVE_VMSDIR_H#  include "vmsdir.h"# endif /* HAVE_VMSDIR_H */#endif/* In GNU systems, <dirent.h> defines this macro for us.  */#ifdef _D_NAMLEN#undef NAMLEN#define NAMLEN(d) _D_NAMLEN(d)#endif#if (defined (POSIX) || defined (WINDOWS32)) && !defined (__GNU_LIBRARY__)/* Posix does not require that the d_ino field be present, and some   systems do not provide it. */#define REAL_DIR_ENTRY(dp) 1#define FAKE_DIR_ENTRY(dp)#else#define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)#define FAKE_DIR_ENTRY(dp) (dp->d_ino = 1)#endif /* POSIX */#ifdef __MSDOS__#include <ctype.h>#include <fcntl.h>/* If it's MSDOS that doesn't have _USE_LFN, disable LFN support.  */#ifndef _USE_LFN#define _USE_LFN 0#endifstatic char *dosify (filename)     char *filename;{  static char dos_filename[14];  char *df;  int i;  if (filename == 0 || _USE_LFN)    return filename;  /* FIXME: what about filenames which violate     8+3 constraints, like "config.h.in", or ".emacs"?  */  if (strpbrk (filename, "\"*+,;<=>?[\\]|") != 0)    return filename;  df = dos_filename;  /* First, transform the name part.  */  for (i = 0; *filename != '\0' && i < 8 && *filename != '.'; ++i)    *df++ = tolower (*filename++);  /* Now skip to the next dot.  */  while (*filename != '\0' && *filename != '.')    ++filename;  if (*filename != '\0')    {      *df++ = *filename++;      for (i = 0; *filename != '\0' && i < 3 && *filename != '.'; ++i)	*df++ = tolower (*filename++);    }  /* Look for more dots.  */  while (*filename != '\0' && *filename != '.')    ++filename;  if (*filename == '.')    return filename;  *df = 0;  return dos_filename;}#endif /* __MSDOS__ */#ifdef WINDOWS32#include "pathstuff.h"#endif#ifdef _AMIGA#include <ctype.h>#endif#ifdef HAVE_CASE_INSENSITIVE_FSstatic char *downcase (filename)     char *filename;{#ifdef _AMIGA  static char new_filename[136];#else  static char new_filename[PATH_MAX];#endif  char *df;  int i;  if (filename == 0)    return 0;  df = new_filename;  /* First, transform the name part.  */  for (i = 0; *filename != '\0'; ++i)  {    *df++ = tolower (*filename);    ++filename;  }  *df = 0;  return new_filename;}#endif /* HAVE_CASE_INSENSITIVE_FS */#ifdef VMSstatic intvms_hash (name)    char *name;{  int h = 0;  int g;  while (*name)    {      h = (h << 4) + *name++;      g = h & 0xf0000000;      if (g)	{	  h = h ^ (g >> 24);	  h = h ^ g;	}    }  return h;}/* fake stat entry for a directory */static intvmsstat_dir (name, st)    char *name;    struct stat *st;{  char *s;  int h;  DIR *dir;  dir = opendir (name);  if (dir == 0)    return -1;  closedir (dir);  s = strchr (name, ':');	/* find device */  if (s)    {      *s++ = 0;      st->st_dev = (char *)vms_hash (name);      h = vms_hash (s);      *(s-1) = ':';    }  else    {      st->st_dev = 0;      s = name;      h = vms_hash (s);    }  st->st_ino[0] = h & 0xff;  st->st_ino[1] = h & 0xff00;  st->st_ino[2] = h >> 16;  return 0;}#endif /* VMS *//* Hash table of directories.  */#ifndef	DIRECTORY_BUCKETS#define DIRECTORY_BUCKETS 199#endifstruct directory_contents  {    struct directory_contents *next;    dev_t dev;			/* Device and inode numbers of this dir.  */#ifdef WINDOWS32    /*     * Inode means nothing on WINDOWS32. Even file key information is     * unreliable because it is random per file open and undefined     * for remote filesystems. The most unique attribute I can     * come up with is the fully qualified name of the directory. Beware     * though, this is also unreliable. I'm open to suggestion on a better     * way to emulate inode.     */    char *path_key;    int   mtime;        /* controls check for stale directory cache */    int   fs_flags;     /* FS_FAT, FS_NTFS, ... */#define FS_FAT      0x1#define FS_NTFS     0x2#define FS_UNKNOWN  0x4#else#ifdef VMS    ino_t ino[3];#else    ino_t ino;#endif#endif /* WINDOWS32 */    struct dirfile **files;	/* Files in this directory.  */    DIR *dirstream;		/* Stream reading this directory.  */  };/* Table of directory contents hashed by device and inode number.  */static struct directory_contents *directories_contents[DIRECTORY_BUCKETS];struct directory  {    struct directory *next;    char *name;			/* Name of the directory.  */    /* The directory's contents.  This data may be shared by several       entries in the hash table, which refer to the same directory       (identified uniquely by `dev' and `ino') under different names.  */    struct directory_contents *contents;  };/* Table of directories hashed by name.  */static struct directory *directories[DIRECTORY_BUCKETS];/* Never have more than this many directories open at once.  */#define MAX_OPEN_DIRECTORIES 10static unsigned int open_directories = 0;/* Hash table of files in each directory.  */struct dirfile  {    struct dirfile *next;    char *name;			/* Name of the file.  */    char impossible;		/* This file is impossible.  */  };#ifndef	DIRFILE_BUCKETS#define DIRFILE_BUCKETS 107#endifstatic int dir_contents_file_exists_p PARAMS ((struct directory_contents *dir, char *filename));static struct directory *find_directory PARAMS ((char *name));/* Find the directory named NAME and return its `struct directory'.  */static struct directory *find_directory (name)     register char *name;{  register unsigned int hash = 0;  register char *p;  register struct directory *dir;#ifdef WINDOWS32  char* w32_path;  char  fs_label[BUFSIZ];  char  fs_type[BUFSIZ];  long  fs_serno;  long  fs_flags;  long  fs_len;#endif#ifdef VMS  if ((*name == '.') && (*(name+1) == 0))    name = "[]";  else    name = vmsify (name,1);#endif  for (p = name; *p != '\0'; ++p)    HASHI (hash, *p);  hash %= DIRECTORY_BUCKETS;  for (dir = directories[hash]; dir != 0; dir = dir->next)    if (strieq (dir->name, name))      break;  if (dir == 0)    {      struct stat st;      /* The directory was not found.  Create a new entry for it.  */      dir = (struct directory *) xmalloc (sizeof (struct directory));      dir->next = directories[hash];      directories[hash] = dir;      dir->name = savestring (name, p - name);      /* The directory is not in the name hash table.	 Find its device and inode numbers, and look it up by them.  */#ifdef VMS      if (vmsstat_dir (name, &st) < 0)#else#ifdef WINDOWS32      /* Remove any trailing '\'.  Windows32 stat fails even on valid         directories if they end in '\'. */      if (p[-1] == '\\')        p[-1] = '\0';#endif      if (stat (name, &st) < 0)#endif	{	/* Couldn't stat the directory.  Mark this by	   setting the `contents' member to a nil pointer.  */	  dir->contents = 0;	}      else	{	  /* Search the contents hash table; device and inode are the key.  */	  struct directory_contents *dc;#ifdef WINDOWS32          w32_path = w32ify(name, 1);          hash = ((unsigned int) st.st_dev << 16) | (unsigned int) st.st_ctime;#else#ifdef VMS	hash = ((unsigned int) st.st_dev << 16)		| ((unsigned int) st.st_ino[0]		+ (unsigned int) st.st_ino[1]		+ (unsigned int) st.st_ino[2]);#else	  hash = ((unsigned int) st.st_dev << 16) | (unsigned int) st.st_ino;#endif#endif	  hash %= DIRECTORY_BUCKETS;	  for (dc = directories_contents[hash]; dc != 0; dc = dc->next)#ifdef WINDOWS32            if (strieq(dc->path_key, w32_path))#else	    if (dc->dev == st.st_dev#ifdef VMS		&& dc->ino[0] == st.st_ino[0]		&& dc->ino[1] == st.st_ino[1]		&& dc->ino[2] == st.st_ino[2])#else		 && dc->ino == st.st_ino)#endif#endif /* WINDOWS32 */	      break;	  if (dc == 0)	    {	      /* Nope; this really is a directory we haven't seen before.  */	      dc = (struct directory_contents *)		xmalloc (sizeof (struct directory_contents));	      /* Enter it in the contents hash table.  */	      dc->dev = st.st_dev;#ifdef WINDOWS32              dc->path_key = xstrdup(w32_path);              dc->mtime = st.st_mtime;              /*               * NTFS is the only WINDOWS32 filesystem that bumps mtime               * on a directory when files are added/deleted from               * a directory.               */              w32_path[3] = '\0';              if (GetVolumeInformation(w32_path,                     fs_label, sizeof (fs_label),                     &fs_serno, &fs_len,                     &fs_flags, fs_type, sizeof (fs_type)) == FALSE)                dc->fs_flags = FS_UNKNOWN;              else if (!strcmp(fs_type, "FAT"))                dc->fs_flags = FS_FAT;              else if (!strcmp(fs_type, "NTFS"))                dc->fs_flags = FS_NTFS;              else                dc->fs_flags = FS_UNKNOWN;#else#ifdef VMS	      dc->ino[0] = st.st_ino[0];	      dc->ino[1] = st.st_ino[1];	      dc->ino[2] = st.st_ino[2];#else	      dc->ino = st.st_ino;#endif#endif /* WINDOWS32 */	      dc->next = directories_contents[hash];	      directories_contents[hash] = dc;	      dc->dirstream = opendir (name);	      if (dc->dirstream == 0)		{		/* Couldn't open the directory.  Mark this by		   setting the `files' member to a nil pointer.  */		  dc->files = 0;		}	      else		{		  /* Allocate an array of buckets for files and zero it.  */		  dc->files = (struct dirfile **)		    xmalloc (sizeof (struct dirfile *) * DIRFILE_BUCKETS);		  bzero ((char *) dc->files,			 sizeof (struct dirfile *) * DIRFILE_BUCKETS);		  /* Keep track of how many directories are open.  */		  ++open_directories;		  if (open_directories == MAX_OPEN_DIRECTORIES)		    /* We have too many directories open already.		       Read the entire directory and then close it.  */		    (void) dir_contents_file_exists_p (dc, (char *) 0);		}	    }	  /* Point the name-hashed entry for DIR at its contents data.  */	  dir->contents = dc;	}    }  return dir;}/* Return 1 if the name FILENAME is entered in DIR's hash table.   FILENAME must contain no slashes.  */static intdir_contents_file_exists_p (dir, filename)     register struct directory_contents *dir;     register char *filename;{  register unsigned int hash;  register char *p;  register struct dirfile *df;  register struct dirent *d;#ifdef WINDOWS32  struct stat st;  int rehash = 0;#endif  if (dir == 0 || dir->files == 0)    {    /* The directory could not be stat'd or opened.  */      return 0;    }#ifdef __MSDOS__  filename = dosify (filename);#endif#ifdef HAVE_CASE_INSENSITIVE_FS  filename = downcase (filename);#endif#ifdef VMS  filename = vmsify (filename,0);#endif  hash = 0;  if (filename != 0)    {      if (*filename == '\0')	{	/* Checking if the directory exists.  */	  return 1;	}      for (p = filename; *p != '\0'; ++p)	HASH (hash, *p);      hash %= DIRFILE_BUCKETS;      /* Search the list of hashed files.  */      for (df = dir->files[hash]; df != 0; df = df->next)	{	  if (strieq (df->name, filename))	    {	      return !df->impossible;	    }	}    }  /* The file was not found in the hashed list.     Try to read the directory further.  */  if (dir->dirstream == 0)    {#ifdef WINDOWS32      /*       * Check to see if directory has changed since last read. FAT       * filesystems force a rehash always as mtime does not change       * on directories (ugh!).       */      if (dir->path_key &&          (dir->fs_flags & FS_FAT ||           (stat(dir->path_key, &st) == 0 &&            st.st_mtime > dir->mtime))) {        /* reset date stamp to show most recent re-process */        dir->mtime = st.st_mtime;        /* make sure directory can still be opened */        dir->dirstream = opendir(dir->path_key);        if (dir->dirstream)          rehash = 1;        else          return 0; /* couldn't re-read - fail */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -