* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
static CURLcode file_connect(struct connectdata *conn, bool *done);
static CURLcode file_disconnect(struct connectdata *conn,
bool dead_connection);
-
+static CURLcode file_setup_connection(struct connectdata *conn);
/*
* FILE scheme handler.
const struct Curl_handler Curl_handler_file = {
"FILE", /* scheme */
- ZERO_NULL, /* setup_connection */
+ file_setup_connection, /* setup_connection */
file_do, /* do_it */
file_done, /* done */
ZERO_NULL, /* do_more */
};
+static CURLcode file_setup_connection(struct connectdata *conn)
+{
+ /* allocate the FILE specific struct */
+ conn->data->req.protop = calloc(1, sizeof(struct FILEPROTO));
+ if(!conn->data->req.protop)
+ return CURLE_OUT_OF_MEMORY;
+
+ return CURLE_OK;
+}
+
/*
Check if this is a range download, and if so, set the internal variables
properly. This code is copied from the FTP implementation and might as
if((-1 == to) && (from>=0)) {
/* X - */
data->state.resume_from = from;
- DEBUGF(infof(data, "RANGE %" FORMAT_OFF_T " to end of file\n",
+ DEBUGF(infof(data, "RANGE %" CURL_FORMAT_CURL_OFF_T " to end of file\n",
from));
}
else if(from < 0) {
/* -Y */
data->req.maxdownload = -from;
data->state.resume_from = from;
- DEBUGF(infof(data, "RANGE the last %" FORMAT_OFF_T " bytes\n",
+ DEBUGF(infof(data, "RANGE the last %" CURL_FORMAT_CURL_OFF_T " bytes\n",
-from));
}
else {
totalsize = to-from;
data->req.maxdownload = totalsize+1; /* include last byte */
data->state.resume_from = from;
- DEBUGF(infof(data, "RANGE from %" FORMAT_OFF_T
- " getting %" FORMAT_OFF_T " bytes\n",
+ DEBUGF(infof(data, "RANGE from %" CURL_FORMAT_CURL_OFF_T
+ " getting %" CURL_FORMAT_CURL_OFF_T " bytes\n",
from, data->req.maxdownload));
}
- DEBUGF(infof(data, "range-download from %" FORMAT_OFF_T
- " to %" FORMAT_OFF_T ", totally %" FORMAT_OFF_T " bytes\n",
+ DEBUGF(infof(data, "range-download from %" CURL_FORMAT_CURL_OFF_T
+ " to %" CURL_FORMAT_CURL_OFF_T ", totally %"
+ CURL_FORMAT_CURL_OFF_T " bytes\n",
from, to, data->req.maxdownload));
}
else
{
struct SessionHandle *data = conn->data;
char *real_path;
- struct FILEPROTO *file;
+ struct FILEPROTO *file = data->req.protop;
int fd;
#ifdef DOS_FILESYSTEM
int i;
char *actual_path;
#endif
+ int real_path_len;
- /* If there already is a protocol-specific struct allocated for this
- sessionhandle, deal with it */
- Curl_reset_reqproto(conn);
-
- real_path = curl_easy_unescape(data, data->state.path, 0, NULL);
+ real_path = curl_easy_unescape(data, data->state.path, 0, &real_path_len);
if(!real_path)
return CURLE_OUT_OF_MEMORY;
- if(!data->state.proto.file) {
- file = calloc(1, sizeof(struct FILEPROTO));
- if(!file) {
- free(real_path);
- return CURLE_OUT_OF_MEMORY;
- }
- data->state.proto.file = file;
- }
- else {
- /* file is not a protocol that can deal with "persistancy" */
- file = data->state.proto.file;
- Curl_safefree(file->freepath);
- file->path = NULL;
- if(file->fd != -1)
- close(file->fd);
- file->fd = -1;
- }
-
#ifdef DOS_FILESYSTEM
/* If the first character is a slash, and there's
something that looks like a drive at the beginning of
(actual_path[2] == ':' || actual_path[2] == '|')) {
actual_path[2] = ':';
actual_path++;
+ real_path_len--;
}
/* change path separators from '/' to '\\' for DOS, Windows and OS/2 */
- for(i=0; actual_path[i] != '\0'; ++i)
+ for(i=0; i < real_path_len; ++i)
if(actual_path[i] == '/')
actual_path[i] = '\\';
+ else if(!actual_path[i]) /* binary zero */
+ return CURLE_URL_MALFORMAT;
fd = open_readonly(actual_path, O_RDONLY|O_BINARY);
file->path = actual_path;
#else
+ if(memchr(real_path, 0, real_path_len))
+ /* binary zeroes indicate foul play */
+ return CURLE_URL_MALFORMAT;
+
fd = open_readonly(real_path, O_RDONLY);
file->path = real_path;
#endif
static CURLcode file_done(struct connectdata *conn,
CURLcode status, bool premature)
{
- struct FILEPROTO *file = conn->data->state.proto.file;
+ struct FILEPROTO *file = conn->data->req.protop;
(void)status; /* not used */
(void)premature; /* not used */
static CURLcode file_disconnect(struct connectdata *conn,
bool dead_connection)
{
- struct FILEPROTO *file = conn->data->state.proto.file;
+ struct FILEPROTO *file = conn->data->req.protop;
(void)dead_connection; /* not used */
if(file) {
static CURLcode file_upload(struct connectdata *conn)
{
- struct FILEPROTO *file = conn->data->state.proto.file;
+ struct FILEPROTO *file = conn->data->req.protop;
const char *dir = strchr(file->path, DIRSEP);
int fd;
int mode;
- CURLcode res=CURLE_OK;
+ CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
char *buf = data->state.buffer;
size_t nread;
return CURLE_WRITE_ERROR;
}
- if(-1 != data->set.infilesize)
+ if(-1 != data->state.infilesize)
/* known size of data to "upload" */
- Curl_pgrsSetUploadSize(data, data->set.infilesize);
+ Curl_pgrsSetUploadSize(data, data->state.infilesize);
/* treat the negative resume offset value as the case of "-" */
if(data->state.resume_from < 0) {
data->state.resume_from = (curl_off_t)file_stat.st_size;
}
- while(res == CURLE_OK) {
+ while(!result) {
int readcount;
- res = Curl_fillreadbuffer(conn, BUFSIZE, &readcount);
- if(res)
+ result = Curl_fillreadbuffer(conn, BUFSIZE, &readcount);
+ if(result)
break;
if(readcount <= 0) /* fix questionable compare error. curlvms */
/* write the data to the target */
nwrite = write(fd, buf2, nread);
if(nwrite != nread) {
- res = CURLE_SEND_ERROR;
+ result = CURLE_SEND_ERROR;
break;
}
Curl_pgrsSetUploadCounter(data, bytecount);
if(Curl_pgrsUpdate(conn))
- res = CURLE_ABORTED_BY_CALLBACK;
+ result = CURLE_ABORTED_BY_CALLBACK;
else
- res = Curl_speedcheck(data, now);
+ result = Curl_speedcheck(data, now);
}
- if(!res && Curl_pgrsUpdate(conn))
- res = CURLE_ABORTED_BY_CALLBACK;
+ if(!result && Curl_pgrsUpdate(conn))
+ result = CURLE_ABORTED_BY_CALLBACK;
close(fd);
- return res;
+ return result;
}
/*
are supported. This means that files on remotely mounted directories
(via NFS, Samba, NT sharing) can be accessed through a file:// URL
*/
- CURLcode res = CURLE_OK;
+ CURLcode result = CURLE_OK;
struct_stat statbuf; /* struct_stat instead of struct stat just to allow the
Windows version to have a different struct without
having to redefine the simple word 'stat' */
curl_off_t bytecount = 0;
int fd;
struct timeval now = Curl_tvnow();
+ struct FILEPROTO *file;
*done = TRUE; /* unconditionally */
if(data->set.upload)
return file_upload(conn);
+ file = conn->data->req.protop;
+
/* get the fd from the connection phase */
- fd = conn->data->state.proto.file->fd;
+ fd = file->fd;
/* VMS: This only works reliable for STREAMLF files */
if(-1 != fstat(fd, &statbuf)) {
information. Which for FILE can't be much more than the file size and
date. */
if(data->set.opt_no_body && data->set.include_header && fstated) {
- CURLcode result;
snprintf(buf, sizeof(data->state.buffer),
- "Content-Length: %" FORMAT_OFF_T "\r\n", expected_size);
+ "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", expected_size);
result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0);
if(result)
return result;
Curl_pgrsTime(data, TIMER_STARTTRANSFER);
- while(res == CURLE_OK) {
+ while(!result) {
/* Don't fill a whole buffer if we want less than all data */
size_t bytestoread =
(expected_size < CURL_OFF_T_C(BUFSIZE) - CURL_OFF_T_C(1)) ?
bytecount += nread;
expected_size -= nread;
- res = Curl_client_write(conn, CLIENTWRITE_BODY, buf, nread);
- if(res)
- return res;
+ result = Curl_client_write(conn, CLIENTWRITE_BODY, buf, nread);
+ if(result)
+ return result;
Curl_pgrsSetDownloadCounter(data, bytecount);
if(Curl_pgrsUpdate(conn))
- res = CURLE_ABORTED_BY_CALLBACK;
+ result = CURLE_ABORTED_BY_CALLBACK;
else
- res = Curl_speedcheck(data, now);
+ result = Curl_speedcheck(data, now);
}
if(Curl_pgrsUpdate(conn))
- res = CURLE_ABORTED_BY_CALLBACK;
+ result = CURLE_ABORTED_BY_CALLBACK;
- return res;
+ return result;
}
#endif