From: Tilman Sauerbeck Date: Fri, 24 Nov 2006 20:59:10 +0000 (+0100) Subject: Fixed the permission lookup problem for hardlinks. X-Git-Url: http://gitweb/?a=commitdiff_plain;h=80db05ef8d1a1ce7d7948a9d06732209f5f84fce;p=pkgutils-cross.git Fixed the permission lookup problem for hardlinks. We now do two runs over the archive, where the first one remembers permissions for hardlink targets, which are then looked up in the second run. --- diff --git a/pkgutil.cc b/pkgutil.cc index 54c80b6..ce94501 100644 --- a/pkgutil.cc +++ b/pkgutil.cc @@ -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';