1231200Smm/*- 2231200Smm * Copyright (c) 2003-2007 Tim Kientzle 3231200Smm * Copyright (c) 2010-2011 Michihiro NAKAJIMA 4231200Smm * All rights reserved. 5231200Smm * 6231200Smm * Redistribution and use in source and binary forms, with or without 7231200Smm * modification, are permitted provided that the following conditions 8231200Smm * are met: 9231200Smm * 1. Redistributions of source code must retain the above copyright 10231200Smm * notice, this list of conditions and the following disclaimer. 11231200Smm * 2. Redistributions in binary form must reproduce the above copyright 12231200Smm * notice, this list of conditions and the following disclaimer in the 13231200Smm * documentation and/or other materials provided with the distribution. 14231200Smm * 15231200Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 16231200Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17231200Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18231200Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 19231200Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20231200Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21231200Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22231200Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23231200Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24231200Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25231200Smm */ 26231200Smm 27231200Smm#include "archive_platform.h" 28231200Smm__FBSDID("$FreeBSD$"); 29231200Smm 30231200Smm#include "archive.h" 31231200Smm#include "archive_entry.h" 32231200Smm#include "archive_private.h" 33231200Smm#include "archive_entry_private.h" 34231200Smm 35231200Smm/* 36231200Smm * sparse handling 37231200Smm */ 38231200Smm 39231200Smmvoid 40231200Smmarchive_entry_sparse_clear(struct archive_entry *entry) 41231200Smm{ 42231200Smm struct ae_sparse *sp; 43231200Smm 44231200Smm while (entry->sparse_head != NULL) { 45231200Smm sp = entry->sparse_head->next; 46231200Smm free(entry->sparse_head); 47231200Smm entry->sparse_head = sp; 48231200Smm } 49231200Smm entry->sparse_tail = NULL; 50231200Smm} 51231200Smm 52231200Smmvoid 53231200Smmarchive_entry_sparse_add_entry(struct archive_entry *entry, 54231200Smm int64_t offset, int64_t length) 55231200Smm{ 56231200Smm struct ae_sparse *sp; 57231200Smm 58231200Smm if (offset < 0 || length < 0) 59231200Smm /* Invalid value */ 60231200Smm return; 61231200Smm if (offset + length < 0 || 62231200Smm offset + length > archive_entry_size(entry)) 63231200Smm /* A value of "length" parameter is too large. */ 64231200Smm return; 65231200Smm if ((sp = entry->sparse_tail) != NULL) { 66231200Smm if (sp->offset + sp->length > offset) 67231200Smm /* Invalid value. */ 68231200Smm return; 69231200Smm if (sp->offset + sp->length == offset) { 70231200Smm if (sp->offset + sp->length + length < 0) 71231200Smm /* A value of "length" parameter is 72231200Smm * too large. */ 73231200Smm return; 74231200Smm /* Expand existing sparse block size. */ 75231200Smm sp->length += length; 76231200Smm return; 77231200Smm } 78231200Smm } 79231200Smm 80231200Smm if ((sp = (struct ae_sparse *)malloc(sizeof(*sp))) == NULL) 81231200Smm /* XXX Error XXX */ 82231200Smm return; 83231200Smm 84231200Smm sp->offset = offset; 85231200Smm sp->length = length; 86231200Smm sp->next = NULL; 87231200Smm 88231200Smm if (entry->sparse_head == NULL) 89231200Smm entry->sparse_head = entry->sparse_tail = sp; 90231200Smm else { 91231200Smm /* Add a new sparse block to the tail of list. */ 92231200Smm if (entry->sparse_tail != NULL) 93231200Smm entry->sparse_tail->next = sp; 94231200Smm entry->sparse_tail = sp; 95231200Smm } 96231200Smm} 97231200Smm 98231200Smm 99231200Smm/* 100231200Smm * returns number of the sparse entries 101231200Smm */ 102231200Smmint 103231200Smmarchive_entry_sparse_count(struct archive_entry *entry) 104231200Smm{ 105231200Smm struct ae_sparse *sp; 106231200Smm int count = 0; 107231200Smm 108231200Smm for (sp = entry->sparse_head; sp != NULL; sp = sp->next) 109231200Smm count++; 110231200Smm 111231200Smm /* 112231200Smm * Sanity check if this entry is exactly sparse. 113231200Smm * If amount of sparse blocks is just one and it indicates the whole 114231200Smm * file data, we should remove it and return zero. 115231200Smm */ 116231200Smm if (count == 1) { 117231200Smm sp = entry->sparse_head; 118231200Smm if (sp->offset == 0 && 119231200Smm sp->length >= archive_entry_size(entry)) { 120231200Smm count = 0; 121231200Smm archive_entry_sparse_clear(entry); 122231200Smm } 123231200Smm } 124231200Smm 125231200Smm return (count); 126231200Smm} 127231200Smm 128231200Smmint 129231200Smmarchive_entry_sparse_reset(struct archive_entry * entry) 130231200Smm{ 131231200Smm entry->sparse_p = entry->sparse_head; 132231200Smm 133231200Smm return archive_entry_sparse_count(entry); 134231200Smm} 135231200Smm 136231200Smmint 137231200Smmarchive_entry_sparse_next(struct archive_entry * entry, 138231200Smm int64_t *offset, int64_t *length) 139231200Smm{ 140231200Smm if (entry->sparse_p) { 141231200Smm *offset = entry->sparse_p->offset; 142231200Smm *length = entry->sparse_p->length; 143231200Smm 144231200Smm entry->sparse_p = entry->sparse_p->next; 145231200Smm 146231200Smm return (ARCHIVE_OK); 147231200Smm } else { 148231200Smm *offset = 0; 149231200Smm *length = 0; 150231200Smm return (ARCHIVE_WARN); 151231200Smm } 152231200Smm} 153231200Smm 154231200Smm/* 155231200Smm * end of sparse handling 156231200Smm */ 157