diff options
Diffstat (limited to 'Source/CPack/cmCPackDebGenerator.cxx')
-rw-r--r-- | Source/CPack/cmCPackDebGenerator.cxx | 397 |
1 files changed, 73 insertions, 324 deletions
diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index af54fce..7fc3c26 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -6,28 +6,17 @@ #include "cmCPackComponentGroup.h" #include "cmCPackGenerator.h" #include "cmCPackLog.h" +#include "cmCryptoHash.h" #include "cmGeneratedFileStream.h" #include "cmSystemTools.h" #include "cm_sys_stat.h" #include "cmsys/Glob.hxx" -#include <limits.h> -#include <map> #include <ostream> #include <set> -#include <stdio.h> #include <string.h> #include <utility> -// NOTE: -// A debian package .deb is simply an 'ar' archive. The only subtle difference -// is that debian uses the BSD ar style archive whereas most Linux distro have -// a GNU ar. -// See http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=161593 for more info -// Therefore we provide our own implementation of a BSD-ar: -static int ar_append(const char* archive, - const std::vector<std::string>& files); - cmCPackDebGenerator::cmCPackDebGenerator() { } @@ -115,37 +104,31 @@ int cmCPackDebGenerator::PackageComponents(bool ignoreGroup) // The default behavior is to have one package by component group // unless CPACK_COMPONENTS_IGNORE_GROUP is specified. if (!ignoreGroup) { - std::map<std::string, cmCPackComponentGroup>::iterator compGIt; - for (compGIt = this->ComponentGroups.begin(); - compGIt != this->ComponentGroups.end(); ++compGIt) { - cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Packaging component group: " - << compGIt->first << std::endl); + for (auto const& compG : this->ComponentGroups) { + cmCPackLogger(cmCPackLog::LOG_VERBOSE, + "Packaging component group: " << compG.first << std::endl); // Begin the archive for this group - retval &= PackageOnePack(initialTopLevel, compGIt->first); + retval &= PackageOnePack(initialTopLevel, compG.first); } // Handle Orphan components (components not belonging to any groups) - std::map<std::string, cmCPackComponent>::iterator compIt; - for (compIt = this->Components.begin(); compIt != this->Components.end(); - ++compIt) { + for (auto const& comp : this->Components) { // Does the component belong to a group? - if (compIt->second.Group == CM_NULLPTR) { + if (comp.second.Group == nullptr) { cmCPackLogger( cmCPackLog::LOG_VERBOSE, "Component <" - << compIt->second.Name + << comp.second.Name << "> does not belong to any group, package it separately." << std::endl); // Begin the archive for this orphan component - retval &= PackageOnePack(initialTopLevel, compIt->first); + retval &= PackageOnePack(initialTopLevel, comp.first); } } } // CPACK_COMPONENTS_IGNORE_GROUPS is set // We build 1 package per component else { - std::map<std::string, cmCPackComponent>::iterator compIt; - for (compIt = this->Components.begin(); compIt != this->Components.end(); - ++compIt) { - retval &= PackageOnePack(initialTopLevel, compIt->first); + for (auto const& comp : this->Components) { + retval &= PackageOnePack(initialTopLevel, comp.first); } } return retval; @@ -346,10 +329,8 @@ int cmCPackDebGenerator::createDeb() { std::string dirName = this->GetOption("CPACK_TEMPORARY_DIRECTORY"); dirName += '/'; - for (std::vector<std::string>::const_iterator fileIt = - packageFiles.begin(); - fileIt != packageFiles.end(); ++fileIt) { - totalSize += cmSystemTools::FileLength(*fileIt); + for (std::string const& file : packageFiles) { + totalSize += cmSystemTools::FileLength(file); } } out << "Installed-Size: " << (totalSize + 1023) / 1024 << "\n"; @@ -410,7 +391,7 @@ int cmCPackDebGenerator::createDeb() compression_suffix = ".gz"; tar_compression_type = cmArchiveWrite::CompressGZip; } else if (!strcmp(debian_compression_type, "none")) { - compression_suffix = ""; + compression_suffix.clear(); tar_compression_type = cmArchiveWrite::CompressNone; } else { cmCPackLogger(cmCPackLog::LOG_ERROR, @@ -456,10 +437,7 @@ int cmCPackDebGenerator::createDeb() // we have to reconstruct the parent folders as well - for (std::vector<std::string>::const_iterator fileIt = - packageFiles.begin(); - fileIt != packageFiles.end(); ++fileIt) { - std::string currentPath = *fileIt; + for (std::string currentPath : packageFiles) { while (currentPath != strGenWDIR) { // the last one IS strGenWDIR, but we do not want this one: // XXX/application/usr/bin/myprogram with GEN_WDIR=XXX/application @@ -469,22 +447,40 @@ int cmCPackDebGenerator::createDeb() } } - for (std::set<std::string>::const_iterator fileIt = orderedFiles.begin(); - fileIt != orderedFiles.end(); ++fileIt) { - cmCPackLogger(cmCPackLog::LOG_DEBUG, "FILEIT: \"" << *fileIt << "\"" + for (std::string const& file : orderedFiles) { + cmCPackLogger(cmCPackLog::LOG_DEBUG, "FILEIT: \"" << file << "\"" << std::endl); - std::string::size_type slashPos = fileIt->find('/', topLevelLength + 1); + std::string::size_type slashPos = file.find('/', topLevelLength + 1); std::string relativeDir = - fileIt->substr(topLevelLength, slashPos - topLevelLength); + file.substr(topLevelLength, slashPos - topLevelLength); cmCPackLogger(cmCPackLog::LOG_DEBUG, "RELATIVEDIR: \"" << relativeDir << "\"" << std::endl); +#ifdef WIN32 + std::string mode_t_adt_filename = file + ":cmake_mode_t"; + cmsys::ifstream permissionStream(mode_t_adt_filename.c_str()); + + mode_t permissions = 0; + + if (permissionStream) { + permissionStream >> std::oct >> permissions; + } + + if (permissions != 0) { + data_tar.SetPermissions(permissions); + } else if (cmSystemTools::FileIsDirectory(file)) { + data_tar.SetPermissions(0755); + } else { + data_tar.ClearPermissions(); + } +#endif + // do not recurse because the loop will do it - if (!data_tar.Add(*fileIt, topLevelLength, ".", false)) { + if (!data_tar.Add(file, topLevelLength, ".", false)) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem adding file to tar:" << std::endl << "#top level directory: " << strGenWDIR << std::endl - << "#file: " << *fileIt << std::endl + << "#file: " << file << std::endl << "#error:" << data_tar.GetError() << std::endl); return 0; } @@ -499,25 +495,21 @@ int cmCPackDebGenerator::createDeb() std::string topLevelWithTrailingSlash = this->GetOption("CPACK_TEMPORARY_DIRECTORY"); topLevelWithTrailingSlash += '/'; - for (std::vector<std::string>::const_iterator fileIt = - packageFiles.begin(); - fileIt != packageFiles.end(); ++fileIt) { + for (std::string const& file : packageFiles) { // hash only regular files - if (cmSystemTools::FileIsDirectory(*fileIt) || - cmSystemTools::FileIsSymlink(*fileIt)) { + if (cmSystemTools::FileIsDirectory(file) || + cmSystemTools::FileIsSymlink(file)) { continue; } - char md5sum[33]; - if (!cmSystemTools::ComputeFileMD5(*fileIt, md5sum)) { + std::string output = + cmSystemTools::ComputeFileHash(file, cmCryptoHash::AlgoMD5); + if (output.empty()) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem computing the md5 of " - << *fileIt << std::endl); + << file << std::endl); } - md5sum[32] = 0; - - std::string output(md5sum); - output += " " + *fileIt + "\n"; + output += " " + file + "\n"; // debian md5sums entries are like this: // 014f3604694729f3bf19263bac599765 usr/bin/ccmake // thus strip the full path (with the trailing slash) @@ -553,8 +545,8 @@ int cmCPackDebGenerator::createDeb() and https://lintian.debian.org/tags/control-file-has-bad-permissions.html */ - const mode_t permission644 = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; - const mode_t permissionExecute = S_IXUSR | S_IXGRP | S_IXOTH; + const mode_t permission644 = 0644; + const mode_t permissionExecute = 0111; const mode_t permission755 = permission644 | permissionExecute; // for md5sum and control (that we have generated here), we use 644 @@ -634,9 +626,8 @@ int cmCPackDebGenerator::createDeb() std::vector<std::string> controlExtraList; cmSystemTools::ExpandListArgument(controlExtra, controlExtraList); - for (std::vector<std::string>::iterator i = controlExtraList.begin(); - i != controlExtraList.end(); ++i) { - std::string filenamename = cmsys::SystemTools::GetFilenameName(*i); + for (std::string const& i : controlExtraList) { + std::string filenamename = cmsys::SystemTools::GetFilenameName(i); std::string localcopy = strGenWDIR + "/" + filenamename; if (permissionStrictPolicy) { @@ -646,7 +637,7 @@ int cmCPackDebGenerator::createDeb() } // if we can copy the file, it means it does exist, let's add it: - if (cmsys::SystemTools::CopyFileIfDifferent(*i, localcopy)) { + if (cmsys::SystemTools::CopyFileIfDifferent(i, localcopy)) { control_tar.Add(localcopy, strGenWDIR.length(), "."); } } @@ -654,23 +645,25 @@ int cmCPackDebGenerator::createDeb() } // ar -r your-package-name.deb debian-binary control.tar.* data.tar.* - // since debian packages require BSD ar (most Linux distros and even - // FreeBSD and NetBSD ship GNU ar) we use a copy of OpenBSD ar here. - std::vector<std::string> arFiles; - std::string topLevelString = strGenWDIR + "/"; - arFiles.push_back(topLevelString + "debian-binary"); - arFiles.push_back(topLevelString + "control.tar.gz"); - arFiles.push_back(topLevelString + "data.tar" + compression_suffix); - std::string outputFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); - outputFileName += "/"; - outputFileName += this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME"); - int res = ar_append(outputFileName.c_str(), arFiles); - if (res != 0) { - std::string tmpFile = - this->GetOption("GEN_CPACK_TEMPORARY_PACKAGE_FILE_NAME"); - tmpFile += "/Deb.log"; - cmGeneratedFileStream ofs(tmpFile.c_str()); - ofs << "# Problem creating archive using: " << res << std::endl; + // A debian package .deb is simply an 'ar' archive. The only subtle + // difference is that debian uses the BSD ar style archive whereas most + // Linux distro have a GNU ar. + // See http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=161593 for more info + std::string const outputDir = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); + std::string const outputName = this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME"); + std::string const outputPath = outputDir + "/" + outputName; + std::string const tlDir = strGenWDIR + "/"; + cmGeneratedFileStream debStream; + debStream.Open(outputPath.c_str(), false, true); + cmArchiveWrite deb(debStream, cmArchiveWrite::CompressNone, "arbsd"); + if (!deb.Add(tlDir + "debian-binary", tlDir.length()) || + !deb.Add(tlDir + "control.tar.gz", tlDir.length()) || + !deb.Add(tlDir + "data.tar" + compression_suffix, tlDir.length())) { + cmCPackLogger(cmCPackLog::LOG_ERROR, "Error creating debian package:" + << std::endl + << "#top level directory: " << outputDir << std::endl + << "#file: " << outputName << std::endl + << "#error:" << deb.GetError() << std::endl); return 0; } return 1; @@ -695,252 +688,8 @@ std::string cmCPackDebGenerator::GetComponentInstallDirNameSuffix( // the current COMPONENT belongs to. std::string groupVar = "CPACK_COMPONENT_" + cmSystemTools::UpperCase(componentName) + "_GROUP"; - if (CM_NULLPTR != GetOption(groupVar)) { + if (nullptr != GetOption(groupVar)) { return std::string(GetOption(groupVar)); } return componentName; } - -// The following code is taken from OpenBSD ar: -// http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ar/ -// It has been slightly modified: -// -return error codes instead exit() in functions -// -use the stdio file I/O functions instead the file descriptor based ones -// -merged into one cxx file -// -no additional options supported -// The coding style hasn't been modified. - -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Hugh Smith at The University of Guelph. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#define ARMAG "!<arch>\n" /* ar "magic number" */ -#define SARMAG 8 /* strlen(ARMAG); */ - -#define AR_EFMT1 "#1/" /* extended format #1 */ -#define ARFMAG "`\n" - -/* Header format strings. */ -#define HDR1 "%s%-13d%-12ld%-6u%-6u%-8o%-10lld%2s" -#define HDR2 "%-16.16s%-12ld%-6u%-6u%-8o%-10lld%2s" - -struct ar_hdr -{ - char ar_name[16]; /* name */ - char ar_date[12]; /* modification time */ - char ar_uid[6]; /* user id */ - char ar_gid[6]; /* group id */ - char ar_mode[8]; /* octal file permissions */ - char ar_size[10]; /* size in bytes */ - char ar_fmag[2]; /* consistency check */ -}; - -/* Set up file copy. */ -#define SETCF(from, fromname, to, toname, pad) \ - { \ - cf.rFile = from; \ - cf.rname = fromname; \ - cf.wFile = to; \ - cf.wname = toname; \ - cf.flags = pad; \ - } - -/* File copy structure. */ -typedef struct -{ - FILE* rFile; /* read file descriptor */ - const char* rname; /* read name */ - FILE* wFile; /* write file descriptor */ - const char* wname; /* write name */ -#define NOPAD 0x00 /* don't pad */ -#define WPAD 0x02 /* pad on writes */ - unsigned int flags; /* pad flags */ -} CF; - -/* misc.c */ - -static const char* ar_rname(const char* path) -{ - const char* ind = strrchr(path, '/'); - return (ind) ? ind + 1 : path; -} - -/* archive.c */ - -typedef struct ar_hdr HDR; -static char ar_hb[sizeof(HDR) + 1]; /* real header */ - -static size_t ar_already_written; - -/* copy_ar -- - * Copy size bytes from one file to another - taking care to handle the - * extra byte (for odd size files) when reading archives and writing an - * extra byte if necessary when adding files to archive. The length of - * the object is the long name plus the object itself; the variable - * already_written gets set if a long name was written. - * - * The padding is really unnecessary, and is almost certainly a remnant - * of early archive formats where the header included binary data which - * a PDP-11 required to start on an even byte boundary. (Or, perhaps, - * because 16-bit word addressed copies were faster?) Anyhow, it should - * have been ripped out long ago. - */ -static int copy_ar(CF* cfp, off_t size) -{ - static char pad = '\n'; - off_t sz = size; - size_t nr, nw; - char buf[8 * 1024]; - - if (sz == 0) { - return 0; - } - - FILE* from = cfp->rFile; - FILE* to = cfp->wFile; - while (sz && - (nr = fread(buf, 1, sz < static_cast<off_t>(sizeof(buf)) - ? static_cast<size_t>(sz) - : sizeof(buf), - from)) > 0) { - sz -= nr; - for (size_t off = 0; off < nr; nr -= off, off += nw) { - if ((nw = fwrite(buf + off, 1, nr, to)) < nr) { - return -1; - } - } - } - if (sz) { - return -2; - } - - if (cfp->flags & WPAD && (size + ar_already_written) & 1 && - fwrite(&pad, 1, 1, to) != 1) { - return -4; - } - - return 0; -} - -/* put_arobj -- Write an archive member to a file. */ -static int put_arobj(CF* cfp, struct stat* sb) -{ - int result = 0; - struct ar_hdr* hdr; - - /* If passed an sb structure, reading a file from disk. Get stat(2) - * information, build a name and construct a header. (Files are named - * by their last component in the archive.) */ - const char* name = ar_rname(cfp->rname); - (void)stat(cfp->rname, sb); - - /* If not truncating names and the name is too long or contains - * a space, use extended format 1. */ - size_t lname = strlen(name); - uid_t uid = sb->st_uid; - gid_t gid = sb->st_gid; - if (uid > USHRT_MAX) { - uid = USHRT_MAX; - } - if (gid > USHRT_MAX) { - gid = USHRT_MAX; - } - if (lname > sizeof(hdr->ar_name) || strchr(name, ' ')) { - (void)sprintf(ar_hb, HDR1, AR_EFMT1, (int)lname, (long int)sb->st_mtime, - (unsigned)uid, (unsigned)gid, (unsigned)sb->st_mode, - (long long)sb->st_size + lname, ARFMAG); - } else { - lname = 0; - (void)sprintf(ar_hb, HDR2, name, (long int)sb->st_mtime, (unsigned)uid, - (unsigned)gid, (unsigned)sb->st_mode, (long long)sb->st_size, - ARFMAG); - } - off_t size = sb->st_size; - - if (fwrite(ar_hb, 1, sizeof(HDR), cfp->wFile) != sizeof(HDR)) { - return -1; - } - - if (lname) { - if (fwrite(name, 1, lname, cfp->wFile) != lname) { - return -2; - } - ar_already_written = lname; - } - result = copy_ar(cfp, size); - ar_already_written = 0; - return result; -} - -/* append.c */ - -/* append -- - * Append files to the archive - modifies original archive or creates - * a new archive if named archive does not exist. - */ -static int ar_append(const char* archive, - const std::vector<std::string>& files) -{ - int eval = 0; - FILE* aFile = cmSystemTools::Fopen(archive, "wb+"); - if (aFile != CM_NULLPTR) { - fwrite(ARMAG, SARMAG, 1, aFile); - if (fseek(aFile, 0, SEEK_END) != -1) { - CF cf; - struct stat sb; - /* Read from disk, write to an archive; pad on write. */ - SETCF(CM_NULLPTR, CM_NULLPTR, aFile, archive, WPAD); - for (std::vector<std::string>::const_iterator fileIt = files.begin(); - fileIt != files.end(); ++fileIt) { - const char* filename = fileIt->c_str(); - FILE* file = cmSystemTools::Fopen(filename, "rb"); - if (file == CM_NULLPTR) { - eval = -1; - continue; - } - cf.rFile = file; - cf.rname = filename; - int result = put_arobj(&cf, &sb); - (void)fclose(file); - if (result != 0) { - eval = -2; - break; - } - } - } else { - eval = -3; - } - fclose(aFile); - } else { - eval = -4; - } - return eval; -} |