Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Kitware
GitHub Repository: Kitware/CMake
Path: blob/master/Utilities/cmlibarchive/libarchive/archive_cmdline.c
3153 views
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_set_path(struct archive_cmdline *, const char *);
40
static int cmdline_add_arg(struct archive_cmdline *, const char *);
41
42
static ssize_t
43
extract_quotation(struct archive_string *as, const char *p)
44
{
45
const char *s;
46
47
for (s = p + 1; *s;) {
48
if (*s == '\\') {
49
if (s[1] != '\0') {
50
archive_strappend_char(as, s[1]);
51
s += 2;
52
} else
53
s++;
54
} else if (*s == '"')
55
break;
56
else {
57
archive_strappend_char(as, s[0]);
58
s++;
59
}
60
}
61
if (*s != '"')
62
return (ARCHIVE_FAILED);/* Invalid sequence. */
63
return ((ssize_t)(s + 1 - p));
64
}
65
66
static ssize_t
67
get_argument(struct archive_string *as, const char *p)
68
{
69
const char *s = p;
70
71
archive_string_empty(as);
72
73
/* Skip beginning space characters. */
74
while (*s != '\0' && *s == ' ')
75
s++;
76
/* Copy non-space characters. */
77
while (*s != '\0' && *s != ' ') {
78
if (*s == '\\') {
79
if (s[1] != '\0') {
80
archive_strappend_char(as, s[1]);
81
s += 2;
82
} else {
83
s++;/* Ignore this character.*/
84
break;
85
}
86
} else if (*s == '"') {
87
ssize_t q = extract_quotation(as, s);
88
if (q < 0)
89
return (ARCHIVE_FAILED);/* Invalid sequence. */
90
s += q;
91
} else {
92
archive_strappend_char(as, s[0]);
93
s++;
94
}
95
}
96
return ((ssize_t)(s - p));
97
}
98
99
/*
100
* Set up command line arguments.
101
* Returns ARCHIVE_OK if everything okey.
102
* Returns ARCHIVE_FAILED if there is a lack of the `"' terminator or an
103
* empty command line.
104
* Returns ARCHIVE_FATAL if no memory.
105
*/
106
int
107
__archive_cmdline_parse(struct archive_cmdline *data, const char *cmd)
108
{
109
struct archive_string as;
110
const char *p;
111
ssize_t al;
112
int r;
113
114
archive_string_init(&as);
115
116
/* Get first argument as a command path. */
117
al = get_argument(&as, cmd);
118
if (al < 0) {
119
r = ARCHIVE_FAILED;/* Invalid sequence. */
120
goto exit_function;
121
}
122
if (archive_strlen(&as) == 0) {
123
r = ARCHIVE_FAILED;/* An empty command path. */
124
goto exit_function;
125
}
126
r = cmdline_set_path(data, as.s);
127
if (r != ARCHIVE_OK)
128
goto exit_function;
129
p = strrchr(as.s, '/');
130
if (p == NULL)
131
p = as.s;
132
else
133
p++;
134
r = cmdline_add_arg(data, p);
135
if (r != ARCHIVE_OK)
136
goto exit_function;
137
cmd += al;
138
139
for (;;) {
140
al = get_argument(&as, cmd);
141
if (al < 0) {
142
r = ARCHIVE_FAILED;/* Invalid sequence. */
143
goto exit_function;
144
}
145
if (al == 0)
146
break;
147
cmd += al;
148
if (archive_strlen(&as) == 0 && *cmd == '\0')
149
break;
150
r = cmdline_add_arg(data, as.s);
151
if (r != ARCHIVE_OK)
152
goto exit_function;
153
}
154
r = ARCHIVE_OK;
155
exit_function:
156
archive_string_free(&as);
157
return (r);
158
}
159
160
/*
161
* Set the program path.
162
*/
163
static int
164
cmdline_set_path(struct archive_cmdline *data, const char *path)
165
{
166
char *newptr;
167
168
newptr = realloc(data->path, strlen(path) + 1);
169
if (newptr == NULL)
170
return (ARCHIVE_FATAL);
171
data->path = newptr;
172
strcpy(data->path, path);
173
return (ARCHIVE_OK);
174
}
175
176
/*
177
* Add a argument for the program.
178
*/
179
static int
180
cmdline_add_arg(struct archive_cmdline *data, const char *arg)
181
{
182
char **newargv;
183
184
if (data->path == NULL)
185
return (ARCHIVE_FAILED);
186
187
newargv = realloc(data->argv, (data->argc + 2) * sizeof(char *));
188
if (newargv == NULL)
189
return (ARCHIVE_FATAL);
190
data->argv = newargv;
191
data->argv[data->argc] = strdup(arg);
192
if (data->argv[data->argc] == NULL)
193
return (ARCHIVE_FATAL);
194
/* Set the terminator of argv. */
195
data->argv[++data->argc] = NULL;
196
return (ARCHIVE_OK);
197
}
198
199
struct archive_cmdline *
200
__archive_cmdline_allocate(void)
201
{
202
return (struct archive_cmdline *)
203
calloc(1, sizeof(struct archive_cmdline));
204
}
205
206
/*
207
* Release the resources.
208
*/
209
int
210
__archive_cmdline_free(struct archive_cmdline *data)
211
{
212
213
if (data) {
214
free(data->path);
215
if (data->argv != NULL) {
216
int i;
217
for (i = 0; data->argv[i] != NULL; i++)
218
free(data->argv[i]);
219
free(data->argv);
220
}
221
free(data);
222
}
223
return (ARCHIVE_OK);
224
}
225
226
227