LTP GCOV extension - code coverage report
Current view: directory - src/libutil - archive.cc
Test: app.info
Date: 2008-11-20 Instrumented lines: 146
Code covered: 86.3 % Executed lines: 126

       1                 : #include <cerrno>
       2                 : #include <algorithm>
       3                 : #include <vector>
       4                 : 
       5                 : #include <sys/types.h>
       6                 : #include <sys/stat.h>
       7                 : #include <unistd.h>
       8                 : #include <dirent.h>
       9                 : #include <fcntl.h>
      10                 : 
      11                 : #include "archive.hh"
      12                 : #include "util.hh"
      13                 : 
      14                 : 
      15                 : namespace nix {
      16                 : 
      17                 : 
      18            1151 : static string archiveVersion1 = "nix-archive-1";
      19                 : 
      20                 : 
      21            1151 : PathFilter defaultPathFilter;
      22                 : 
      23                 : 
      24                 : static void dump(const string & path, Sink & sink, PathFilter & filter);
      25                 : 
      26                 : 
      27             158 : static void dumpEntries(const Path & path, Sink & sink, PathFilter & filter)
      28                 : {
      29             158 :     Strings names = readDirectory(path);
      30             158 :     vector<string> names2(names.begin(), names.end());
      31             316 :     sort(names2.begin(), names2.end());
      32                 : 
      33             420 :     for (vector<string>::iterator i = names2.begin();
      34                 :          i != names2.end(); ++i)
      35                 :     {
      36             262 :         Path entry = path + "/" + *i;
      37             262 :         if (filter(entry)) {
      38             256 :             writeString("entry", sink);
      39             512 :             writeString("(", sink);
      40             512 :             writeString("name", sink);
      41             256 :             writeString(*i, sink);
      42             256 :             writeString("node", sink);
      43             256 :             dump(entry, sink, filter);
      44             256 :             writeString(")", sink);
      45                 :         }
      46             158 :     }
      47             158 : }
      48                 : 
      49                 : 
      50                 : static void dumpContents(const Path & path, unsigned int size, 
      51            5657 :     Sink & sink)
      52                 : {
      53            5657 :     writeString("contents", sink);
      54            5657 :     writeInt(size, sink);
      55                 : 
      56            5657 :     AutoCloseFD fd = open(path.c_str(), O_RDONLY);
      57           11314 :     if (fd == -1) throw SysError(format("opening file `%1%'") % path);
      58                 :     
      59                 :     unsigned char buf[65536];
      60            5657 :     unsigned int left = size;
      61                 : 
      62           11961 :     while (left > 0) {
      63             647 :         size_t n = left > sizeof(buf) ? sizeof(buf) : left;
      64             647 :         readFull(fd, buf, n);
      65             647 :         left -= n;
      66             647 :         sink(buf, n);
      67                 :     }
      68                 : 
      69            5657 :     writePadding(size, sink);
      70            5657 : }
      71                 : 
      72                 : 
      73            5929 : static void dump(const Path & path, Sink & sink, PathFilter & filter)
      74                 : {
      75                 :     struct stat st;
      76            5929 :     if (lstat(path.c_str(), &st))
      77               0 :         throw SysError(format("getting attributes of path `%1%'") % path);
      78                 : 
      79            5929 :     writeString("(", sink);
      80                 : 
      81            5929 :     if (S_ISREG(st.st_mode)) {
      82            5657 :         writeString("type", sink);
      83           11314 :         writeString("regular", sink);
      84            5657 :         if (st.st_mode & S_IXUSR) {
      85             114 :             writeString("executable", sink);
      86             228 :             writeString("", sink);
      87                 :         }
      88            5657 :         dumpContents(path, st.st_size, sink);
      89                 :     } 
      90                 : 
      91             272 :     else if (S_ISDIR(st.st_mode)) {
      92             158 :         writeString("type", sink);
      93             316 :         writeString("directory", sink);
      94             158 :         dumpEntries(path, sink, filter);
      95                 :     }
      96                 : 
      97             114 :     else if (S_ISLNK(st.st_mode)) {
      98             114 :         writeString("type", sink);
      99             228 :         writeString("symlink", sink);
     100             228 :         writeString("target", sink);
     101             228 :         writeString(readLink(path), sink);
     102                 :     }
     103                 : 
     104               0 :     else throw Error("unknown file type: " + path);
     105                 : 
     106            5929 :     writeString(")", sink);
     107            5929 : }
     108                 : 
     109                 : 
     110            5673 : void dumpPath(const Path & path, Sink & sink, PathFilter & filter)
     111                 : {
     112            5673 :     writeString(archiveVersion1, sink);
     113            5673 :     dump(path, sink, filter);
     114            5673 : }
     115                 : 
     116                 : 
     117               0 : static Error badArchive(string s)
     118                 : {
     119               0 :     return Error("bad archive: " + s);
     120                 : }
     121                 : 
     122                 : 
     123               0 : static void skipGeneric(Source & source)
     124                 : {
     125               0 :     if (readString(source) == "(") {
     126               0 :         while (readString(source) != ")")
     127               0 :             skipGeneric(source);
     128                 :     }
     129               0 : }
     130                 : 
     131                 : 
     132                 : static void restore(const Path & path, Source & source);
     133                 : 
     134                 : 
     135              26 : static void restoreEntry(const Path & path, Source & source)
     136                 : {
     137              26 :     string s, name;
     138                 : 
     139              26 :     s = readString(source);
     140              26 :     if (s != "(") throw badArchive("expected open tag");
     141                 : 
     142              52 :     while (1) {
     143              78 :         checkInterrupt();
     144                 : 
     145              78 :         s = readString(source);
     146                 : 
     147              78 :         if (s == ")") {
     148              26 :             break;
     149              52 :         } else if (s == "name") {
     150              26 :             name = readString(source);
     151              26 :         } else if (s == "node") {
     152              26 :             if (s == "") throw badArchive("entry name missing");
     153              26 :             restore(path + "/" + name, source);
     154                 :         } else {
     155               0 :             throw badArchive("unknown field " + s);
     156                 :             skipGeneric(source);
     157                 :         }
     158              26 :     }
     159              26 : }
     160                 : 
     161                 : 
     162             133 : static void restoreContents(int fd, const Path & path, Source & source)
     163                 : {
     164             133 :     unsigned int size = readInt(source);
     165             133 :     unsigned int left = size;
     166                 :     unsigned char buf[65536];
     167                 : 
     168             396 :     while (left) {
     169             130 :         checkInterrupt();
     170             130 :         unsigned int n = sizeof(buf);
     171             130 :         if (n > left) n = left;
     172             130 :         source(buf, n);
     173             130 :         writeFull(fd, buf, n);
     174             130 :         left -= n;
     175                 :     }
     176                 : 
     177             133 :     readPadding(size, source);
     178             133 : }
     179                 : 
     180                 : 
     181             157 : static void restore(const Path & path, Source & source)
     182                 : {
     183             157 :     string s;
     184                 : 
     185             157 :     s = readString(source);
     186             157 :     if (s != "(") throw badArchive("expected open tag");
     187                 : 
     188             157 :     enum { tpUnknown, tpRegular, tpDirectory, tpSymlink } type = tpUnknown;
     189             157 :     AutoCloseFD fd;
     190                 : 
     191             365 :     while (1) {
     192             522 :         checkInterrupt();
     193                 : 
     194             522 :         s = readString(source);
     195                 : 
     196             522 :         if (s == ")") {
     197             157 :             break;
     198                 :         }
     199                 : 
     200             365 :         else if (s == "type") {
     201             157 :             if (type != tpUnknown)
     202               0 :                 throw badArchive("multiple type fields");
     203             157 :             string t = readString(source);
     204                 : 
     205             157 :             if (t == "regular") {
     206             133 :                 type = tpRegular;
     207             133 :                 fd = open(path.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0666);
     208             133 :                 if (fd == -1)
     209               0 :                     throw SysError("creating file " + path);
     210                 :             }
     211                 : 
     212              24 :             else if (t == "directory") {
     213              12 :                 type = tpDirectory;
     214              12 :                 if (mkdir(path.c_str(), 0777) == -1)
     215               0 :                     throw SysError("creating directory " + path);
     216                 :             }
     217                 : 
     218              12 :             else if (t == "symlink") {
     219              12 :                 type = tpSymlink;
     220                 :             }
     221                 :             
     222               0 :             else throw badArchive("unknown file type " + t);
     223                 :             
     224                 :         }
     225                 : 
     226             208 :         else if (s == "contents" && type == tpRegular) {
     227             133 :             restoreContents(fd, path, source);
     228                 :         }
     229                 : 
     230              75 :         else if (s == "executable" && type == tpRegular) {
     231              37 :             readString(source);
     232                 :             struct stat st;
     233              37 :             if (fstat(fd, &st) == -1)
     234               0 :                 throw SysError("fstat");
     235              37 :             if (fchmod(fd, st.st_mode | (S_IXUSR | S_IXGRP | S_IXOTH)) == -1)
     236               0 :                 throw SysError("fchmod");
     237                 :         }
     238                 : 
     239              38 :         else if (s == "entry" && type == tpDirectory) {
     240              26 :             restoreEntry(path, source);
     241                 :         }
     242                 : 
     243              12 :         else if (s == "target" && type == tpSymlink) {
     244              12 :             string target = readString(source);
     245              12 :             if (symlink(target.c_str(), path.c_str()) == -1)
     246               0 :                 throw SysError("creating symlink " + path);
     247                 :         }
     248                 : 
     249                 :         else {
     250               0 :             throw badArchive("unknown field " + s);
     251                 :             skipGeneric(source);
     252                 :         }
     253                 :         
     254             157 :     }
     255             157 : }
     256                 : 
     257                 : 
     258             131 : void restorePath(const Path & path, Source & source)
     259                 : {
     260             131 :     if (readString(source) != archiveVersion1)
     261               0 :         throw badArchive("expected Nix archive");
     262             131 :     restore(path, source);
     263             131 : }
     264                 : 
     265               0 :  
     266            1106 : }

Generated by: LTP GCOV extension version 1.6