Added support for handling binary files. default tip
authorMadhusudan.C.S <madhusudancs@gmail.com>
Mon, 18 Jan 2010 17:21:39 +0530
changeset 1 47438813ede2
parent 0 30d751ac6d49
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.
ftp/Makefile
ftp/ftp.x
ftp/ftpc.c
ftp/ftps.c
--- 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;