Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Kitware
GitHub Repository: Kitware/CMake
Path: blob/master/Utilities/cmlibarchive/libarchive/archive_entry_sparse.c
3153 views
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
157