From 52fc686908805c8b6078c2dab4aa0d92ee7e7010 Mon Sep 17 00:00:00 2001 From: andrew Date: Wed, 18 Feb 2009 02:33:36 -0600 Subject: [PATCH] adding first version of filesystem interactions. currently just sends a file, does not yet receive a file --- filesystem.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++++++ filesystem.h | 24 ++++++++++ 2 files changed, 154 insertions(+) diff --git a/filesystem.c b/filesystem.c index e69de29..e1889ee 100644 --- a/filesystem.c +++ b/filesystem.c @@ -0,0 +1,130 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cftp.h" +#include "filesystem.h" + +/* + * Checks if a file exists. Required for send, causes receive to fail if this + * returns true. Returns int. + */ +int exist(const char *filename) +{ + struct stat sbuf; + if(stat(filename, &sbuf) == -1 && (errno == ENOENT || errno == EACCES)) + { + return 0; + } + return 1; +} + +/* + * Returns the size of the requested file. Takes a string of the filename, + * expects the file to exist, too. + * + */ +int filesize(const char *filename) +{ + struct stat fstat; + if(stat(filename, &fstat) != -1) + { + return fstat.st_size; + } + return 0; +} + +/* + * This function will send a file to a remote host. Expects a socket integer + * and a string containing the full path to the local file name. File cannot + * exceed MAXFILE definition. + * + */ +void send_file(int skt, const char *filename) +{ + char errmsg[ERRMSGLEN], cmd[CMDLEN], arg[MSGLEN], msg[MSGLEN]; + char *basefname; + int fsize = 0, segments = 0, cur_segment; + FILE *infile; + + memset(errmsg, '\0', ERRMSGLEN); + memset(cmd, '\0', CMDLEN); + memset(arg, '\0', MSGLEN); + memset(msg, (unsigned char)0, MSGLEN); + + /* file must exist */ + if(!exist(filename)) + { + error("The file does not exist!"); + return; + } + + /* file must be in valid size range, do not send endpoint sizes */ + fsize = filesize(filename); + if(fsize <= 0 || fsize >= MAXFILE) + { + error("That file is inappropriately sized!"); + return; + } + segments = ceil(MAXFILE / MSGLEN); + + /* make a copy then figure out just the filename */ + strcpy(msg, filename); + basefname = basename(msg); + sprintf(errmsg, "Sending file (%s) in %d segments.", basefname, segments); + debug("Filesystem", errmsg); + + /* send the command, we do not send the user command because we just want + * to send the base filename. also, we expect a response from the server, + * either cts or err. + */ + sprintf(msg, "put:%s", basefname); + send_message(skt, msg); + split_command(msg, cmd, arg); + if(!strcmp(cmd, "err")) + { + sprintf(errmsg, "ERROR Not sending the file: %s", arg); + error(errmsg); + return; + } + else if(strcmp(cmd, "cts") != 0) + { + sprintf(errmsg, "ERROR invalid reponse from remote: %s", msg); + error(errmsg); + return; + } + + /* send number of segments and file size to the other size cmd:arg style */ + sprintf(msg, "%d:%d", segments, fsize); + /* do not expect a response, only data after this */ + send(skt, msg, strlen(msg), 0); + + /* now read in the file, MSGLEN at a time and send the chunk to the host */ + infile = fopen(filename, "r"); + for(cur_segment = 0; cur_segment < segments; cur_segment++) + { + fread(msg, MSGLEN, 1, infile); + sprintf(errmsg, "\rSending File: %.2f%%", floor(cur_segment / segments * 100.0)); + debug("Filesystem", errmsg); + send_message(skt, msg); + } +} + +/* + * This will receive a file from a remote host. Expects a socket integer and + * a filename. The file will be basename'd and saved into /tmp. + * + */ +void receive_file(int skt, const char *filename) +{ + unsigned char fbuf[MAXFILE]; + int fsize = 0, segments = 0, cur_segment = 0; +} + diff --git a/filesystem.h b/filesystem.h index e69de29..d370247 100644 --- a/filesystem.h +++ b/filesystem.h @@ -0,0 +1,24 @@ +#ifndef __FILESYSTEM_H +#define __FILESYSTEM_H + +/* + * This is the public API for CFTP's filesystem access. You just have to + * ask it to send or receive a file, and this will handle the rest. Errors + * raised if not accessible or if you are trying to overwrite a file. No files + * may be overwritten. All files written to client or server are saved in /tmp. + * + */ + +/* + * The MAXFILE size is calculated to be the largest integer in CMDLEN - 1 + * characters times MSGLEN. + * + * 9999 * 128 bytes = 1279872 bytes maximum + * + */ +#define MAXFILE 1279872 +void send_file(int, const char *); +void receive_file(int, const char *); + +#endif +