Added support for handling binary files.
The problem was I was using XDR strings for reading data, storing it
and transferring to the client from the server. But since this is no
better than null-terminated string, whenever data had \000 the data
used to become corrupt from that point. So now I changed all data to
be integer arrays so there is no question of corruption.
--- a/ftp/Makefile Mon Jan 18 14:10:13 2010 +0530
+++ b/ftp/Makefile Mon Jan 18 17:21:39 2010 +0530
@@ -1,17 +1,29 @@
# Makefile: To build client and server for ftp implemented using RPC
-all: stubs ftp_xdr.o ftps ftpc
+all: stubs ftp_xdr.o server client
+
+debug: stubs ftp_xdr.o ftps-dbg ftpc-dbg
server: ftps
+server-dbg: ftps-dbg
+
client: ftpc
+client-dbg: ftpc-dbg
+
ftps: ftp_svc.c ftps.c ftp_xdr.o ftp.h
gcc ftp_svc.c ftps.c ftp_xdr.o -o ftps
+ftps-dbg: ftp_svc.c ftps.c ftp_xdr.o ftp.h
+ gcc ftp_svc.c ftps.c ftp_xdr.o -o ftps-dbg -g
+
ftpc: ftpc.c ftp_clnt.c ftp_xdr.o ftp.h
gcc ftpc.c ftp_clnt.c ftp_xdr.o -o ftpc
+ftpc-dbg: ftpc.c ftp_clnt.c ftp_xdr.o ftp.h
+ gcc ftpc.c ftp_clnt.c ftp_xdr.o -o ftpc-dbg -g
+
ftp_xdr.o: ftp_xdr.c ftp.h
gcc -c ftp_xdr.c
@@ -19,4 +31,4 @@
rpcgen ftp.x
clean:
- rm ftp_xdr.o ftpc ftps ftp_clnt.c ftp_svc.c ftp_xdr.c ftp.h
+ rm ftp_xdr.o ftpc ftps ftp_clnt.c ftp_svc.c ftp_xdr.c ftp.h ftps-dbg ftpc-dbg
--- a/ftp/ftp.x Mon Jan 18 14:10:13 2010 +0530
+++ b/ftp/ftp.x Mon Jan 18 17:21:39 2010 +0530
@@ -14,7 +14,7 @@
* and the byte number at which to start reading the file from
*/
struct request {
- filename name;
+ filename name;
int start;
};
@@ -28,7 +28,7 @@
* sent from the server to the client in the current
* remote procedure call
*/
-typedef int filechunk<MAXLEN>;
+typedef int filechunk[MAXLEN];
/*
* Response sent by the server to the client as a response
@@ -36,8 +36,8 @@
* the current call and number of bytes actually read
*/
struct chunkreceive {
- filechunk data;
- int bytes;
+ filechunk data;
+ int items;
};
/*
@@ -52,9 +52,9 @@
* number of bytes in the data
*/
struct chunksend {
- filename name;
+ filename name;
filechunk data;
- int bytes;
+ int items;
};
/*
@@ -69,10 +69,10 @@
* or will return the error number if an error occured
*/
union readfile_res switch (int errno) {
- case 0:
- chunkreceive chunk;
- default:
- void;
+ case 0:
+ chunkreceive chunk;
+ default:
+ void;
};
/*
@@ -81,9 +81,9 @@
* the remote procedure signature
*/
program FTPPROG {
- version FTPVER {
- readfile_res retrieve_file(request *) = 1;
- int send_file(chunksend *) = 2;
- } = 1;
+ version FTPVER {
+ readfile_res retrieve_file(request *) = 1;
+ int send_file(chunksend *) = 2;
+ } = 1;
} = 0x20000011;
--- a/ftp/ftpc.c Mon Jan 18 14:10:13 2010 +0530
+++ b/ftp/ftpc.c Mon Jan 18 17:21:39 2010 +0530
@@ -12,15 +12,15 @@
int get_file(char *host, char *name)
{
CLIENT *clnt;
- int total_bytes = 0, write_bytes;
+ int bytes = 0, write_items;
readfile_res *result;
- request req;
- FILE *file;
+ request req;
+ FILE *file;
/*
- * Initialize the request with the file name
- */
- req.name = name;
+ * Initialize the request with the file name
+ */
+ req.name = name;
/*
* Create client handle used for calling FTPPROG on
@@ -40,7 +40,7 @@
/*
* Open the file for writing on the client machine
*/
- file = fopen(name, "w");
+ file = fopen(name, "wb");
/*
* Call the remote procedure retrieve_file on the server.
@@ -49,12 +49,12 @@
* by the server. The loop terminates when the data returned
* from the server is less than 1024 bytes
*/
- while (1) {
- /*
- * Specifies the byte position where the next read should be
- * started in the server.
- */
- req.start = total_bytes;
+ while (1) {
+ /*
+ * Specifies the byte position where the next read should be
+ * started in the server.
+ */
+ req.start = bytes;
result = retrieve_file_1(&req, clnt);
if (result == NULL) {
@@ -82,17 +82,17 @@
/*
* Successfully got a chunk of the file.
* Write into our local file and update the
- * total bytes of data read till now.
+ * total bytes of data read till now.
*/
- write_bytes = fwrite(result->readfile_res_u.chunk.data, 1, result->readfile_res_u.chunk.bytes, file);
- total_bytes += result->readfile_res_u.chunk.bytes;
- if (result->readfile_res_u.chunk.bytes < MAXLEN)
- break;
- }
+ write_items = fwrite(result->readfile_res_u.chunk.data, sizeof(int), result->readfile_res_u.chunk.items, file);
+ bytes += result->readfile_res_u.chunk.items * (sizeof(int));
+ if (result->readfile_res_u.chunk.items < MAXLEN)
+ break;
+ }
- fclose(file);
+ fclose(file);
- return 0;
+ return 0;
}
/*
@@ -102,11 +102,10 @@
int put_file(char *host, char *name)
{
CLIENT *clnt;
- char data[1024];
- int read_bytes;
int *result;
- chunksend chunk;
- FILE *file;
+ filechunk data;
+ chunksend chunk;
+ FILE *file;
/*
* Create client handle used for calling FTPPROG on
@@ -124,27 +123,24 @@
}
/*
- * Open the file that should be stored on the server
- */
- file = fopen(name, "r");
+ * Open the file that should be stored on the server
+ */
+ file = fopen(name, "rb");
/*
- * Initialize the chunk to be sent with the name
- * of the file
- */
- chunk.name = name;
+ * Initialize the chunk to be sent with the name
+ * of the file
+ */
+ chunk.name = name;
/*
* Call the remote procedure readdir on the server
- * in a loop sending only 1024 bytes of data in each
- * iteration. The loop terminates once the data less
- * than 1024 bytes is sent.
+ * in a loop sending only 1024 bytes of data in each
+ * iteration. The loop terminates once the data less
+ * than 1024 bytes is sent.
*/
- while (1) {
- read_bytes = fread(data, 1, MAXLEN, file);
-
- chunk.data = data;
- chunk.bytes = read_bytes;
+ while (1) {
+ chunk.items = fread(chunk.data, sizeof(int), MAXLEN, file);
result = send_file_1(&chunk, clnt);
if (result == NULL) {
@@ -173,13 +169,13 @@
* Successfully got a chunk of the file.
* Write into our local file.
*/
- if (read_bytes < MAXLEN)
- break;
- }
+ if (chunk.items < MAXLEN)
+ break;
+ }
- fclose(file);
+ fclose(file);
- return 0;
+ return 0;
}
/*
@@ -188,21 +184,21 @@
*/
int read_command(char *host)
{
- char command[MAXLEN];
+ char command[MAXLEN];
- printf("> ");
- fflush(stdin);
- gets(command);
+ printf("> ");
+ fflush(stdin);
+ gets(command);
if (strncmp(command, "get", 3) == 0) {
- return get_file(host, command+4);
- } else if(strncmp(command, "put", 3) == 0){
- return put_file(host, command+4);
- } else if(strncmp(command, "exit", 4) == 0){
- exit(0);
+ return get_file(host, command+4);
+ } else if(strncmp(command, "put", 3) == 0){
+ return put_file(host, command+4);
+ } else if(strncmp(command, "exit", 4) == 0){
+ exit(0);
} else {
- return -1;
- }
+ return -1;
+ }
}
int main(int argc, char *argv[])
@@ -216,9 +212,9 @@
/*
* Command handling loop
- */
+ */
while(TRUE) {
- result = read_command(argv[1]);
+ result = read_command(argv[1]);
}
return 0;
--- a/ftp/ftps.c Mon Jan 18 14:10:13 2010 +0530
+++ b/ftp/ftps.c Mon Jan 18 17:21:39 2010 +0530
@@ -6,46 +6,43 @@
readfile_res* retrieve_file_1_svc(request *req, struct svc_req *rqstp)
{
- FILE *file;
- char data[1024];
- int bytes;
- static readfile_res res;
+ FILE *file;
+ filechunk data;
+ static readfile_res res;
- file = fopen(req->name, "r");
+ file = fopen(req->name, "rb");
if (file == NULL) {
- res.errno = errno;
- return (&res);
+ res.errno = errno;
+ return (&res);
}
xdr_free((xdrproc_t)xdr_readfile_res, (char *)&res);
fseek (file, req->start, SEEK_SET);
- bytes = fread(data, 1, MAXLEN, file);
- res.readfile_res_u.chunk.data = data;
- res.readfile_res_u.chunk.bytes = bytes;
+ res.readfile_res_u.chunk.items = fread(res.readfile_res_u.chunk.data, sizeof(int), MAXLEN, file);
- /*
+ /*
* Return the result
*/
res.errno = 0;
fclose(file);
- return (&res);
+ return (&res);
}
int* send_file_1_svc(chunksend *rec, struct svc_req *rqstp)
{
- FILE *file;
- int write_bytes;
+ FILE *file;
+ int write_items;
static int result;
- file = fopen(rec->name, "a");
- if (file == NULL) {
- result = errno;
- return &result;
- }
+ file = fopen(rec->name, "ab");
+ if (file == NULL) {
+ result = errno;
+ return &result;
+ }
- write_bytes = fwrite(rec->data, 1, rec->bytes, file);
- fclose(file);
+ write_items = fwrite(rec->data, sizeof(int), rec->items, file);
+ fclose(file);
result = 0;
return &result;