Home | History | Annotate | Line # | Download | only in libarchive
      1 /*-
      2  * Copyright (c) 2003-2007 Tim Kientzle
      3  * Copyright (c) 2010-2011 Michihiro NAKAJIMA
      4  * All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
     16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     18  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
     19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     25  */
     26 
     27 #include "archive_platform.h"
     28 
     29 #include "archive.h"
     30 #include "archive_entry.h"
     31 #include "archive_private.h"
     32 #include "archive_entry_private.h"
     33 
     34 /*
     35  * sparse handling
     36  */
     37 
     38 void
     39 archive_entry_sparse_clear(struct archive_entry *entry)
     40 {
     41 	struct ae_sparse *sp;
     42 
     43 	while (entry->sparse_head != NULL) {
     44 		sp = entry->sparse_head->next;
     45 		free(entry->sparse_head);
     46 		entry->sparse_head = sp;
     47 	}
     48 	entry->sparse_tail = NULL;
     49 }
     50 
     51 void
     52 archive_entry_sparse_add_entry(struct archive_entry *entry,
     53 	la_int64_t offset, la_int64_t length)
     54 {
     55 	struct ae_sparse *sp;
     56 
     57 	if (offset < 0 || length < 0)
     58 		/* Invalid value */
     59 		return;
     60 	if (offset > INT64_MAX - length ||
     61 	    offset + length > archive_entry_size(entry))
     62 		/* A value of "length" parameter is too large. */
     63 		return;
     64 	if ((sp = entry->sparse_tail) != NULL) {
     65 		if (sp->offset + sp->length > offset)
     66 			/* Invalid value. */
     67 			return;
     68 		if (sp->offset + sp->length == offset) {
     69 			if (sp->offset + sp->length + length < 0)
     70 				/* A value of "length" parameter is
     71 				 * too large. */
     72 				return;
     73 			/* Expand existing sparse block size. */
     74 			sp->length += length;
     75 			return;
     76 		}
     77 	}
     78 
     79 	if ((sp = malloc(sizeof(*sp))) == NULL)
     80 		/* XXX Error XXX */
     81 		return;
     82 
     83 	sp->offset = offset;
     84 	sp->length = length;
     85 	sp->next = NULL;
     86 
     87 	if (entry->sparse_head == NULL)
     88 		entry->sparse_head = entry->sparse_tail = sp;
     89 	else {
     90 		/* Add a new sparse block to the tail of list. */
     91 		if (entry->sparse_tail != NULL)
     92 			entry->sparse_tail->next = sp;
     93 		entry->sparse_tail = sp;
     94 	}
     95 }
     96 
     97 
     98 /*
     99  * returns number of the sparse entries
    100  */
    101 int
    102 archive_entry_sparse_count(struct archive_entry *entry)
    103 {
    104 	struct ae_sparse *sp;
    105 	int count = 0;
    106 
    107 	for (sp = entry->sparse_head; sp != NULL; sp = sp->next)
    108 		count++;
    109 
    110 	/*
    111 	 * Sanity check if this entry is exactly sparse.
    112 	 * If amount of sparse blocks is just one and it indicates the whole
    113 	 * file data, we should remove it and return zero.
    114 	 */
    115 	if (count == 1) {
    116 		sp = entry->sparse_head;
    117 		if (sp->offset == 0 &&
    118 		    sp->length >= archive_entry_size(entry)) {
    119 			count = 0;
    120 			archive_entry_sparse_clear(entry);
    121 		}
    122 	}
    123 
    124 	return (count);
    125 }
    126 
    127 int
    128 archive_entry_sparse_reset(struct archive_entry * entry)
    129 {
    130 	entry->sparse_p = entry->sparse_head;
    131 
    132 	return archive_entry_sparse_count(entry);
    133 }
    134 
    135 int
    136 archive_entry_sparse_next(struct archive_entry * entry,
    137 	la_int64_t *offset, la_int64_t *length)
    138 {
    139 	if (entry->sparse_p) {
    140 		*offset = entry->sparse_p->offset;
    141 		*length = entry->sparse_p->length;
    142 
    143 		entry->sparse_p = entry->sparse_p->next;
    144 
    145 		return (ARCHIVE_OK);
    146 	} else {
    147 		*offset = 0;
    148 		*length = 0;
    149 		return (ARCHIVE_WARN);
    150 	}
    151 }
    152 
    153 /*
    154  * end of sparse handling
    155  */
    156