Coverage Report

Created: 2026-03-12 06:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Utilities/cmlibarchive/libarchive/archive_entry_sparse.c
Line
Count
Source
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
45.4k
{
41
45.4k
  struct ae_sparse *sp;
42
43
45.4k
  while (entry->sparse_head != NULL) {
44
0
    sp = entry->sparse_head->next;
45
0
    free(entry->sparse_head);
46
0
    entry->sparse_head = sp;
47
0
  }
48
45.4k
  entry->sparse_tail = NULL;
49
45.4k
}
50
51
void
52
archive_entry_sparse_add_entry(struct archive_entry *entry,
53
  la_int64_t offset, la_int64_t length)
54
0
{
55
0
  struct ae_sparse *sp;
56
57
0
  if (offset < 0 || length < 0)
58
    /* Invalid value */
59
0
    return;
60
0
  if (offset > INT64_MAX - length ||
61
0
      offset + length > archive_entry_size(entry))
62
    /* A value of "length" parameter is too large. */
63
0
    return;
64
0
  if ((sp = entry->sparse_tail) != NULL) {
65
0
    if (sp->offset + sp->length > offset)
66
      /* Invalid value. */
67
0
      return;
68
0
    if (sp->offset + sp->length == offset) {
69
0
      if (sp->offset + sp->length + length < 0)
70
        /* A value of "length" parameter is
71
         * too large. */
72
0
        return;
73
      /* Expand existing sparse block size. */
74
0
      sp->length += length;
75
0
      return;
76
0
    }
77
0
  }
78
79
0
  if ((sp = malloc(sizeof(*sp))) == NULL)
80
    /* XXX Error XXX */
81
0
    return;
82
83
0
  sp->offset = offset;
84
0
  sp->length = length;
85
0
  sp->next = NULL;
86
87
0
  if (entry->sparse_head == NULL)
88
0
    entry->sparse_head = entry->sparse_tail = sp;
89
0
  else {
90
    /* Add a new sparse block to the tail of list. */
91
0
    if (entry->sparse_tail != NULL)
92
0
      entry->sparse_tail->next = sp;
93
0
    entry->sparse_tail = sp;
94
0
  }
95
0
}
96
97
98
/*
99
 * returns number of the sparse entries
100
 */
101
int
102
archive_entry_sparse_count(struct archive_entry *entry)
103
0
{
104
0
  struct ae_sparse *sp;
105
0
  int count = 0;
106
107
0
  for (sp = entry->sparse_head; sp != NULL; sp = sp->next)
108
0
    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
0
  if (count == 1) {
116
0
    sp = entry->sparse_head;
117
0
    if (sp->offset == 0 &&
118
0
        sp->length >= archive_entry_size(entry)) {
119
0
      count = 0;
120
0
      archive_entry_sparse_clear(entry);
121
0
    }
122
0
  }
123
124
0
  return (count);
125
0
}
126
127
int
128
archive_entry_sparse_reset(struct archive_entry * entry)
129
0
{
130
0
  entry->sparse_p = entry->sparse_head;
131
132
0
  return archive_entry_sparse_count(entry);
133
0
}
134
135
int
136
archive_entry_sparse_next(struct archive_entry * entry,
137
  la_int64_t *offset, la_int64_t *length)
138
0
{
139
0
  if (entry->sparse_p) {
140
0
    *offset = entry->sparse_p->offset;
141
0
    *length = entry->sparse_p->length;
142
143
0
    entry->sparse_p = entry->sparse_p->next;
144
145
0
    return (ARCHIVE_OK);
146
0
  } else {
147
0
    *offset = 0;
148
0
    *length = 0;
149
0
    return (ARCHIVE_WARN);
150
0
  }
151
0
}
152
153
/*
154
 * end of sparse handling
155
 */