Skip to content

Commit b99a4f2

Browse files
committed
[*] Fix header ordering relating to #define LIBACQUIRE_IMPLEMENTATION; [acquire/acquire_config.h.in] Fix version resolution ; [acquire_*.h,cli] Improve implementations ;
1 parent b781282 commit b99a4f2

File tree

12 files changed

+341
-206
lines changed

12 files changed

+341
-206
lines changed

acquire/acquire_config.h.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#ifndef LIBACQUIRE_VERSION_H
88
#define LIBACQUIRE_VERSION_H
99

10-
#define VERSION "@libacquire_VERSION@"
10+
#define VERSION "@acquire_VERSION@"
1111
#define TMPDIR "@TMPDIR@"
1212

1313
/* Crypto library */

acquire/acquire_crc32c.h

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ static const unsigned int crctable[256] = {
8787
unsigned int crc32_algo(unsigned int iv, unsigned char *buf, long long len) {
8888
unsigned int crc = iv ^ ~0;
8989
for (; len; len--)
90-
crc = ((crc >> 8) & ~0) ^ crctable[(crc & 0xff) ^ *(buf++)];
90+
crc = (crc >> 8) ^ crctable[(crc & 0xff) ^ *buf++];
9191
return crc ^ ~0;
9292
}
9393

@@ -104,6 +104,8 @@ unsigned int crc32_file(FILE *file) {
104104
bool crc32c(const char *filename, const char *hash) {
105105
unsigned int crc32_res;
106106
FILE *fh;
107+
/* Format computed CRC32C in hex into buffer 9 chars, zero terminated */
108+
char computed[9];
107109
#if defined(_MSC_VER) || defined(__STDC_LIB_EXT1__) && __STDC_WANT_LIB_EXT1__
108110
fopen_s(&fh, filename, "rb");
109111
#else
@@ -115,6 +117,31 @@ bool crc32c(const char *filename, const char *hash) {
115117
fclose(fh);
116118
}
117119
return true;
120+
121+
crc32_res = crc32_file(fh);
122+
fclose(fh);
123+
124+
/* Verify CRC32C checksum: input hash string expected to be hex digits */
125+
snprintf(computed, sizeof(computed), "%08x", crc32_res);
126+
127+
/* Case insensitive compare */
128+
{
129+
int i;
130+
for (i = 0; computed[i] && hash[i]; i++) {
131+
char c1 = computed[i];
132+
char c2 = hash[i];
133+
/* convert both to lowercase */
134+
if (c1 >= 'A' && c1 <= 'F')
135+
c1 += ('a' - 'A');
136+
if (c2 >= 'A' && c2 <= 'F')
137+
c2 += ('a' - 'A');
138+
if (c1 != c2)
139+
return false;
140+
}
141+
if (computed[i] != '\0' || hash[i] != '\0')
142+
return false;
143+
}
144+
return true;
118145
}
119146

120147
#ifdef __cplusplus

acquire/acquire_libcurl.h

Lines changed: 79 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -148,29 +148,31 @@ FILE *get_dnld_stream(char const *const fname) {
148148
return fp;
149149
}
150150

151-
size_t write_cb(const void *buffer, size_t sz, size_t nmemb, void *userdata) {
152-
size_t ret = 0;
153-
struct dnld_params_t *dnld_params = (struct dnld_params_t *)userdata;
151+
size_t write_cb(const void *buffer, const size_t sz, size_t nmemb,
152+
void *userdata) {
153+
struct dnld_params_t *dnld_params = userdata;
154154

155155
if (!dnld_params->dnld_remote_fname[0]) {
156-
ret = get_oname_from_url(dnld_params->dnld_url,
157-
dnld_params->dnld_remote_fname);
156+
get_oname_from_url(dnld_params->dnld_url, dnld_params->dnld_remote_fname);
158157
}
159158

160-
if (ret != 0)
161-
return ret;
162-
163159
if (!dnld_params->dnld_stream) {
164160
dnld_params->dnld_stream =
165161
get_dnld_stream(dnld_params->dnld_full_local_fname);
162+
if (!dnld_params->dnld_stream)
163+
return 0;
166164
}
167165

168-
ret = fwrite(buffer, sz, nmemb, dnld_params->dnld_stream);
169-
170-
if (ret == (sz * nmemb)) {
171-
dnld_params->dnld_file_sz += ret;
166+
{
167+
const size_t bytes_written =
168+
fwrite(buffer, sz, nmemb, dnld_params->dnld_stream);
169+
if (bytes_written == sz * nmemb) {
170+
dnld_params->dnld_file_sz += bytes_written;
171+
return bytes_written;
172+
}
172173
}
173-
return ret;
174+
175+
return 0;
174176
}
175177

176178
int download(const char *url, enum Checksum checksum, const char *hash,
@@ -179,34 +181,47 @@ int download(const char *url, enum Checksum checksum, const char *hash,
179181
CURL *curl;
180182
CURLcode cerr = CURLE_OK;
181183
struct dnld_params_t dnld_params;
182-
size_t i;
183184
const char *path;
184185

185186
memset(&dnld_params, 0, sizeof(dnld_params));
186187

187188
if (is_file(target_location)) {
188-
/* This next branch subsumes the `is_downloaded` function? */
189-
if (filesize(target_location) > 0 /* && check checksum */) {
190-
return EEXIST /*CURLE_ALREADY_COMPLETE*/;
191-
} else
192-
set_remote_fname_to_target_location: {
193-
const size_t target_location_n = strlen(target_location);
189+
if (filesize(target_location) > 0) {
190+
return EEXIST;
191+
} else {
192+
/* treat target_location as a filename */
194193
strncpy(dnld_params.dnld_remote_fname, target_location,
195-
target_location_n);
194+
sizeof(dnld_params.dnld_remote_fname) - 1);
195+
dnld_params.dnld_remote_fname[sizeof(dnld_params.dnld_remote_fname) - 1] =
196+
'\0';
196197
strncpy(dnld_params.dnld_full_local_fname, target_location,
197-
target_location_n);
198+
sizeof(dnld_params.dnld_full_local_fname) - 1);
199+
dnld_params
200+
.dnld_full_local_fname[sizeof(dnld_params.dnld_full_local_fname) -
201+
1] = '\0';
198202
}
199203
} else if (is_relative(target_location)) {
200-
goto set_remote_fname_to_target_location;
204+
/* same as above */
205+
strncpy(dnld_params.dnld_remote_fname, target_location,
206+
sizeof(dnld_params.dnld_remote_fname) - 1);
207+
dnld_params.dnld_remote_fname[sizeof(dnld_params.dnld_remote_fname) - 1] =
208+
'\0';
209+
strncpy(dnld_params.dnld_full_local_fname, target_location,
210+
sizeof(dnld_params.dnld_full_local_fname) - 1);
211+
dnld_params
212+
.dnld_full_local_fname[sizeof(dnld_params.dnld_full_local_fname) - 1] =
213+
'\0';
201214
} else if (!is_directory(target_location)) {
202-
fprintf(stderr, "Create \"%s\" and ensure its accessible, then try again\n",
215+
fprintf(stderr,
216+
"Create \"%s\" and ensure it's accessible, then try again\n",
203217
target_location);
204218
return CURLINFO_OS_ERRNO + 2;
205219
}
206220

207-
curl_global_init((size_t)CURL_GLOBAL_ALL);
221+
strncpy(dnld_params.dnld_url, url, sizeof(dnld_params.dnld_url) - 1);
222+
dnld_params.dnld_url[sizeof(dnld_params.dnld_url) - 1] = '\0';
208223

209-
strncpy(dnld_params.dnld_url, url, strlen(url));
224+
curl_global_init(CURL_GLOBAL_ALL);
210225

211226
curl = curl_easy_init();
212227
if (!curl) {
@@ -215,84 +230,93 @@ int download(const char *url, enum Checksum checksum, const char *hash,
215230
return EXIT_FAILURE;
216231
}
217232

218-
#define handle_curl_error(cerr, name) \
219-
if ((cerr) != CURLE_OK) { \
220-
fprintf(stderr, "%s: failed with err %d\n", name, cerr); \
233+
#define handle_curl_error(cerr_, name) \
234+
if ((cerr_) != CURLE_OK) { \
235+
fprintf(stderr, "%s: failed with err %d: %s\n", name, cerr_, \
236+
curl_easy_strerror(cerr_)); \
221237
goto bail; \
222238
} else
239+
223240
cerr = curl_easy_setopt(curl, CURLOPT_URL, url);
224241
handle_curl_error(cerr, "CURLOPT_URL");
225242

226-
if (url[0] == 'f' && url[1] == 't' && url[2] == 'p' && url[3] == 's')
227-
curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
228-
else
243+
if (strncmp(url, "ftps", 4) == 0) {
244+
curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL);
245+
} else {
229246
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
247+
}
230248

231249
/* ask libcurl to use TLS version 1.2 or later */
232250
curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
233251

234-
curl_easy_setopt(curl, CURLOPT_VERBOSE, verbosity);
252+
curl_easy_setopt(curl, CURLOPT_VERBOSE, (long)verbosity);
235253

236-
/* disable progress meter, set to 0L to enable it */
254+
/* disable progress meter by default */
237255
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L);
238256

239257
cerr = curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, dnld_header_parse);
240-
handle_curl_error(cerr, "CURLOPT_HEADERFUNCTION")
258+
handle_curl_error(cerr, "CURLOPT_HEADERFUNCTION");
241259

242-
cerr = curl_easy_setopt(curl, CURLOPT_HEADERDATA, &dnld_params);
260+
cerr = curl_easy_setopt(curl, CURLOPT_HEADERDATA, (void *)&dnld_params);
243261
handle_curl_error(cerr, "CURLOPT_HEADERDATA");
244262

245263
if (strlen(dnld_params.dnld_remote_fname) == 0 ||
246264
strcmp(dnld_params.dnld_remote_fname, "/") == 0) {
247265
path = get_path_from_url(url);
248-
for (i = 0; i < strlen(path); i++)
249-
dnld_params.dnld_remote_fname[i] = path[i];
250-
dnld_params.dnld_remote_fname[i + 1] = '\0';
266+
if (strlen(path) >= sizeof(dnld_params.dnld_remote_fname))
267+
path = ""; /* fail silently, will error below */
268+
269+
strncpy(dnld_params.dnld_remote_fname, path,
270+
sizeof(dnld_params.dnld_remote_fname) - 1);
271+
dnld_params.dnld_remote_fname[sizeof(dnld_params.dnld_remote_fname) - 1] =
272+
'\0';
251273
}
252274

253-
if (dnld_params.dnld_full_local_fname[0] != 0)
254-
/*pass*/;
255-
else if (strlen(dnld_params.dnld_remote_fname) == 0 ||
256-
strcmp(dnld_params.dnld_remote_fname, "/") == 0) {
257-
fprintf(stderr, "unable to derive a filename to save to, from: %s\n", url);
258-
goto bail;
259-
} else {
260-
snprintf(dnld_params.dnld_full_local_fname, NAME_MAX + 1, "%s/%s",
261-
target_location, dnld_params.dnld_remote_fname);
275+
if (dnld_params.dnld_full_local_fname[0] == '\0') {
276+
if (strlen(dnld_params.dnld_remote_fname) == 0 ||
277+
strcmp(dnld_params.dnld_remote_fname, "/") == 0) {
278+
fprintf(stderr, "unable to derive a filename to save to, from: %s\n",
279+
url);
280+
goto bail;
281+
} else {
282+
snprintf(dnld_params.dnld_full_local_fname,
283+
sizeof(dnld_params.dnld_full_local_fname), "%s%c%s",
284+
target_location, '/', dnld_params.dnld_remote_fname);
285+
}
262286
}
263287

264-
/* fold this condition into one `stat` call? */
265288
if (is_file(dnld_params.dnld_full_local_fname) &&
266289
filesize(dnld_params.dnld_full_local_fname) > 0) {
267-
cerr = CURLE_ALREADY_COMPLETE;
290+
cerr = CURLE_OK /* simulate CURLE_ALREADY_COMPLETE */;
268291
goto bail;
269292
}
270293

271294
cerr = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
272295
handle_curl_error(cerr, "CURLOPT_WRITEFUNCTION");
273296

274-
cerr = curl_easy_setopt(curl, CURLOPT_WRITEDATA, &dnld_params);
297+
cerr = curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&dnld_params);
275298
handle_curl_error(cerr, "CURLOPT_WRITEDATA");
276299

277300
cerr = curl_easy_perform(curl);
278301
if (cerr != CURLE_OK)
279302
fprintf(stderr, "curl_easy_perform() failed: %s\n",
280303
curl_easy_strerror(cerr));
281304

282-
fclose(dnld_params.dnld_stream);
305+
if (dnld_params.dnld_stream) {
306+
fclose(dnld_params.dnld_stream);
307+
dnld_params.dnld_stream = NULL;
308+
}
283309

284310
if (dnld_params.dnld_file_sz < 1) {
285311
fprintf(stderr, "Downloaded an empty file\n");
286312
cerr = CURLE_GOT_NOTHING;
287313
}
288314

289315
bail:
290-
291-
/* always cleanup */
292316
curl_easy_cleanup(curl);
293317
curl_global_cleanup();
294318

295-
if (cerr != CURLE_OK && cerr != CURLE_ALREADY_COMPLETE) {
319+
if (cerr != CURLE_OK) {
296320
fprintf(stderr, "curl failed with: %s\n", curl_easy_strerror(cerr));
297321
return EXIT_FAILURE;
298322
}

acquire/acquire_libfetch.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -796,14 +796,22 @@ int download(const char *url, enum Checksum checksum, const char *hash,
796796
const char target_location[NAME_MAX], bool follow, size_t retry,
797797
size_t verbosity) {
798798
int result;
799-
800-
const char *file_name = get_path_from_url(url);
799+
const char *file_name;
801800
char full_local_fname[NAME_MAX + 1];
802801

803-
if (verbosity < v_level)
802+
file_name = get_path_from_url(url);
803+
804+
if (verbosity < (size_t)v_level)
804805
v_level = (int)verbosity;
805806

806-
snprintf(full_local_fname, NAME_MAX + 1, "%s/%s", target_location, file_name);
807+
/* Construct full path */
808+
if (strlen(target_location) + 1 + strlen(file_name) >=
809+
sizeof(full_local_fname)) {
810+
/* path too long */
811+
return -1;
812+
}
813+
snprintf(full_local_fname, sizeof(full_local_fname), "%s/%s", target_location,
814+
file_name);
807815

808816
result = fetch((char *)url, full_local_fname);
809817
if (result != EXIT_SUCCESS)

0 commit comments

Comments
 (0)