initial support for "uploading" to file:// URLs

This commit is contained in:
Daniel Stenberg 2004-05-25 21:47:29 +00:00
Родитель 765754d39d
Коммит fd802db39f
10 изменённых файлов: 177 добавлений и 29 удалений

Просмотреть файл

@ -7,6 +7,8 @@
Changelog Changelog
Daniel (24 May 2004) Daniel (24 May 2004)
- libcurl now supports "uploading" to file:// URLs.
- Simon Josefsson added a idn_free() function in libidn 0.4.5 as a reaction to - Simon Josefsson added a idn_free() function in libidn 0.4.5 as a reaction to
Gisle's previous mail. We now use this function, and thus we require libidn Gisle's previous mail. We now use this function, and thus we require libidn
0.4.5 or later. No earler version will do. 0.4.5 or later. No earler version will do.

Просмотреть файл

@ -83,7 +83,8 @@
#include "file.h" #include "file.h"
#include "speedcheck.h" #include "speedcheck.h"
#include "getinfo.h" #include "getinfo.h"
#include "transfer.h" /* for Curl_readwrite_init() */ #include "transfer.h"
#include "url.h"
#include "memory.h" #include "memory.h"
#define _MPRINTF_REPLACE /* use our functions only */ #define _MPRINTF_REPLACE /* use our functions only */
@ -148,13 +149,16 @@ CURLcode Curl_file_connect(struct connectdata *conn)
actual_path[i] = '\\'; actual_path[i] = '\\';
fd = open(actual_path, O_RDONLY | O_BINARY); /* no CR/LF translation! */ fd = open(actual_path, O_RDONLY | O_BINARY); /* no CR/LF translation! */
file->path = actual_path;
#else #else
fd = open(real_path, O_RDONLY); fd = open(real_path, O_RDONLY);
file->path = real_path;
#endif #endif
free(real_path); file->freepath = real_path; /* free this when done */
if(fd == -1) { if(!conn->data->set.upload && (fd == -1)) {
failf(conn->data, "Couldn't open file %s", conn->path); failf(conn->data, "Couldn't open file %s", conn->path);
Curl_file_done(conn, CURLE_FILE_COULDNT_READ_FILE);
return CURLE_FILE_COULDNT_READ_FILE; return CURLE_FILE_COULDNT_READ_FILE;
} }
file->fd = fd; file->fd = fd;
@ -166,6 +170,83 @@ CURLcode Curl_file_connect(struct connectdata *conn)
#define lseek(x,y,z) _lseeki64(x, y, z) #define lseek(x,y,z) _lseeki64(x, y, z)
#endif #endif
CURLcode Curl_file_done(struct connectdata *conn,
CURLcode status)
{
struct FILEPROTO *file = conn->proto.file;
(void)status; /* not used */
Curl_safefree(file->path);
return CURLE_OK;
}
static CURLcode file_upload(struct connectdata *conn)
{
struct FILEPROTO *file = conn->proto.file;
char *dir = strchr(file->path, '/');
FILE *fp;
CURLcode res=CURLE_OK;
struct SessionHandle *data = conn->data;
char *buf = data->state.buffer;
size_t nread;
size_t nwrite;
curl_off_t bytecount = 0;
struct timeval now = Curl_tvnow();
/*
* Since FILE: doesn't do the full init, we need to provide some extra
* assignments here.
*/
conn->fread = data->set.fread;
conn->fread_in = data->set.in;
conn->upload_fromhere = buf;
if(!dir)
return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */
if(!dir[1])
return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */
fp = fopen(file->path, "wb");
if(!fp) {
failf(data, "Can't open %s for writing", file->path);
return CURLE_WRITE_ERROR;
}
if(-1 != data->set.infilesize)
/* known size of data to "upload" */
Curl_pgrsSetUploadSize(data, data->set.infilesize);
while (res == CURLE_OK) {
nread = Curl_fillreadbuffer(conn, BUFSIZE);
if (nread <= 0)
break;
/* write the data to the target */
nwrite = fwrite(buf, 1, nread, fp);
if(nwrite != nread) {
res = CURLE_SEND_ERROR;
break;
}
bytecount += nread;
Curl_pgrsSetUploadCounter(data, bytecount);
if(Curl_pgrsUpdate(conn))
res = CURLE_ABORTED_BY_CALLBACK;
else
res = Curl_speedcheck(data, now);
}
if(!res && Curl_pgrsUpdate(conn))
res = CURLE_ABORTED_BY_CALLBACK;
fclose(fp);
return res;
}
/* /*
* Curl_file() is the protocol-specific function for the do-phase, separated * Curl_file() is the protocol-specific function for the do-phase, separated
* from the connect-phase above. Other protocols merely setup the transfer in * from the connect-phase above. Other protocols merely setup the transfer in
@ -196,6 +277,9 @@ CURLcode Curl_file(struct connectdata *conn)
Curl_initinfo(data); Curl_initinfo(data);
Curl_pgrsStartNow(data); Curl_pgrsStartNow(data);
if(data->set.upload)
return file_upload(conn);
/* get the fd from the connection phase */ /* get the fd from the connection phase */
fd = conn->proto.file->fd; fd = conn->proto.file->fd;
@ -272,10 +356,6 @@ CURLcode Curl_file(struct connectdata *conn)
break; break;
bytecount += nread; bytecount += nread;
/* NOTE: The following call to fwrite does CR/LF translation on
Windows systems if the target is stdout. Use -O or -o parameters
to prevent CR/LF translation (this then goes to a binary mode
file descriptor). */
res = Curl_client_write(data, CLIENTWRITE_BODY, buf, nread); res = Curl_client_write(data, CLIENTWRITE_BODY, buf, nread);
if(res) if(res)

