http: use strbufs instead of fixed buffers
We keep the names of incoming packs and objects in fixed PATH_MAX-size buffers, and snprintf() into them. This is unlikely to end up with truncated filenames, but it is possible (especially on systems where PATH_MAX is shorter than actual paths can be). Let's switch to using strbufs, which makes the question go away entirely. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
468165c1d8
commit
390c6cbc5e
66
http.c
66
http.c
@ -2087,6 +2087,7 @@ void release_http_pack_request(struct http_pack_request *preq)
|
|||||||
preq->packfile = NULL;
|
preq->packfile = NULL;
|
||||||
}
|
}
|
||||||
preq->slot = NULL;
|
preq->slot = NULL;
|
||||||
|
strbuf_release(&preq->tmpfile);
|
||||||
free(preq->url);
|
free(preq->url);
|
||||||
free(preq);
|
free(preq);
|
||||||
}
|
}
|
||||||
@ -2109,19 +2110,19 @@ int finish_http_pack_request(struct http_pack_request *preq)
|
|||||||
lst = &((*lst)->next);
|
lst = &((*lst)->next);
|
||||||
*lst = (*lst)->next;
|
*lst = (*lst)->next;
|
||||||
|
|
||||||
if (!strip_suffix(preq->tmpfile, ".pack.temp", &len))
|
if (!strip_suffix(preq->tmpfile.buf, ".pack.temp", &len))
|
||||||
die("BUG: pack tmpfile does not end in .pack.temp?");
|
die("BUG: pack tmpfile does not end in .pack.temp?");
|
||||||
tmp_idx = xstrfmt("%.*s.idx.temp", (int)len, preq->tmpfile);
|
tmp_idx = xstrfmt("%.*s.idx.temp", (int)len, preq->tmpfile.buf);
|
||||||
|
|
||||||
argv_array_push(&ip.args, "index-pack");
|
argv_array_push(&ip.args, "index-pack");
|
||||||
argv_array_pushl(&ip.args, "-o", tmp_idx, NULL);
|
argv_array_pushl(&ip.args, "-o", tmp_idx, NULL);
|
||||||
argv_array_push(&ip.args, preq->tmpfile);
|
argv_array_push(&ip.args, preq->tmpfile.buf);
|
||||||
ip.git_cmd = 1;
|
ip.git_cmd = 1;
|
||||||
ip.no_stdin = 1;
|
ip.no_stdin = 1;
|
||||||
ip.no_stdout = 1;
|
ip.no_stdout = 1;
|
||||||
|
|
||||||
if (run_command(&ip)) {
|
if (run_command(&ip)) {
|
||||||
unlink(preq->tmpfile);
|
unlink(preq->tmpfile.buf);
|
||||||
unlink(tmp_idx);
|
unlink(tmp_idx);
|
||||||
free(tmp_idx);
|
free(tmp_idx);
|
||||||
return -1;
|
return -1;
|
||||||
@ -2129,7 +2130,7 @@ int finish_http_pack_request(struct http_pack_request *preq)
|
|||||||
|
|
||||||
unlink(sha1_pack_index_name(p->sha1));
|
unlink(sha1_pack_index_name(p->sha1));
|
||||||
|
|
||||||
if (finalize_object_file(preq->tmpfile, sha1_pack_name(p->sha1))
|
if (finalize_object_file(preq->tmpfile.buf, sha1_pack_name(p->sha1))
|
||||||
|| finalize_object_file(tmp_idx, sha1_pack_index_name(p->sha1))) {
|
|| finalize_object_file(tmp_idx, sha1_pack_index_name(p->sha1))) {
|
||||||
free(tmp_idx);
|
free(tmp_idx);
|
||||||
return -1;
|
return -1;
|
||||||
@ -2148,6 +2149,7 @@ struct http_pack_request *new_http_pack_request(
|
|||||||
struct http_pack_request *preq;
|
struct http_pack_request *preq;
|
||||||
|
|
||||||
preq = xcalloc(1, sizeof(*preq));
|
preq = xcalloc(1, sizeof(*preq));
|
||||||
|
strbuf_init(&preq->tmpfile, 0);
|
||||||
preq->target = target;
|
preq->target = target;
|
||||||
|
|
||||||
end_url_with_slash(&buf, base_url);
|
end_url_with_slash(&buf, base_url);
|
||||||
@ -2155,12 +2157,11 @@ struct http_pack_request *new_http_pack_request(
|
|||||||
sha1_to_hex(target->sha1));
|
sha1_to_hex(target->sha1));
|
||||||
preq->url = strbuf_detach(&buf, NULL);
|
preq->url = strbuf_detach(&buf, NULL);
|
||||||
|
|
||||||
snprintf(preq->tmpfile, sizeof(preq->tmpfile), "%s.temp",
|
strbuf_addf(&preq->tmpfile, "%s.temp", sha1_pack_name(target->sha1));
|
||||||
sha1_pack_name(target->sha1));
|
preq->packfile = fopen(preq->tmpfile.buf, "a");
|
||||||
preq->packfile = fopen(preq->tmpfile, "a");
|
|
||||||
if (!preq->packfile) {
|
if (!preq->packfile) {
|
||||||
error("Unable to open local file %s for pack",
|
error("Unable to open local file %s for pack",
|
||||||
preq->tmpfile);
|
preq->tmpfile.buf);
|
||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2187,6 +2188,7 @@ struct http_pack_request *new_http_pack_request(
|
|||||||
return preq;
|
return preq;
|
||||||
|
|
||||||
abort:
|
abort:
|
||||||
|
strbuf_release(&preq->tmpfile);
|
||||||
free(preq->url);
|
free(preq->url);
|
||||||
free(preq);
|
free(preq);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -2237,7 +2239,7 @@ struct http_object_request *new_http_object_request(const char *base_url,
|
|||||||
{
|
{
|
||||||
char *hex = sha1_to_hex(sha1);
|
char *hex = sha1_to_hex(sha1);
|
||||||
struct strbuf filename = STRBUF_INIT;
|
struct strbuf filename = STRBUF_INIT;
|
||||||
char prevfile[PATH_MAX];
|
struct strbuf prevfile = STRBUF_INIT;
|
||||||
int prevlocal;
|
int prevlocal;
|
||||||
char prev_buf[PREV_BUF_SIZE];
|
char prev_buf[PREV_BUF_SIZE];
|
||||||
ssize_t prev_read = 0;
|
ssize_t prev_read = 0;
|
||||||
@ -2245,40 +2247,41 @@ struct http_object_request *new_http_object_request(const char *base_url,
|
|||||||
struct http_object_request *freq;
|
struct http_object_request *freq;
|
||||||
|
|
||||||
freq = xcalloc(1, sizeof(*freq));
|
freq = xcalloc(1, sizeof(*freq));
|
||||||
|
strbuf_init(&freq->tmpfile, 0);
|
||||||
hashcpy(freq->sha1, sha1);
|
hashcpy(freq->sha1, sha1);
|
||||||
freq->localfile = -1;
|
freq->localfile = -1;
|
||||||
|
|
||||||
sha1_file_name(&filename, sha1);
|
sha1_file_name(&filename, sha1);
|
||||||
snprintf(freq->tmpfile, sizeof(freq->tmpfile),
|
strbuf_addf(&freq->tmpfile, "%s.temp", filename.buf);
|
||||||
"%s.temp", filename.buf);
|
|
||||||
|
|
||||||
snprintf(prevfile, sizeof(prevfile), "%s.prev", filename.buf);
|
strbuf_addf(&prevfile, "%s.prev", filename.buf);
|
||||||
unlink_or_warn(prevfile);
|
unlink_or_warn(prevfile.buf);
|
||||||
rename(freq->tmpfile, prevfile);
|
rename(freq->tmpfile.buf, prevfile.buf);
|
||||||
unlink_or_warn(freq->tmpfile);
|
unlink_or_warn(freq->tmpfile.buf);
|
||||||
strbuf_release(&filename);
|
strbuf_release(&filename);
|
||||||
|
|
||||||
if (freq->localfile != -1)
|
if (freq->localfile != -1)
|
||||||
error("fd leakage in start: %d", freq->localfile);
|
error("fd leakage in start: %d", freq->localfile);
|
||||||
freq->localfile = open(freq->tmpfile,
|
freq->localfile = open(freq->tmpfile.buf,
|
||||||
O_WRONLY | O_CREAT | O_EXCL, 0666);
|
O_WRONLY | O_CREAT | O_EXCL, 0666);
|
||||||
/*
|
/*
|
||||||
* This could have failed due to the "lazy directory creation";
|
* This could have failed due to the "lazy directory creation";
|
||||||
* try to mkdir the last path component.
|
* try to mkdir the last path component.
|
||||||
*/
|
*/
|
||||||
if (freq->localfile < 0 && errno == ENOENT) {
|
if (freq->localfile < 0 && errno == ENOENT) {
|
||||||
char *dir = strrchr(freq->tmpfile, '/');
|
char *dir = strrchr(freq->tmpfile.buf, '/');
|
||||||
if (dir) {
|
if (dir) {
|
||||||
*dir = 0;
|
*dir = 0;
|
||||||
mkdir(freq->tmpfile, 0777);
|
mkdir(freq->tmpfile.buf, 0777);
|
||||||
*dir = '/';
|
*dir = '/';
|
||||||
}
|
}
|
||||||
freq->localfile = open(freq->tmpfile,
|
freq->localfile = open(freq->tmpfile.buf,
|
||||||
O_WRONLY | O_CREAT | O_EXCL, 0666);
|
O_WRONLY | O_CREAT | O_EXCL, 0666);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (freq->localfile < 0) {
|
if (freq->localfile < 0) {
|
||||||
error_errno("Couldn't create temporary file %s", freq->tmpfile);
|
error_errno("Couldn't create temporary file %s",
|
||||||
|
freq->tmpfile.buf);
|
||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2292,7 +2295,7 @@ struct http_object_request *new_http_object_request(const char *base_url,
|
|||||||
* If a previous temp file is present, process what was already
|
* If a previous temp file is present, process what was already
|
||||||
* fetched.
|
* fetched.
|
||||||
*/
|
*/
|
||||||
prevlocal = open(prevfile, O_RDONLY);
|
prevlocal = open(prevfile.buf, O_RDONLY);
|
||||||
if (prevlocal != -1) {
|
if (prevlocal != -1) {
|
||||||
do {
|
do {
|
||||||
prev_read = xread(prevlocal, prev_buf, PREV_BUF_SIZE);
|
prev_read = xread(prevlocal, prev_buf, PREV_BUF_SIZE);
|
||||||
@ -2309,7 +2312,8 @@ struct http_object_request *new_http_object_request(const char *base_url,
|
|||||||
} while (prev_read > 0);
|
} while (prev_read > 0);
|
||||||
close(prevlocal);
|
close(prevlocal);
|
||||||
}
|
}
|
||||||
unlink_or_warn(prevfile);
|
unlink_or_warn(prevfile.buf);
|
||||||
|
strbuf_release(&prevfile);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reset inflate/SHA1 if there was an error reading the previous temp
|
* Reset inflate/SHA1 if there was an error reading the previous temp
|
||||||
@ -2324,7 +2328,7 @@ struct http_object_request *new_http_object_request(const char *base_url,
|
|||||||
lseek(freq->localfile, 0, SEEK_SET);
|
lseek(freq->localfile, 0, SEEK_SET);
|
||||||
if (ftruncate(freq->localfile, 0) < 0) {
|
if (ftruncate(freq->localfile, 0) < 0) {
|
||||||
error_errno("Couldn't truncate temporary file %s",
|
error_errno("Couldn't truncate temporary file %s",
|
||||||
freq->tmpfile);
|
freq->tmpfile.buf);
|
||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2354,6 +2358,7 @@ struct http_object_request *new_http_object_request(const char *base_url,
|
|||||||
return freq;
|
return freq;
|
||||||
|
|
||||||
abort:
|
abort:
|
||||||
|
strbuf_release(&prevfile);
|
||||||
free(freq->url);
|
free(freq->url);
|
||||||
free(freq);
|
free(freq);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -2381,25 +2386,25 @@ int finish_http_object_request(struct http_object_request *freq)
|
|||||||
if (freq->http_code == 416) {
|
if (freq->http_code == 416) {
|
||||||
warning("requested range invalid; we may already have all the data.");
|
warning("requested range invalid; we may already have all the data.");
|
||||||
} else if (freq->curl_result != CURLE_OK) {
|
} else if (freq->curl_result != CURLE_OK) {
|
||||||
if (stat(freq->tmpfile, &st) == 0)
|
if (stat(freq->tmpfile.buf, &st) == 0)
|
||||||
if (st.st_size == 0)
|
if (st.st_size == 0)
|
||||||
unlink_or_warn(freq->tmpfile);
|
unlink_or_warn(freq->tmpfile.buf);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
git_inflate_end(&freq->stream);
|
git_inflate_end(&freq->stream);
|
||||||
git_SHA1_Final(freq->real_sha1, &freq->c);
|
git_SHA1_Final(freq->real_sha1, &freq->c);
|
||||||
if (freq->zret != Z_STREAM_END) {
|
if (freq->zret != Z_STREAM_END) {
|
||||||
unlink_or_warn(freq->tmpfile);
|
unlink_or_warn(freq->tmpfile.buf);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (hashcmp(freq->sha1, freq->real_sha1)) {
|
if (hashcmp(freq->sha1, freq->real_sha1)) {
|
||||||
unlink_or_warn(freq->tmpfile);
|
unlink_or_warn(freq->tmpfile.buf);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sha1_file_name(&filename, freq->sha1);
|
sha1_file_name(&filename, freq->sha1);
|
||||||
freq->rename = finalize_object_file(freq->tmpfile, filename.buf);
|
freq->rename = finalize_object_file(freq->tmpfile.buf, filename.buf);
|
||||||
strbuf_release(&filename);
|
strbuf_release(&filename);
|
||||||
|
|
||||||
return freq->rename;
|
return freq->rename;
|
||||||
@ -2407,7 +2412,7 @@ int finish_http_object_request(struct http_object_request *freq)
|
|||||||
|
|
||||||
void abort_http_object_request(struct http_object_request *freq)
|
void abort_http_object_request(struct http_object_request *freq)
|
||||||
{
|
{
|
||||||
unlink_or_warn(freq->tmpfile);
|
unlink_or_warn(freq->tmpfile.buf);
|
||||||
|
|
||||||
release_http_object_request(freq);
|
release_http_object_request(freq);
|
||||||
}
|
}
|
||||||
@ -2427,4 +2432,5 @@ void release_http_object_request(struct http_object_request *freq)
|
|||||||
release_active_slot(freq->slot);
|
release_active_slot(freq->slot);
|
||||||
freq->slot = NULL;
|
freq->slot = NULL;
|
||||||
}
|
}
|
||||||
|
strbuf_release(&freq->tmpfile);
|
||||||
}
|
}
|
||||||
|
4
http.h
4
http.h
@ -200,7 +200,7 @@ struct http_pack_request {
|
|||||||
struct packed_git *target;
|
struct packed_git *target;
|
||||||
struct packed_git **lst;
|
struct packed_git **lst;
|
||||||
FILE *packfile;
|
FILE *packfile;
|
||||||
char tmpfile[PATH_MAX];
|
struct strbuf tmpfile;
|
||||||
struct active_request_slot *slot;
|
struct active_request_slot *slot;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -212,7 +212,7 @@ extern void release_http_pack_request(struct http_pack_request *preq);
|
|||||||
/* Helpers for fetching object */
|
/* Helpers for fetching object */
|
||||||
struct http_object_request {
|
struct http_object_request {
|
||||||
char *url;
|
char *url;
|
||||||
char tmpfile[PATH_MAX];
|
struct strbuf tmpfile;
|
||||||
int localfile;
|
int localfile;
|
||||||
CURLcode curl_result;
|
CURLcode curl_result;
|
||||||
char errorstr[CURL_ERROR_SIZE];
|
char errorstr[CURL_ERROR_SIZE];
|
||||||
|
Loading…
Reference in New Issue
Block a user