Commit fd802db3 authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

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

parent 765754d3
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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.
+94 −14
Original line number Diff line number Diff line
@@ -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)
+3 −2
Original line number Diff line number Diff line
@@ -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
+2 −3
Original line number Diff line number Diff line
@@ -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 */
+9 −7
Original line number Diff line number Diff line
@@ -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,
Loading