Просмотреть файл

@ -24,7 +24,8 @@
* $Id$ * $Id$
***************************************************************************/ ***************************************************************************/
#ifndef CURL_DISABLE_FILE #ifndef CURL_DISABLE_FILE
CURLcode Curl_file(struct connectdata *conn); CURLcode Curl_file(struct connectdata *);
CURLcode Curl_file_connect(struct connectdata *conn); CURLcode Curl_file_done(struct connectdata *, CURLcode);
CURLcode Curl_file_connect(struct connectdata *);
#endif #endif
#endif #endif

Просмотреть файл

@ -125,8 +125,7 @@ static struct timeval notimeout={0,0};
* This function will call the read callback to fill our buffer with data * This function will call the read callback to fill our buffer with data
* to upload. * to upload.
*/ */
static int fillbuffer(struct connectdata *conn, int Curl_fillreadbuffer(struct connectdata *conn, int bytes)
int bytes)
{ {
int buffersize = bytes; int buffersize = bytes;
int nread; int nread;
@ -1124,7 +1123,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
break; break;
} }
nread = fillbuffer(conn, BUFSIZE); nread = Curl_fillreadbuffer(conn, BUFSIZE);
} }
else else
nread = 0; /* we're done uploading/reading */ nread = 0; /* we're done uploading/reading */

Просмотреть файл

@ -34,6 +34,8 @@ void Curl_single_fdset(struct connectdata *conn,
int *max_fd); int *max_fd);
CURLcode Curl_readwrite_init(struct connectdata *conn); CURLcode Curl_readwrite_init(struct connectdata *conn);
int Curl_fillreadbuffer(struct connectdata *conn, int bytes);
/* This sets up a forthcoming transfer */ /* This sets up a forthcoming transfer */
CURLcode CURLcode
Curl_Transfer (struct connectdata *data, Curl_Transfer (struct connectdata *data,

Просмотреть файл

@ -2711,7 +2711,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
conn->protocol |= PROT_FILE; conn->protocol |= PROT_FILE;
conn->curl_do = Curl_file; conn->curl_do = Curl_file;
/* no done() function */ conn->curl_done = Curl_file_done;
/* anyway, this is supposed to be the connect function so we better /* anyway, this is supposed to be the connect function so we better
at least check that the file is present here! */ at least check that the file is present here! */

Просмотреть файл

@ -272,6 +272,9 @@ struct FTP {
* FILE unique setup * FILE unique setup
***************************************************************************/ ***************************************************************************/
struct FILEPROTO { struct FILEPROTO {
char *path; /* the path we operate on */
char *freepath; /* pointer to the allocated block we must free, this might
differ from the 'path' pointer */
int fd; /* open file descriptor to read from! */ int fd; /* open file descriptor to read from! */
}; };

Просмотреть файл

@ -24,7 +24,7 @@ EXTRA_DIST = test1 test108 test117 test127 test20 test27 test34 test46 \
test150 test151 test152 test153 test154 test155 test156 test157 \ test150 test151 test152 test153 test154 test155 test156 test157 \
test158 test159 test511 test160 test161 test162 test163 test164 \ test158 test159 test511 test160 test161 test162 test163 test164 \
test512 test165 test166 test167 test168 test169 test170 test171 \ test512 test165 test166 test167 test168 test169 test170 test171 \
test172 test172 test204 test205
# The following tests have been removed from the dist since they no longer # The following tests have been removed from the dist since they no longer
# work. We need to fix the test suite's FTPS server first, then bring them # work. We need to fix the test suite's FTPS server first, then bring them

32
tests/data/test204 Normal file
Просмотреть файл

@ -0,0 +1,32 @@
# no Server-side
# Client-side
<client>
<server>
none
</server>
<name>
"upload" with file://
</name>
<command>
file://localhost/%PWD/log/result204.txt -T log/upload204.txt
</command>
<file name="log/upload204.txt">
data
in
file
to
write
</file>
</client>
# Verify data after the test has been "shot"
<verify>
<file name="log/result204.txt">
data
in
file
to
write
</file>
</verify>

29
tests/data/test205 Normal file
Просмотреть файл

@ -0,0 +1,29 @@
# no Server-side
# Client-side
<client>
<server>
none
</server>
<name>
"upload" with file://
</name>
<command>
file://localhost/%PWD/log/nonexisting/result205.txt -T log/upload205.txt
</command>
<file name="log/upload205.txt">
data
in
file
to
write
</file>
</client>
# Verify data after the test has been "shot"
<verify>
# 23 => CURLE_WRITE_ERROR
<errorcode>
23
</errorcode>
</verify>