Re: patch: reget working again [Re: Reget: bug or feature?]



Pavel Roskin wrote:
On Tue, 20 Jan 2004, Alexander Savelyev wrote:


Arpad Biro wrote:

Hi,

MC 4.6.1-pre1:

It seems that when copying files, "reget" means to append the last
s-t bytes of the source file to the target file, where s is the source
size and t is the target size.

However, when performing "move", "reget" works differently:
the whole source file is appended to the target.

Is this difference a bug or a feature?

It's a bug, below is a patch for this feature. Using global variable the
same patch only 6 rows length :)


"long long" is not portable.

	fixed

We need a configure check for format
specification that would work with off_t.  Ideally, conversion to off_t
should be a separate patch.

I still don't understand how O_FTPREGET is supposed to work and why it's
needed.

	It's necessary because FTP protocol supposes use seek (command REST)
only before open (command RETR).
	We from ftpfs_open_data_connection have no access to (FileOpContext)ctx
(ctx->reget) and we should transfer it by a call mc_open from
copy_file_file for vfs_s_open where is called linear_start.

copy_file_file -> mc_open -> vfs_s_open -> linear_start
(ftpfs_linear_start) -> ftpfs_open_data_connection (ftp command "REST
offset")


It should be documented in a comment before O_FTPREGET.  I
remember is was discussed already.  There is a comment in vfs.h that
explains how reget should be implemented:

	I read it.

/* O_LINEAR is strange beast, be careful. If you open file asserting
 * O_RDONLY | O_LINEAR, you promise:
 *
 *      a) to read file linearly from beginning to the end
 *      b) not to open another file before you close this one
 *              (this will likely go away in future)
 *      as a special gift, you may
 *      c) lseek() immediately after open(), giving ftpfs chance to
 *         reget. Be warned that this lseek() can fail, and you _have_
 *         to handle that gratefully.

	c) is wrong

 *
 * O_LINEAR allows filesystems not to create temporary file in some
 * cases (ftp transfer).                                -- pavel ucw cz
 */

If lseek() after open() with O_LINEAR cannot be used, I'd like to see this
comment adjusted.


	adjusted.

	patch below.

--
~.

   Alexander

mailto:i fano com ua


--- mc/src/file.c.old	Sun Jan 25 04:54:26 2004
+++ mc/src/file.c	Sun Jan 25 06:29:30 2004
@@ -583,22 +583,30 @@
     }
 
     gettimeofday (&tv_transfer_start, (struct timezone *) NULL);
