Coverage Report

Created: 2026-10-28 06:38

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
78
{
68
78
  const char *s = p;
69
70
78
  archive_string_empty(as);
71
72
  /* Skip beginning space characters. */
73
112
  while (*s == ' ')
74
34
    s++;
75
  /* Copy non-space characters. */
76
240
  while (*s != '\0' && *s != ' ') {
77
162
    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
162
    } 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
162
    } else {
91
162
      archive_strappend_char(as, s[0]);
92
162
      s++;
93
162
    }
94
162
  }
95
78
  return ((ssize_t)(s - p));
96
78
}
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
22
{
108
22
  struct archive_string as;
109
22
  const char *p;
110
22
  ssize_t al;
111
22
  int r;
112
113
22
  archive_string_init(&as);
114
115
  /* Get first argument as a command path. */
116
22
  al = get_argument(&as, cmd);
117
22
  if (al < 0) {
118
0
    r = ARCHIVE_FAILED;/* Invalid sequence. */
119
0
    goto exit_function;
120
0
  }
121
22
  if (archive_strlen(&as) == 0) {
122
0
    r = ARCHIVE_FAILED;/* An empty command path. */
123
0
    goto exit_function;
124
0
  }
125
22
  free(data->path);
126
22
  data->path = strdup(as.s);
127
22
  if (data->path == NULL) {
128
0
    r = ARCHIVE_FATAL;
129
0
    goto exit_function;
130
0
  }
131
22
  p = strrchr(as.s, '/');
132
22
  if (p == NULL)
133
22
    p = as.s;
134
0
  else
135
0
    p++;
136
22
  r = cmdline_add_arg(data, p);
137
22
  if (r != ARCHIVE_OK)
138
0
    goto exit_function;
139
22
  cmd += al;
140
141
56
  for (;;) {
142
56
    al = get_argument(&as, cmd);
143
56
    if (al < 0) {
144
0
      r = ARCHIVE_FAILED;/* Invalid sequence. */
145
0
      goto exit_function;
146
0
    }
147
56
    if (al == 0)
148
22
      break;
149
34
    cmd += al;
150
34
    if (archive_strlen(&as) == 0 && *cmd == '\0')
151
0
      break;
152
34
    r = cmdline_add_arg(data, as.s);
153
34
    if (r != ARCHIVE_OK)
154
0
      goto exit_function;
155
34
  }
156
22
  r = ARCHIVE_OK;
157
22
exit_function:
158
22
  archive_string_free(&as);
159
22
  return (r);
160
22
}
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
56
{
168
56
  char **newargv;
169
170
56
  if (data->path == NULL)
171
0
    return (ARCHIVE_FAILED);
172
173
56
  newargv = realloc(data->argv, (data->argc + 2) * sizeof(char *));
174
56
  if (newargv == NULL)
175
0
    return (ARCHIVE_FATAL);
176
56
  data->argv = newargv;
177
56
  data->argv[data->argc] = strdup(arg);
178
56
  if (data->argv[data->argc] == NULL)
179
0
    return (ARCHIVE_FATAL);
180
  /* Set the terminator of argv. */
181
56
  data->argv[++data->argc] = NULL;
182
56
  return (ARCHIVE_OK);
183
56
}
184
185
struct archive_cmdline *
186
__archive_cmdline_allocate(void)
187
22
{
188
22
  return (struct archive_cmdline *)
189
22
    calloc(1, sizeof(struct archive_cmdline));
190
22
}
191
192
/*
193
 * Release the resources.
194
 */
195
int
196
__archive_cmdline_free(struct archive_cmdline *data)
197
22
{
198
199
22
  if (data) {
200
22
    free(data->path);
201
22
    if (data->argv != NULL) {
202
22
      int i;
203
78
      for (i = 0; data->argv[i] != NULL; i++)
204
56
        free(data->argv[i]);
205
22
      free(data->argv);
206
22
    }
207
22
    free(data);
208
22
  }
209
22
  return (ARCHIVE_OK);
210
22
}
211