]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Add a bitmap in the entry to track which values have been
authorTim Kientzle <kientzle@gmail.com>
Sat, 26 Jul 2008 10:32:39 +0000 (06:32 -0400)
committerTim Kientzle <kientzle@gmail.com>
Sat, 26 Jul 2008 10:32:39 +0000 (06:32 -0400)
set.  Change the ad hoc symlink and hardlink tracking to use
the new bitmap, add tracking for atime and size fields.
This is motivated by some errors restoring Zip entries where
the file size is not known and by errors restoring file
times (utimes(2) sets both atime and mtime, old tar archives
only store mtime).
PR: bin/124915

SVN-Revision: 165

libarchive/archive_entry.c
libarchive/archive_entry.h
libarchive/archive_entry_private.h

index 69921c309f1d97f08336e4c53c9e900579a4d18e..b0bbdd3c12d77ebbe807bba3bad59b486c558342 100644 (file)
@@ -395,8 +395,7 @@ archive_entry_clone(struct archive_entry *entry)
        aes_copy(&entry2->ae_hardlink, &entry->ae_hardlink);
        aes_copy(&entry2->ae_pathname, &entry->ae_pathname);
        aes_copy(&entry2->ae_symlink, &entry->ae_symlink);
-       entry2->ae_hardlinkset = entry->ae_hardlinkset;
-       entry2->ae_symlinkset = entry->ae_symlinkset;
+       entry2->ae_set = entry->ae_set;
        aes_copy(&entry2->ae_uname, &entry->ae_uname);
 
        /* Copy ACL data over. */
@@ -455,6 +454,12 @@ archive_entry_atime_nsec(struct archive_entry *entry)
        return (entry->ae_stat.aest_atime_nsec);
 }
 
+int
+archive_entry_atime_is_set(struct archive_entry *entry)
+{
+       return (entry->ae_set & AE_SET_ATIME);
+}
+
 time_t
 archive_entry_ctime(struct archive_entry *entry)
 {
@@ -562,17 +567,17 @@ archive_entry_gname_w(struct archive_entry *entry)
 const char *
 archive_entry_hardlink(struct archive_entry *entry)
 {
-       if (!entry->ae_hardlinkset)
-               return (NULL);
-       return (aes_get_mbs(&entry->ae_hardlink));
+       if (entry->ae_set & AE_SET_HARDLINK)
+               return (aes_get_mbs(&entry->ae_hardlink));
+       return (NULL);
 }
 
 const wchar_t *
 archive_entry_hardlink_w(struct archive_entry *entry)
 {
-       if (!entry->ae_hardlinkset)
-               return (NULL);
-       return (aes_get_wcs(&entry->ae_hardlink));
+       if (entry->ae_set & AE_SET_HARDLINK)
+               return (aes_get_wcs(&entry->ae_hardlink));
+       return (NULL);
 }
 
 ino_t
@@ -651,6 +656,12 @@ archive_entry_size(struct archive_entry *entry)
        return (entry->ae_stat.aest_size);
 }
 
