C++ Library to handle BagIt structures. BagIt is a standard format to create transfer packages for digital preservation purposes. See https://en.wikipedia.org/wiki/BagIt for details http://andreas-romeyke.de
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

124 lines
4.9 KiB

#include "manifest.hpp"
#include <iostream>
#include <fstream>
#include <sstream>
#include <boost/filesystem.hpp>
//#include <filesystem> // c++17
//namespace fs = std::filesystem;
namespace fs = boost::filesystem;
using namespace std;
multimap<checksum_string_t,filename_t> Manifest::get_checksum_file_pairs(checksum_algorithms alg) {
string filename = this->manifest_algorithm_files[ alg ];
multimap<checksum_string_t,filename_t> checksum_file_pairs;
// cout << "using file " << filename << endl;
ifstream file;
file.open( filename );
if (file.is_open()) {
string line;
while (getline(file, line)) {
stringstream line_ss ( line );
string checksum;
string subfile;
line_ss >> checksum;
line_ss >> subfile;
checksum_file_pairs.insert( pair<checksum_string_t, filename_t>(checksum,subfile) );
// cout << "checksum="<<checksum<<" file="<<subfile<<endl;
}
file.close();
}
return checksum_file_pairs;
}
bool Manifest::validate() {
Checksum checksum;
bool is_valid = true;
for (map<checksum_algorithms,string>::iterator it=this->manifest_algorithm_files.begin(); it!=this->manifest_algorithm_files.end(); ++it) {
//cout << "validate using file '"<< (it->second) << "' (" << (it->first) << ")" <<endl;
multimap<checksum_string_t,filename_t>checksum_file_pairs = this->get_checksum_file_pairs( it->first );
for (multimap<checksum_string_t,filename_t>::iterator ch=checksum_file_pairs.begin(); ch!=checksum_file_pairs.end(); ++ch) {
string expected_checksum = ch->first;
string file = this->basedir + ch->second;
string calc_checksum = checksum.checksum_of_file( file, it->first );
//cout << "\t" << "file="<<file <<" expected:"<<expected_checksum << " found: " << calc_checksum << endl;
if (calc_checksum.empty()) {
this->log << "Bagit file '" << file << "', checksum '" << expected_checksum << "' is expected by file '" << it->second << "', but file was not found" << endl;
is_valid = false;
}
else if (0 != expected_checksum.compare( calc_checksum)) {
// cout << ( "Bagit file '" + file + "', checksum '" + expected_checksum + "' is expected, but found: '" + calc_checksum + "'") << endl;
this->log << "Bagit file '" << file << "', checksum '" << expected_checksum << "' is expected by file '" << it->second << "', but found: '" << calc_checksum << "'" << endl;
is_valid = false;
}
fs::path p{ file };
fs::file_status s = fs::status( p );
if (! fs::is_regular_file( p )) {
this->log << "Bagit file '" << file << "' does not exists in '" << this->basedir << "'" << endl;
}
}
}
//cout << "MANIFEST validate, calling debug()" << endl;
//this->debug();
//cout << "MANIFEST validate, finished" << endl;
return is_valid;
}
void Manifest::debug() {
//cout << "DEBUG: basedir='"<<this->basedir<<"'"<<endl;
//cout << "DEBUG: list of manifest files:"<<endl;
for (map<checksum_algorithms,string>::iterator it=this->manifest_algorithm_files.begin(); it!=this->manifest_algorithm_files.end(); ++it) {
// cout << "DEBUG:\tvalidate using file '"<< (it->second) << "' (" << (it->first) << ")" <<endl;
}
//cout << "DEBUG" << endl;
}
list<string> Manifest::get_checksummed_files() {
list<string> files;
for (map<checksum_algorithms,string>::iterator it=this->manifest_algorithm_files.begin(); it!=this->manifest_algorithm_files.end(); ++it) {
multimap<checksum_string_t,filename_t>checksum_file_pairs = this->get_checksum_file_pairs( it->first );
for (multimap<checksum_string_t,filename_t>::iterator ch=checksum_file_pairs.begin(); ch!=checksum_file_pairs.end(); ++ch) {
string file = this->basedir + ch->second;
// cout << "MF: '" << file << "'" << endl;
files.push_back( file );
}
}
return files;
}
bool Manifest::store( string basedir, list<string>& files ) {
Checksum checksum;
for (map<checksum_algorithms, string>::iterator it=this->manifest_algorithm_files.begin(); it!=this->manifest_algorithm_files.end(); ++it) {
checksum_algorithms alg = it->first;
// test if file exists
string algfilename = basedir + it->second;
cout << "DEBUG manifest::store, file='"<<algfilename << "' (newbase='" << basedir << "', filename='" << it->second << "'" <<endl;
ofstream alg_txt_file;
alg_txt_file.open( algfilename );
if (alg_txt_file.is_open()) {
list<string>::iterator ch;
for (ch=files.begin(); ch!=files.end(); ++ch) {
string filename = basedir + *ch;
cout << "\tfilename='"<<filename<<"'"<<endl;
string checksum_string = checksum.checksum_of_file( filename, alg);
alg_txt_file << checksum_string << " " << *ch << endl;
}
alg_txt_file.close();
}
}
return true;
}
void Manifest::get_logstream( stringstream & log ) {
log << this->log.rdbuf();
}
void Manifest::reset_logstream() {
this->log.str(std::string());
}
// vim: set tabstop=4 softtabstop=0 expandtab shiftwidth=4 smarttab