LCOV - code coverage report
Current view: top level - libreoffice/dmake/unix - dcache.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 49 69 71.0 %
Date: 2012-12-17 Functions: 1 1 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             : --
       3             : -- SYNOPSIS
       4             : --      Directory cache management routines.
       5             : --
       6             : -- DESCRIPTION
       7             : --      This is the code that maintains a directory cache for each directory
       8             : --      that dmake visits.  The entire directory is thus only read once and
       9             : --      the need for performing costly 'stat' calls when performing target
      10             : --      inference is much reduced.  The improvement in performance should be
      11             : --      significant for NFS or remote mounted file systems.
      12             : --
      13             : -- AUTHOR
      14             : --      Dennis Vadura, dvadura@dmake.wticorp.com
      15             : --
      16             : -- WWW
      17             : --      http://dmake.wticorp.com/
      18             : --
      19             : -- COPYRIGHT
      20             : --      Copyright (c) 1996,1997 by WTI Corp.  All rights reserved.
      21             : --
      22             : --      This program is NOT free software; you can redistribute it and/or
      23             : --      modify it under the terms of the Software License Agreement Provided
      24             : --      in the file <distribution-root>/readme/license.txt.
      25             : --
      26             : -- LOG
      27             : --      Use cvs log to obtain detailed change logs.
      28             : */
      29             : 
      30             : /* For Borland 5.00 compile, for some reason they seem to insist on pulling
      31             :  * in the winnt.h if __WIN32__ is defined and you include <dirent.h>.  This
      32             :  * is, in my opinion, a BUG! on Borland's part.
      33             :  */
      34             : #if defined(__BORLANDC__) && defined(__WIN32__)
      35             : #undef __WIN32__
      36             : #endif
      37             : 
      38             : #ifdef __APPLE__
      39             : #include <sys/types.h>
      40             : #endif
      41             : #include <dirent.h>
      42             : #include "extern.h"
      43             : #include "sysintf.h"
      44             : 
      45             : 
      46             : typedef struct ent {
      47             :    char    *name;
      48             :    uint32  hkey;
      49             :    time_t  mtime;
      50             :    int     isdir;
      51             :    struct ent *next;
      52             : } Entry, *EntryPtr;
      53             : 
      54             : 
      55             : typedef struct mydir {
      56             :    char         *path;
      57             :    uint32        hkey;
      58             :    EntryPtr      entries;
      59             :    struct mydir *next;
      60             : } DirEntry, *DirEntryPtr;
      61             : 
      62             : static DirEntryPtr dtab[HASH_TABLE_SIZE];
      63             : 
      64             : 
      65             : /* Stat a path using the directory cache.
      66             :  *
      67             :  * We build a cannonical representation of the path using either an absolute
      68             :  * path name if that is what 'path' is or the relative path name constructed
      69             :  * from 'path' and the present value of Pwd.
      70             :  *
      71             :  * The present value of Pwd then gives a directory path that we search for
      72             :  * in our cache using a hash lookup.  If the directory component is located
      73             :  * then we search the basename component of the path and return the result of
      74             :  * the search:  0L if the component is not in the cache and it's time stamp
      75             :  * otherwise.
      76             :  *
      77             :  * If the directory is not in our cache we insert it into the cache by
      78             :  * openning the directory and reading all of the files within.  Once read
      79             :  * then we return the result of the above search.
      80             :  *
      81             :  * Optionally, if force is TRUE, and we did NOT read the directory to provide
      82             :  * the result then stat the file anyway and update the internal cache.
      83             :  */
      84             : 
      85             : PUBLIC time_t
      86       37761 : CacheStat(path, force)
      87             : char        *path;
      88             : int          force;
      89             : {
      90             :    struct stat stbuf;
      91             :    DirEntryPtr dp;
      92             :    EntryPtr    ep;
      93             :    uint32 hkey;
      94             :    uint16 hv;
      95             :    char *fpath;
      96             :    char *spath;
      97             :    char *comp;
      98             :    char *dir;
      99             :    char *udir; /* Hold the unchanged (DcacheRespCase) directory. */
     100       37761 :    int  loaded=FALSE;
     101             : 
     102       37761 :    if (If_root_path(path))
     103        1464 :       spath = path;
     104             :    else
     105       36297 :       spath = Build_path(Pwd,path);
     106             : 
     107       37761 :    fpath = DmStrDup(spath);
     108             : 
     109       37761 :    comp  = Basename(fpath); /* Use before the Filedir() call. */
     110       37761 :    dir   = Filedir(fpath);
     111             : 
     112             :    /* do caching and comparing lower case if told so. */
     113       37761 :    if( !STOBOOL(DcacheRespCase) ) {
     114           0 :       udir = DmStrDup(dir);
     115           0 :       strlwr(comp);
     116           0 :       strlwr(dir);
     117             :    } else
     118       37761 :       udir = dir;
     119             : 
     120       37761 :    hv = Hash(dir,&hkey);
     121             : 
     122       37981 :    for(dp=dtab[hv]; dp; dp=dp->next)
     123       36553 :       if (hkey == dp->hkey && strcmp(dp->path,dir) == 0)
     124       36333 :      break;
     125             : 
     126       37761 :    if (!dp) {
     127             :       /* Not cached yet, doing it now. */
     128             :       DIR *dirp;
     129             :       struct dirent *direntp;
     130             : 
     131        1428 :       if( Verbose & V_DIR_CACHE )
     132           0 :      printf( "%s:  Caching directory [%s]\n", Pname, dir  );
     133             : 
     134             :       /* Load the directory, we have the right hash position already */
     135        1428 :       loaded = TRUE;
     136             : 
     137        1428 :       TALLOC(dp,1,DirEntry);
     138        1428 :       dp->next = dtab[hv];
     139        1428 :       dtab[hv] = dp;
     140        1428 :       dp->path = DmStrDup(dir);
     141        1428 :       dp->hkey = hkey;
     142             : 
     143             :       /* We use the unchanged (not potentially lowercased because of
     144             :        * DcacheRespCase) directory as this would fail on a case sensitive
     145             :        * file system.
     146             :        * Note: Using case insensitive directory caching on case sensitive
     147             :        * file systems is a *BAD* idea. If in doubt use case sensitive
     148             :        * directory caching even on case insensitive file systems as the
     149             :        * worst case in this szenario is that /foo/bar/ and /foo/BAR/ are
     150             :        * cached separately (with the same content) even though they are
     151             :        * the same directory. This would only happen if different targets
     152             :        * using different upper/lower case spellings for the same directory
     153             :        * and is *never* a good idea. */
     154        1428 :       if (Set_dir(udir) == 0) {
     155        1428 :      if((dirp=opendir(".")) != NIL(DIR)) {
     156       64849 :         while((direntp=readdir(dirp)) != NULL) {
     157       61993 :            TALLOC(ep,1,Entry);
     158       61993 :            ep->name = DmStrDup(direntp->d_name); /* basename only */
     159       61993 :            if( !STOBOOL(DcacheRespCase) )
     160           0 :           strlwr(ep->name);
     161             : 
     162       61993 :            Hash(ep->name, &ep->hkey); /* This sets ep->hkey. */
     163             : 
     164       61993 :            ep->next = dp->entries;
     165       61993 :            dp->entries = ep;
     166       61993 :            DMSTAT(direntp->d_name,&stbuf);
     167       61993 :            ep->isdir = (stbuf.st_mode & S_IFDIR);
     168       61993 :            ep->mtime = stbuf.st_mtime;
     169             :         }
     170        1428 :         closedir(dirp);
     171             :      }
     172        1428 :      Set_dir(Pwd);
     173             :       }
     174             :    }
     175             : 
     176       37761 :    Hash(comp, &hkey); /* Calculate hkey. */
     177             : 
     178             :    /* search in dp->entries for comp. */
     179       37761 :    if (dp) {
     180     2714212 :       for(ep=dp->entries; ep; ep=ep->next)
     181     2712493 :      if(hkey == ep->hkey && strcmp(ep->name,comp) == 0)
     182       36042 :         break;
     183             :    }
     184             :    else
     185           0 :       ep = NULL;
     186             : 
     187       37761 :    if( force && !loaded) {
     188         542 :       if (strlen(comp) > NameMax || DMSTAT(spath,&stbuf) != 0) {
     189             :      /* Either file to long or the stat failed. */
     190         542 :      if (strlen(comp) > NameMax)
     191           0 :         Warning( "File [%s] longer than value of NAMEMAX [%d].\n\
     192             :     Assume unix time 0.\n", comp, NameMax );
     193        1084 :      if(ep)
     194           0 :         ep->mtime = 0L;
     195             :       }
     196             :       else {
     197           0 :      if (!ep) {
     198           0 :         TALLOC(ep,1,Entry);
     199           0 :         ep->name = DmStrDup(comp);
     200           0 :         if( !STOBOOL(DcacheRespCase) )
     201           0 :            strlwr(ep->name);
     202           0 :         Hash(ep->name, &ep->hkey);
     203           0 :         ep->next = dp->entries;
     204           0 :         ep->isdir = (stbuf.st_mode & S_IFDIR);
     205           0 :         dp->entries = ep;
     206             :      }
     207             : 
     208           0 :      ep->mtime = stbuf.st_mtime;
     209             :       }
     210             : 
     211         542 :       if( Verbose & V_DIR_CACHE )
     212           0 :      printf("%s:  Updating dir cache entry for [%s], new time is %ld\n",
     213             :             Pname, spath, ep ? ep->mtime : 0L);
     214             :    }
     215             : 
     216       37761 :    if( udir != dir )
     217           0 :       FREE(udir); /* Keep this before the free of fpath. */
     218             : 
     219       37761 :    FREE(fpath);
     220       37761 :    return(!ep ? (time_t)0L : ((STOBOOL(Augmake) && ep->isdir)?0L:ep->mtime));
     221             : }

Generated by: LCOV version 1.10