Back to index

tetex-bin  3.0
dir.c
Go to the documentation of this file.
00001 /* dir.c: directory operations.
00002 
00003 Copyright (C) 1992, 93, 94, 95, 2000 Free Software Foundation, Inc.
00004 
00005 This library is free software; you can redistribute it and/or
00006 modify it under the terms of the GNU Library General Public
00007 License as published by the Free Software Foundation; either
00008 version 2 of the License, or (at your option) any later version.
00009 
00010 This library is distributed in the hope that it will be useful,
00011 but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 Library General Public License for more details.
00014 
00015 You should have received a copy of the GNU Library General Public
00016 License along with this library; if not, write to the Free Software
00017 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
00018 
00019 #include <kpathsea/config.h>
00020 
00021 #include <kpathsea/c-dir.h>
00022 #include <kpathsea/c-stat.h>
00023 #include <kpathsea/hash.h>
00024 #include <kpathsea/pathsearch.h>
00025 
00026 /* Return true if FN is a directory or a symlink to a directory,
00027    false if not. */
00028 
00029 boolean
00030 dir_p P1C(const_string, fn)
00031 {
00032   /* FIXME : using the stat() replacement in gnuw32, 
00033         we could avoid this win32 specific code. However,
00034         I wonder if it would be as fast as this one is ?
00035   */
00036 #ifdef WIN32
00037   int fa;
00038 
00039   kpse_normalize_path((string)fn);
00040   fa = GetFileAttributes(fn);
00041 
00042   if (KPSE_DEBUG_P(KPSE_DEBUG_STAT)) {
00043     if (fa == 0xFFFFFFFF) {
00044       fprintf(stderr, "failed to get file attributes for %s (%d)\n",
00045              fn, GetLastError());
00046     } else {
00047       fprintf(stderr, "path %s %s a directory\n",
00048              fn , (fa & FILE_ATTRIBUTE_DIRECTORY) ? 
00049              "is"  : "is not");
00050     }
00051   }
00052   return (fa != 0xFFFFFFFF && (fa & FILE_ATTRIBUTE_DIRECTORY));
00053 #else
00054   struct stat stats;
00055   return stat (fn, &stats) == 0 && S_ISDIR (stats.st_mode);
00056 #endif
00057 }
00058 
00059 /*
00060   Return -1 if FN isn't a directory, else its number of links.
00061   Duplicate the call to stat; no need to incur overhead of a function
00062   call for that little bit of cleanliness.
00063    
00064   The process is a bit different under Win32 : the first call
00065   memoizes the nlinks value, the following ones retrieve it.
00066 */
00067 int
00068 dir_links P2C(const_string, fn, long, nlinks)
00069 {
00070   static hash_table_type link_table;
00071   string *hash_ret;
00072   
00073   if (link_table.size == 0)
00074     link_table = hash_create (457);
00075 
00076 #ifdef KPSE_DEBUG
00077   /* This is annoying, but since we're storing integers as pointers, we
00078      can't print them as strings.  */
00079   if (KPSE_DEBUG_P (KPSE_DEBUG_HASH))
00080     kpse_debug_hash_lookup_int = true;
00081 #endif
00082 
00083   hash_ret = hash_lookup (link_table, fn);
00084   
00085 #ifdef KPSE_DEBUG
00086   if (KPSE_DEBUG_P (KPSE_DEBUG_HASH))
00087     kpse_debug_hash_lookup_int = false;
00088 #endif
00089 
00090   /* Have to cast the int we need to/from the const_string that the hash
00091      table stores for values. Let's hope an int fits in a pointer.  */
00092   if (hash_ret) {
00093 #ifdef WIN32
00094       memcpy(&nlinks, hash_ret, sizeof(nlinks));
00095 #else
00096       nlinks = (long) *hash_ret;
00097 #endif
00098   } else { 
00099 #ifdef WIN32
00100       /* Insert it only if we have some informations about it. */
00101       if (nlinks) {
00102         char str_nlinks[sizeof(nlinks)+1];
00103         memcpy(str_nlinks, (char *)&nlinks, sizeof(nlinks));
00104         str_nlinks[sizeof(nlinks)] = '\0';
00105         /* It's up to us to copy the value.  */
00106         hash_insert(&link_table, xstrdup(fn), (const_string)str_nlinks);
00107       }
00108 #else
00109       struct stat stats;
00110       if (stat (fn, &stats) == 0 && S_ISDIR (stats.st_mode))
00111         nlinks = stats.st_nlink;
00112       else
00113         nlinks = -1;
00114       /* It's up to us to copy the value.  */
00115       hash_insert(&link_table, xstrdup(fn), (const_string)nlinks);
00116 #endif
00117 
00118 #ifdef KPSE_DEBUG
00119       if (KPSE_DEBUG_P (KPSE_DEBUG_STAT))
00120         DEBUGF2 ("dir_links(%s) => %ld\n", fn, nlinks);
00121 #endif
00122   }
00123 
00124   /* In any case, return nlinks 
00125      (either 0, the value inserted or the value retrieved. */
00126   return nlinks;
00127 }