degate  0.1.2
ProjectArchiver.cc
Go to the documentation of this file.
00001 /*
00002 
00003   This file is part of the IC reverse engineering tool degate.
00004 
00005   Copyright 2008, 2009, 2010 by Martin Schobert
00006 
00007   Degate is free software: you can redistribute it and/or modify
00008   it under the terms of the GNU General Public License as published by
00009   the Free Software Foundation, either version 3 of the License, or
00010   any later version.
00011 
00012   Degate is distributed in the hope that it will be useful,
00013   but WITHOUT ANY WARRANTY; without even the implied warranty of
00014   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015   GNU General Public License for more details.
00016 
00017   You should have received a copy of the GNU General Public License
00018   along with degate. If not, see <http://www.gnu.org/licenses/>.
00019 
00020 */
00021 
00022 #include <zip.h>
00023 
00024 #include <globals.h>
00025 #include <ProjectArchiver.h>
00026 #include <list>
00027 #include <memory>
00028 
00029 #include <boost/filesystem/operations.hpp>
00030 #include <boost/filesystem/path.hpp>
00031 #include <boost/format.hpp>
00032 #include <boost/foreach.hpp>
00033 
00034 
00035 using namespace std;
00036 using namespace degate;
00037 using namespace boost::filesystem;
00038 
00039 void ProjectArchiver::add_single_file(struct zip * zip_archive,
00040                                       path const& archive_file,
00041                                       path const& base_dir_path,
00042                                       path const& file,
00043                                       path const& prepend_dir) const {
00044 
00045   assert(zip_archive != NULL);
00046   struct zip_source *source;
00047 
00048   path stripped = prepend_dir / strip_path(file, base_dir_path);
00049 
00050   debug(TM, "Add file %s as %s to zip archive.",
00051         file.string().c_str(), stripped.string().c_str());
00052 
00053   if((source = zip_source_file(zip_archive,
00054                                file.string().c_str(), 0, 0)) == NULL) {
00055     boost::format f("Cannot add file %1% to zip archive %2%: %3%");
00056     f % file % archive_file % zip_strerror(zip_archive);
00057     throw ZipException(f.str());
00058   }
00059 
00060   if(zip_add(zip_archive,
00061              stripped.string().c_str(),
00062              source) < 0) {
00063 
00064     boost::format f("Cannot add file %1% to zip archive %2%: %3%");
00065     f % file % archive_file % zip_strerror(zip_archive);
00066     throw ZipException(f.str());
00067   }
00068 }
00069 
00070 
00071 void ProjectArchiver::add_directory(struct zip * zip_archive,
00072                                     path const& archive_file,
00073                                     path const& base_dir_path,
00074                                     path const& dir,
00075                                     path const& prepend_dir) const {
00076 
00077   directory_iterator end_iter;
00078 
00079   for(directory_iterator iter(dir); iter != end_iter; ++iter) {
00080 
00081     path stripped = prepend_dir / strip_path(iter->path(), base_dir_path);
00082 
00083     if(is_directory(iter->path())) {
00084 
00085 #if BOOST_FILESYSTEM_VERSION==3
00086       std::string rel_dir = get_filename_from_path(stripped.native());
00087 #else
00088       std::string rel_dir = get_filename_from_path(stripped.native_file_string());
00089 #endif
00090       std::string pattern = "scaling_";
00091       bool skip = rel_dir.length() >= pattern.length() && (rel_dir.compare(0, pattern.length(), pattern) == 0);
00092 
00093       if(!skip) {
00094 
00095         if(zip_add_dir(zip_archive, stripped.string().c_str()) < 0) {
00096           boost::format f("Cannot add directory %1% to zip archive %2%: %3%");
00097           f % iter->path() % archive_file % zip_strerror(zip_archive);
00098           throw ZipException(f.str());
00099         }
00100 
00101         add_directory(zip_archive, archive_file, base_dir_path, 
00102                       iter->path(), // already prefixed with dir
00103                       prepend_dir);
00104       }
00105 
00106     }
00107     else {
00108       add_single_file(zip_archive, archive_file, base_dir_path, iter->path(), prepend_dir);
00109     }
00110   }
00111 
00112 }
00113 
00114 
00115 void ProjectArchiver::export_data(path const& project_dir,
00116                                   path const& archive_file,
00117                                   path const& prepend_dir) const {
00118 
00119   struct zip *zip_archive;
00120   int err;
00121 
00122   if((zip_archive = zip_open(archive_file.string().c_str(), ZIP_CREATE, &err)) == NULL) {
00123     char errstr[1024];
00124     zip_error_to_str(errstr, sizeof(errstr), err, errno);
00125     throw ZipException(errstr);
00126   }
00127 
00128   if(zip_add_dir(zip_archive, prepend_dir.string().c_str()) < 0) {
00129     boost::format f("Cannot add directory %1% to zip archive %2%: %3%");
00130     f % prepend_dir % archive_file % zip_strerror(zip_archive);
00131     throw ZipException(f.str());
00132   }
00133 
00134   try {
00135     add_directory(zip_archive, archive_file, project_dir, project_dir, prepend_dir);
00136   }
00137   catch(ZipException const& ex) {
00138     // rethrow exception, but free zip_archive resource first
00139     if(zip_archive != NULL) zip_close(zip_archive);
00140     throw;
00141   }
00142 
00143   if(zip_archive != NULL && zip_close(zip_archive) < 0) {
00144     boost::format f("Cannot write zip archive %1%: %2%");
00145     f % archive_file % zip_strerror(zip_archive);
00146     throw ZipException(f.str());
00147   }
00148 
00149 }