Skip to content

Commit 3944ba0

Browse files
mstorsjogitster
authored andcommitted
Allow curl to rewind the read buffers
When using multi-pass authentication methods, the curl library may need to rewind the read buffers (depending on how much already has been fed to the server) used for providing data to HTTP PUT, POST or PROPFIND, and in order to allow the library to do so, we need to tell it how by providing either an ioctl callback or a seek callback. This patch adds an ioctl callback, which should be usable on older curl versions (since 7.12.3) than the seek callback (introduced in curl 7.18.0). Some HTTP servers (such as Apache) give an 401 error reply immediately after receiving the headers (so no data has been read from the read buffers, and thus no rewinding is needed), but other servers (such as Lighttpd) only replies after the whole request has been sent and all data has been read from the read buffers, making rewinding necessary. Signed-off-by: Martin Storsjo <martin@martin.st> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent dffc131 commit 3944ba0

File tree

3 files changed

+50
-0
lines changed

3 files changed

+50
-0
lines changed

http-push.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,10 @@ static void start_put(struct transfer_request *request)
567567
curl_easy_setopt(slot->curl, CURLOPT_INFILE, &request->buffer);
568568
curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, request->buffer.buf.len);
569569
curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
570+
#ifndef NO_CURL_IOCTL
571+
curl_easy_setopt(slot->curl, CURLOPT_IOCTLFUNCTION, ioctl_buffer);
572+
curl_easy_setopt(slot->curl, CURLOPT_IOCTLDATA, &request->buffer);
573+
#endif
570574
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
571575
curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PUT);
572576
curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
@@ -1267,6 +1271,10 @@ static struct remote_lock *lock_remote(const char *path, long timeout)
12671271
curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
12681272
curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.buf.len);
12691273
curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
1274+
#ifndef NO_CURL_IOCTL
1275+
curl_easy_setopt(slot->curl, CURLOPT_IOCTLFUNCTION, ioctl_buffer);
1276+
curl_easy_setopt(slot->curl, CURLOPT_IOCTLDATA, &out_buffer);
1277+
#endif
12701278
curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
12711279
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
12721280
curl_easy_setopt(slot->curl, CURLOPT_URL, url);
@@ -1508,6 +1516,10 @@ static void remote_ls(const char *path, int flags,
15081516
curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
15091517
curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.buf.len);
15101518
curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
1519+
#ifndef NO_CURL_IOCTL
1520+
curl_easy_setopt(slot->curl, CURLOPT_IOCTLFUNCTION, ioctl_buffer);
1521+
curl_easy_setopt(slot->curl, CURLOPT_IOCTLDATA, &out_buffer);
1522+
#endif
15111523
curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
15121524
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
15131525
curl_easy_setopt(slot->curl, CURLOPT_URL, url);
@@ -1584,6 +1596,10 @@ static int locking_available(void)
15841596
curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
15851597
curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.buf.len);
15861598
curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
1599+
#ifndef NO_CURL_IOCTL
1600+
curl_easy_setopt(slot->curl, CURLOPT_IOCTLFUNCTION, ioctl_buffer);
1601+
curl_easy_setopt(slot->curl, CURLOPT_IOCTLDATA, &out_buffer);
1602+
#endif
15871603
curl_easy_setopt(slot->curl, CURLOPT_FILE, &in_buffer);
15881604
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
15891605
curl_easy_setopt(slot->curl, CURLOPT_URL, repo->url);
@@ -1766,6 +1782,10 @@ static int update_remote(unsigned char *sha1, struct remote_lock *lock)
17661782
curl_easy_setopt(slot->curl, CURLOPT_INFILE, &out_buffer);
17671783
curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, out_buffer.buf.len);
17681784
curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
1785+
#ifndef NO_CURL_IOCTL
1786+
curl_easy_setopt(slot->curl, CURLOPT_IOCTLFUNCTION, ioctl_buffer);
1787+
curl_easy_setopt(slot->curl, CURLOPT_IOCTLDATA, &out_buffer);
1788+
#endif
17691789
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
17701790
curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PUT);
17711791
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
@@ -1910,6 +1930,10 @@ static void update_remote_info_refs(struct remote_lock *lock)
19101930
curl_easy_setopt(slot->curl, CURLOPT_INFILE, &buffer);
19111931
curl_easy_setopt(slot->curl, CURLOPT_INFILESIZE, buffer.buf.len);
19121932
curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, fread_buffer);
1933+
#ifndef NO_CURL_IOCTL
1934+
curl_easy_setopt(slot->curl, CURLOPT_IOCTLFUNCTION, ioctl_buffer);
1935+
curl_easy_setopt(slot->curl, CURLOPT_IOCTLDATA, &buffer);
1936+
#endif
19131937
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
19141938
curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_PUT);
19151939
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);

http.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,25 @@ size_t fread_buffer(void *ptr, size_t eltsize, size_t nmemb, void *buffer_)
4444
return size;
4545
}
4646

47+
#ifndef NO_CURL_IOCTL
48+
curlioerr ioctl_buffer(CURL *handle, int cmd, void *clientp)
49+
{
50+
struct buffer *buffer = clientp;
51+
52+
switch (cmd) {
53+
case CURLIOCMD_NOP:
54+
return CURLIOE_OK;
55+
56+
case CURLIOCMD_RESTARTREAD:
57+
buffer->posn = 0;
58+
return CURLIOE_OK;
59+
60+
default:
61+
return CURLIOE_UNKNOWNCMD;
62+
}
63+
}
64+
#endif
65+
4766
size_t fwrite_buffer(const void *ptr, size_t eltsize, size_t nmemb, void *buffer_)
4867
{
4968
size_t size = eltsize * nmemb;

http.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@
3737
#define CURLE_HTTP_RETURNED_ERROR CURLE_HTTP_NOT_FOUND
3838
#endif
3939

40+
#if LIBCURL_VERSION_NUM < 0x070c03
41+
#define NO_CURL_IOCTL
42+
#endif
43+
4044
struct slot_results
4145
{
4246
CURLcode curl_result;
@@ -67,6 +71,9 @@ struct buffer
6771
extern size_t fread_buffer(void *ptr, size_t eltsize, size_t nmemb, void *strbuf);
6872
extern size_t fwrite_buffer(const void *ptr, size_t eltsize, size_t nmemb, void *strbuf);
6973
extern size_t fwrite_null(const void *ptr, size_t eltsize, size_t nmemb, void *strbuf);
74+
#ifndef NO_CURL_IOCTL
75+
extern curlioerr ioctl_buffer(CURL *handle, int cmd, void *clientp);
76+
#endif
7077

7178
/* Slot lifecycle functions */
7279
extern struct active_request_slot *get_active_slot(void);

0 commit comments

Comments
 (0)