]> granicus.if.org Git - curl/commitdiff
initial support for "uploading" to file:// URLs
authorDaniel Stenberg <daniel@haxx.se>
Tue, 25 May 2004 21:47:29 +0000 (21:47 +0000)
committerDaniel Stenberg <daniel@haxx.se>
Tue, 25 May 2004 21:47:29 +0000 (21:47 +0000)
CHANGES
lib/file.c
lib/file.h
lib/transfer.c
lib/transfer.h
lib/url.c
lib/urldata.h
tests/data/Makefile.am
tests/data/test204 [new file with mode: 0644]
tests/data/test205 [new file with mode: 0644]

diff --git a/CHANGES b/CHANGES
index 40faf005666ca5c3cc7266161c7794612e041e51..b5c85a8e4c901ea4b7f5b9d1a9658a58943caa7a 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -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.
index 05a1fde58cd105793b660b3accf331da7d266729..e366314263111a918d3b100205ade78f95cfdd6f 100644 (file)
@@ -1,8 +1,8 @@
 /***************************************************************************
- *                                  _   _ ____  _     
- *  Project                     ___| | | |  _ \| |    
- *                             / __| | | | |_) | |    
- *                            | (__| |_| |  _ <| |___ 
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
  * Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
@@ -10,7 +10,7 @@
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * are also available at http://curl.haxx.se/docs/copyright.html.
- * 
+ *
  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  * copies of the Software, and permit persons to whom the Software is
  * furnished to do so, under the terms of the COPYING 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
@@ -176,7 +257,7 @@ CURLcode Curl_file_connect(struct connectdata *conn)
  */
 CURLcode Curl_file(struct connectdata *conn)
 {
-  /* This implementation ignores the host name in conformance with 
+  /* This implementation ignores the host name in conformance with
      RFC 1738. Only local files (reachable via the standard file system)
      are supported. This means that files on remotely mounted directories
      (via NFS, Samba, NT sharing) can be accessed through a file:// URL
@@ -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)
@@ -286,7 +366,7 @@ CURLcode Curl_file(struct connectdata *conn)
     if(Curl_pgrsUpdate(conn))
       res = CURLE_ABORTED_BY_CALLBACK;
     else
-      res = Curl_speedcheck (data, now);
+      res = Curl_speedcheck(data, now);
   }
   if(Curl_pgrsUpdate(conn))
     res = CURLE_ABORTED_BY_CALLBACK;
index 4d1d881e6f9203272dc4a598c84fa663e199ce1b..689b8aeca7cf1288ec2f6552d27e338e3ba7043a 100644 (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
index b8ccfe256eeef2fd5191973cb90c4d9fe89aa572..91187aab8c212f167e4f810f2a218afc5534fe40 100644 (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 */
index c99c2034767e62287b4ab07e6427ce62a3421192..422bb064c6f7154f298101292790767819160a99 100644 (file)
@@ -1,10 +1,10 @@
 #ifndef __TRANSFER_H
 #define __TRANSFER_H
 /***************************************************************************
- *                                  _   _ ____  _     
- *  Project                     ___| | | |  _ \| |    
- *                             / __| | | | |_) | |    
- *                            | (__| |_| |  _ <| |___ 
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
  * Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
@@ -12,7 +12,7 @@
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * are also available at http://curl.haxx.se/docs/copyright.html.
- * 
+ *
  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  * copies of the Software, and permit persons to whom the Software is
  * furnished to do so, under the terms of the COPYING file.
@@ -27,15 +27,17 @@ CURLcode Curl_pretransfer(struct SessionHandle *data);
 CURLcode Curl_posttransfer(struct SessionHandle *data);
 CURLcode Curl_follow(struct SessionHandle *data, char *newurl);
 CURLcode Curl_readwrite(struct connectdata *conn, bool *done);
-void Curl_single_fdset(struct connectdata *conn, 
+void Curl_single_fdset(struct connectdata *conn,
                        fd_set *read_fd_set,
                        fd_set *write_fd_set,
                        fd_set *exc_fd_set,
                        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 
+CURLcode
 Curl_Transfer (struct connectdata *data,
                int sockindex,          /* socket index to read from or -1 */
                curl_off_t size,                /* -1 if unknown at this point */
index d65f6aec955fa221300b450a4fad08007157bec6..188bf4c9e74a836a4664364c9845235aee7ccd86 100644 (file)
--- a/lib/url.c
+++ b/lib/url.c
@@ -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! */
index 21f3ce7c051e3adeb2b80b0c6c6ac1a4ef953ff0..ef5d1a5f58017ae23e8d7336529288bd3c042553 100644 (file)
@@ -272,7 +272,10 @@ struct FTP {
  * FILE unique setup
  ***************************************************************************/
 struct FILEPROTO {
-  int fd; /* open file descriptor to read from! */
+  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! */
 };
 
 /*
index 8ed9d8e2dcce0575aa711206b4d0f88397132b16..35ca93c3d7d29656b086dbb8ac68b3e9f6e98882 100644 (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
diff --git a/tests/data/test204 b/tests/data/test204
new file mode 100644 (file)
index 0000000..cd661d3
--- /dev/null
@@ -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>
diff --git a/tests/data/test205 b/tests/data/test205
new file mode 100644 (file)
index 0000000..b829190
--- /dev/null
@@ -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>