CRUX-ARM : Home

Home :: Documentation :: Download :: Development :: Community :: Ports :: Packages :: Bugs :: Links :: About :: Donors
Switched from libtar to libarchive.
authorMatthias-Christian Ott <matthias.christian@tiscali.de>
Wed, 15 Nov 2006 19:32:56 +0000 (20:32 +0100)
committerTilman Sauerbeck <tilman@crux.nu>
Wed, 15 Nov 2006 19:32:56 +0000 (20:32 +0100)
Makefile
pkgutil.cc

index 5c1881c71fdecb2e4a09c5b159002a9e4b27d832..2035ef69db730377d588bb31aaf10a03ae7d8c23 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -25,33 +25,20 @@ MANDIR = /usr/man
 ETCDIR = /etc
 
 VERSION = 5.21
-LIBTAR_VERSION = 1.2.11
 
 CXXFLAGS += -DNDEBUG
 CXXFLAGS += -O2 -Wall -pedantic -D_GNU_SOURCE -DVERSION=\"$(VERSION)\" \
-           -Ilibtar-$(LIBTAR_VERSION)/lib -Ilibtar-$(LIBTAR_VERSION)/listhash \
            -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
 
-LDFLAGS += -static -Llibtar-$(LIBTAR_VERSION)/lib -ltar -lz
+LDFLAGS += -static -larchive -lz -lbz2
 
 OBJECTS = main.o pkgutil.o pkgadd.o pkgrm.o pkginfo.o
 
 MANPAGES = pkgadd.8 pkgrm.8 pkginfo.8 pkgmk.8 rejmerge.8
 
-LIBTAR = libtar-$(LIBTAR_VERSION)/lib/libtar.a
-
 all: pkgadd pkgmk rejmerge man
 
-$(LIBTAR):
-       (tar xzf libtar-$(LIBTAR_VERSION).tar.gz; \
-       cd libtar-$(LIBTAR_VERSION); \
-       patch -p1 < ../libtar-$(LIBTAR_VERSION)-fix_mem_leak.patch; \
-       patch -p1 < ../libtar-$(LIBTAR_VERSION)-reduce_mem_usage.patch; \
-       patch -p1 < ../libtar-$(LIBTAR_VERSION)-fix_linkname_overflow.patch; \
-       LDFLAGS="" ./configure --disable-encap --disable-encap-install; \
-       make)
-
-pkgadd: $(LIBTAR) .depend $(OBJECTS)
+pkgadd: .depend $(OBJECTS)
        $(CXX) $(OBJECTS) -o $@ $(LDFLAGS)
 
 pkgmk: pkgmk.in
@@ -108,6 +95,5 @@ clean:
 
 distclean: clean
        rm -f pkgadd pkginfo pkgrm pkgmk rejmerge
-       rm -rf libtar-$(LIBTAR_VERSION)
 
 # End of file
index bdc1563541bdabd2c65da2bce8b6a9ffca2fff5d..39f68f5d3eb707c1fe7276f5ffe92c84d591fac5 100644 (file)
 #include <fcntl.h>
 #include <zlib.h>
 #include <libgen.h>
-#include <libtar.h>
+#include <archive.h>
+#include <archive_entry.h>
 
 using __gnu_cxx::stdio_filebuf;
 