+    {
+	int notftp = strncmp(src_path, "/#ftp:", 6);
 
-    while ((src_desc = mc_open (src_path, O_RDONLY | O_LINEAR)) < 0) {
-	return_status =
-	    file_error (_(" Cannot open source file \"%s\" \n %s "),
+	while (1) {
+	    if (notftp || !ctx->do_reget)
+	        src_desc = mc_open (src_path, O_RDONLY | O_LINEAR);
+	    else
+	        src_desc = mc_open (src_path, O_RDONLY | O_LINEAR | O_FTPREGET, ctx->do_reget);
+	    if (src_desc >= 0)
+		break;
+	    return_status =
+		file_error (_(" Cannot open source file \"%s\" \n %s "),
 			src_path);
-	if (return_status == FILE_RETRY)
-	    continue;
-	ctx->do_append = 0;
-	return return_status;
-    }
-
-    if (ctx->do_reget) {
-	if (mc_lseek (src_desc, ctx->do_reget, SEEK_SET) != ctx->do_reget) {
-	    message (1, _("Warning"),
+	    if (return_status == FILE_RETRY)
+		continue;
+	    ctx->do_append = 0;
+	    return return_status;
+	}
+	if (ctx->do_reget && notftp) {
+	    if (mc_lseek (src_desc, ctx->do_reget, SEEK_SET) != ctx->do_reget) {
+		message (1, _("Warning"),
 			_(" Reget failed, about to overwrite file "));
-	    ctx->do_reget = ctx->do_append = 0;
+		ctx->do_reget = ctx->do_append = 0;
+	    }
 	}
     }
 
@@ -618,6 +626,9 @@
     utb.modtime = sb.st_mtime;
     file_size = sb.st_size;
 
+    if(ctx->do_reget)
+	n_read_total = ctx->do_reget;
+
     /* Create the new regular file with small permissions initially,
        do not create a security hole.  FIXME: You have security hole
        here, btw. Imagine copying to /tmp and symlink attack :-( */
@@ -739,8 +750,8 @@
 
 		if (n_read_total) {
 		    ctx->eta_secs =
-			((dt / (double) n_read_total) * file_size) - dt;
-		    ctx->bps = n_read_total / ((dt < 1) ? 1 : dt);
+			((dt / (double) (n_read_total - ctx->do_reget)) * (file_size - ctx->do_reget)) - dt;
+		    ctx->bps = (n_read_total - ctx->do_reget) / ((dt < 1) ? 1 : dt);
 		} else
 		    ctx->eta_secs = 0.0;
 	    }
@@ -751,7 +762,7 @@
 		    (tv_current.tv_sec - tv_transfer_start.tv_sec);
 		if (ctx->bps_time < 1)
 		    ctx->bps_time = 1;
-		ctx->bps = n_read_total / ctx->bps_time;
+		ctx->bps = (n_read_total - ctx->do_reget) / ctx->bps_time;
 	    }
 
 	    file_progress_set_stalled_label (ctx, stalled_msg);
--- mc/src/fileopctx.c.old	Sun Jan 25 04:54:26 2004
+++ mc/src/fileopctx.c	Sun Jan 25 05:04:00 2004
@@ -45,7 +45,6 @@
     ctx->eta_secs = 0.0;
     ctx->progress_bytes = 0.0;
     ctx->op_preserve = TRUE;
-    ctx->do_reget = TRUE;
     ctx->stat_func = (mc_stat_fn) mc_lstat;
     ctx->preserve = TRUE;
     ctx->preserve_uidgid = (geteuid () == 0) ? TRUE : FALSE;
--- mc/src/fileopctx.h.old	Sun Jan 25 04:54:26 2004
+++ mc/src/fileopctx.h	Sun Jan 25 05:04:00 2004
@@ -55,7 +55,7 @@
 	int recursive_result;
 
 	/* Whether to do a reget */
-	int do_reget;
+	off_t do_reget;
 
 	/* Controls appending to files */
 	int do_append;
--- mc/vfs/direntry.c.old	Wed Nov 26 23:10:43 2003
+++ mc/vfs/direntry.c	Sun Jan 25 05:04:00 2004
@@ -690,14 +690,22 @@
 }
 
 static void *
-vfs_s_open (struct vfs_class *me, const char *file, int flags, int mode)
+vfs_s_open (struct vfs_class *me, const char *file, int flags, int mode, ...)
 {
     int was_changed = 0;
     struct vfs_s_fh *fh;
     struct vfs_s_super *super;
     char *q;
     struct vfs_s_inode *ino;
+    va_list ap;
+    off_t reget = 0;
 
+    if(flags & O_FTPREGET) {
+	va_start (ap, mode);
+	reget = va_arg (ap, off_t);
+	va_end (ap);
+	flags &= ~O_FTPREGET;
+    }
     if ((q = vfs_s_get_path (me, file, &super, 0)) == NULL)
 	return NULL;
     ino = vfs_s_find_inode (me, super, q, LINK_FOLLOW, FL_NONE);
@@ -747,7 +755,7 @@
     if (IS_LINEAR (flags)) {
 	if (MEDATA->linear_start) {
 	    print_vfs_message (_("Starting linear transfer..."));
-	    if (!MEDATA->linear_start (me, fh, 0)) {
+	    if (!MEDATA->linear_start (me, fh, reget)) {
 		g_free (fh);
 		return NULL;
 	    }
--- mc/vfs/fish.c.old	Sat Dec  6 06:24:56 2003
+++ mc/vfs/fish.c	Sun Jan 25 05:04:00 2004
@@ -571,10 +571,12 @@
     return -1;
 }
 
-static int fish_linear_start(struct vfs_class *me, struct vfs_s_fh *fh, int offset)
+static int fish_linear_start(struct vfs_class *me, struct vfs_s_fh *fh, off_t offset)
 {
     char *name;
     char *quoted_name;
+    int i;
+
     if (offset)
         ERRNOR (E_NOTSUPP, 0);
     name = vfs_s_fullpath (me, fh->ino);
@@ -584,7 +586,7 @@
     g_free (name);
     name = quoted_name;
     fh->u.fish.append = 0;
-    offset = fish_command (me, FH_SUPER, WANT_STRING,
+    i = fish_command (me, FH_SUPER, WANT_STRING,
 		"#RETR /%s\n"
 		"ls -l /%s 2>/dev/null | (\n"
 		  "read var1 var2 var3 var4 var5 var6\n"
@@ -595,7 +597,7 @@
 		"echo '### 200'\n", 
 		name, name, name );
     g_free (name);
-    if (offset != PRELIM) ERRNOR (E_REMOTE, 0);
+    if (i != PRELIM) ERRNOR (E_REMOTE, 0);
     fh->linear = LS_LINEAR_OPEN;
     fh->u.fish.got = 0;
     if (sscanf( reply_str, "%d", &fh->u.fish.total )!=1)
--- mc/vfs/ftpfs.c.old	Wed Nov 26 23:10:44 2003
+++ mc/vfs/ftpfs.c	Sun Jan 25 05:35:06 2004
@@ -930,17 +930,17 @@
 
 static int
 ftpfs_open_data_connection (struct vfs_class *me, struct vfs_s_super *super, const char *cmd,
-		      const char *remote, int isbinary, int reget)
+		      const char *remote, int isbinary, off_t reget)
 {
     struct sockaddr_in from;
     int s, j, data, fromlen = sizeof(from);
-    
+
     if ((s = ftpfs_initconn (me, super)) == -1)
         return -1;
     if (ftpfs_changetype (me, super, isbinary) == -1)
         return -1;
-    if (reget > 0){
-	j = ftpfs_command (me, super, WAIT_REPLY, "REST %d", reget);
+    if (reget){
+	j = ftpfs_command (me, super, WAIT_REPLY, "REST %qu", *(double*)&reget);
 	if (j != CONTINUE)
 	    return -1;
     }
@@ -1370,7 +1370,7 @@
 }
 
 static int 
-ftpfs_linear_start(struct vfs_class *me, struct vfs_s_fh *fh, int offset)
+ftpfs_linear_start(struct vfs_class *me, struct vfs_s_fh *fh, off_t offset)
 {
     char *name = vfs_s_fullpath (me, fh->ino);
 
--- mc/vfs/vfs.c.old	Wed Nov 26 23:25:30 2003
+++ mc/vfs/vfs.c	Sun Jan 25 05:04:00 2004
@@ -310,22 +310,28 @@
     int  mode;
     void *info;
     va_list ap;
+    off_t reget = 0;
 
     char *file = vfs_canon (filename);
     struct vfs_class *vfs = vfs_get_class (file);
 
     /* Get the mode flag */	/* FIXME: should look if O_CREAT is present */
     va_start (ap, flags);
-    mode = va_arg (ap, int);
+    if (flags & O_FTPREGET)
+	reget = va_arg (ap, off_t);
+    else
+	mode = va_arg (ap, int);
     va_end (ap);
-    
     if (!vfs->open) {
 	g_free (file);
 	errno = -EOPNOTSUPP;
 	return -1;
     }
 
-    info = (*vfs->open) (vfs, file, flags, mode);	/* open must be supported */
+    if(flags & O_FTPREGET)
+	info = (*vfs->open) (vfs, file, flags, 0, reget);	/* open must be supported */
+    else
+	info = (*vfs->open) (vfs, file, flags, mode);	/* open must be supported */
     g_free (file);
     if (!info){
 	errno = ferrno (vfs);
--- mc/vfs/vfs.h.old	Wed Nov 26 23:10:44 2003
+++ mc/vfs/vfs.h	Sun Jan 25 15:39:45 2004
@@ -28,7 +28,7 @@
     int (*which) (struct vfs_class *me, char *path);
 
     void *(*open) (struct vfs_class *me, const char *fname, int flags,
-		   int mode);
+		   int mode, /* offset for ftp reget */ ...);
     int (*close) (void *vfs_info);
     int (*read) (void *vfs_info, char *buffer, int count);
     int (*write) (void *vfs_info, char *buf, int count);
@@ -216,6 +216,11 @@
 #define NO_LINEAR(a) (((a) == (O_RDONLY | O_LINEAR)) ? O_RDONLY : (a))
 #endif
 
+/* ftpfs only
+ * passing offset in open() for reget
+ */
+#define O_FTPREGET 0x80000000
+
 /* O_LINEAR is strange beast, be careful. If you open file asserting
  * O_RDONLY | O_LINEAR, you promise:
  *
@@ -223,9 +228,10 @@
  *	b) not to open another file before you close this one
  *		(this will likely go away in future)
  *	as a special gift, you may
- *	c) lseek() immediately after open(), giving ftpfs chance to
+ *	c) for non ftpfs: lseek() immediately after open(), giving chance to
  *	   reget. Be warned that this lseek() can fail, and you _have_
  *         to handle that gratefully.
+ *	d) for ftpfs: when using O_FTPREGET open() do "REST" before "RETR".
  *
  * O_LINEAR allows filesystems not to create temporary file in some
  * cases (ftp transfer).				-- pavel ucw cz
--- mc/vfs/xdirentry.h.old	Fri Nov 14 10:25:51 2003
+++ mc/vfs/xdirentry.h	Sun Jan 25 05:04:00 2004
@@ -148,7 +148,7 @@
 		       char *path, char *localname);
 
     int (*linear_start) (struct vfs_class *me, struct vfs_s_fh *fh,
-			 int from);
+			 off_t from);
     int (*linear_read) (struct vfs_class *me, struct vfs_s_fh *fh,
 			void *buf, int len);
     void (*linear_close) (struct vfs_class *me, struct vfs_s_fh *fh);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]