Permalink
Browse files

Issue #189: Don't rely on dev/ino being zero when they

have not been set.  Instead, explicitly track when these
values are set.  In particular, this fixes the check
that prevents adding an archive to itself on NetBSD.

SVN-Revision: 3743
  • Loading branch information...
1 parent 51e7b57 commit 7457cf5404c114bff301fafd7d876632df07079c @kientzle kientzle committed Nov 3, 2011
@@ -321,6 +321,12 @@ archive_entry_dev(struct archive_entry *entry)
return (entry->ae_stat.aest_dev);
}
+int
+archive_entry_dev_is_set(struct archive_entry *entry)
+{
+ return (entry->ae_set & AE_SET_DEV);
+}
+
dev_t
archive_entry_devmajor(struct archive_entry *entry)
{
@@ -456,6 +462,12 @@ archive_entry_ino(struct archive_entry *entry)
return (entry->ae_stat.aest_ino);
}
+int
+archive_entry_ino_is_set(struct archive_entry *entry)
+{
+ return (entry->ae_set & AE_SET_INO);
+}
+
int64_t
archive_entry_ino64(struct archive_entry *entry)
{
@@ -732,13 +744,15 @@ void
archive_entry_set_ino(struct archive_entry *entry, int64_t ino)
{
entry->stat_valid = 0;
+ entry->ae_set |= AE_SET_INO;
entry->ae_stat.aest_ino = ino;
}
void
archive_entry_set_ino64(struct archive_entry *entry, int64_t ino)
{
entry->stat_valid = 0;
+ entry->ae_set |= AE_SET_INO;
entry->ae_stat.aest_ino = ino;
}
@@ -855,6 +869,7 @@ void
archive_entry_set_dev(struct archive_entry *entry, dev_t d)
{
entry->stat_valid = 0;
+ entry->ae_set |= AE_SET_DEV;
entry->ae_stat.aest_dev_is_broken_down = 0;
entry->ae_stat.aest_dev = d;
}
@@ -863,6 +878,7 @@ void
archive_entry_set_devmajor(struct archive_entry *entry, dev_t m)
{
entry->stat_valid = 0;
+ entry->ae_set |= AE_SET_DEV;
entry->ae_stat.aest_dev_is_broken_down = 1;
entry->ae_stat.aest_devmajor = m;
}
@@ -871,6 +887,7 @@ void
archive_entry_set_devminor(struct archive_entry *entry, dev_t m)
{
entry->stat_valid = 0;
+ entry->ae_set |= AE_SET_DEV;
entry->ae_stat.aest_dev_is_broken_down = 1;
entry->ae_stat.aest_devminor = m;
}
@@ -206,6 +206,7 @@ __LA_DECL time_t archive_entry_ctime(struct archive_entry *);
__LA_DECL long archive_entry_ctime_nsec(struct archive_entry *);
__LA_DECL int archive_entry_ctime_is_set(struct archive_entry *);
__LA_DECL dev_t archive_entry_dev(struct archive_entry *);
+__LA_DECL int archive_entry_dev_is_set(struct archive_entry *);
__LA_DECL dev_t archive_entry_devmajor(struct archive_entry *);
__LA_DECL dev_t archive_entry_devminor(struct archive_entry *);
__LA_DECL __LA_MODE_T archive_entry_filetype(struct archive_entry *);
@@ -220,6 +221,7 @@ __LA_DECL const char *archive_entry_hardlink(struct archive_entry *);
__LA_DECL const wchar_t *archive_entry_hardlink_w(struct archive_entry *);
__LA_DECL __LA_INT64_T archive_entry_ino(struct archive_entry *);
__LA_DECL __LA_INT64_T archive_entry_ino64(struct archive_entry *);
+__LA_DECL int archive_entry_ino_is_set(struct archive_entry *);
__LA_DECL __LA_MODE_T archive_entry_mode(struct archive_entry *);
__LA_DECL time_t archive_entry_mtime(struct archive_entry *);
__LA_DECL long archive_entry_mtime_nsec(struct archive_entry *);
@@ -136,6 +136,8 @@ struct archive_entry {
#define AE_SET_MTIME 16
#define AE_SET_BIRTHTIME 32
#define AE_SET_SIZE 64
+#define AE_SET_INO 128
+#define AE_SET_DEV 256
/*
* Use aes here so that we get transparent mbs<->wcs conversions.
@@ -127,7 +127,7 @@ archive_read_extract_set_skip_file(struct archive *_a, int64_t d, int64_t i)
if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_MAGIC,
ARCHIVE_STATE_ANY, "archive_read_extract_set_skip_file"))
return;
-
+ a->skip_file_set = 1;
a->skip_file_dev = d;
a->skip_file_ino = i;
}
@@ -100,8 +100,9 @@ archive_read_extract2(struct archive *_a, struct archive_entry *entry,
int r, r2;
/* Set up for this particular entry. */
- archive_write_disk_set_skip_file(ad,
- a->skip_file_dev, a->skip_file_ino);
+ if (a->skip_file_set)
+ archive_write_disk_set_skip_file(ad,
+ a->skip_file_dev, a->skip_file_ino);
r = archive_write_header(ad, entry);
if (r < ARCHIVE_WARN)
r = ARCHIVE_WARN;
@@ -130,6 +130,7 @@ struct archive_read {
struct archive_entry *entry;
/* Dev/ino of the archive being read/written. */
+ int skip_file_set;
dev_t skip_file_dev;
ino_t skip_file_ino;
@@ -197,6 +197,7 @@ archive_write_set_skip_file(struct archive *_a, int64_t d, int64_t i)
struct archive_write *a = (struct archive_write *)_a;
archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
ARCHIVE_STATE_ANY, "archive_write_set_skip_file");
+ a->skip_file_set = 1;
a->skip_file_dev = d;
a->skip_file_ino = i;
return (ARCHIVE_OK);
@@ -619,9 +620,10 @@ _archive_write_header(struct archive *_a, struct archive_entry *entry)
if (ret < ARCHIVE_OK && ret != ARCHIVE_WARN)
return (ret);
- if (a->skip_file_dev != 0 &&
+ if (a->skip_file_set &&
+ archive_entry_dev_is_set(entry) &&
+ archive_entry_ino_is_set(entry) &&
archive_entry_dev(entry) == a->skip_file_dev &&
- a->skip_file_ino != 0 &&
archive_entry_ino64(entry) == a->skip_file_ino) {
archive_set_error(&a->archive, 0,
"Can't add archive to itself");
@@ -187,6 +187,7 @@ struct archive_write_disk {
struct fixup_entry *fixup_list;
struct fixup_entry *current_fixup;
int64_t user_uid;
+ int skip_file_set;
dev_t skip_file_dev;
ino_t skip_file_ino;
time_t start_time;
@@ -616,6 +617,7 @@ archive_write_disk_set_skip_file(struct archive *_a, int64_t d, int64_t i)
struct archive_write_disk *a = (struct archive_write_disk *)_a;
archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
ARCHIVE_STATE_ANY, "archive_write_disk_set_skip_file");
+ a->skip_file_set = 1;
a->skip_file_dev = d;
a->skip_file_ino = i;
return (ARCHIVE_OK);
@@ -1117,8 +1119,7 @@ restore_entry(struct archive_write_disk *a)
}
/* If it's our archive, we're done. */
- if (a->skip_file_dev > 0 &&
- a->skip_file_ino > 0 &&
+ if (a->skip_file_set &&
a->st.st_dev == a->skip_file_dev &&
a->st.st_ino == a->skip_file_ino) {
archive_set_error(&a->archive, 0, "Refusing to overwrite archive");
@@ -128,6 +128,7 @@ struct archive_write_disk {
struct fixup_entry *fixup_list;
struct fixup_entry *current_fixup;
int64_t user_uid;
+ int skip_file_set;
dev_t skip_file_dev;
ino_t skip_file_ino;
time_t start_time;
@@ -869,6 +870,7 @@ archive_write_disk_set_skip_file(struct archive *_a, int64_t d, int64_t i)
struct archive_write_disk *a = (struct archive_write_disk *)_a;
archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
ARCHIVE_STATE_ANY, "archive_write_disk_set_skip_file");
+ a->skip_file_set = 1;
a->skip_file_dev = d;
a->skip_file_ino = i;
return (ARCHIVE_OK);
@@ -1362,8 +1364,7 @@ restore_entry(struct archive_write_disk *a)
}
/* If it's our archive, we're done. */
- if (a->skip_file_dev > 0 &&
- a->skip_file_ino > 0 &&
+ if (a->skip_file_set &&
bhfi_dev(&a->st) == a->skip_file_dev &&
bhfi_ino(&a->st) == a->skip_file_ino) {
archive_set_error(&a->archive, 0, "Refusing to overwrite archive");
@@ -71,6 +71,7 @@ struct archive_write {
struct archive archive;
/* Dev/ino of the archive being written. */
+ int skip_file_set;
dev_t skip_file_dev;
int64_t skip_file_ino;
@@ -63,6 +63,7 @@ DEFINE_TEST(test_entry)
size_t xsize; /* For xattr tests. */
wchar_t wc;
long l;
+ int i;
assert((e = archive_entry_new()) != NULL);
@@ -153,7 +154,9 @@ DEFINE_TEST(test_entry)
assert(!archive_entry_ctime_is_set(e));
/* dev */
+ assert(!archive_entry_dev_is_set(e));
archive_entry_set_dev(e, 235);
+ assert(archive_entry_dev_is_set(e));
assertEqualInt(archive_entry_dev(e), 235);
/* devmajor/devminor are tested specially below. */
@@ -197,8 +200,15 @@ DEFINE_TEST(test_entry)
assertEqualWString(archive_entry_hardlink_w(e), NULL);
/* ino */
+ assert(!archive_entry_ino_is_set(e));
archive_entry_set_ino(e, 8593);
+ assert(archive_entry_ino_is_set(e));
assertEqualInt(archive_entry_ino(e), 8593);
+ assertEqualInt(archive_entry_ino64(e), 8593);
+ archive_entry_set_ino64(e, 8594);
+ assert(archive_entry_ino_is_set(e));
+ assertEqualInt(archive_entry_ino(e), 8594);
+ assertEqualInt(archive_entry_ino64(e), 8594);
/* link */
archive_entry_set_hardlink(e, "hardlinkname");
@@ -807,27 +817,25 @@ DEFINE_TEST(test_entry)
assert(NULL == archive_entry_symlink_w(e));
}
-#if HAVE_WCSCPY
l = 0x12345678L;
wc = (wchar_t)l; /* Wide character too big for UTF-8. */
if (NULL == setlocale(LC_ALL, "C") || (long)wc != l) {
skipping("Testing charset conversion failure requires 32-bit wchar_t and support for \"C\" locale.");
} else {
/*
* Build the string L"xxx\U12345678yyy\u5678zzz" without
- * using C99 \u#### syntax, which isn't uniformly
- * supported. (GCC 3.4.6, for instance, defaults to
- * "c89 plus GNU extensions.")
+ * using wcscpy or C99 \u#### syntax.
*/
- wcscpy(wbuff, L"xxxAyyyBzzz");
+ name = "xxxAyyyBzzz";
+ for (i = 0; i < strlen(name); ++i)
+ wbuff[i] = name[i];
wbuff[3] = (wchar_t)0x12345678;
wbuff[7] = (wchar_t)0x5678;
- /* A wide filename that cannot be converted to narrow. */
+ /* A Unicode filename that cannot be converted to UTF-8. */
archive_entry_copy_pathname_w(e, wbuff);
failure("Converting wide characters from Unicode should fail.");
assertEqualString(NULL, archive_entry_pathname(e));
}
-#endif
/* Release the experimental entry. */
archive_entry_free(e);

0 comments on commit 7457cf5

Please sign in to comment.