[patch] client/client.c: commands reget and reput

Josef Zlomek josef.zlomek at email.cz
Tue Aug 20 08:27:18 GMT 2002


Hello!

I have written the commands reget and reput for smbclient.
When user gets/puts a large file and the connection brokes
the user is unhappy (s)he has to transfer the file from the beginning.
So with this patch (s)he can use command reget/reput that
will continue in the transfer, i.e. it will seek both in local and remote file
to position of the end of target file and continue with the transfer from this position.
Although the local networks are fast, it takes several minutes to tranfer
a 650 MB large file (e.g. ISO image) so I think these commands are useful.

Patch for the main branch (HEAD) follows, it needs my patch
"[patch] basic seeking support for XFILE" to be installed before this patch.

Josef


diff -ur samba.cvs/source/client/client.c samba.reget_reput/source/client/client.c
--- samba.cvs/source/client/client.c	Sat Jul 13 05:51:27 2002
+++ samba.reget_reput/source/client/client.c	Tue Aug 20 10:13:38 2002
@@ -60,6 +60,7 @@
 /* value for unused fid field in trans2 secondary request */
 #define FID_UNUSED (0xFFFF)
 
+BOOL restart_at_file_end = False;
 time_t newer_than = 0;
 static int archive_level = 0;
 
@@ -651,7 +652,7 @@
   ****************************************************************************/
 static int do_get(char *rname,char *lname)
 {  
-	int handle=0,fnum;
+	int handle = -1, fnum;
 	BOOL newhandle = False;
 	char *data;
 	struct timeval tp_start;
@@ -659,6 +660,7 @@
 	uint16 attr;
 	size_t size;
 	off_t nread = 0;
+	off_t start = 0;
 	int rc = 0;
 
 	GetTimeOfDay(&tp_start);
@@ -677,7 +679,18 @@
 	if(!strcmp(lname,"-")) {
 		handle = fileno(stdout);
 	} else {
-		handle = sys_open(lname,O_WRONLY|O_CREAT|O_TRUNC,0644);
+		if (restart_at_file_end) {
+			handle = sys_open(lname,O_WRONLY|O_CREAT,0644);
+			if (handle >= 0) {
+				start = sys_lseek(handle, 0, SEEK_END);
+				if (start == -1) {
+					d_printf("Error seeking local file\n");
+					return 1;
+				}
+			}
+		}
+		if (handle < 0)
+			handle = sys_open(lname,O_WRONLY|O_CREAT|O_TRUNC,0644);
 		newhandle = True;
 	}
 	if (handle < 0) {
@@ -704,7 +717,7 @@
 	}
 
 	while (1) {
-		int n = cli_read(cli, fnum, data, nread, read_size);
+		int n = cli_read(cli, fnum, data, nread + start, read_size);
 
 		if (n <= 0) break;
  
@@ -717,7 +730,7 @@
 		nread += n;
 	}
 
-	if (nread < size) {
+	if (nread + start < size) {
 		DEBUG (0, ("Short read when getting file %s. Only got %ld bytes.\n",
 			    rname, (long)nread));
 
@@ -787,6 +800,21 @@
 
 
 /****************************************************************************
+  get a file restarting at end of local file
+  ****************************************************************************/
+static int cmd_reget(void)
+{
+	int rc;
+
+	restart_at_file_end = True;
+	rc = cmd_get();
+	restart_at_file_end = False;
+
+	return rc;
+}
+
+
+/****************************************************************************
   do a mget operation on one file
   ****************************************************************************/
 static void do_mget(file_info *finfo)
@@ -1048,9 +1076,10 @@
   ****************************************************************************/
 static int do_put(char *rname,char *lname)
 {
-	int fnum;
+	int fnum = -1;
 	XFILE *f;
-	int nread=0;
+	size_t nread = 0;
+	size_t start = 0;
 	char *buf=NULL;
 	int maxwrite=io_bufsize;
 	int rc = 0;
@@ -1058,7 +1087,21 @@
 	struct timeval tp_start;
 	GetTimeOfDay(&tp_start);
 
-	fnum = cli_open(cli, rname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
+	if (restart_at_file_end) {
+		fnum = cli_open(cli, rname, O_RDWR|O_CREAT, DENY_NONE);
+		if (fnum >= 0) {
+			if (!cli_qfileinfo(cli, fnum, NULL, &start,
+					   NULL, NULL, NULL, NULL, NULL) &&
+			    !cli_getattrE(cli, fnum, NULL, &start,
+					  NULL, NULL, NULL)) {
+				d_printf("getattrib: %s\n",cli_errstr(cli));
+				return 1;
+			}
+		}
+	}
+	if (fnum == -1) {
+		fnum = cli_open(cli, rname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
+	}
   
 	if (fnum == -1) {
 		d_printf("%s opening remote file %s\n",cli_errstr(cli),rname);
@@ -1075,6 +1118,12 @@
 		/* size of file is not known */
 	} else {
 		f = x_fopen(lname,O_RDONLY, 0);
+		if (f != NULL && restart_at_file_end) {
+			if (x_lseek(f, start, SEEK_SET) == -1) {
+				d_printf("Error seeking local file\n");
+				return 1;
+			}
+		}
 	}
 
 	if (!f) {
@@ -1104,7 +1153,7 @@
 			break;
 		}
 
-		ret = cli_write(cli, fnum, 0, buf, nread, n);
+		ret = cli_write(cli, fnum, 0, buf, nread + start, n);
 
 		if (n != ret) {
 			d_printf("Error writing file: %s\n", cli_errstr(cli));
@@ -1195,6 +1244,22 @@
 	return do_put(rname,lname);
 }
 
+
+/****************************************************************************
+  put a file restarting at end of local file
+  ****************************************************************************/
+static int cmd_reput(void)
+{
+	int rc;
+
+	restart_at_file_end = True;
+	rc = cmd_put();
+	restart_at_file_end = False;
+
+	return rc;
+}
+
+
 /*************************************
   File list structure
 *************************************/
@@ -2009,7 +2074,9 @@
   {"quit",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}},
   {"rd",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}},
   {"recurse",cmd_recurse,"toggle directory recursion for mget and mput",{COMPL_NONE,COMPL_NONE}},  
+  {"reget",cmd_reget,"<remote name> [local name] get a file restarting at end of local file",{COMPL_REMOTE,COMPL_LOCAL}},
   {"rename",cmd_rename,"<src> <dest> rename some files",{COMPL_REMOTE,COMPL_REMOTE}},
+  {"reput",cmd_reput,"<local name> [remote name] put a file restarting at end of remote file",{COMPL_LOCAL,COMPL_REMOTE}},
   {"rm",cmd_del,"<mask> delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
   {"rmdir",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}},
   {"setmode",cmd_setmode,"filename <setmode string> change modes of file",{COMPL_REMOTE,COMPL_NONE}},



More information about the samba-technical mailing list