summaryrefslogtreecommitdiff
path: root/lib/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/file.c')
-rw-r--r--lib/file.c163
1 files changed, 85 insertions, 78 deletions
diff --git a/lib/file.c b/lib/file.c
index 8e4ee075f..038bf42e1 100644
--- a/lib/file.c
+++ b/lib/file.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2012, 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
@@ -20,33 +20,13 @@
*
***************************************************************************/
-#include "setup.h"
+#include "curl_setup.h"
#ifndef CURL_DISABLE_FILE
-/* -- WIN32 approved -- */
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <ctype.h>
-
-#ifdef WIN32
-#include <time.h>
-#include <io.h>
-#include <fcntl.h>
-#else
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
+
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
@@ -68,8 +48,6 @@
#include <fcntl.h>
#endif
-#endif /* WIN32 */
-
#include "strtoofft.h"
#include "urldata.h"
#include <curl/curl.h>
@@ -83,6 +61,7 @@
#include "url.h"
#include "curl_memory.h"
#include "parsedate.h" /* for the week day and month names */
+#include "warnless.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
@@ -90,7 +69,8 @@
/* The last #include file should be: */
#include "memdebug.h"
-#if defined(WIN32) || defined(MSDOS) || defined(__EMX__) || defined(__SYMBIAN32__)
+#if defined(WIN32) || defined(MSDOS) || defined(__EMX__) || \
+ defined(__SYMBIAN32__)
#define DOS_FILESYSTEM 1
#endif
@@ -108,6 +88,9 @@ static CURLcode file_do(struct connectdata *, bool *done);
static CURLcode file_done(struct connectdata *conn,
CURLcode status, bool premature);
static CURLcode file_connect(struct connectdata *conn, bool *done);
+static CURLcode file_disconnect(struct connectdata *conn,
+ bool dead_connection);
+
/*
* FILE scheme handler.
@@ -124,10 +107,13 @@ const struct Curl_handler Curl_handler_file = {
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
+ ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
- ZERO_NULL, /* disconnect */
+ file_disconnect, /* disconnect */
+ ZERO_NULL, /* readwrite */
0, /* defport */
- PROT_FILE /* protocol */
+ CURLPROTO_FILE, /* protocol */
+ PROTOPT_NONETWORK | PROTOPT_NOURLQUERY /* flags */
};
@@ -192,7 +178,7 @@ static CURLcode file_range(struct connectdata *conn)
static CURLcode file_connect(struct connectdata *conn, bool *done)
{
struct SessionHandle *data = conn->data;
- char *real_path = curl_easy_unescape(data, data->state.path, 0, NULL);
+ char *real_path;
struct FILEPROTO *file;
int fd;
#ifdef DOS_FILESYSTEM
@@ -200,13 +186,14 @@ static CURLcode file_connect(struct connectdata *conn, bool *done)
char *actual_path;
#endif
- if(!real_path)
- return CURLE_OUT_OF_MEMORY;
-
/* 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);
+ if(!real_path)
+ return CURLE_OUT_OF_MEMORY;
+
if(!data->state.proto.file) {
file = calloc(1, sizeof(struct FILEPROTO));
if(!file) {
@@ -219,10 +206,9 @@ static CURLcode file_connect(struct connectdata *conn, bool *done)
/* 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->path = NULL;
- file->freepath = NULL;
file->fd = -1;
}
@@ -244,18 +230,17 @@ static CURLcode file_connect(struct connectdata *conn, bool *done)
actual_path = real_path;
if((actual_path[0] == '/') &&
actual_path[1] &&
- (actual_path[2] == ':' || actual_path[2] == '|'))
- {
+ (actual_path[2] == ':' || actual_path[2] == '|')) {
actual_path[2] = ':';
actual_path++;
}
/* change path separators from '/' to '\\' for DOS, Windows and OS/2 */
- for (i=0; actual_path[i] != '\0'; ++i)
+ for(i=0; actual_path[i] != '\0'; ++i)
if(actual_path[i] == '/')
actual_path[i] = '\\';
- fd = open_readonly(actual_path, O_RDONLY|O_BINARY); /* no CR/LF translation */
+ fd = open_readonly(actual_path, O_RDONLY|O_BINARY);
file->path = actual_path;
#else
fd = open_readonly(real_path, O_RDONLY);
@@ -280,10 +265,31 @@ static CURLcode file_done(struct connectdata *conn,
struct FILEPROTO *file = conn->data->state.proto.file;
(void)status; /* not used */
(void)premature; /* not used */
- Curl_safefree(file->freepath);
- if(file->fd != -1)
- close(file->fd);
+ if(file) {
+ Curl_safefree(file->freepath);
+ file->path = NULL;
+ if(file->fd != -1)
+ close(file->fd);
+ file->fd = -1;
+ }
+
+ return CURLE_OK;
+}
+
+static CURLcode file_disconnect(struct connectdata *conn,
+ bool dead_connection)
+{
+ struct FILEPROTO *file = conn->data->state.proto.file;
+ (void)dead_connection; /* not used */
+
+ if(file) {
+ Curl_safefree(file->freepath);
+ file->path = NULL;
+ if(file->fd != -1)
+ close(file->fd);
+ file->fd = -1;
+ }
return CURLE_OK;
}
@@ -298,7 +304,8 @@ static CURLcode file_upload(struct connectdata *conn)
{
struct FILEPROTO *file = conn->data->state.proto.file;
const char *dir = strchr(file->path, DIRSEP);
- FILE *fp;
+ int fd;
+ int mode;
CURLcode res=CURLE_OK;
struct SessionHandle *data = conn->data;
char *buf = data->state.buffer;
@@ -321,29 +328,21 @@ static CURLcode file_upload(struct connectdata *conn)
return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */
if(!dir[1])
- return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */
-
- if(data->state.resume_from)
- fp = fopen( file->path, "ab" );
- else {
- int fd;
+ return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */
-#ifdef DOS_FILESYSTEM
- fd = open(file->path, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,
- conn->data->set.new_file_perms);
+#ifdef O_BINARY
+#define MODE_DEFAULT O_WRONLY|O_CREAT|O_BINARY
#else
- fd = open(file->path, O_WRONLY|O_CREAT|O_TRUNC,
- conn->data->set.new_file_perms);
+#define MODE_DEFAULT O_WRONLY|O_CREAT
#endif
- if(fd < 0) {
- failf(data, "Can't open %s for writing", file->path);
- return CURLE_WRITE_ERROR;
- }
- close(fd);
- fp = fopen(file->path, "wb");
- }
- if(!fp) {
+ if(data->state.resume_from)
+ mode = MODE_DEFAULT|O_APPEND;
+ else
+ mode = MODE_DEFAULT|O_TRUNC;
+
+ fd = open(file->path, mode, conn->data->set.new_file_perms);
+ if(fd < 0) {
failf(data, "Can't open %s for writing", file->path);
return CURLE_WRITE_ERROR;
}
@@ -354,8 +353,8 @@ static CURLcode file_upload(struct connectdata *conn)
/* treat the negative resume offset value as the case of "-" */
if(data->state.resume_from < 0) {
- if(fstat(fileno(fp), &file_stat)) {
- fclose(fp);
+ if(fstat(fd, &file_stat)) {
+ close(fd);
failf(data, "Can't get the size of %s", file->path);
return CURLE_WRITE_ERROR;
}
@@ -376,7 +375,7 @@ static CURLcode file_upload(struct connectdata *conn)
/*skip bytes before resume point*/
if(data->state.resume_from) {
- if( (curl_off_t)nread <= data->state.resume_from ) {
+ if((curl_off_t)nread <= data->state.resume_from ) {
data->state.resume_from -= nread;
nread = 0;
buf2 = buf;
@@ -391,7 +390,7 @@ static CURLcode file_upload(struct connectdata *conn)
buf2 = buf;
/* write the data to the target */
- nwrite = fwrite(buf2, 1, nread, fp);
+ nwrite = write(fd, buf2, nread);
if(nwrite != nread) {
res = CURLE_SEND_ERROR;
break;
@@ -409,7 +408,7 @@ static CURLcode file_upload(struct connectdata *conn)
if(!res && Curl_pgrsUpdate(conn))
res = CURLE_ABORTED_BY_CALLBACK;
- fclose(fp);
+ close(fd);
return res;
}
@@ -436,7 +435,6 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
curl_off_t expected_size=0;
bool fstated=FALSE;
ssize_t nread;
- size_t bytestoread;
struct SessionHandle *data = conn->data;
char *buf = data->state.buffer;
curl_off_t bytecount = 0;
@@ -455,7 +453,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
fd = conn->data->state.proto.file->fd;
/* VMS: This only works reliable for STREAMLF files */
- if( -1 != fstat(fd, &statbuf)) {
+ if(-1 != fstat(fd, &statbuf)) {
/* we could stat it, then read out the size */
expected_size = statbuf.st_size;
/* and store the modification time */
@@ -463,6 +461,13 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
fstated = TRUE;
}
+ if(fstated && !data->state.range && data->set.timecondition) {
+ if(!Curl_meets_timecondition(data, (time_t)data->info.filetime)) {
+ *done = TRUE;
+ return CURLE_OK;
+ }
+ }
+
/* If we have selected NOBODY and HEADER, it means that we only want file
information. Which for FILE can't be much more than the file size and
date. */
@@ -480,14 +485,13 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
return result;
if(fstated) {
- const struct tm *tm;
time_t filetime = (time_t)statbuf.st_mtime;
-#ifdef HAVE_GMTIME_R
struct tm buffer;
- tm = (const struct tm *)gmtime_r(&filetime, &buffer);
-#else
- tm = gmtime(&filetime);
-#endif
+ const struct tm *tm = &buffer;
+ result = Curl_gmtime(filetime, &buffer);
+ if(result)
+ return result;
+
/* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
snprintf(buf, BUFSIZE-1,
"Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
@@ -529,7 +533,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
}
/* A high water mark has been specified so we obey... */
- if (data->req.maxdownload > 0)
+ if(data->req.maxdownload > 0)
expected_size = data->req.maxdownload;
if(fstated && (expected_size == 0))
@@ -552,13 +556,16 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
while(res == CURLE_OK) {
/* Don't fill a whole buffer if we want less than all data */
- bytestoread = (expected_size < BUFSIZE-1)?(size_t)expected_size:BUFSIZE-1;
+ size_t bytestoread =
+ (expected_size < CURL_OFF_T_C(BUFSIZE) - CURL_OFF_T_C(1)) ?
+ curlx_sotouz(expected_size) : BUFSIZE - 1;
+
nread = read(fd, buf, bytestoread);
- if( nread > 0)
+ if(nread > 0)
buf[nread] = 0;
- if (nread <= 0 || expected_size == 0)
+ if(nread <= 0 || expected_size == 0)
break;
bytecount += nread;