-static tartype_t gztype = {
-       (openfunc_t)unistd_gzopen,
-       (closefunc_t)gzclose,
-       (readfunc_t)gzread,
-       (writefunc_t)gzwrite
-};
-
 pkgutil::pkgutil(const string& name)
        : utilname(name)
 {
@@ -333,7 +327,8 @@ pair<string, pkgutil::pkginfo_t> pkgutil::pkg_open(const string& filename) const
 {
        pair<string, pkginfo_t> result;
        unsigned int i;
-       TAR* t;
+       struct archive* archive;
+       struct archive_entry* entry;
 
        // Extract name and version from filename
        string basename(filename, filename.rfind('/') + 1);
@@ -347,47 +342,75 @@ pair<string, pkgutil::pkginfo_t> pkgutil::pkg_open(const string& filename) const
        result.first = name;
        result.second.version = version;
 
-       if (tar_open(&t, const_cast<char*>(filename.c_str()), &gztype, O_RDONLY, 0, TAR_GNU) == -1)
+       archive = archive_read_new();
+       archive_read_support_compression_all(archive);
+       archive_read_support_format_all(archive);
+
+       if (archive_read_open_filename(archive,
+           const_cast<char*>(filename.c_str()),
+           ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK)
                throw runtime_error_with_errno("could not open " + filename);
 
-       for (i = 0; !th_read(t); ++i) {
-               result.second.files.insert(result.second.files.end(), th_get_pathname(t));
-               if (TH_ISREG(t) && tar_skip_regfile(t))
+       for (i = 0; archive_read_next_header(archive, &entry) ==
+            ARCHIVE_OK; ++i) {
+               const struct stat* status;
+
+               result.second.files.insert(result.second.files.end(),
+                                          archive_entry_pathname(entry));
+
+               status = archive_entry_stat(entry);
+
+               if (S_ISREG(status->st_mode) &&
+                   archive_read_data_skip(archive) != ARCHIVE_OK)
                        throw runtime_error_with_errno("could not read " + filename);
        }
    
        if (i == 0) {
-               if (errno == 0)
+               if (archive_errno(archive) == 0)
                        throw runtime_error("empty package");
                else
                        throw runtime_error("could not read " + filename);
        }
 
-       tar_close(t);
+       archive_read_finish(archive);
 
        return result;
 }
 
 void pkgutil::pkg_install(const string& filename, const set<string>& keep_list, const set<string>& non_install_list) const
 {
-       TAR* t;
+       struct archive* archive;
+       struct archive_entry* entry;
        unsigned int i;
 
-       if (tar_open(&t, const_cast<char*>(filename.c_str()), &gztype, O_RDONLY, 0, TAR_GNU) == -1)
+       archive = archive_read_new();
+       archive_read_support_compression_all(archive);
+       archive_read_support_format_all(archive);
+
+       if (archive_read_open_filename(archive,
+           const_cast<char*>(filename.c_str()),
+           ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK)
                throw runtime_error_with_errno("could not open " + filename);
 
-       for (i = 0; !th_read(t); ++i) {
-               string archive_filename = th_get_pathname(t);
+       chdir(root.c_str());
+
+       for (i = 0; archive_read_next_header(archive, &entry) ==
+            ARCHIVE_OK; ++i) {
+               string archive_filename = archive_entry_pathname(entry);
                string reject_dir = trim_filename(root + string("/") + string(PKG_REJECTED));
                string original_filename = trim_filename(root + string("/") + archive_filename);
                string real_filename = original_filename;
 
                // Check if file is filtered out via INSTALL
                if (non_install_list.find(archive_filename) != non_install_list.end()) {
+                       const struct stat* status;
+
                        cout << utilname << ": ignoring " << archive_filename << endl;
 
-                       if (TH_ISREG(t))
-                               tar_skip_regfile(t);
+                       status = archive_entry_stat(entry);
+
+                       if (S_ISREG(status->st_mode))
+                               archive_read_data_skip(archive);
 
                        continue;
                }
@@ -396,11 +419,15 @@ void pkgutil::pkg_install(const string& filename, const set<string>& keep_list,
                if (file_exists(real_filename) && keep_list.find(archive_filename) != keep_list.end())
                        real_filename = trim_filename(reject_dir + string("/") + archive_filename);
 
+               archive_entry_set_pathname(entry, const_cast<char*>
+                                          (real_filename.c_str()));
+
                // Extract file
-               if (tar_extract_file(t, const_cast<char*>(real_filename.c_str()))) {
+               if (archive_read_extract(archive, entry, 0) !=
+                   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 = strerror(errno);
+                       const char* msg = archive_error_string(archive);
                        cerr << utilname << ": could not install " + archive_filename << ": " << msg << endl;
                        continue;
                }
@@ -408,9 +435,12 @@ void pkgutil::pkg_install(const string& filename, const set<string>& keep_list,
                // Check rejected file
                if (real_filename != original_filename) {
                        bool remove_file = false;
+                       const struct stat* status;
+
+                       status = archive_entry_stat(entry);
 
                        // Directory
-                       if (TH_ISDIR(t))
+                       if (S_ISDIR(status->st_mode))
                                remove_file = permissions_equal(real_filename, original_filename);
                        // Other files
                        else
@@ -426,13 +456,13 @@ void pkgutil::pkg_install(const string& filename, const set<string>& keep_list,
        }
 
        if (i == 0) {
-               if (errno == 0)
+               if (archive_errno(archive) == 0)
                        throw runtime_error("empty package");
                else
                        throw runtime_error("could not read " + filename);
        }
 
-       tar_close(t);
+       archive_read_finish(archive);
 }
 
 void pkgutil::ldconfig() const
@@ -459,25 +489,37 @@ void pkgutil::ldconfig() const
 void pkgutil::pkg_footprint(string& filename) const
 {
         unsigned int i;
-        TAR* t;
+       struct archive* archive;
+       struct archive_entry* entry;
 
-        if (tar_open(&t, const_cast<char*>(filename.c_str()), &gztype, O_RDONLY, 0, TAR_GNU) == -1)
+       archive = archive_read_new();
+       archive_read_support_compression_all(archive);
+       archive_read_support_format_all(archive);
+
+       if (archive_read_open_filename(archive,
+           const_cast<char*>(filename.c_str()),
+           ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK)
                 throw runtime_error_with_errno("could not open " + filename);
 
-        for (i = 0; !th_read(t); ++i) {
+       for (i = 0; archive_read_next_header(archive, &entry) ==
+            ARCHIVE_OK; ++i) {
+               const struct stat* status;
+
+               status = archive_entry_stat(entry);
+
                // Access permissions
-               if (TH_ISSYM(t)) {
+               if (S_ISLNK(status->st_mode)) {
                        // Access permissions on symlinks differ among filesystems, e.g. XFS and ext2 have different.
                        // To avoid getting different footprints we always use "lrwxrwxrwx".
                        cout << "lrwxrwxrwx";
                } else {
-                       cout << mtos(th_get_mode(t));
+                       cout << mtos(archive_entry_mode(entry));
                }
 
                cout << '\t';
 
                // User
-               uid_t uid = th_get_uid(t);
+               uid_t uid = archive_entry_uid(entry);
                struct passwd* pw = getpwuid(uid);
                if (pw)
                        cout << pw->pw_name;
@@ -487,7 +529,7 @@ void pkgutil::pkg_footprint(string& filename) const
                cout << '/';
 
                // Group
-               gid_t gid = th_get_gid(t);
+               gid_t gid = archive_entry_gid(entry);
                struct group* gr = getgrgid(gid);
                if (gr)
                        cout << gr->gr_name;
@@ -495,34 +537,39 @@ void pkgutil::pkg_footprint(string& filename) const
                        cout << gid;
 
                // Filename
-               cout << '\t' << th_get_pathname(t);
+               cout << '\t' << archive_entry_pathname(entry);
 
                // Special cases
-               if (TH_ISSYM(t)) {
+               if (S_ISLNK(status->st_mode)) {
                        // Symlink
-                       cout << " -> " << th_get_linkname(t);
-               } else if (TH_ISCHR(t) || TH_ISBLK(t)) {
+                       cout << " -> " << archive_entry_symlink(entry);
+               } else if (S_ISCHR(status->st_mode) ||
+                          S_ISBLK(status->st_mode)) {
                        // Device
-                       cout << " (" << th_get_devmajor(t) << ", " << th_get_devminor(t) << ")";
-               } else if (TH_ISREG(t) && !th_get_size(t)) {
+                       cout << " (" << archive_entry_rdevmajor(entry)
+                            << ", " << archive_entry_rdevminor(entry)
+                            << ")";
+               } else if (S_ISREG(status->st_mode) &&
+                          archive_entry_size(entry) == 0) {
                        // Empty regular file
                        cout << " (EMPTY)";
                }
 
                cout << '\n';
                
-                if (TH_ISREG(t) && tar_skip_regfile(t))
+               if (S_ISREG(status->st_mode) &&
+                   archive_read_data_skip(archive))
                         throw runtime_error_with_errno("could not read " + filename);
         }
    
         if (i == 0) {
-                if (errno == 0)
+               if (archive_errno(archive) == 0)
                         throw runtime_error("empty package");
                 else
                         throw runtime_error("could not read " + filename);
         }
 
-        tar_close(t);
+       archive_read_finish(archive);
 }
 
 void pkgutil::print_version() const