about summary refs log blame commit diff
path: root/third_party/nix/src/libstore/export-import.cc
blob: 8e9314433990ad3afd989e4761053fc0ae1db4d7 (plain) (tree)
1
2
3
4
5
6
7
8
                    
 


                                      
 

               


                                
                                            
                                                   
                                                                   



                                                             

  


                                                                    
 

                                                   
 





                                                                            
 
            

 

                                                      
 
                                          
 
                                      
 



                                                             
                                                                           

                                                                               
   
 

                                                                              

 

                                                                     



                                                   


                 
                 

                                                                               
     
 


                                          
 
                                     
                               
                                                                  
     
 
                       
 
                                             
 

                                                                     
 
                                                             
 
                                      
                                

                                    
 

                                                          
 
                                        


                               
 
                                                                     
 

                             
 
             

 
                   
#include <algorithm>

#include "libstore/store-api.hh"
#include "libstore/worker-protocol.hh"
#include "libutil/archive.hh"

namespace nix {

struct HashAndWriteSink : Sink {
  Sink& writeSink;
  HashSink hashSink;
  explicit HashAndWriteSink(Sink& writeSink)
      : writeSink(writeSink), hashSink(htSHA256) {}
  void operator()(const unsigned char* data, size_t len) override {
    writeSink(data, len);
    hashSink(data, len);
  }
  Hash currentHash() { return hashSink.currentHash().first; }
};

void Store::exportPaths(const Paths& paths, Sink& sink) {
  Paths sorted = topoSortPaths(PathSet(paths.begin(), paths.end()));
  std::reverse(sorted.begin(), sorted.end());

  std::string doneLabel("paths exported");
  // logger->incExpected(doneLabel, sorted.size());

  for (auto& path : sorted) {
    // Activity act(*logger, lvlInfo, format("exporting path '%s'") % path);
    sink << 1;
    exportPath(path, sink);
    // logger->incProgress(doneLabel);
  }

  sink << 0;
}

void Store::exportPath(const Path& path, Sink& sink) {
  auto info = queryPathInfo(path);

  HashAndWriteSink hashAndWriteSink(sink);

  narFromPath(path, hashAndWriteSink);

  /* Refuse to export paths that have changed.  This prevents
     filesystem corruption from spreading to other machines.
     Don't complain if the stored hash is zero (unknown). */
  Hash hash = hashAndWriteSink.currentHash();
  if (hash != info->narHash && info->narHash != Hash(info->narHash.type)) {
    throw Error(format("hash of path '%1%' has changed from '%2%' to '%3%'!") %
                path % info->narHash.to_string() % hash.to_string());
  }

  hashAndWriteSink << exportMagic << path << info->references << info->deriver
                   << 0;
}

Paths Store::importPaths(Source& source,
                         const std::shared_ptr<FSAccessor>& accessor,
                         CheckSigsFlag checkSigs) {
  Paths res;
  while (true) {
    auto n = readNum<uint64_t>(source);
    if (n == 0) {
      break;
    }
    if (n != 1) {
      throw Error(
          "input doesn't look like something created by 'nix-store --export'");
    }

    /* Extract the NAR from the source. */
    TeeSink tee(source);
    parseDump(tee, tee.source);

    uint32_t magic = readInt(source);
    if (magic != exportMagic) {
      throw Error("Nix archive cannot be imported; wrong format");
    }

    ValidPathInfo info;

    info.path = readStorePath(*this, source);

    // Activity act(*logger, lvlInfo, format("importing path '%s'") %
    // info.path);

    info.references = readStorePaths<PathSet>(*this, source);

    info.deriver = readString(source);
    if (!info.deriver.empty()) {
      assertStorePath(info.deriver);
    }

    info.narHash = hashString(htSHA256, *tee.source.data);
    info.narSize = tee.source.data->size();

    // Ignore optional legacy signature.
    if (readInt(source) == 1) {
      readString(source);
    }

    addToStore(info, tee.source.data, NoRepair, checkSigs, accessor);

    res.push_back(info.path);
  }

  return res;
}

}  // namespace nix