Re: patch: reget working again [Re: Reget: bug or feature?]
- From: Alexander Savelyev <i fano com ua>
- To: Pavel Roskin <proski gnu org>
- Cc: Arpad Biro <biro_arpad yahoo com>, mc-devel gnome org
- Subject: Re: patch: reget working again [Re: Reget: bug or feature?]
- Date: Sun, 25 Jan 2004 15:44:40 +0200
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*)®et);
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]