]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Introduce new API archive_entry_sparse_* to manage sparse files.
authorMichihiro NAKAJIMA <ggcueroad@gmail.com>
Tue, 2 Feb 2010 11:02:08 +0000 (06:02 -0500)
committerMichihiro NAKAJIMA <ggcueroad@gmail.com>
Tue, 2 Feb 2010 11:02:08 +0000 (06:02 -0500)
SVN-Revision: 1855

libarchive/archive_entry.c
libarchive/archive_entry.h
libarchive/archive_entry_private.h
libarchive/archive_entry_sparse.c [new file with mode: 0644]

index f734b8c4f51d0429fc20a4ad9ba9b43a902a8de0..550fdf16a62791611f940c1171dcce4fbede60dc 100644 (file)
@@ -383,8 +383,10 @@ archive_entry_clear(struct archive_entry *entry)
        aes_clean(&entry->ae_uname);
        archive_entry_acl_clear(entry);
        archive_entry_xattr_clear(entry);
+       archive_entry_sparse_clear(entry);
        free(entry->stat);
        memset(entry, 0, sizeof(*entry));
+       entry->sparse_tail = &(entry->sparse_head);
        return entry;
 }
 
@@ -394,12 +396,12 @@ archive_entry_clone(struct archive_entry *entry)
        struct archive_entry *entry2;
        struct ae_acl *ap, *ap2;
        struct ae_xattr *xp;
+       struct ae_sparse *sp;
 
        /* Allocate new structure and copy over all of the fields. */
-       entry2 = (struct archive_entry *)malloc(sizeof(*entry2));
+       entry2 = archive_entry_new();
        if (entry2 == NULL)
                return (NULL);
-       memset(entry2, 0, sizeof(*entry2));
        entry2->ae_stat = entry->ae_stat;
        entry2->ae_fflags_set = entry->ae_fflags_set;
        entry2->ae_fflags_clear = entry->ae_fflags_clear;
@@ -431,6 +433,14 @@ archive_entry_clone(struct archive_entry *entry)
                xp = xp->next;
        }
 
+       /* Copy sparse data over. */
+       sp = entry->sparse_head;
+       while (sp != NULL) {
+               archive_entry_sparse_add_entry(entry2,
+                   sp->offset, sp->length);
+               sp = sp->next;
+       }
+
        return (entry2);
 }
 
@@ -450,6 +460,7 @@ archive_entry_new(void)
        if (entry == NULL)
                return (NULL);
        memset(entry, 0, sizeof(*entry));
+       entry->sparse_tail = &(entry->sparse_head);
        return (entry);
 }
 
index d5728179eb7d3d8a1d5f0c85abc0761d240a1cb2..abd0be57ade58bbc664568441b6aa844a640d30f 100644 (file)
@@ -437,6 +437,24 @@ __LA_DECL int      archive_entry_xattr_reset(struct archive_entry *);
 __LA_DECL int  archive_entry_xattr_next(struct archive_entry *,
            const char ** /* name */, const void ** /* value */, size_t *);
 
+/*
+ * sparse
+ */
+
+__LA_DECL void  archive_entry_sparse_clear(struct archive_entry *);
+__LA_DECL void  archive_entry_sparse_add_entry(struct archive_entry *,
+           int64_t /* offset */, int64_t /* length */);
+
+/*
+ * To retrieve the xattr list, first "reset", then repeatedly ask for the
+ * "next" entry.
+ */
+
+__LA_DECL int  archive_entry_sparse_count(struct archive_entry *);
+__LA_DECL int  archive_entry_sparse_reset(struct archive_entry *);
+__LA_DECL int  archive_entry_sparse_next(struct archive_entry *,
+           int64_t * /* offset */, int64_t * /* length */);
+
 /*
  * Utility to match up hardlinks.
  *
index 5ab4f75f0bce0765d63204325c0826ef6c6692f9..6da775efa31450bc8b7ff13032a80bb988014cc1 100644 (file)
@@ -70,6 +70,13 @@ struct ae_xattr {
        size_t  size;
 };
 
+struct ae_sparse {
+       struct ae_sparse *next;
+
+       int64_t  offset;
+       int64_t  length;
+};
+
 /*
  * Description of an archive entry.
  *
@@ -176,6 +183,11 @@ struct archive_entry {
        struct ae_xattr *xattr_head;
        struct ae_xattr *xattr_p;
 
+       /* sparse support. */
+       struct ae_sparse *sparse_head;
+       struct ae_sparse **sparse_tail;
+       struct ae_sparse *sparse_p;
+
        /* Miscellaneous. */
        char             strmode[12];
 };
diff --git a/libarchive/archive_entry_sparse.c b/libarchive/archive_entry_sparse.c
new file mode 100644 (file)
index 0000000..3e142fe
--- /dev/null
@@ -0,0 +1,114 @@
+/*-
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2010 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+__FBSDID("$FreeBSD$");
+
+#include "archive.h"
+#include "archive_entry.h"
+#include "archive_private.h"
+#include "archive_entry_private.h"
+
+/*
+ * sparse handling
+ */
+
+void
+archive_entry_sparse_clear(struct archive_entry *entry)
+{
+       struct ae_sparse *sp;
+
+       while (entry->sparse_head != NULL) {
+               sp = entry->sparse_head->next;
+               free(entry->sparse_head);
+               entry->sparse_head = sp;
+       }
+       entry->sparse_tail = &(entry->sparse_head);
+}
+
+void
+archive_entry_sparse_add_entry(struct archive_entry *entry,
+       int64_t offset, int64_t length)
+{
+       struct ae_sparse *sp;
+
+       if ((sp = (struct ae_sparse *)malloc(sizeof(*sp))) == NULL)
+               /* XXX Error XXX */
+               return;
+
+       sp->offset = offset;
+       sp->length = length;
+       sp->next = NULL;
+
+       *entry->sparse_tail = sp;
+       entry->sparse_tail = &(sp->next);
+}
+
+
+/*
+ * returns number of the sparse entries
+ */
+int
+archive_entry_sparse_count(struct archive_entry *entry)
+{
+       struct ae_sparse *sp;
+       int count = 0;
+
+       for (sp = entry->sparse_head; sp != NULL; sp = sp->next)
+               count++;
+
+       return count;
+}
+
+int
+archive_entry_sparse_reset(struct archive_entry * entry)
+{
+       entry->sparse_p = entry->sparse_head;
+
+       return archive_entry_sparse_count(entry);
+}
+
+int
+archive_entry_sparse_next(struct archive_entry * entry,
+       int64_t *offset, int64_t *length)
+{
+       if (entry->sparse_p) {
+               *offset = entry->sparse_p->offset;
+               *length = entry->sparse_p->length;
+
+               entry->sparse_p = entry->sparse_p->next;
+
+               return (ARCHIVE_OK);
+       } else {
+               *offset = 0;
+               *length = 0;
+               return (ARCHIVE_WARN);
+       }
+}
+
+/*
+ * end of sparse handling
+ */