LTP GCOV extension - code coverage report
Current view: directory - src/libstore - references.cc
Test: app.info
Date: 2006-10-11 Instrumented lines: 81
Code covered: 91.4 % Executed lines: 74

       1                 : #include "references.hh"
       2                 : #include "hash.hh"
       3                 : #include "util.hh"
       4                 : 
       5                 : #include <cerrno>
       6                 : #include <map>
       7                 : 
       8                 : #include <sys/types.h>
       9                 : #include <sys/stat.h>
      10                 : #include <unistd.h>
      11                 : #include <dirent.h>
      12                 : #include <fcntl.h>
      13                 : 
      14                 : 
      15                 : namespace nix {
      16                 : 
      17                 : 
      18                 : static unsigned int refLength = 32; /* characters */
      19                 : 
      20                 : 
      21                 : static void search(size_t len, const unsigned char * s,
      22                 :     StringSet & ids, StringSet & seen)
      23             207 : {
      24             207 :     static bool initialised = false;
      25             207 :     static bool isBase32[256];
      26             207 :     if (!initialised) {
      27              23 :         for (unsigned int i = 0; i < 256; ++i) isBase32[i] = false;
      28             759 :         for (unsigned int i = 0; i < base32Chars.size(); ++i)
      29             736 :             isBase32[(unsigned char) base32Chars[i]] = true;
      30              23 :         initialised = true;
      31                 :     }
      32                 :     
      33             814 :     for (unsigned int i = 0; i + refLength <= len; ) {
      34             825 :         int j;
      35             825 :         bool match = true;
      36           20878 :         for (j = refLength - 1; j >= 0; --j)
      37           20271 :             if (!isBase32[(unsigned char) s[i + j]]) {
      38             218 :                 i += j + 1;
      39             218 :                 match = false;
      40             218 :                 break;
      41                 :             }
      42             825 :         if (!match) continue;
      43             607 :         string ref((const char *) s + i, refLength);
      44             607 :         if (ids.find(ref) != ids.end()) {
      45              32 :             debug(format("found reference to `%1%' at offset `%2%'")
      46                 :                   % ref % i);
      47              32 :             seen.insert(ref);
      48              32 :             ids.erase(ref);
      49                 :         }
      50             607 :         ++i;
      51                 :     }
      52                 : }
      53                 : 
      54                 : 
      55                 : void checkPath(const string & path,
      56                 :     StringSet & ids, StringSet & seen)
      57             163 : {
      58             163 :     checkInterrupt();
      59                 :     
      60             163 :     debug(format("checking `%1%'") % path);
      61                 : 
      62             163 :     struct stat st;
      63             163 :     if (lstat(path.c_str(), &st))
      64               0 :         throw SysError(format("getting attributes of path `%1%'") % path);
      65                 : 
      66             163 :     if (S_ISDIR(st.st_mode)) {
      67              59 :         Strings names = readDirectory(path);
      68             162 :         for (Strings::iterator i = names.begin(); i != names.end(); i++) {
      69             103 :             search(i->size(), (const unsigned char *) i->c_str(), ids, seen);
      70             103 :             checkPath(path + "/" + *i, ids, seen);
      71                 :         }
      72                 :     }
      73                 : 
      74             104 :     else if (S_ISREG(st.st_mode)) {
      75                 :         
      76              67 :         AutoCloseFD fd = open(path.c_str(), O_RDONLY);
      77              67 :         if (fd == -1) throw SysError(format("opening file `%1%'") % path);
      78                 : 
      79              67 :         size_t bufSize = 1024 * 1024;
      80              67 :         assert(refLength <= bufSize);
      81              67 :         unsigned char * buf = new unsigned char[bufSize];
      82                 : 
      83              67 :         size_t left = st.st_size;
      84              67 :         bool firstBlock = true;
      85                 :         
      86             134 :         while (left > 0) {
      87              67 :             checkInterrupt();
      88                 :             
      89              67 :             size_t read = left > bufSize ? bufSize : left;
      90              67 :             size_t copiedBytes = 0;
      91                 : 
      92              67 :             if (!firstBlock) {
      93                 :                 /* Move the last (refLength - 1) bytes from the last
      94                 :                    block to the start of the buffer to deal with
      95                 :                    references that cross block boundaries. */
      96               0 :                 copiedBytes = refLength - 1;
      97               0 :                 if (read + copiedBytes > bufSize)
      98               0 :                     read -= copiedBytes;
      99               0 :                 memcpy(buf, buf + (bufSize - copiedBytes), copiedBytes);
     100                 :             }
     101              67 :             firstBlock = false;
     102                 : 
     103              67 :             readFull(fd, buf + copiedBytes, read);
     104              67 :             left -= read;
     105                 : 
     106              67 :             search(copiedBytes + read, buf, ids, seen);
     107                 :         }
     108                 :         
     109              67 :         delete[] buf; /* !!! autodelete */
     110                 :     }
     111                 :     
     112              37 :     else if (S_ISLNK(st.st_mode)) {
     113              37 :         string target = readLink(path);
     114              37 :         search(target.size(), (const unsigned char *) target.c_str(), ids, seen);
     115                 :     }
     116                 :     
     117               0 :     else throw Error(format("unknown file type: %1%") % path);
     118                 : }
     119                 : 
     120                 : 
     121                 : PathSet scanForReferences(const string & path, const PathSet & paths)
     122              60 : {
     123              60 :     std::map<string, Path> backMap;
     124              60 :     StringSet ids;
     125              60 :     StringSet seen;
     126                 : 
     127                 :     /* For efficiency (and a higher hit rate), just search for the
     128                 :        hash part of the file name.  (This assumes that all references
     129                 :        have the form `HASH-bla'). */
     130             245 :     for (PathSet::const_iterator i = paths.begin(); i != paths.end(); i++) {
     131             185 :         string baseName = baseNameOf(*i);
     132             185 :         string::size_type pos = baseName.find('-');
     133             185 :         if (pos == string::npos)
     134               0 :             throw Error(format("bad reference `%1%'") % *i);
     135             185 :         string s = string(baseName, 0, pos);
     136             185 :         assert(s.size() == refLength);
     137             185 :         assert(backMap.find(s) == backMap.end());
     138                 :         // parseHash(htSHA256, s);
     139             185 :         ids.insert(s);
     140             185 :         backMap[s] = *i;
     141                 :     }
     142                 : 
     143              60 :     checkPath(path, ids, seen);
     144                 : 
     145              60 :     PathSet found;
     146              92 :     for (StringSet::iterator i = seen.begin(); i != seen.end(); i++) {
     147              32 :         std::map<string, Path>::iterator j;
     148              32 :         if ((j = backMap.find(*i)) == backMap.end()) abort();
     149              32 :         found.insert(j->second);
     150                 :     }
     151                 : 
     152              60 :     return found;
     153                 : }
     154                 : 
     155                 :  
     156                 : }

Generated by: LTP GCOV extension version 1.1