+int
+archive_entry_size_is_set(struct archive_entry *entry)
+{
+       return (entry->ae_set & AE_SET_SIZE);
+}
+
 const char *
 archive_entry_sourcepath(struct archive_entry *entry)
 {
@@ -660,17 +671,17 @@ archive_entry_sourcepath(struct archive_entry *entry)
 const char *
 archive_entry_symlink(struct archive_entry *entry)
 {
-       if (!entry->ae_symlinkset)
-               return (NULL);
-       return (aes_get_mbs(&entry->ae_symlink));
+       if (entry->ae_set & AE_SET_SYMLINK)
+               return (aes_get_mbs(&entry->ae_symlink));
+       return (NULL);
 }
 
 const wchar_t *
 archive_entry_symlink_w(struct archive_entry *entry)
 {
-       if (!entry->ae_symlinkset)
-               return (NULL);
-       return (aes_get_wcs(&entry->ae_symlink));
+       if (entry->ae_set & AE_SET_SYMLINK)
+               return (aes_get_wcs(&entry->ae_symlink));
+       return (NULL);
 }
 
 uid_t
@@ -773,7 +784,9 @@ archive_entry_set_hardlink(struct archive_entry *entry, const char *target)
 {
        aes_set_mbs(&entry->ae_hardlink, target);
        if (target != NULL)
-               entry->ae_hardlinkset = 1;
+               entry->ae_set |= AE_SET_HARDLINK;
+       else
+               entry->ae_set &= ~AE_SET_HARDLINK;
 }
 
 void
@@ -781,7 +794,9 @@ archive_entry_copy_hardlink(struct archive_entry *entry, const char *target)
 {
        aes_copy_mbs(&entry->ae_hardlink, target);
        if (target != NULL)
-               entry->ae_hardlinkset = 1;
+               entry->ae_set |= AE_SET_HARDLINK;
+       else
+               entry->ae_set &= ~AE_SET_HARDLINK;
 }
 
 void
@@ -789,13 +804,16 @@ archive_entry_copy_hardlink_w(struct archive_entry *entry, const wchar_t *target
 {
        aes_copy_wcs(&entry->ae_hardlink, target);
        if (target != NULL)
-               entry->ae_hardlinkset = 1;
+               entry->ae_set |= AE_SET_HARDLINK;
+       else
+               entry->ae_set &= ~AE_SET_HARDLINK;
 }
 
 void
 archive_entry_set_atime(struct archive_entry *entry, time_t t, long ns)
 {
        entry->stat_valid = 0;
+       entry->ae_set |= AE_SET_ATIME;
        entry->ae_stat.aest_atime = t;
        entry->ae_stat.aest_atime_nsec = ns;
 }
@@ -836,7 +854,7 @@ archive_entry_set_devminor(struct archive_entry *entry, dev_t m)
 void
 archive_entry_set_link(struct archive_entry *entry, const char *target)
 {
-       if (entry->ae_symlinkset)
+       if (entry->ae_set & AE_SET_SYMLINK)
                aes_set_mbs(&entry->ae_symlink, target);
        else
                aes_set_mbs(&entry->ae_hardlink, target);
@@ -846,7 +864,7 @@ archive_entry_set_link(struct archive_entry *entry, const char *target)
 void
 archive_entry_copy_link(struct archive_entry *entry, const char *target)
 {
-       if (entry->ae_symlinkset)
+       if (entry->ae_set & AE_SET_SYMLINK)
                aes_copy_mbs(&entry->ae_symlink, target);
        else
                aes_copy_mbs(&entry->ae_hardlink, target);
@@ -856,7 +874,7 @@ archive_entry_copy_link(struct archive_entry *entry, const char *target)
 void
 archive_entry_copy_link_w(struct archive_entry *entry, const wchar_t *target)
 {
-       if (entry->ae_symlinkset)
+       if (entry->ae_set & AE_SET_SYMLINK)
                aes_copy_wcs(&entry->ae_symlink, target);
        else
                aes_copy_wcs(&entry->ae_hardlink, target);
@@ -865,7 +883,7 @@ archive_entry_copy_link_w(struct archive_entry *entry, const wchar_t *target)
 int
 archive_entry_update_link_utf8(struct archive_entry *entry, const char *target)
 {
-       if (entry->ae_symlinkset)
+       if (entry->ae_set & AE_SET_SYMLINK)
                return (aes_update_utf8(&entry->ae_symlink, target));
        else
                return (aes_update_utf8(&entry->ae_hardlink, target));
@@ -954,6 +972,7 @@ archive_entry_set_size(struct archive_entry *entry, int64_t s)
 {
        entry->stat_valid = 0;
        entry->ae_stat.aest_size = s;
+       entry->ae_set |= AE_SET_SIZE;
 }
 
 void
@@ -967,7 +986,9 @@ archive_entry_set_symlink(struct archive_entry *entry, const char *linkname)
 {
        aes_set_mbs(&entry->ae_symlink, linkname);
        if (linkname != NULL)
-               entry->ae_symlinkset = 1;
+               entry->ae_set |= AE_SET_SYMLINK;
+       else
+               entry->ae_set &= ~AE_SET_SYMLINK;
 }
 
 void
@@ -975,7 +996,9 @@ archive_entry_copy_symlink(struct archive_entry *entry, const char *linkname)
 {
        aes_copy_mbs(&entry->ae_symlink, linkname);
        if (linkname != NULL)
-               entry->ae_symlinkset = 1;
+               entry->ae_set |= AE_SET_SYMLINK;
+       else
+               entry->ae_set &= ~AE_SET_SYMLINK;
 }
 
 void
@@ -983,7 +1006,9 @@ archive_entry_copy_symlink_w(struct archive_entry *entry, const wchar_t *linknam
 {
        aes_copy_wcs(&entry->ae_symlink, linkname);
        if (linkname != NULL)
-               entry->ae_symlinkset = 1;
+               entry->ae_set |= AE_SET_SYMLINK;
+       else
+               entry->ae_set &= ~AE_SET_SYMLINK;
 }
 
 void
index ee96c56a79dbbcdd576ae696678027e116820b71..91239f2c1e56e3f8c1e1252073d6c35dcf201e39 100644 (file)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2003-2008 Tim Kientzle
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -152,10 +152,26 @@ __LA_DECL struct archive_entry    *archive_entry_new(void);
 
 /*
  * Retrieve fields from an archive_entry.
+ *
+ * There are a number of implicit conversions among these fields.  For
+ * example, if a regular string field is set and you read the _w wide
+ * character field, the entry will implicitly convert narrow-to-wide
+ * using the current locale.  Similarly, dev values are automatically
+ * updated when you write devmajor or devminor and vice versa.
+ *
+ * In addition, fields can be "set" or "unset."  Unset string fields
+ * return NULL, non-string fields have _is_set() functions to test
+ * whether they've been set.  You can "unset" a string field by
+ * assigning NULL; there is currently no way to unset a non-string
+ * field.
+ *
+ * Note: There is one ambiguity in the above; string fields will
+ * also return NULL when implicit character set conversions fail.
+ * This is usually what you want.
  */
-
 __LA_DECL time_t        archive_entry_atime(struct archive_entry *);
 __LA_DECL long          archive_entry_atime_nsec(struct archive_entry *);
+__LA_DECL int           archive_entry_atime_is_set(struct archive_entry *);
 __LA_DECL time_t        archive_entry_ctime(struct archive_entry *);
 __LA_DECL long          archive_entry_ctime_nsec(struct archive_entry *);
 __LA_DECL dev_t                 archive_entry_dev(struct archive_entry *);
@@ -183,6 +199,7 @@ __LA_DECL dev_t              archive_entry_rdevmajor(struct archive_entry *);
 __LA_DECL dev_t                 archive_entry_rdevminor(struct archive_entry *);
 __LA_DECL const char   *archive_entry_sourcepath(struct archive_entry *);
 __LA_DECL int64_t       archive_entry_size(struct archive_entry *);
+__LA_DECL int           archive_entry_size_is_set(struct archive_entry *);
 __LA_DECL const char   *archive_entry_strmode(struct archive_entry *);
 __LA_DECL const char   *archive_entry_symlink(struct archive_entry *);
 __LA_DECL const wchar_t        *archive_entry_symlink_w(struct archive_entry *);
@@ -195,6 +212,10 @@ __LA_DECL const wchar_t    *archive_entry_uname_w(struct archive_entry *);
  *
  * Note that string 'set' functions do not copy the string, only the pointer.
  * In contrast, 'copy' functions do copy the object pointed to.
+ *
+ * Note: As of libarchive 2.4, 'set' functions do copy the string and
+ * are therefore exact synonyms for the 'copy' versions.  The 'copy'
+ * names will be retired in libarchive 3.0.
  */
 
 __LA_DECL void archive_entry_set_atime(struct archive_entry *, time_t, long);
index 0289290b1981a5f5888d934ff9d9d58d36b20e88..0aa05e5a768ab7766b7bd534207b4c903cdb68b3 100644 (file)
@@ -136,6 +136,12 @@ struct archive_entry {
                dev_t           aest_rdevminor;
        } ae_stat;
 
+       int ae_set; /* bitmap of fields that are currently set */
+#define        AE_SET_HARDLINK 1
+#define        AE_SET_SYMLINK  2
+#define        AE_SET_ATIME    4
+#define        AE_SET_SIZE     32
+
        /*
         * Use aes here so that we get transparent mbs<->wcs conversions.
         */
@@ -147,8 +153,6 @@ struct archive_entry {
        struct aes ae_pathname; /* Name of entry */
        struct aes ae_symlink;          /* symlink contents */
        struct aes ae_uname;            /* Name of owner */
-       unsigned char   ae_hardlinkset;
-       unsigned char   ae_symlinkset;
 
        /* Not used within libarchive; useful for some clients. */
        struct aes ae_sourcepath;       /* Path this entry is sourced from. */