From: Michihiro NAKAJIMA Date: Tue, 2 Feb 2010 11:02:08 +0000 (-0500) Subject: Introduce new API archive_entry_sparse_* to manage sparse files. X-Git-Tag: v3.0.0a~1293 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7f46be4f1ec38ea4ae3e964db8051b33168818c2;p=thirdparty%2Flibarchive.git Introduce new API archive_entry_sparse_* to manage sparse files. SVN-Revision: 1855 --- diff --git a/libarchive/archive_entry.c b/libarchive/archive_entry.c index f734b8c4f..550fdf16a 100644 --- a/libarchive/archive_entry.c +++ b/libarchive/archive_entry.c @@ -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); } diff --git a/libarchive/archive_entry.h b/libarchive/archive_entry.h index d5728179e..abd0be57a 100644 --- a/libarchive/archive_entry.h +++ b/libarchive/archive_entry.h @@ -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. * diff --git a/libarchive/archive_entry_private.h b/libarchive/archive_entry_private.h index 5ab4f75f0..6da775efa 100644 --- a/libarchive/archive_entry_private.h +++ b/libarchive/archive_entry_private.h @@ -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 index 000000000..3e142feda --- /dev/null +++ b/libarchive/archive_entry_sparse.c @@ -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 + */