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

This commit is contained in:
Daniel Stenberg 2004-05-25 21:47:29 +00:00
parent 765754d39d
commit fd802db39f
10 changed files with 177 additions and 29 deletions

View File

@ -7,6 +7,8 @@
Changelog
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
Gisle's previous mail. We now use this function, and thus we require libidn
0.4.5 or later. No earler version will do.

View File

@ -83,7 +83,8 @@
#include "file.h"
#include "speedcheck.h"
#include "getinfo.h"
#include "transfer.h" /* for Curl_readwrite_init() */
#include "transfer.h"
#include "url.h"
#include "memory.h"
#define _MPRINTF_REPLACE /* use our functions only */
@ -148,13 +149,16 @@ CURLcode Curl_file_connect(struct connectdata *conn)
actual_path[i] = '\\';
fd = open(actual_path, O_RDONLY | O_BINARY); /* no CR/LF translation! */
file->path = actual_path;
#else
fd = open(real_path, O_RDONLY);
file->path = real_path;
#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);
Curl_file_done(conn, CURLE_FILE_COULDNT_READ_FILE);
return CURLE_FILE_COULDNT_READ_FILE;
}
file->fd = fd;
@ -166,6 +170,83 @@ CURLcode Curl_file_connect(struct connectdata *conn)
#define lseek(x,y,z) _lseeki64(x, y, z)
#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
* 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_pgrsStartNow(data);
if(data->set.upload)
return file_upload(conn);
/* get the fd from the connection phase */
fd = conn->proto.file->fd;
@ -272,10 +356,6 @@ CURLcode Curl_file(struct connectdata *conn)
break;
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);
if(res)

View File

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

View File

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

View File

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

View File

@ -2711,7 +2711,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
conn->protocol |= PROT_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
at least check that the file is present here! */

View File

@ -272,6 +272,9 @@ struct FTP {
* FILE unique setup
***************************************************************************/
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! */
};

View File

@ -24,7 +24,7 @@ EXTRA_DIST = test1 test108 test117 test127 test20 test27 test34 test46 \
test150 test151 test152 test153 test154 test155 test156 test157 \
test158 test159 test511 test160 test161 test162 test163 test164 \
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
# work. We need to fix the test suite's FTPS server first, then bring them

32
tests/data/test204 Normal file
View 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
View 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>