summaryrefslogtreecommitdiff
path: root/libs/libcurl/src/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'libs/libcurl/src/file.c')
-rw-r--r--libs/libcurl/src/file.c108
1 files changed, 68 insertions, 40 deletions
diff --git a/libs/libcurl/src/file.c b/libs/libcurl/src/file.c
index 1c8b2b2c85..8b514cfd2d 100644
--- a/libs/libcurl/src/file.c
+++ b/libs/libcurl/src/file.c
@@ -58,7 +58,6 @@
#include <dirent.h>
#endif
-#include "strtoofft.h"
#include "urldata.h"
#include <curl/curl.h>
#include "progress.h"
@@ -71,24 +70,28 @@
#include "transfer.h"
#include "url.h"
#include "parsedate.h" /* for the week day and month names */
-#include "warnless.h"
+#include "curlx/warnless.h"
#include "curl_range.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
-#if defined(_WIN32) || defined(MSDOS) || defined(__EMX__)
+#if defined(_WIN32) || defined(MSDOS)
#define DOS_FILESYSTEM 1
#elif defined(__amigaos4__)
#define AMIGA_FILESYSTEM 1
#endif
-#ifdef OPEN_NEEDS_ARG3
-# define open_readonly(p,f) open((p),(f),(0))
-#else
-# define open_readonly(p,f) open((p),(f))
-#endif
+/* meta key for storing protocol meta at easy handle */
+#define CURL_META_FILE_EASY "meta:proto:file:easy"
+
+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! */
+};
/*
* Forward declarations.
@@ -126,6 +129,7 @@ const struct Curl_handler Curl_handler_file = {
ZERO_NULL, /* write_resp_hd */
ZERO_NULL, /* connection_check */
ZERO_NULL, /* attach connection */
+ ZERO_NULL, /* follow */
0, /* defport */
CURLPROTO_FILE, /* protocol */
CURLPROTO_FILE, /* family */
@@ -133,13 +137,34 @@ const struct Curl_handler Curl_handler_file = {
};
+static void file_cleanup(struct FILEPROTO *file)
+{
+ Curl_safefree(file->freepath);
+ file->path = NULL;
+ if(file->fd != -1) {
+ close(file->fd);
+ file->fd = -1;
+ }
+}
+
+static void file_easy_dtor(void *key, size_t klen, void *entry)
+{
+ struct FILEPROTO *file = entry;
+ (void)key;
+ (void)klen;
+ file_cleanup(file);
+ free(file);
+}
+
static CURLcode file_setup_connection(struct Curl_easy *data,
struct connectdata *conn)
{
+ struct FILEPROTO *filep;
(void)conn;
/* allocate the FILE specific struct */
- data->req.p.file = calloc(1, sizeof(struct FILEPROTO));
- if(!data->req.p.file)
+ filep = calloc(1, sizeof(*filep));
+ if(!filep ||
+ Curl_meta_set(data, CURL_META_FILE_EASY, filep, file_easy_dtor))
return CURLE_OUT_OF_MEMORY;
return CURLE_OK;
@@ -153,7 +178,7 @@ static CURLcode file_setup_connection(struct Curl_easy *data,
static CURLcode file_connect(struct Curl_easy *data, bool *done)
{
char *real_path;
- struct FILEPROTO *file = data->req.p.file;
+ struct FILEPROTO *file = Curl_meta_get(data, CURL_META_FILE_EASY);
int fd;
#ifdef DOS_FILESYSTEM
size_t i;
@@ -162,6 +187,9 @@ static CURLcode file_connect(struct Curl_easy *data, bool *done)
size_t real_path_len;
CURLcode result;
+ if(!file)
+ return CURLE_FAILED_INIT;
+
if(file->path) {
/* already connected.
* the handler->connect_it() is normally only called once, but
@@ -209,7 +237,7 @@ static CURLcode file_connect(struct Curl_easy *data, bool *done)
return CURLE_URL_MALFORMAT;
}
- fd = open_readonly(actual_path, O_RDONLY|O_BINARY);
+ fd = open(actual_path, O_RDONLY|CURL_O_BINARY);
file->path = actual_path;
#else
if(memchr(real_path, 0, real_path_len)) {
@@ -233,20 +261,20 @@ static CURLcode file_connect(struct Curl_easy *data, bool *done)
extern int __unix_path_semantics;
if(strchr(real_path + 1, ':')) {
/* Amiga absolute path */
- fd = open_readonly(real_path + 1, O_RDONLY);
+ fd = open(real_path + 1, O_RDONLY);
file->path++;
}
else if(__unix_path_semantics) {
/* -lunix fallback */
- fd = open_readonly(real_path, O_RDONLY);
+ fd = open(real_path, O_RDONLY);
}
}
#else
- fd = open_readonly(real_path, O_RDONLY);
+ fd = open(real_path, O_RDONLY);
file->path = real_path;
#endif
#endif
- Curl_safefree(file->freepath);
+ free(file->freepath);
file->freepath = real_path; /* free this when done */
file->fd = fd;
@@ -263,17 +291,12 @@ static CURLcode file_connect(struct Curl_easy *data, bool *done)
static CURLcode file_done(struct Curl_easy *data,
CURLcode status, bool premature)
{
- struct FILEPROTO *file = data->req.p.file;
+ struct FILEPROTO *file = Curl_meta_get(data, CURL_META_FILE_EASY);
(void)status; /* not used */
(void)premature; /* not used */
- if(file) {
- Curl_safefree(file->freepath);
- file->path = NULL;
- if(file->fd != -1)
- close(file->fd);
- file->fd = -1;
- }
+ if(file)
+ file_cleanup(file);
return CURLE_OK;
}
@@ -293,9 +316,9 @@ static CURLcode file_disconnect(struct Curl_easy *data,
#define DIRSEP '/'
#endif
-static CURLcode file_upload(struct Curl_easy *data)
+static CURLcode file_upload(struct Curl_easy *data,
+ struct FILEPROTO *file)
{
- struct FILEPROTO *file = data->req.p.file;
const char *dir = strchr(file->path, DIRSEP);
int fd;
int mode;
@@ -318,18 +341,18 @@ static CURLcode file_upload(struct Curl_easy *data)
if(!dir[1])
return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */
-#ifdef O_BINARY
-#define MODE_DEFAULT O_WRONLY|O_CREAT|O_BINARY
-#else
-#define MODE_DEFAULT O_WRONLY|O_CREAT
-#endif
-
+ mode = O_WRONLY|O_CREAT|CURL_O_BINARY;
if(data->state.resume_from)
- mode = MODE_DEFAULT|O_APPEND;
+ mode |= O_APPEND;
else
- mode = MODE_DEFAULT|O_TRUNC;
+ mode |= O_TRUNC;
+#if (defined(ANDROID) || defined(__ANDROID__)) && \
+ (defined(__i386__) || defined(__arm__))
+ fd = open(file->path, mode, (mode_t)data->set.new_file_perms);
+#else
fd = open(file->path, mode, data->set.new_file_perms);
+#endif
if(fd < 0) {
failf(data, "cannot open %s for writing", file->path);
return CURLE_WRITE_ERROR;
@@ -397,7 +420,7 @@ static CURLcode file_upload(struct Curl_easy *data)
if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
else
- result = Curl_speedcheck(data, Curl_now());
+ result = Curl_speedcheck(data, curlx_now());
}
if(!result && Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
@@ -424,6 +447,7 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
are supported. This means that files on remotely mounted directories
(via NFS, Samba, NT sharing) can be accessed through a file:// URL
*/
+ struct FILEPROTO *file = Curl_meta_get(data, CURL_META_FILE_EASY);
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
@@ -432,16 +456,15 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
bool size_known;
bool fstated = FALSE;
int fd;
- struct FILEPROTO *file;
char *xfer_buf;
size_t xfer_blen;
*done = TRUE; /* unconditionally */
+ if(!file)
+ return CURLE_FAILED_INIT;
if(data->state.upload)
- return file_upload(data);
-
- file = data->req.p.file;
+ return file_upload(data, file);
/* get the fd from the connection phase */
fd = file->fd;
@@ -553,8 +576,13 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
if(data->state.resume_from) {
if(!S_ISDIR(statbuf.st_mode)) {
+#if defined(__AMIGA__) || defined(__MINGW32CE__)
+ if(data->state.resume_from !=
+ lseek(fd, (off_t)data->state.resume_from, SEEK_SET))
+#else
if(data->state.resume_from !=
lseek(fd, data->state.resume_from, SEEK_SET))
+#endif
return CURLE_BAD_DOWNLOAD_RESUME;
}
else {
@@ -597,7 +625,7 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
if(Curl_pgrsUpdate(data))
result = CURLE_ABORTED_BY_CALLBACK;
else
- result = Curl_speedcheck(data, Curl_now());
+ result = Curl_speedcheck(data, curlx_now());
if(result)
goto out;
}