Coverage Report

Created: 2026-09-14 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Utilities/cmlibarchive/libarchive/archive_cmdline.c
Line
Count
Source
1
/*-
2
 * Copyright (c) 2012 Michihiro NAKAJIMA 
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 *
14
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17
 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
 */
25
26
#include "archive_platform.h"
27
28
#ifdef HAVE_STRING_H
29
#  include <string.h>
30
#endif
31
#ifdef HAVE_STDLIB_H
32
#  include <stdlib.h>
33
#endif
34
35
#include "archive.h"
36
#include "archive_cmdline_private.h"
37
#include "archive_string.h"
38
39
static int cmdline_add_arg(struct archive_cmdline *, const char *);
40
41
static ssize_t
42
extract_quotation(struct archive_string *as, const char *p)
43
0
{
44
0
  const char *s;
45
46
0
  for (s = p + 1; *s;) {
47
0
    if (*s == '\\') {
48
0
      if (s[1] != '\0') {
49
0
        archive_strappend_char(as, s[1]);
50
0
        s += 2;
51
0
      } else
52
0
        s++;
53
0
    } else if (*s == '"')
54
0
      break;
55
0
    else {
56
0
      archive_strappend_char(as, s[0]);
57
0
      s++;
58
0
    }
59
0
  }
60
0
  if (*s != '"')
61
0
    return (ARCHIVE_FAILED);/* Invalid sequence. */
62
0
  return ((ssize_t)(s + 1 - p));
63
0
}
64
65
static ssize_t
66
get_argument(struct archive_string *as, const char *p)
67
58
{
68
58
  const char *s = p;
69
70
58
  archive_string_empty(as);
71
72
  /* Skip beginning space characters. */
73
84
  while (*s == ' ')
74
26
    s++;
75
  /* Copy non-space characters. */
76
178
  while (*s != '\0' && *s != ' ') {
77
120
    if (*s == '\\') {
78
0
      if (s[1] != '\0') {
79
0
        archive_strappend_char(as, s[1]);
80
0
        s += 2;
81
0
      } else {
82
0
        s++;/* Ignore this character.*/
83
0
        break;
84
0
      }
85
120
    } else if (*s == '"') {
86
0
      ssize_t q = extract_quotation(as, s);
87
0
      if (q < 0)
88
0
        return (ARCHIVE_FAILED);/* Invalid sequence. */
89
0
      s += q;
90
120
    } else {
91
120
      archive_strappend_char(as, s[0]);
92
120
      s++;
93
120
    }
94
120
  }
95
58
  return ((ssize_t)(s - p));
96
58
}
97
98
/*
99
 * Set up command line arguments.
100
 * Returns ARCHIVE_OK if everything okay.
101
 * Returns ARCHIVE_FAILED if there is a lack of the `"' terminator or an
102
 * empty command line.
103
 * Returns ARCHIVE_FATAL if no memory.
104
 */
105
int
106
__archive_cmdline_parse(struct archive_cmdline *data, const char *cmd)
107
16
{
108
16
  struct archive_string as;
109
16
  const char *p;
110
16
  ssize_t al;
111
16
  int r;
112
113
16
  archive_string_init(&as);
114
115
  /* Get first argument as a command path. */
116
16
  al = get_argument(&as, cmd);
117
16
  if (al < 0) {
118
0
    r = ARCHIVE_FAILED;/* Invalid sequence. */
119
0
    goto exit_function;
120
0
  }
121
16
  if (archive_strlen(&as) == 0) {
122
0
    r = ARCHIVE_FAILED;/* An empty command path. */
123
0
    goto exit_function;
124
0
  }
125
16
  free(data->path);
126
16
  data->path = strdup(as.s);
127
16
  if (data->path == NULL) {
128
0
    r = ARCHIVE_FATAL;
129
0
    goto exit_function;
130
0
  }
131
16
  p = strrchr(as.s, '/');
132
16
  if (p == NULL)
133
16
    p = as.s;
134
0
  else
135
0
    p++;
136
16
  r = cmdline_add_arg(data, p);
137
16
  if (r != ARCHIVE_OK)
138
0
    goto exit_function;
139
16
  cmd += al;
140
141
42
  for (;;) {
142
42
    al = get_argument(&as, cmd);
143
42
    if (al < 0) {
144
0
      r = ARCHIVE_FAILED;/* Invalid sequence. */
145
0
      goto exit_function;
146
0
    }
147
42
    if (al == 0)
148
16
      break;
149
26
    cmd += al;
150
26
    if (archive_strlen(&as) == 0 && *cmd == '\0')
151
0
      break;
152
26
    r = cmdline_add_arg(data, as.s);
153
26
    if (r != ARCHIVE_OK)
154
0
      goto exit_function;
155
26
  }
156
16
  r = ARCHIVE_OK;
157
16
exit_function:
158
16
  archive_string_free(&as);
159
16
  return (r);
160
16
}
161
162
/*
163
 * Add an argument for the program.
164
 */
165
static int
166
cmdline_add_arg(struct archive_cmdline *data, const char *arg)
167
42
{
168
42
  char **newargv;
169
170
42
  if (data->path == NULL)
171
0
    return (ARCHIVE_FAILED);
172
173
42
  newargv = realloc(data->argv, (data->argc + 2) * sizeof(char *));
174
42
  if (newargv == NULL)
175
0
    return (ARCHIVE_FATAL);
176
42
  data->argv = newargv;
177
42
  data->argv[data->argc] = strdup(arg);
178
42
  if (data->argv[data->argc] == NULL)
179
0
    return (ARCHIVE_FATAL);
180
  /* Set the terminator of argv. */
181
42
  data->argv[++data->argc] = NULL;
182
42
  return (ARCHIVE_OK);
183
42
}
184
185
struct archive_cmdline *
186
__archive_cmdline_allocate(void)
187
16
{
188
16
  return (struct archive_cmdline *)
189
16
    calloc(1, sizeof(struct archive_cmdline));
190
16
}
191
192
/*
193
 * Release the resources.
194
 */
195
int
196
__archive_cmdline_free(struct archive_cmdline *data)
197
16
{
198
199
16
  if (data) {
200
16
    free(data->path);
201
16
    if (data->argv != NULL) {
202
16
      int i;
203
58
      for (i = 0; data->argv[i] != NULL; i++)
204
42
        free(data->argv[i]);
205
16
      free(data->argv);
206
16
    }
207
16
    free(data);
208
16
  }
209
16
  return (ARCHIVE_OK);
210
16
}
211