X-Git-Url: http://gitweb/?a=blobdiff_plain;f=pkgutil.cc;h=943c420f23a9d807b1fac599fc00dbe2a20899b3;hb=bfb5480be95ac565f1a057750429857385478be9;hp=54c80b60c079d626450a931510a9da589618d69e;hpb=7f84e1cc9e8e7ae698e8b648f7dbba98a2753150;p=pkgutils-cross.git diff --git a/pkgutil.cc b/pkgutil.cc index 54c80b6..943c420 100644 --- a/pkgutil.cc +++ b/pkgutil.cc @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include @@ -422,8 +421,9 @@ void pkgutil::pkg_install(const string& filename, const set& keep_list, (real_filename.c_str())); // Extract file - if (archive_read_extract(archive, entry, 0) != - ARCHIVE_OK) { + unsigned int flags = ARCHIVE_EXTRACT_OWNER | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_UNLINK; + + if (archive_read_extract(archive, entry, flags) != ARCHIVE_OK) { // If a file fails to install we just print an error message and // continue trying to install the rest of the package. const char* msg = archive_error_string(archive); @@ -489,6 +489,42 @@ void pkgutil::pkg_footprint(string& filename) const struct archive* archive; struct archive_entry* entry; + map hardlink_target_modes; + + // We first do a run over the archive and remember the modes + // of regular files. + // In the second run, we print the footprint - using the stored + // modes for hardlinks. + // + // FIXME the code duplication here is butt ugly + archive = archive_read_new(); + archive_read_support_compression_all(archive); + archive_read_support_format_all(archive); + + if (archive_read_open_filename(archive, + const_cast(filename.c_str()), + ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) + throw runtime_error_with_errno("could not open " + filename, archive_errno(archive)); + + for (i = 0; archive_read_next_header(archive, &entry) == + ARCHIVE_OK; ++i) { + + mode_t mode = archive_entry_mode(entry); + + if (!archive_entry_hardlink(entry)) { + const char *s = archive_entry_pathname(entry); + + hardlink_target_modes[s] = mode; + } + + if (S_ISREG(mode) && archive_read_data_skip(archive)) + throw runtime_error_with_errno("could not read " + filename, archive_errno(archive)); + } + + archive_read_finish(archive); + + // Too bad, there doesn't seem to be a way to reuse our archive + // instance archive = archive_read_new(); archive_read_support_compression_all(archive); archive_read_support_format_all(archive); @@ -508,7 +544,12 @@ void pkgutil::pkg_footprint(string& filename) const // To avoid getting different footprints we always use "lrwxrwxrwx". cout << "lrwxrwxrwx"; } else { - cout << mtos(mode); + const char *h = archive_entry_hardlink(entry); + + if (h) + cout << mtos(hardlink_target_modes[h]); + else + cout << mtos(mode); } cout << '\t'; @@ -657,42 +698,6 @@ string mtos(mode_t mode) return s; } -int unistd_gzopen(char* pathname, int flags, mode_t mode) -{ - char* gz_mode; - - switch (flags & O_ACCMODE) { - case O_WRONLY: - gz_mode = "w"; - break; - - case O_RDONLY: - gz_mode = "r"; - break; - - case O_RDWR: - default: - errno = EINVAL; - return -1; - } - - int fd; - gzFile gz_file; - - if ((fd = open(pathname, flags, mode)) == -1) - return -1; - - if ((flags & O_CREAT) && fchmod(fd, mode)) - return -1; - - if (!(gz_file = gzdopen(fd, gz_mode))) { - errno = ENOMEM; - return -1; - } - - return (int)gz_file; -} - string trim_filename(const string& filename) { string search("//");