vfs_s_super and vfs_s_fh now don't contain members specific to any vfs.

Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
Signed-off-by: Slava Zanko <slavazanko@gmail.com>
This commit is contained in:
Andrew Borodin 2011-03-28 17:08:56 +03:00
parent 2e839a6ec6
commit 68628184b1
6 changed files with 531 additions and 441 deletions

View File

@ -1207,7 +1207,7 @@ vfs_s_open (struct vfs_class *me, const char *file, int flags, mode_t mode)
fh->linear = LS_LINEAR_PREOPEN;
}
}
else if ((MEDATA->fh_open) && (MEDATA->fh_open (me, fh, flags, mode)))
else if ((MEDATA->fh_open != NULL) && (MEDATA->fh_open (me, fh, flags, mode) != 0))
{
g_free (fh);
return NULL;
@ -1285,6 +1285,7 @@ vfs_s_retrieve_file (struct vfs_class *me, struct vfs_s_inode *ino)
close (handle);
tty_disable_interrupt_key ();
g_free (fh.data);
return 0;
error_1:
@ -1296,6 +1297,7 @@ vfs_s_retrieve_file (struct vfs_class *me, struct vfs_s_inode *ino)
error_4:
g_free (ino->localname);
ino->localname = NULL;
g_free (fh.data);
return -1;
}

View File

@ -60,68 +60,7 @@ struct vfs_s_super
int fd_usage; /* Number of open files */
int ino_usage; /* Usage count of this superblock */
int want_stale; /* If set, we do not flush cache properly */
union
{
#ifdef ENABLE_VFS_FISH
struct
{
int sockr, sockw;
char *cwdir;
char *host, *user;
char *password;
int flags;
char *scr_ls;
char *scr_chmod;
char *scr_exists;
char *scr_mkdir;
char *scr_unlink;
char *scr_chown;
char *scr_rmdir;
char *scr_ln;
char *scr_mv;
char *scr_hardlink;
char *scr_get;
char *scr_send;
char *scr_append;
char *scr_info;
int host_flags;
char *scr_env;
} fish;
#endif /* ENABLE_VFS_FISH */
#ifdef ENABLE_VFS_FTP
struct
{
int sock;
char *cwdir;
char *host, *user;
char *password;
int port;
char *proxy; /* proxy server, NULL if no proxy */
int failed_on_login; /* used to pass the failure reason to upper levels */
int use_passive_connection;
int remote_is_amiga; /* No leading slash allowed for AmiTCP (Amiga) */
int isbinary;
int cwd_deferred; /* current_directory was changed but CWD command hasn't
been sent yet */
int strict; /* ftp server doesn't understand
* "LIST -la <path>"; use "CWD <path>"/
* "LIST" instead
*/
int ctl_connection_busy;
} ftp;
#endif /* ENABLE_VFS_FTP */
#if defined(ENABLE_VFS_CPIO) || defined(ENABLE_VFS_TAR)
struct
{
int fd;
struct stat st;
int type; /* Type of the archive */
struct defer_inode *deferred; /* List of inodes for which another entries may appear */
} arch;
#endif /* ENABLE_VFS_CPIO || ENABLE_VFS_TAR */
} u;
void *data; /* This is for filesystem-specific use */
};
/*
@ -158,22 +97,7 @@ struct vfs_s_fh
int handle; /* This is for module's use, but if != -1, will be mc_close()d */
int changed; /* Did this file change? */
int linear; /* Is that file open with O_LINEAR? */
union
{
#ifdef ENABLE_VFS_FISH
struct
{
off_t got, total;
int append;
} fish;
#endif /* ENABLE_VFS_FISH */
#ifdef ENABLE_VFS_FTP
struct
{
int sock, append;
} ftp;
#endif /* ENABLE_VFS_FTP */
} u;
void *data; /* This is for filesystem-specific use */
};
/*

View File

@ -49,13 +49,19 @@
/* If some time reentrancy should be needed change it to */
/* #define CPIO_POS(super) (super)->u.arch.fd */
#define CPIO_SEEK_SET(super, where) mc_lseek((super)->u.arch.fd, CPIO_POS(super) = (where), SEEK_SET)
#define CPIO_SEEK_CUR(super, where) mc_lseek((super)->u.arch.fd, CPIO_POS(super) += (where), SEEK_SET)
#define CPIO_SEEK_SET(super, where) \
mc_lseek (((cpio_super_data_t *)(super)->data)->fd, \
CPIO_POS(super) = (where), SEEK_SET)
#define CPIO_SEEK_CUR(super, where) \
mc_lseek (((cpio_super_data_t *)(super)->data)->fd, \
CPIO_POS(super) += (where), SEEK_SET)
#define MAGIC_LENGTH (6) /* How many bytes we have to read ahead */
#define SEEKBACK CPIO_SEEK_CUR(super, ptr - top)
#define RETURN(x) return(super->u.arch.type = (x))
#define TYPEIS(x) ((super->u.arch.type == CPIO_UNKNOWN) || (super->u.arch.type == (x)))
#define RETURN(x) return (((cpio_super_data_t *)super->data)->type = (x))
#define TYPEIS(x) \
((((cpio_super_data_t *)super->data)->type == CPIO_UNKNOWN) || \
(((cpio_super_data_t *)super->data)->type == (x)))
#define HEAD_LENGTH (26)
@ -121,6 +127,14 @@ struct defer_inode
struct vfs_s_inode *inode;
};
typedef struct
{
int fd;
struct stat st;
int type; /* Type of the archive */
struct defer_inode *deferred; /* List of inodes for which another entries may appear */
} cpio_super_data_t;
/*** file scope variables ************************************************************************/
static struct vfs_class vfs_cpiofs_ops;
@ -152,7 +166,7 @@ cpio_defer_find (struct defer_inode *l, struct defer_inode *i)
static int
cpio_skip_padding (struct vfs_s_super *super)
{
switch (super->u.arch.type)
switch (((cpio_super_data_t *) super->data)->type)
{
case CPIO_BIN:
case CPIO_BINRE:
@ -174,18 +188,25 @@ static void
cpio_free_archive (struct vfs_class *me, struct vfs_s_super *super)
{
struct defer_inode *l, *lnext;
cpio_super_data_t *arch = (cpio_super_data_t *) super->data;
(void) me;
if (super->u.arch.fd != -1)
mc_close (super->u.arch.fd);
super->u.arch.fd = -1;
for (l = super->u.arch.deferred; l; l = lnext)
if (super->data == NULL)
return;
if (arch->fd != -1)
mc_close (arch->fd);
arch->fd = -1;
for (l = arch->deferred; l != NULL; l = lnext)
{
lnext = l->next;
g_free (l);
}
super->u.arch.deferred = NULL;
arch->deferred = NULL;
g_free (super->data);
super->data = NULL;
}
/* --------------------------------------------------------------------------------------------- */
@ -194,6 +215,7 @@ static int
cpio_open_cpio_file (struct vfs_class *me, struct vfs_s_super *super, const char *name)
{
int fd, type;
cpio_super_data_t *arch;
mode_t mode;
struct vfs_s_inode *root;
@ -205,9 +227,12 @@ cpio_open_cpio_file (struct vfs_class *me, struct vfs_s_super *super, const char
}
super->name = g_strdup (name);
super->u.arch.fd = -1; /* for now */
mc_stat (name, &(super->u.arch.st));
super->u.arch.type = CPIO_UNKNOWN;
super->data = g_new (cpio_super_data_t, 1);
arch = (cpio_super_data_t *) super->data;
arch->fd = -1; /* for now */
mc_stat (name, &arch->st);
arch->type = CPIO_UNKNOWN;
arch->deferred = NULL;
type = get_compression_type (fd, name);
if (type != COMPRESSION_NONE)
@ -226,12 +251,12 @@ cpio_open_cpio_file (struct vfs_class *me, struct vfs_s_super *super, const char
g_free (s);
}
super->u.arch.fd = fd;
mode = super->u.arch.st.st_mode & 07777;
arch->fd = fd;
mode = arch->st.st_mode & 07777;
mode |= (mode & 0444) >> 2; /* set eXec where Read is */
mode |= S_IFDIR;
root = vfs_s_new_inode (me, super, &(super->u.arch.st));
root = vfs_s_new_inode (me, super, &arch->st);
root->st.st_mode = mode;
root->data_offset = -1;
root->st.st_nlink++;
@ -272,25 +297,27 @@ cpio_read_head (struct vfs_class *me, struct vfs_s_super *super)
static int
cpio_find_head (struct vfs_class *me, struct vfs_s_super *super)
{
char buf[256];
cpio_super_data_t *arch = (cpio_super_data_t *) super->data;
char buf[BUF_SMALL * 2];
int ptr = 0;
ssize_t top;
ssize_t tmp;
top = mc_read (super->u.arch.fd, buf, 256);
top = mc_read (arch->fd, buf, sizeof (buf));
if (top > 0)
CPIO_POS (super) += top;
for (;;)
while (TRUE)
{
if (ptr + MAGIC_LENGTH >= top)
{
if (top > 128)
if (top > (ssize_t) (sizeof (buf) / 2))
{
memmove (buf, buf + top - 128, 128);
ptr -= top - 128;
top = 128;
memmove (buf, buf + top - sizeof (buf) / 2, sizeof (buf) / 2);
ptr -= top - sizeof (buf) / 2;
top = sizeof (buf) / 2;
}
tmp = mc_read (super->u.arch.fd, buf, top);
tmp = mc_read (arch->fd, buf, top);
if (tmp == 0 || tmp == -1)
{
message (D_ERROR, MSG_ERROR, _("Premature end of cpio archive\n%s"), super->name);
@ -310,17 +337,17 @@ cpio_find_head (struct vfs_class *me, struct vfs_s_super *super)
SEEKBACK;
RETURN (CPIO_BINRE);
}
else if (TYPEIS (CPIO_OLDC) && (!strncmp (buf + ptr, "070707", 6)))
else if (TYPEIS (CPIO_OLDC) && (strncmp (buf + ptr, "070707", 6) == 0))
{
SEEKBACK;
RETURN (CPIO_OLDC);
}
else if (TYPEIS (CPIO_NEWC) && (!strncmp (buf + ptr, "070701", 6)))
else if (TYPEIS (CPIO_NEWC) && (strncmp (buf + ptr, "070701", 6) == 0))
{
SEEKBACK;
RETURN (CPIO_NEWC);
}
else if (TYPEIS (CPIO_CRC) && (!strncmp (buf + ptr, "070702", 6)))
else if (TYPEIS (CPIO_CRC) && (strncmp (buf + ptr, "070702", 6) == 0))
{
SEEKBACK;
RETURN (CPIO_CRC);
@ -334,6 +361,7 @@ cpio_find_head (struct vfs_class *me, struct vfs_s_super *super)
static int
cpio_create_entry (struct vfs_class *me, struct vfs_s_super *super, struct stat *st, char *name)
{
cpio_super_data_t *arch = (cpio_super_data_t *) super->data;
struct vfs_s_inode *inode = NULL;
struct vfs_s_inode *root = super->root;
struct vfs_s_entry *entry = NULL;
@ -364,15 +392,14 @@ cpio_create_entry (struct vfs_class *me, struct vfs_s_super *super, struct stat
break;
}
if ((st->st_nlink > 1)
&& ((super->u.arch.type == CPIO_NEWC) || (super->u.arch.type == CPIO_CRC)))
if ((st->st_nlink > 1) && ((arch->type == CPIO_NEWC) || (arch->type == CPIO_CRC)))
{ /* For case of hardlinked files */
struct defer_inode i, *l;
i.inumber = st->st_ino;
i.device = st->st_dev;
i.inode = NULL;
l = cpio_defer_find (super->u.arch.deferred, &i);
l = cpio_defer_find (arch->deferred, &i);
if (l != NULL)
{
inode = l->inode;
@ -439,17 +466,17 @@ cpio_create_entry (struct vfs_class *me, struct vfs_s_super *super, struct stat
if (inode == NULL)
{
inode = vfs_s_new_inode (me, super, st);
if ((st->st_nlink > 0)
&& ((super->u.arch.type == CPIO_NEWC) || (super->u.arch.type == CPIO_CRC)))
if ((st->st_nlink > 0) && ((arch->type == CPIO_NEWC) || (arch->type == CPIO_CRC)))
{
/* For case of hardlinked files */
struct defer_inode *i;
i = g_new (struct defer_inode, 1);
i->inumber = st->st_ino;
i->device = st->st_dev;
i->inode = inode;
i->next = super->u.arch.deferred;
super->u.arch.deferred = i;
i->next = arch->deferred;
arch->deferred = i;
}
}
@ -467,7 +494,7 @@ cpio_create_entry (struct vfs_class *me, struct vfs_s_super *super, struct stat
{
inode->linkname = g_malloc (st->st_size + 1);
if (mc_read (super->u.arch.fd, inode->linkname, st->st_size) < st->st_size)
if (mc_read (arch->fd, inode->linkname, st->st_size) < st->st_size)
{
inode->linkname[0] = '\0';
return STATUS_EOF;
@ -492,15 +519,17 @@ cpio_read_bin_head (struct vfs_class *me, struct vfs_s_super *super)
struct old_cpio_header buf;
short shorts[HEAD_LENGTH >> 1];
} u;
cpio_super_data_t *arch = (cpio_super_data_t *) super->data;
ssize_t len;
char *name;
struct stat st;
len = mc_read (super->u.arch.fd, (char *) &u.buf, HEAD_LENGTH);
len = mc_read (arch->fd, (char *) &u.buf, HEAD_LENGTH);
if (len < HEAD_LENGTH)
return STATUS_EOF;
CPIO_POS (super) += len;
if (super->u.arch.type == CPIO_BINRE)
if (arch->type == CPIO_BINRE)
{
int i;
for (i = 0; i < (HEAD_LENGTH >> 1); i++)
@ -513,7 +542,7 @@ cpio_read_bin_head (struct vfs_class *me, struct vfs_s_super *super)
return STATUS_FAIL;
}
name = g_malloc (u.buf.c_namesize);
len = mc_read (super->u.arch.fd, name, u.buf.c_namesize);
len = mc_read (arch->fd, name, u.buf.c_namesize);
if (len < u.buf.c_namesize)
{
g_free (name);
@ -550,6 +579,7 @@ cpio_read_bin_head (struct vfs_class *me, struct vfs_s_super *super)
static ssize_t
cpio_read_oldc_head (struct vfs_class *me, struct vfs_s_super *super)
{
cpio_super_data_t *arch = (cpio_super_data_t *) super->data;
struct new_cpio_header hd;
union
{
@ -559,7 +589,7 @@ cpio_read_oldc_head (struct vfs_class *me, struct vfs_s_super *super)
ssize_t len;
char *name;
if (mc_read (super->u.arch.fd, u.buf, HEAD_LENGTH) != HEAD_LENGTH)
if (mc_read (arch->fd, u.buf, HEAD_LENGTH) != HEAD_LENGTH)
return STATUS_EOF;
CPIO_POS (super) += HEAD_LENGTH;
u.buf[HEAD_LENGTH] = 0;
@ -579,7 +609,7 @@ cpio_read_oldc_head (struct vfs_class *me, struct vfs_s_super *super)
return STATUS_FAIL;
}
name = g_malloc (hd.c_namesize);
len = mc_read (super->u.arch.fd, name, hd.c_namesize);
len = mc_read (arch->fd, name, hd.c_namesize);
if ((len == -1) || ((unsigned long) len < hd.c_namesize))
{
g_free (name);
@ -616,6 +646,7 @@ cpio_read_oldc_head (struct vfs_class *me, struct vfs_s_super *super)
static ssize_t
cpio_read_crc_head (struct vfs_class *me, struct vfs_s_super *super)
{
cpio_super_data_t *arch = (cpio_super_data_t *) super->data;
struct new_cpio_header hd;
union
{
@ -625,7 +656,7 @@ cpio_read_crc_head (struct vfs_class *me, struct vfs_s_super *super)
ssize_t len;
char *name;
if (mc_read (super->u.arch.fd, u.buf, HEAD_LENGTH) != HEAD_LENGTH)
if (mc_read (arch->fd, u.buf, HEAD_LENGTH) != HEAD_LENGTH)
return STATUS_EOF;
CPIO_POS (super) += HEAD_LENGTH;
@ -642,8 +673,8 @@ cpio_read_crc_head (struct vfs_class *me, struct vfs_s_super *super)
return STATUS_FAIL;
}
if ((super->u.arch.type == CPIO_NEWC && hd.c_magic != 070701) ||
(super->u.arch.type == CPIO_CRC && hd.c_magic != 070702))
if ((arch->type == CPIO_NEWC && hd.c_magic != 070701) ||
(arch->type == CPIO_CRC && hd.c_magic != 070702))
return STATUS_FAIL;
if (hd.c_namesize == 0 || hd.c_namesize > MC_MAXPATHLEN)
@ -653,7 +684,7 @@ cpio_read_crc_head (struct vfs_class *me, struct vfs_s_super *super)
}
name = g_malloc (hd.c_namesize);
len = mc_read (super->u.arch.fd, name, hd.c_namesize);
len = mc_read (arch->fd, name, hd.c_namesize);
if ((len == -1) || ((unsigned long) len < hd.c_namesize))
{
@ -696,7 +727,7 @@ cpio_open_archive (struct vfs_class *me, struct vfs_s_super *super, const char *
if (cpio_open_cpio_file (me, super, name) == -1)
return -1;
for (;;)
while (TRUE)
{
status = cpio_read_head (me, super);
@ -727,9 +758,7 @@ cpio_super_check (struct vfs_class *me, const char *archive_name, char *op)
(void) me;
(void) op;
if (mc_stat (archive_name, &sb))
return NULL;
return &sb;
return (mc_stat (archive_name, &sb) == 0 ? &sb : NULL);
}
/* --------------------------------------------------------------------------------------------- */
@ -747,7 +776,7 @@ cpio_super_same (struct vfs_class *me, struct vfs_s_super *parc,
return 0;
/* Has the cached archive been changed on the disk? */
if (parc->u.arch.st.st_mtime < archive_stat->st_mtime)
if (((cpio_super_data_t *) parc->data)->st.st_mtime < archive_stat->st_mtime)
{
/* Yes, reload! */
(*vfs_cpiofs_ops.free) ((vfsid) parc);
@ -765,7 +794,7 @@ static ssize_t
cpio_read (void *fh, char *buffer, size_t count)
{
off_t begin = FH->ino->data_offset;
int fd = FH_SUPER->u.arch.fd;
int fd = ((cpio_super_data_t *) FH_SUPER->data)->fd;
struct vfs_class *me = FH_SUPER->me;
ssize_t res;
@ -787,9 +816,10 @@ cpio_read (void *fh, char *buffer, size_t count)
static int
cpio_fh_open (struct vfs_class *me, struct vfs_s_fh *fh, int flags, mode_t mode)
{
(void) fh;
(void) mode;
fh->data = NULL;
if ((flags & O_ACCMODE) != O_RDONLY)
ERRNOR (EROFS, -1);
return 0;

View File

@ -113,7 +113,7 @@ int fish_directory_timeout = 900;
#define FISH_HAVE_DATE_MDYT 32
#define FISH_HAVE_TAIL 64
#define SUP super->u.fish
#define SUP ((fish_super_data_t *) super->data)
#define PREFIX \
char buf[BUF_LARGE]; \
@ -132,6 +132,38 @@ int fish_directory_timeout = 900;
/*** file scope type declarations ****************************************************************/
typedef struct
{
int sockr, sockw;
char *cwdir;
char *host, *user;
char *password;
int flags;
char *scr_ls;
char *scr_chmod;
char *scr_exists;
char *scr_mkdir;
char *scr_unlink;
char *scr_chown;
char *scr_rmdir;
char *scr_ln;
char *scr_mv;
char *scr_hardlink;
char *scr_get;
char *scr_send;
char *scr_append;
char *scr_info;
int host_flags;
char *scr_env;
} fish_super_data_t;
typedef struct
{
off_t got;
off_t total;
int append;
} fish_fh_data_t;
/*** file scope variables ************************************************************************/
static char reply_str[80];
@ -191,7 +223,7 @@ fish_decode_reply (char *s, int was_garbage)
static int
fish_get_reply (struct vfs_class *me, int sock, char *string_buf, int string_len)
{
char answer[1024];
char answer[BUF_1K];
int was_garbage = 0;
for (;;)
@ -238,7 +270,7 @@ fish_command (struct vfs_class *me, struct vfs_s_super *super, int wait_reply, c
tty_enable_interrupt_key ();
status = write (SUP.sockw, str, strlen (str));
status = write (SUP->sockw, str, strlen (str));
g_free (str);
tty_disable_interrupt_key ();
@ -246,7 +278,7 @@ fish_command (struct vfs_class *me, struct vfs_s_super *super, int wait_reply, c
return TRANSIENT;
if (wait_reply)
return fish_get_reply (me, SUP.sockr,
return fish_get_reply (me, SUP->sockr,
(wait_reply & WANT_STRING) ? reply_str :
NULL, sizeof (reply_str) - 1);
return COMPLETE;
@ -257,33 +289,35 @@ fish_command (struct vfs_class *me, struct vfs_s_super *super, int wait_reply, c
static void
fish_free_archive (struct vfs_class *me, struct vfs_s_super *super)
{
if ((SUP.sockw != -1) || (SUP.sockr != -1))
if ((SUP->sockw != -1) || (SUP->sockr != -1))
{
vfs_print_message (_("fish: Disconnecting from %s"), super->name ? super->name : "???");
fish_command (me, super, NONE, "#BYE\nexit\n");
close (SUP.sockw);
close (SUP.sockr);
SUP.sockw = SUP.sockr = -1;
close (SUP->sockw);
close (SUP->sockr);
SUP->sockw = SUP->sockr = -1;
}
g_free (SUP.host);
g_free (SUP.user);
g_free (SUP.cwdir);
g_free (SUP.password);
g_free (SUP.scr_ls);
g_free (SUP.scr_exists);
g_free (SUP.scr_mkdir);
g_free (SUP.scr_unlink);
g_free (SUP.scr_chown);
g_free (SUP.scr_chmod);
g_free (SUP.scr_rmdir);
g_free (SUP.scr_ln);
g_free (SUP.scr_mv);
g_free (SUP.scr_hardlink);
g_free (SUP.scr_get);
g_free (SUP.scr_send);
g_free (SUP.scr_append);
g_free (SUP.scr_info);
g_free (SUP.scr_env);
g_free (SUP->host);
g_free (SUP->user);
g_free (SUP->cwdir);
g_free (SUP->password);
g_free (SUP->scr_ls);
g_free (SUP->scr_exists);
g_free (SUP->scr_mkdir);
g_free (SUP->scr_unlink);
g_free (SUP->scr_chown);
g_free (SUP->scr_chmod);
g_free (SUP->scr_rmdir);
g_free (SUP->scr_ln);
g_free (SUP->scr_mv);
g_free (SUP->scr_hardlink);
g_free (SUP->scr_get);
g_free (SUP->scr_send);
g_free (SUP->scr_append);
g_free (SUP->scr_info);
g_free (SUP->scr_env);
g_free (SUP);
super->data = NULL;
}
/* --------------------------------------------------------------------------------------------- */
@ -305,9 +339,9 @@ fish_pipeopen (struct vfs_s_super *super, const char *path, const char *argv[])
vfs_die ("Cannot fork(): %m.");
/* We are the parent */
close (fileset1[0]);
SUP.sockw = fileset1[1];
SUP->sockw = fileset1[1];
close (fileset2[1]);
SUP.sockr = fileset2[0];
SUP->sockr = fileset2[0];
}
else
{
@ -364,18 +398,19 @@ fish_set_env (int flags)
static gboolean
fish_info (struct vfs_class *me, struct vfs_s_super *super)
{
char buffer[8192];
if (fish_command (me, super, NONE, SUP.scr_info) == COMPLETE)
char buffer[BUF_8K];
if (fish_command (me, super, NONE, SUP->scr_info) == COMPLETE)
{
while (1)
while (TRUE)
{
int res;
res = vfs_s_get_line_interruptible (me, buffer, sizeof (buffer), SUP.sockr);
if ((!res) || (res == EINTR))
res = vfs_s_get_line_interruptible (me, buffer, sizeof (buffer), SUP->sockr);
if ((res == 0) || (res == EINTR))
ERRNOR (ECONNRESET, FALSE);
if (!strncmp (buffer, "### ", 4))
if (strncmp (buffer, "### ", 4) == 0)
break;
SUP.host_flags = atol (buffer);
SUP->host_flags = atol (buffer);
}
return TRUE;
}
@ -402,17 +437,17 @@ fish_open_archive_pipeopen (struct vfs_s_super *super)
{
char gbuf[10];
const char *argv[10]; /* All of 10 is used now */
const char *xsh = (SUP.flags == FISH_FLAG_RSH ? "rsh" : "ssh");
const char *xsh = (SUP->flags == FISH_FLAG_RSH ? "rsh" : "ssh");
int i = 0;
argv[i++] = xsh;
if (SUP.flags == FISH_FLAG_COMPRESSED)
if (SUP->flags == FISH_FLAG_COMPRESSED)
argv[i++] = "-C";
if (SUP.flags > FISH_FLAG_RSH)
if (SUP->flags > FISH_FLAG_RSH)
{
argv[i++] = "-p";
g_snprintf (gbuf, sizeof (gbuf), "%d", SUP.flags);
g_snprintf (gbuf, sizeof (gbuf), "%d", SUP->flags);
argv[i++] = gbuf;
}
@ -423,18 +458,18 @@ fish_open_archive_pipeopen (struct vfs_s_super *super)
* option breaks it for some)
*/
if (SUP.user)
if (SUP->user)
{
argv[i++] = "-l";
argv[i++] = SUP.user;
argv[i++] = SUP->user;
}
else
{
/* The rest of the code assumes it to be a valid username */
SUP.user = vfs_get_local_username ();
SUP->user = vfs_get_local_username ();
}
argv[i++] = SUP.host;
argv[i++] = SUP->host;
argv[i++] = "echo FISH:; /bin/sh";
argv[i++] = NULL;
@ -450,7 +485,7 @@ fish_open_archive_talk (struct vfs_class *me, struct vfs_s_super *super)
printf ("\n%s\n", _("fish: Waiting for initial line..."));
if (!vfs_s_get_line (me, SUP.sockr, answer, sizeof (answer), ':'))
if (!vfs_s_get_line (me, SUP->sockr, answer, sizeof (answer), ':'))
return FALSE;
if (strstr (answer, "assword"))
@ -462,22 +497,22 @@ fish_open_archive_talk (struct vfs_class *me, struct vfs_s_super *super)
return FALSE;
#if 0
if (!SUP.password)
if (!SUP->password)
{
char *p, *op;
p = g_strdup_printf (_("fish: Password is required for %s"), SUP.user);
p = g_strdup_printf (_("fish: Password is required for %s"), SUP->user);
op = vfs_get_password (p);
g_free (p);
if (op == NULL)
return FALSE;
SUP.password = op;
SUP->password = op;
}
printf ("\n%s\n", _("fish: Sending password..."));
{
size_t str_len;
str_len = strlen (SUP.password);
if ((write (SUP.sockw, SUP.password, str_len) != (ssize_t) str_len)
|| (write (SUP.sockw, "\n", 1) != 1))
str_len = strlen (SUP->password);
if ((write (SUP->sockw, SUP->password, str_len) != (ssize_t) str_len)
|| (write (SUP->sockw, "\n", 1) != 1))
{
return FALSE;
}
@ -531,13 +566,13 @@ fish_open_archive_int (struct vfs_class *me, struct vfs_s_super *super)
vfs_print_message (_("fish: Getting host info..."));
if (fish_info (me, super))
SUP.scr_env = fish_set_env (SUP.host_flags);
SUP->scr_env = fish_set_env (SUP->host_flags);
vfs_print_message (_("fish: Setting up current directory..."));
SUP.cwdir = fish_getcwd (me, super);
vfs_print_message (_("fish: Connected, home %s."), SUP.cwdir);
SUP->cwdir = fish_getcwd (me, super);
vfs_print_message (_("fish: Connected, home %s."), SUP->cwdir);
#if 0
super->name = g_strconcat ("/#sh:", SUP.user, "@", SUP.host, "/", (char *) NULL);
super->name = g_strconcat ("/#sh:", SUP->user, "@", SUP->host, "/", (char *) NULL);
#endif
super->name = g_strdup (PATH_SEP_STR);
@ -556,34 +591,36 @@ fish_open_archive (struct vfs_class *me, struct vfs_s_super *super,
(void) archive_name;
super->data = g_new0 (fish_super_data_t, 1);
p = vfs_split_url (strchr (op, ':') + 1, &host, &user, &flags,
&password, 0, URL_NOSLASH | URL_USE_ANONYMOUS);
g_free (p);
SUP.host = host;
SUP.user = user;
SUP.flags = flags;
if (!strncmp (op, "rsh:", 4))
SUP.flags = FISH_FLAG_RSH;
SUP.cwdir = NULL;
if (password)
SUP.password = password;
SUP.scr_ls = fish_load_script_from_file (host, FISH_LS_FILE, FISH_LS_DEF_CONTENT);
SUP.scr_exists = fish_load_script_from_file (host, FISH_EXISTS_FILE, FISH_EXISTS_DEF_CONTENT);
SUP.scr_mkdir = fish_load_script_from_file (host, FISH_MKDIR_FILE, FISH_MKDIR_DEF_CONTENT);
SUP.scr_unlink = fish_load_script_from_file (host, FISH_UNLINK_FILE, FISH_UNLINK_DEF_CONTENT);
SUP.scr_chown = fish_load_script_from_file (host, FISH_CHOWN_FILE, FISH_CHOWN_DEF_CONTENT);
SUP.scr_chmod = fish_load_script_from_file (host, FISH_CHMOD_FILE, FISH_CHMOD_DEF_CONTENT);
SUP.scr_rmdir = fish_load_script_from_file (host, FISH_RMDIR_FILE, FISH_RMDIR_DEF_CONTENT);
SUP.scr_ln = fish_load_script_from_file (host, FISH_LN_FILE, FISH_LN_DEF_CONTENT);
SUP.scr_mv = fish_load_script_from_file (host, FISH_MV_FILE, FISH_MV_DEF_CONTENT);
SUP.scr_hardlink =
super->data = g_new0 (fish_super_data_t, 1);
SUP->host = host;
SUP->user = user;
SUP->flags = flags;
if (strncmp (op, "rsh:", 4) == 0)
SUP->flags = FISH_FLAG_RSH;
SUP->cwdir = NULL;
if (password != NULL)
SUP->password = password;
SUP->scr_ls = fish_load_script_from_file (host, FISH_LS_FILE, FISH_LS_DEF_CONTENT);
SUP->scr_exists = fish_load_script_from_file (host, FISH_EXISTS_FILE, FISH_EXISTS_DEF_CONTENT);
SUP->scr_mkdir = fish_load_script_from_file (host, FISH_MKDIR_FILE, FISH_MKDIR_DEF_CONTENT);
SUP->scr_unlink = fish_load_script_from_file (host, FISH_UNLINK_FILE, FISH_UNLINK_DEF_CONTENT);
SUP->scr_chown = fish_load_script_from_file (host, FISH_CHOWN_FILE, FISH_CHOWN_DEF_CONTENT);
SUP->scr_chmod = fish_load_script_from_file (host, FISH_CHMOD_FILE, FISH_CHMOD_DEF_CONTENT);
SUP->scr_rmdir = fish_load_script_from_file (host, FISH_RMDIR_FILE, FISH_RMDIR_DEF_CONTENT);
SUP->scr_ln = fish_load_script_from_file (host, FISH_LN_FILE, FISH_LN_DEF_CONTENT);
SUP->scr_mv = fish_load_script_from_file (host, FISH_MV_FILE, FISH_MV_DEF_CONTENT);
SUP->scr_hardlink =
fish_load_script_from_file (host, FISH_HARDLINK_FILE, FISH_HARDLINK_DEF_CONTENT);
SUP.scr_get = fish_load_script_from_file (host, FISH_GET_FILE, FISH_GET_DEF_CONTENT);
SUP.scr_send = fish_load_script_from_file (host, FISH_SEND_FILE, FISH_SEND_DEF_CONTENT);
SUP.scr_append = fish_load_script_from_file (host, FISH_APPEND_FILE, FISH_APPEND_DEF_CONTENT);
SUP.scr_info = fish_load_script_from_file (host, FISH_INFO_FILE, FISH_INFO_DEF_CONTENT);
SUP->scr_get = fish_load_script_from_file (host, FISH_GET_FILE, FISH_GET_DEF_CONTENT);
SUP->scr_send = fish_load_script_from_file (host, FISH_SEND_FILE, FISH_SEND_DEF_CONTENT);
SUP->scr_append = fish_load_script_from_file (host, FISH_APPEND_FILE, FISH_APPEND_DEF_CONTENT);
SUP->scr_info = fish_load_script_from_file (host, FISH_INFO_FILE, FISH_INFO_DEF_CONTENT);
return fish_open_archive_int (me, super);
}
@ -609,8 +646,8 @@ fish_archive_same (struct vfs_class *me, struct vfs_s_super *super,
if (user == NULL)
user = vfs_get_local_username ();
result = ((strcmp (host, SUP.host) == 0)
&& (strcmp (user, SUP.user) == 0) && (flags == SUP.flags));
result = ((strcmp (host, SUP->host) == 0)
&& (strcmp (user, SUP->user) == 0) && (flags == SUP->flags));
g_free (host);
g_free (user);
@ -647,14 +684,14 @@ fish_dir_load (struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path)
gettimeofday (&dir->timestamp, NULL);
dir->timestamp.tv_sec += fish_directory_timeout;
quoted_path = strutils_shell_escape (remote_path);
shell_commands = g_strconcat (SUP.scr_env, "FISH_FILENAME=%s;\n", SUP.scr_ls, (char *) NULL);
shell_commands = g_strconcat (SUP->scr_env, "FISH_FILENAME=%s;\n", SUP->scr_ls, (char *) NULL);
fish_command (me, super, NONE, shell_commands, quoted_path);
g_free (shell_commands);
g_free (quoted_path);
ent = vfs_s_generate_entry (me, NULL, dir, 0);
while (1)
while (TRUE)
{
int res = vfs_s_get_line_interruptible (me, buffer, sizeof (buffer), SUP.sockr);
int res = vfs_s_get_line_interruptible (me, buffer, sizeof (buffer), SUP->sockr);
if ((!res) || (res == EINTR))
{
vfs_s_free_entry (me, ent);
@ -806,8 +843,8 @@ fish_dir_load (struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path)
reply_code = fish_decode_reply (buffer + 4, 0);
if (reply_code == COMPLETE)
{
g_free (SUP.cwdir);
SUP.cwdir = g_strdup (remote_path);
g_free (SUP->cwdir);
SUP->cwdir = g_strdup (remote_path);
vfs_print_message (_("%s: done."), me->name);
return 0;
}
@ -830,6 +867,7 @@ fish_dir_load (struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path)
static int
fish_file_store (struct vfs_class *me, struct vfs_s_fh *fh, char *name, char *localname)
{
fish_fh_data_t *fish = (fish_fh_data_t *) fh->data;
gchar *shell_commands = NULL;
struct vfs_s_super *super = FH_SUPER;
int n, total;
@ -882,18 +920,20 @@ fish_file_store (struct vfs_class *me, struct vfs_s_fh *fh, char *name, char *lo
vfs_print_message (_("fish: store %s: sending command..."), quoted_name);
/* FIXME: File size is limited to ULONG_MAX */
if (!fh->u.fish.append)
if (!fish->append)
{
shell_commands = g_strconcat (SUP.scr_env, "FISH_FILENAME=%s FISH_FILESIZE=%" PRIuMAX ";\n",
SUP.scr_append, (char *) NULL);
shell_commands =
g_strconcat (SUP->scr_env, "FISH_FILENAME=%s FISH_FILESIZE=%" PRIuMAX ";\n",
SUP->scr_append, (char *) NULL);
n = fish_command (me, super, WAIT_REPLY, shell_commands, quoted_name,
(uintmax_t) s.st_size);
g_free (shell_commands);
}
else
{
shell_commands = g_strconcat (SUP.scr_env, "FISH_FILENAME=%s FISH_FILESIZE=%" PRIuMAX ";\n",
SUP.scr_send, (char *) NULL);
shell_commands =
g_strconcat (SUP->scr_env, "FISH_FILENAME=%s FISH_FILESIZE=%" PRIuMAX ";\n",
SUP->scr_send, (char *) NULL);
n = fish_command (me, super, WAIT_REPLY, shell_commands, quoted_name,
(uintmax_t) s.st_size);
g_free (shell_commands);
@ -906,7 +946,7 @@ fish_file_store (struct vfs_class *me, struct vfs_s_fh *fh, char *name, char *lo
total = 0;
while (1)
while (TRUE)
{
int t;
while ((n = read (h, buffer, sizeof (buffer))) < 0)
@ -921,7 +961,7 @@ fish_file_store (struct vfs_class *me, struct vfs_s_fh *fh, char *name, char *lo
if (n == 0)
break;
t = write (SUP.sockw, buffer, n);
t = write (SUP->sockw, buffer, n);
if (t != n)
{
if (t == -1)
@ -938,12 +978,12 @@ fish_file_store (struct vfs_class *me, struct vfs_s_fh *fh, char *name, char *lo
}
close (h);
g_free (quoted_name);
if ((fish_get_reply (me, SUP.sockr, NULL, 0) != COMPLETE) || was_error)
if ((fish_get_reply (me, SUP->sockr, NULL, 0) != COMPLETE) || was_error)
ERRNOR (E_REMOTE, -1);
return 0;
error_return:
close (h);
fish_get_reply (me, SUP.sockr, NULL, 0);
fish_get_reply (me, SUP->sockr, NULL, 0);
g_free (quoted_name);
return -1;
}
@ -953,17 +993,23 @@ fish_file_store (struct vfs_class *me, struct vfs_s_fh *fh, char *name, char *lo
static int
fish_linear_start (struct vfs_class *me, struct vfs_s_fh *fh, off_t offset)
{
fish_fh_data_t *fish;
gchar *shell_commands = NULL;
struct vfs_s_super *super = FH_SUPER;
char *name;
char *quoted_name;
if (fh->data == NULL)
fh->data = g_new0 (fish_fh_data_t, 1);
fish = (fish_fh_data_t *) fh->data;
name = vfs_s_fullpath (me, fh->ino);
if (name == NULL)
return 0;
quoted_name = strutils_shell_escape (name);
g_free (name);
fh->u.fish.append = 0;
fish->append = 0;
/*
* Check whether the remote file is readable by using `dd' to copy
@ -972,20 +1018,21 @@ fish_linear_start (struct vfs_class *me, struct vfs_s_fh *fh, off_t offset)
* standard output (i.e. over the network).
*/
shell_commands = g_strconcat (SUP.scr_env, "FISH_FILENAME=%s FISH_START_OFFSET=%" PRIuMAX ";\n",
SUP.scr_get, (char *) NULL);
shell_commands =
g_strconcat (SUP->scr_env, "FISH_FILENAME=%s FISH_START_OFFSET=%" PRIuMAX ";\n",
SUP->scr_get, (char *) NULL);
offset = fish_command (me, super, WANT_STRING, shell_commands, quoted_name, (uintmax_t) offset);
g_free (shell_commands);
g_free (quoted_name);
if (offset != PRELIM)
ERRNOR (E_REMOTE, 0);
fh->linear = LS_LINEAR_OPEN;
fh->u.fish.got = 0;
fish->got = 0;
errno = 0;
#if SIZEOF_OFF_T == SIZEOF_LONG
fh->u.fish.total = (off_t) strtol (reply_str, NULL, 10);
fish->total = (off_t) strtol (reply_str, NULL, 10);
#else
fh->u.fish.total = (off_t) strtoll (reply_str, NULL, 10);
fish->total = (off_t) strtoll (reply_str, NULL, 10);
#endif
if (errno != 0)
ERRNOR (E_REMOTE, 0);
@ -997,25 +1044,26 @@ fish_linear_start (struct vfs_class *me, struct vfs_s_fh *fh, off_t offset)
static void
fish_linear_abort (struct vfs_class *me, struct vfs_s_fh *fh)
{
fish_fh_data_t *fish = (fish_fh_data_t *) fh->data;
struct vfs_s_super *super = FH_SUPER;
char buffer[8192];
char buffer[BUF_8K];
int n;
vfs_print_message (_("Aborting transfer..."));
do
{
n = MIN (8192, fh->u.fish.total - fh->u.fish.got);
n = MIN (sizeof (buffer), (size_t) (fish->total - fish->got));
if (n != 0)
{
n = read (SUP.sockr, buffer, n);
n = read (SUP->sockr, buffer, n);
if (n < 0)
return;
fh->u.fish.got += n;
fish->got += n;
}
}
while (n != 0);
if (fish_get_reply (me, SUP.sockr, NULL, 0) != COMPLETE)
if (fish_get_reply (me, SUP->sockr, NULL, 0) != COMPLETE)
vfs_print_message (_("Error reported after abort."));
else
vfs_print_message (_("Aborted transfer would be successful."));
@ -1026,11 +1074,14 @@ fish_linear_abort (struct vfs_class *me, struct vfs_s_fh *fh)
static int
fish_linear_read (struct vfs_class *me, struct vfs_s_fh *fh, void *buf, size_t len)
{
fish_fh_data_t *fish = (fish_fh_data_t *) fh->data;
struct vfs_s_super *super = FH_SUPER;
ssize_t n = 0;
len = MIN ((size_t) (fh->u.fish.total - fh->u.fish.got), len);
len = MIN ((size_t) (fish->total - fish->got), len);
tty_disable_interrupt_key ();
while (len != 0 && ((n = read (SUP.sockr, buf, len)) < 0))
while (len != 0 && ((n = read (SUP->sockr, buf, len)) < 0))
{
if ((errno == EINTR) && !tty_got_interrupt ())
continue;
@ -1039,10 +1090,10 @@ fish_linear_read (struct vfs_class *me, struct vfs_s_fh *fh, void *buf, size_t l
tty_enable_interrupt_key ();
if (n > 0)
fh->u.fish.got += n;
fish->got += n;
else if (n < 0)
fish_linear_abort (me, fh);
else if (fish_get_reply (me, SUP.sockr, NULL, 0) != COMPLETE)
else if (fish_get_reply (me, SUP->sockr, NULL, 0) != COMPLETE)
ERRNOR (E_REMOTE, -1);
ERRNOR (errno, n);
}
@ -1052,7 +1103,9 @@ fish_linear_read (struct vfs_class *me, struct vfs_s_fh *fh, void *buf, size_t l
static void
fish_linear_close (struct vfs_class *me, struct vfs_s_fh *fh)
{
if (fh->u.fish.total != fh->u.fish.got)
fish_fh_data_t *fish = (fish_fh_data_t *) fh->data;
if (fish->total != fish->got)
fish_linear_abort (me, fh);
}
@ -1134,8 +1187,8 @@ fish_rename (struct vfs_class *me, const char *path1, const char *path2)
g_free (mpath1);
rpath2 = strutils_shell_escape (crpath2);
g_free (mpath2);
shell_commands = g_strconcat (SUP.scr_env, "FISH_FILEFROM=%s FISH_FILETO=%s;\n",
SUP.scr_mv, (char *) NULL);
shell_commands = g_strconcat (SUP->scr_env, "FISH_FILEFROM=%s FISH_FILETO=%s;\n",
SUP->scr_mv, (char *) NULL);
g_snprintf (buf, sizeof (buf), shell_commands, rpath1, rpath2);
g_free (shell_commands);
g_free (rpath1);
@ -1173,8 +1226,8 @@ fish_link (struct vfs_class *me, const char *path1, const char *path2)
g_free (mpath1);
rpath2 = strutils_shell_escape (crpath2);
g_free (mpath2);
shell_commands = g_strconcat (SUP.scr_env, "FISH_FILEFROM=%s FISH_FILETO=%s;\n",
SUP.scr_hardlink, (char *) NULL);
shell_commands = g_strconcat (SUP->scr_env, "FISH_FILEFROM=%s FISH_FILETO=%s;\n",
SUP->scr_hardlink, (char *) NULL);
g_snprintf (buf, sizeof (buf), shell_commands, rpath1, rpath2);
g_free (shell_commands);
g_free (rpath1);
@ -1206,8 +1259,8 @@ fish_symlink (struct vfs_class *me, const char *setto, const char *path)
g_free (mpath);
qsetto = strutils_shell_escape (setto);
shell_commands = g_strconcat (SUP.scr_env, "FISH_FILEFROM=%s FISH_FILETO=%s;\n",
SUP.scr_ln, (char *) NULL);
shell_commands = g_strconcat (SUP->scr_env, "FISH_FILEFROM=%s FISH_FILETO=%s;\n",
SUP->scr_ln, (char *) NULL);
g_snprintf (buf, sizeof (buf), shell_commands, qsetto, rpath);
g_free (shell_commands);
g_free (qsetto);
@ -1224,8 +1277,8 @@ fish_chmod (struct vfs_class *me, const char *path, int mode)
PREFIX;
shell_commands = g_strconcat (SUP.scr_env, "FISH_FILENAME=%s FISH_FILEMODE=%4.4o;\n",
SUP.scr_chmod, (char *) NULL);
shell_commands = g_strconcat (SUP->scr_env, "FISH_FILENAME=%s FISH_FILEMODE=%4.4o;\n",
SUP->scr_chmod, (char *) NULL);
g_snprintf (buf, sizeof (buf), shell_commands, rpath, mode & 07777);
g_free (shell_commands);
g_free (rpath);
@ -1256,9 +1309,9 @@ fish_chown (struct vfs_class *me, const char *path, uid_t owner, gid_t group)
PREFIX;
shell_commands = g_strconcat (SUP.scr_env,
shell_commands = g_strconcat (SUP->scr_env,
"FISH_FILENAME=%s FISH_FILEOWNER=%s FISH_FILEGROUP=%s;\n",
SUP.scr_chown, (char *) NULL);
SUP->scr_chown, (char *) NULL);
g_snprintf (buf, sizeof (buf), shell_commands, rpath, sowner, sgroup);
g_free (shell_commands);
fish_send_command (me, super, buf, OPT_FLUSH);
@ -1279,7 +1332,7 @@ fish_unlink (struct vfs_class *me, const char *path)
PREFIX;
shell_commands =
g_strconcat (SUP.scr_env, "FISH_FILENAME=%s;\n", SUP.scr_unlink, (char *) NULL);
g_strconcat (SUP->scr_env, "FISH_FILENAME=%s;\n", SUP->scr_unlink, (char *) NULL);
g_snprintf (buf, sizeof (buf), shell_commands, rpath);
g_free (shell_commands);
g_free (rpath);
@ -1296,7 +1349,7 @@ fish_exists (struct vfs_class *me, const char *path)
PREFIX;
shell_commands =
g_strconcat (SUP.scr_env, "FISH_FILENAME=%s;\n", SUP.scr_exists, (char *) NULL);
g_strconcat (SUP->scr_env, "FISH_FILENAME=%s;\n", SUP->scr_exists, (char *) NULL);
g_snprintf (buf, sizeof (buf), shell_commands, rpath);
g_free (shell_commands);
g_free (rpath);
@ -1317,7 +1370,8 @@ fish_mkdir (struct vfs_class *me, const char *path, mode_t mode)
(void) mode;
shell_commands = g_strconcat (SUP.scr_env, "FISH_FILENAME=%s;\n", SUP.scr_mkdir, (char *) NULL);
shell_commands =
g_strconcat (SUP->scr_env, "FISH_FILENAME=%s;\n", SUP->scr_mkdir, (char *) NULL);
g_snprintf (buf, sizeof (buf), shell_commands, rpath);
g_free (shell_commands);
@ -1343,7 +1397,8 @@ fish_rmdir (struct vfs_class *me, const char *path)
PREFIX;
shell_commands = g_strconcat (SUP.scr_env, "FISH_FILENAME=%s;\n", SUP.scr_rmdir, (char *) NULL);
shell_commands =
g_strconcat (SUP->scr_env, "FISH_FILENAME=%s;\n", SUP->scr_rmdir, (char *) NULL);
g_snprintf (buf, sizeof (buf), shell_commands, rpath);
g_free (shell_commands);
g_free (rpath);
@ -1355,29 +1410,47 @@ fish_rmdir (struct vfs_class *me, const char *path)
static int
fish_fh_open (struct vfs_class *me, struct vfs_s_fh *fh, int flags, mode_t mode)
{
fish_fh_data_t *fish;
(void) mode;
fh->u.fish.append = 0;
fh->data = g_new0 (fish_fh_data_t, 1);
fish = (fish_fh_data_t *) fh->data;
/* File will be written only, so no need to retrieve it */
if (((flags & O_WRONLY) == O_WRONLY) && !(flags & (O_RDONLY | O_RDWR)))
if (((flags & O_WRONLY) == O_WRONLY) && ((flags & (O_RDONLY | O_RDWR)) == 0))
{
fh->u.fish.append = flags & O_APPEND;
fish->append = flags & O_APPEND;
if (!fh->ino->localname)
{
int tmp_handle = vfs_mkstemps (&fh->ino->localname, me->name,
fh->ino->ent->name);
if (tmp_handle == -1)
return -1;
goto fail;
close (tmp_handle);
}
return 0;
}
if (!fh->ino->localname)
if (vfs_s_retrieve_file (me, fh->ino) == -1)
return -1;
if (!fh->ino->localname && vfs_s_retrieve_file (me, fh->ino) == -1)
goto fail;
if (!fh->ino->localname)
vfs_die ("retrieve_file failed to fill in localname");
return 0;
fail:
g_free (fh->data);
return -1;
}
/* --------------------------------------------------------------------------------------------- */
static int
fish_fh_close (struct vfs_class *me, struct vfs_s_fh *fh)
{
(void) me;
g_free (fh->data);
return 0;
}
/* --------------------------------------------------------------------------------------------- */
@ -1395,7 +1468,7 @@ fish_fill_names (struct vfs_class *me, fill_names_f func)
char gbuf[10];
const char *flags = "";
switch (SUP.flags)
switch (SUP->flags)
{
case FISH_FLAG_RSH:
flags = ":r";
@ -1404,15 +1477,16 @@ fish_fill_names (struct vfs_class *me, fill_names_f func)
flags = ":C";
break;
default:
if (SUP.flags > FISH_FLAG_RSH)
if (SUP->flags > FISH_FLAG_RSH)
{
g_snprintf (gbuf, sizeof (gbuf), ":%d", SUP.flags);
g_snprintf (gbuf, sizeof (gbuf), ":%d", SUP->flags);
flags = gbuf;
}
break;
}
name = g_strconcat ("/#sh:", SUP.user, "@", SUP.host, flags, "/", SUP.cwdir, (char *) NULL);
name =
g_strconcat ("/#sh:", SUP->user, "@", SUP->host, flags, "/", SUP->cwdir, (char *) NULL);
func (name);
g_free (name);
}
@ -1447,6 +1521,7 @@ init_fish (void)
fish_subclass.open_archive = fish_open_archive;
fish_subclass.free_archive = fish_free_archive;
fish_subclass.fh_open = fish_fh_open;
fish_subclass.fh_close = fish_fh_close;
fish_subclass.dir_load = fish_dir_load;
fish_subclass.file_store = fish_file_store;
fish_subclass.linear_start = fish_linear_start;

View File

@ -146,8 +146,8 @@ int ftpfs_ignore_chattr_errors = 1;
#endif
#define UPLOAD_ZERO_LENGTH_FILE
#define SUP super->u.ftp
#define FH_SOCK fh->u.ftp.sock
#define SUP ((ftp_super_data_t *) super->data)
#define FH_SOCK ((ftp_fh_data_t *) fh->data)->sock
#ifndef INADDR_NONE
#define INADDR_NONE 0xffffffff
@ -194,6 +194,35 @@ typedef enum
NETRC_UNKNOWN
} keyword_t;
typedef struct
{
int sock;
char *cwdir;
char *host;
char *user;
char *password;
int port;
char *proxy; /* proxy server, NULL if no proxy */
int failed_on_login; /* used to pass the failure reason to upper levels */
int use_passive_connection;
int remote_is_amiga; /* No leading slash allowed for AmiTCP (Amiga) */
int isbinary;
int cwd_deferred; /* current_directory was changed but CWD command hasn't
been sent yet */
int strict; /* ftp server doesn't understand
* "LIST -la <path>"; use "CWD <path>"/
* "LIST" instead
*/
int ctl_connection_busy;
} ftp_super_data_t;
typedef struct
{
int sock;
int append;
} ftp_fh_data_t;
/*** file scope variables ************************************************************************/
static int ftpfs_errno;
@ -217,9 +246,9 @@ static const char *netrcp;
/* --------------------------------------------------------------------------------------------- */
/* char *ftpfs_translate_path (struct ftpfs_connection *bucket, char *remote_path)
Translate a Unix path, i.e. MC's internal path representation (e.g.
/somedir/somefile) to a path valid for the remote server. Every path
transfered to the remote server has to be mangled by this function
Translate a Unix path, i.e. MC's internal path representation (e.g.
/somedir/somefile) to a path valid for the remote server. Every path
transfered to the remote server has to be mangled by this function
right prior to sending it.
Currently only Amiga ftp servers are handled in a special manner.
@ -244,7 +273,7 @@ static int ftpfs_netrc_lookup (const char *host, char **login, char **pass);
static char *
ftpfs_translate_path (struct vfs_class *me, struct vfs_s_super *super, const char *remote_path)
{
if (!SUP.remote_is_amiga)
if (!SUP->remote_is_amiga)
return g_strdup (remote_path);
else
{
@ -388,11 +417,11 @@ ftpfs_reconnect (struct vfs_class *me, struct vfs_s_super *super)
int sock = ftpfs_open_socket (me, super);
if (sock != -1)
{
char *cwdir = SUP.cwdir;
close (SUP.sock);
SUP.sock = sock;
SUP.cwdir = NULL;
if (ftpfs_login_server (me, super, SUP.password))
char *cwdir = SUP->cwdir;
close (SUP->sock);
SUP->sock = sock;
SUP->cwdir = NULL;
if (ftpfs_login_server (me, super, SUP->password))
{
if (!cwdir)
return 1;
@ -400,7 +429,7 @@ ftpfs_reconnect (struct vfs_class *me, struct vfs_s_super *super)
g_free (cwdir);
return sock == COMPLETE;
}
SUP.cwdir = cwdir;
SUP->cwdir = cwdir;
}
return 0;
}
@ -443,7 +472,7 @@ ftpfs_command (struct vfs_class *me, struct vfs_s_super *super, int wait_reply,
got_sigpipe = 0;
tty_enable_interrupt_key ();
status = write (SUP.sock, cmdstr, cmdlen);
status = write (SUP->sock, cmdstr, cmdlen);
if (status < 0)
{
@ -456,7 +485,7 @@ ftpfs_command (struct vfs_class *me, struct vfs_s_super *super, int wait_reply,
level = 1;
status = ftpfs_reconnect (me, super);
level = 0;
if (status && (write (SUP.sock, cmdstr, cmdlen) > 0))
if (status && (write (SUP->sock, cmdstr, cmdlen) > 0))
{
goto ok;
}
@ -474,7 +503,7 @@ ftpfs_command (struct vfs_class *me, struct vfs_s_super *super, int wait_reply,
if (wait_reply)
{
status = ftpfs_get_reply (me, SUP.sock,
status = ftpfs_get_reply (me, SUP->sock,
(wait_reply & WANT_STRING) ? reply_str : NULL,
sizeof (reply_str) - 1);
if ((wait_reply & WANT_STRING) && !retry && !level && code == 421)
@ -483,7 +512,7 @@ ftpfs_command (struct vfs_class *me, struct vfs_s_super *super, int wait_reply,
level = 1;
status = ftpfs_reconnect (me, super);
level = 0;
if (status && (write (SUP.sock, cmdstr, cmdlen) > 0))
if (status && (write (SUP->sock, cmdstr, cmdlen) > 0))
{
goto ok;
}
@ -501,16 +530,18 @@ ftpfs_command (struct vfs_class *me, struct vfs_s_super *super, int wait_reply,
static void
ftpfs_free_archive (struct vfs_class *me, struct vfs_s_super *super)
{
if (SUP.sock != -1)
if (SUP->sock != -1)
{
vfs_print_message (_("ftpfs: Disconnecting from %s"), SUP.host);
vfs_print_message (_("ftpfs: Disconnecting from %s"), SUP->host);
ftpfs_command (me, super, NONE, "QUIT");
close (SUP.sock);
close (SUP->sock);
}
g_free (SUP.host);
g_free (SUP.user);
g_free (SUP.cwdir);
g_free (SUP.password);
g_free (SUP->host);
g_free (SUP->user);
g_free (SUP->cwdir);
g_free (SUP->password);
g_free (super->data);
super->data = NULL;
}
/* --------------------------------------------------------------------------------------------- */
@ -518,11 +549,11 @@ ftpfs_free_archive (struct vfs_class *me, struct vfs_s_super *super)
static int
ftpfs_changetype (struct vfs_class *me, struct vfs_s_super *super, int binary)
{
if (binary != SUP.isbinary)
if (binary != SUP->isbinary)
{
if (ftpfs_command (me, super, WAIT_REPLY, "TYPE %c", binary ? 'I' : 'A') != COMPLETE)
ERRNOR (EIO, -1);
SUP.isbinary = binary;
SUP->isbinary = binary;
}
return binary;
}
@ -539,13 +570,13 @@ ftpfs_login_server (struct vfs_class *me, struct vfs_s_super *super, const char
int anon = 0;
char reply_string[BUF_MEDIUM];
SUP.isbinary = TYPE_UNKNOWN;
SUP->isbinary = TYPE_UNKNOWN;
if (SUP.password) /* explicit password */
op = g_strdup (SUP.password);
else if (netrcpass) /* password from netrc */
if (SUP->password != NULL) /* explicit password */
op = g_strdup (SUP->password);
else if (netrcpass != NULL) /* password from netrc */
op = g_strdup (netrcpass);
else if (!strcmp (SUP.user, "anonymous") || !strcmp (SUP.user, "ftp"))
else if (strcmp (SUP->user, "anonymous") == 0 || strcmp (SUP->user, "ftp") == 0)
{
if (!ftpfs_anonymous_passwd) /* default anonymous password */
ftpfs_init_passwd ();
@ -556,12 +587,12 @@ ftpfs_login_server (struct vfs_class *me, struct vfs_s_super *super, const char
{ /* ask user */
char *p;
p = g_strdup_printf (_("FTP: Password required for %s"), SUP.user);
p = g_strdup_printf (_("FTP: Password required for %s"), SUP->user);
op = vfs_get_password (p);
g_free (p);
if (op == NULL)
ERRNOR (EPERM, 0);
SUP.password = g_strdup (op);
SUP->password = g_strdup (op);
}
if (!anon || MEDATA->logfile)
@ -573,26 +604,26 @@ ftpfs_login_server (struct vfs_class *me, struct vfs_s_super *super, const char
}
/* Proxy server accepts: username@host-we-want-to-connect */
if (SUP.proxy)
if (SUP->proxy)
{
name =
g_strconcat (SUP.user, "@",
SUP.host[0] == '!' ? SUP.host + 1 : SUP.host, (char *) NULL);
g_strconcat (SUP->user, "@",
SUP->host[0] == '!' ? SUP->host + 1 : SUP->host, (char *) NULL);
}
else
name = g_strdup (SUP.user);
name = g_strdup (SUP->user);
if (ftpfs_get_reply (me, SUP.sock, reply_string, sizeof (reply_string) - 1) == COMPLETE)
if (ftpfs_get_reply (me, SUP->sock, reply_string, sizeof (reply_string) - 1) == COMPLETE)
{
char *reply_up;
reply_up = g_ascii_strup (reply_string, -1);
SUP.remote_is_amiga = strstr (reply_up, "AMIGA") != 0;
SUP->remote_is_amiga = strstr (reply_up, "AMIGA") != 0;
g_free (reply_up);
if (MEDATA->logfile)
{
fprintf (MEDATA->logfile, "MC -- remote_is_amiga = %d\n", SUP.remote_is_amiga);
fprintf (MEDATA->logfile, "MC -- remote_is_amiga = %d\n", SUP->remote_is_amiga);
fflush (MEDATA->logfile);
}
@ -607,7 +638,7 @@ ftpfs_login_server (struct vfs_class *me, struct vfs_s_super *super, const char
{
char *p;
p = g_strdup_printf (_("FTP: Account required for user %s"), SUP.user);
p = g_strdup_printf (_("FTP: Account required for user %s"), SUP->user);
op = input_dialog (p, _("Account:"), MC_HISTORY_FTPFS_ACCOUNT, "");
g_free (p);
if (op == NULL)
@ -627,15 +658,15 @@ ftpfs_login_server (struct vfs_class *me, struct vfs_s_super *super, const char
return 1;
default:
SUP.failed_on_login = 1;
if (SUP.password)
wipe_password (SUP.password);
SUP.password = 0;
SUP->failed_on_login = 1;
if (SUP->password)
wipe_password (SUP->password);
SUP->password = 0;
goto login_fail;
}
}
message (D_ERROR, MSG_ERROR, _("ftpfs: Login incorrect for user %s "), SUP.user);
message (D_ERROR, MSG_ERROR, _("ftpfs: Login incorrect for user %s "), SUP->user);
login_fail:
wipe_password (pass);
g_free (name);
@ -755,7 +786,7 @@ ftpfs_open_socket (struct vfs_class *me, struct vfs_s_super *super)
(void) me;
/* Use a proxy host? */
host = g_strdup (SUP.host);
host = g_strdup (SUP->host);
if (!host || !*host)
{
@ -766,9 +797,9 @@ ftpfs_open_socket (struct vfs_class *me, struct vfs_s_super *super)
}
/* Hosts to connect to that start with a ! should use proxy */
tmp_port = SUP.port;
tmp_port = SUP->port;
if (SUP.proxy)
if (SUP->proxy)
{
ftpfs_get_proxy_host_and_port (ftpfs_proxy_host, &host, &tmp_port);
}
@ -878,16 +909,16 @@ ftpfs_open_archive_int (struct vfs_class *me, struct vfs_s_super *super)
int retry_seconds, count_down;
/* We do not want to use the passive if we are using proxies */
if (SUP.proxy)
SUP.use_passive_connection = ftpfs_use_passive_connections_over_proxy;
if (SUP->proxy)
SUP->use_passive_connection = ftpfs_use_passive_connections_over_proxy;
retry_seconds = 0;
do
{
SUP.failed_on_login = 0;
SUP->failed_on_login = 0;
SUP.sock = ftpfs_open_socket (me, super);
if (SUP.sock == -1)
SUP->sock = ftpfs_open_socket (me, super);
if (SUP->sock == -1)
return -1;
if (ftpfs_login_server (me, super, NULL))
@ -897,10 +928,10 @@ ftpfs_open_archive_int (struct vfs_class *me, struct vfs_s_super *super)
}
else
{
if (SUP.failed_on_login)
if (SUP->failed_on_login)
{
/* Close only the socket descriptor */
close (SUP.sock);
close (SUP->sock);
}
else
{
@ -928,9 +959,9 @@ ftpfs_open_archive_int (struct vfs_class *me, struct vfs_s_super *super)
}
while (retry_seconds);
SUP.cwdir = ftpfs_get_current_directory (me, super);
if (!SUP.cwdir)
SUP.cwdir = g_strdup (PATH_SEP_STR);
SUP->cwdir = ftpfs_get_current_directory (me, super);
if (!SUP->cwdir)
SUP->cwdir = g_strdup (PATH_SEP_STR);
return 0;
}
@ -947,18 +978,19 @@ ftpfs_open_archive (struct vfs_class *me, struct vfs_s_super *super,
ftpfs_split_url (strchr (op, ':') + 1, &host, &user, &port, &password);
SUP.host = host;
SUP.user = user;
SUP.port = port;
SUP.cwdir = NULL;
SUP.proxy = 0;
super->data = g_new0 (ftp_super_data_t, 1);
SUP->host = host;
SUP->user = user;
SUP->port = port;
SUP->cwdir = NULL;
SUP->proxy = 0;
if (ftpfs_check_proxy (host))
SUP.proxy = ftpfs_proxy_host;
SUP.password = password;
SUP.use_passive_connection = ftpfs_use_passive_connections;
SUP.strict = ftpfs_use_unix_list_options ? RFC_AUTODETECT : RFC_STRICT;
SUP.isbinary = TYPE_UNKNOWN;
SUP.remote_is_amiga = 0;
SUP->proxy = ftpfs_proxy_host;
SUP->password = password;
SUP->use_passive_connection = ftpfs_use_passive_connections;
SUP->strict = ftpfs_use_unix_list_options ? RFC_AUTODETECT : RFC_STRICT;
SUP->isbinary = TYPE_UNKNOWN;
SUP->remote_is_amiga = 0;
super->name = g_strdup ("/");
super->root = vfs_s_new_inode (me, super, vfs_s_default_stat (me, S_IFDIR | 0755));
@ -980,7 +1012,8 @@ ftpfs_archive_same (struct vfs_class *me, struct vfs_s_super *super,
ftpfs_split_url (strchr (op, ':') + 1, &host, &user, &port, 0);
port = ((strcmp (host, SUP.host) == 0) && (strcmp (user, SUP.user) == 0) && (port == SUP.port));
port = ((strcmp (host, SUP->host) == 0) && (strcmp (user, SUP->user) == 0)
&& (port == SUP->port));
g_free (host);
g_free (user);
@ -997,7 +1030,7 @@ ftpfs_get_current_directory (struct vfs_class *me, struct vfs_s_super *super)
char buf[BUF_8K], *bufp, *bufq;
if (ftpfs_command (me, super, NONE, "PWD") == COMPLETE &&
ftpfs_get_reply (me, SUP.sock, buf, sizeof (buf)) == COMPLETE)
ftpfs_get_reply (me, SUP->sock, buf, sizeof (buf)) == COMPLETE)
{
bufp = NULL;
for (bufq = buf; *bufq; bufq++)
@ -1231,10 +1264,10 @@ ftpfs_init_data_socket (struct vfs_class *me, struct vfs_s_super *super,
memset (data_addr, 0, sizeof (struct sockaddr_storage));
*data_addrlen = sizeof (struct sockaddr_storage);
if (SUP.use_passive_connection)
result = getpeername (SUP.sock, (struct sockaddr *) data_addr, data_addrlen);
if (SUP->use_passive_connection)
result = getpeername (SUP->sock, (struct sockaddr *) data_addr, data_addrlen);
else
result = getsockname (SUP.sock, (struct sockaddr *) data_addr, data_addrlen);
result = getsockname (SUP->sock, (struct sockaddr *) data_addr, data_addrlen);
if (result == -1)
return -1;
@ -1279,7 +1312,7 @@ ftpfs_initconn (struct vfs_class *me, struct vfs_s_super *super)
*/
/* Try to establish a passive connection first (if requested) */
if (SUP.use_passive_connection)
if (SUP->use_passive_connection)
{
int data_sock;
data_sock = ftpfs_init_data_socket (me, super, &data_addr, &data_addrlen);
@ -1291,13 +1324,13 @@ ftpfs_initconn (struct vfs_class *me, struct vfs_s_super *super)
return data_sock;
vfs_print_message (_("ftpfs: could not setup passive mode"));
SUP.use_passive_connection = 0;
SUP->use_passive_connection = 0;
close (data_sock);
}
/* If passive setup is diabled or failed, fallback to active connections */
if (!SUP.use_passive_connection)
if (!SUP->use_passive_connection)
{
int data_sock;
data_sock = ftpfs_init_data_socket (me, super, &data_addr, &data_addrlen);
@ -1317,7 +1350,7 @@ ftpfs_initconn (struct vfs_class *me, struct vfs_s_super *super)
}
/* Restore the initial value of use_passive_connection (for subsequent retries) */
SUP.use_passive_connection = SUP.proxy ? ftpfs_use_passive_connections_over_proxy :
SUP->use_passive_connection = SUP->proxy ? ftpfs_use_passive_connections_over_proxy :
ftpfs_use_passive_connections;
ftpfs_errno = EIO;
@ -1360,7 +1393,7 @@ ftpfs_open_data_connection (struct vfs_class *me, struct vfs_s_super *super, con
if (j != PRELIM)
ERRNOR (EPERM, -1);
tty_enable_interrupt_key ();
if (SUP.use_passive_connection)
if (SUP->use_passive_connection)
data = s;
else
{
@ -1385,13 +1418,13 @@ ftpfs_linear_abort (struct vfs_class *me, struct vfs_s_fh *fh)
struct vfs_s_super *super = FH_SUPER;
static unsigned char const ipbuf[3] = { IAC, IP, IAC };
fd_set mask;
char buf[1024];
char buf[BUF_8K];
int dsock = FH_SOCK;
FH_SOCK = -1;
SUP.ctl_connection_busy = 0;
SUP->ctl_connection_busy = 0;
vfs_print_message (_("ftpfs: aborting transfer."));
if (send (SUP.sock, ipbuf, sizeof (ipbuf), MSG_OOB) != sizeof (ipbuf))
if (send (SUP->sock, ipbuf, sizeof (ipbuf), MSG_OOB) != sizeof (ipbuf))
{
vfs_print_message (_("ftpfs: abort error: %s"), unix_error_string (errno));
if (dsock != -1)
@ -1429,8 +1462,8 @@ ftpfs_linear_abort (struct vfs_class *me, struct vfs_s_fh *fh)
}
close (dsock);
}
if ((ftpfs_get_reply (me, SUP.sock, NULL, 0) == TRANSIENT) && (code == 426))
ftpfs_get_reply (me, SUP.sock, NULL, 0);
if ((ftpfs_get_reply (me, SUP->sock, NULL, 0) == TRANSIENT) && (code == 426))
ftpfs_get_reply (me, SUP->sock, NULL, 0);
}
/* --------------------------------------------------------------------------------------------- */
@ -1601,7 +1634,7 @@ resolve_symlink_with_ls_options (struct vfs_class *me, struct vfs_s_super *super
while (fgets (buffer, sizeof (buffer), fp) != NULL);
tty_disable_interrupt_key ();
fclose (fp);
ftpfs_get_reply (me, SUP.sock, NULL, 0);
ftpfs_get_reply (me, SUP->sock, NULL, 0);
}
/* --------------------------------------------------------------------------------------------- */
@ -1611,7 +1644,7 @@ resolve_symlink (struct vfs_class *me, struct vfs_s_super *super, struct vfs_s_i
{
vfs_print_message (_("Resolving symlink..."));
if (SUP.strict_rfc959_list_cmd)
if (SUP->strict_rfc959_list_cmd)
resolve_symlink_without_ls_options (me, super, dir);
else
resolve_symlink_with_ls_options (me, super, dir);
@ -1629,13 +1662,13 @@ ftpfs_dir_load (struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path
char lc_buffer[BUF_8K];
int cd_first;
cd_first = ftpfs_first_cd_then_ls || (SUP.strict == RFC_STRICT)
cd_first = ftpfs_first_cd_then_ls || (SUP->strict == RFC_STRICT)
|| (strchr (remote_path, ' ') != NULL);
again:
vfs_print_message (_("ftpfs: Reading FTP directory %s... %s%s"),
remote_path,
SUP.strict ==
SUP->strict ==
RFC_STRICT ? _("(strict rfc959)") : "", cd_first ? _("(chdir first)") : "");
if (cd_first)
@ -1651,7 +1684,7 @@ ftpfs_dir_load (struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path
gettimeofday (&dir->timestamp, NULL);
dir->timestamp.tv_sec += ftpfs_directory_timeout;
if (SUP.strict == RFC_STRICT)
if (SUP->strict == RFC_STRICT)
sock = ftpfs_open_data_connection (me, super, "LIST", 0, TYPE_ASCII, 0);
else if (cd_first)
/* Dirty hack to avoid autoprepending / to . */
@ -1684,7 +1717,7 @@ ftpfs_dir_load (struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path
me->verrno = ECONNRESET;
close (sock);
tty_disable_interrupt_key ();
ftpfs_get_reply (me, SUP.sock, NULL, 0);
ftpfs_get_reply (me, SUP->sock, NULL, 0);
vfs_print_message (_("%s: failure"), me->name);
return -1;
}
@ -1710,7 +1743,7 @@ ftpfs_dir_load (struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path
close (sock);
me->verrno = E_REMOTE;
if ((ftpfs_get_reply (me, SUP.sock, NULL, 0) != COMPLETE))
if ((ftpfs_get_reply (me, SUP->sock, NULL, 0) != COMPLETE))
goto fallback;
if (num_entries == 0 && cd_first == 0)
@ -1729,18 +1762,18 @@ ftpfs_dir_load (struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path
goto again;
}
if (SUP.strict == RFC_AUTODETECT)
SUP.strict = RFC_DARING;
if (SUP->strict == RFC_AUTODETECT)
SUP->strict = RFC_DARING;
vfs_print_message (_("%s: done."), me->name);
return 0;
fallback:
if (SUP.strict == RFC_AUTODETECT)
if (SUP->strict == RFC_AUTODETECT)
{
/* It's our first attempt to get a directory listing from this
server (UNIX style LIST command) */
SUP.strict = RFC_STRICT;
SUP->strict = RFC_STRICT;
/* I hate goto, but recursive call needs another 8K on stack */
/* return ftpfs_dir_load (me, dir, remote_path); */
cd_first = 1;
@ -1762,17 +1795,18 @@ ftpfs_file_store (struct vfs_class *me, struct vfs_s_fh *fh, char *name, char *l
#else
int flag_one = 1;
#endif
char lc_buffer[8192];
char lc_buffer[BUF_8K];
struct stat s;
char *w_buf;
struct vfs_s_super *super = FH_SUPER;
ftp_fh_data_t *ftp = (ftp_fh_data_t *) fh->data;
h = open (localname, O_RDONLY);
if (h == -1)
ERRNOR (EIO, -1);
sock =
ftpfs_open_data_connection (me, super,
fh->u.ftp.append ? "APPE" : "STOR", name, TYPE_BINARY, 0);
ftpfs_open_data_connection (me, super, ftp->append ? "APPE" : "STOR", name, TYPE_BINARY, 0);
if (sock < 0 || fstat (h, &s) == -1)
{
close (h);
@ -1788,7 +1822,7 @@ ftpfs_file_store (struct vfs_class *me, struct vfs_s_fh *fh, char *name, char *l
n_stored = 0;
tty_enable_interrupt_key ();
while (1)
while (TRUE)
{
while ((n_read = read (h, lc_buffer, sizeof (lc_buffer))) == -1)
{
@ -1829,14 +1863,14 @@ ftpfs_file_store (struct vfs_class *me, struct vfs_s_fh *fh, char *name, char *l
tty_disable_interrupt_key ();
close (sock);
close (h);
if (ftpfs_get_reply (me, SUP.sock, NULL, 0) != COMPLETE)
if (ftpfs_get_reply (me, SUP->sock, NULL, 0) != COMPLETE)
ERRNOR (EIO, -1);
return 0;
error_return:
tty_disable_interrupt_key ();
close (sock);
close (h);
ftpfs_get_reply (me, SUP.sock, NULL, 0);
ftpfs_get_reply (me, SUP->sock, NULL, 0);
return -1;
}
@ -1845,17 +1879,21 @@ ftpfs_file_store (struct vfs_class *me, struct vfs_s_fh *fh, char *name, char *l
static int
ftpfs_linear_start (struct vfs_class *me, struct vfs_s_fh *fh, off_t offset)
{
char *name = vfs_s_fullpath (me, fh->ino);
char *name;
if (!name)
if (fh->data == NULL)
fh->data = g_new0 (ftp_fh_data_t, 1);
name = vfs_s_fullpath (me, fh->ino);
if (name == NULL)
return 0;
FH_SOCK = ftpfs_open_data_connection (me, FH_SUPER, "RETR", name, TYPE_BINARY, offset);
g_free (name);
if (FH_SOCK == -1)
ERRNOR (EACCES, 0);
fh->linear = LS_LINEAR_OPEN;
FH_SUPER->u.ftp.ctl_connection_busy = 1;
fh->u.ftp.append = 0;
((ftp_super_data_t *) (FH_SUPER->data))->ctl_connection_busy = 1;
((ftp_fh_data_t *) fh->data)->append = 0;
return 1;
}
@ -1879,10 +1917,10 @@ ftpfs_linear_read (struct vfs_class *me, struct vfs_s_fh *fh, void *buf, size_t
if (n == 0)
{
SUP.ctl_connection_busy = 0;
SUP->ctl_connection_busy = 0;
close (FH_SOCK);
FH_SOCK = -1;
if ((ftpfs_get_reply (me, SUP.sock, NULL, 0) != COMPLETE))
if ((ftpfs_get_reply (me, SUP->sock, NULL, 0) != COMPLETE))
ERRNOR (E_REMOTE, -1);
return 0;
}
@ -1916,10 +1954,8 @@ ftpfs_ctl (void *fh, int ctlop, void *arg)
if (FH->linear == LS_LINEAR_CLOSED || FH->linear == LS_LINEAR_PREOPEN)
return 0;
v = vfs_s_select_on_two (FH->u.ftp.sock, 0);
if (((v < 0) && (errno == EINTR)) || v == 0)
return 1;
return 0;
v = vfs_s_select_on_two (((ftp_fh_data_t *) (FH->data))->sock, 0);
return (((v < 0) && (errno == EINTR)) || v == 0) ? 1 : 0;
}
default:
return 0;
@ -1932,11 +1968,12 @@ static int
ftpfs_send_command (struct vfs_class *me, const char *filename, const char *cmd, int flags)
{
const char *rpath;
char *p, *mpath = g_strdup (filename);
char *p, *mpath;
struct vfs_s_super *super;
int r;
int flush_directory_cache = (flags & OPT_FLUSH);
mpath = g_strdup (filename);
rpath = vfs_s_get_path_mangle (me, mpath, &super, 0);
if (rpath == NULL)
{
@ -2011,9 +2048,9 @@ ftpfs_is_same_dir (struct vfs_class *me, struct vfs_s_super *super, const char *
{
(void) me;
if (!SUP.cwdir)
if (!SUP->cwdir)
return 0;
if (strcmp (path, SUP.cwdir) == 0)
if (strcmp (path, SUP->cwdir) == 0)
return 1;
return 0;
}
@ -2026,7 +2063,7 @@ ftpfs_chdir_internal (struct vfs_class *me, struct vfs_s_super *super, const cha
int r;
char *p;
if (!SUP.cwd_deferred && ftpfs_is_same_dir (me, super, remote_path))
if (!SUP->cwd_deferred && ftpfs_is_same_dir (me, super, remote_path))
return COMPLETE;
p = ftpfs_translate_path (me, super, remote_path);
@ -2039,9 +2076,9 @@ ftpfs_chdir_internal (struct vfs_class *me, struct vfs_s_super *super, const cha
}
else
{
g_free (SUP.cwdir);
SUP.cwdir = g_strdup (remote_path);
SUP.cwd_deferred = 0;
g_free (SUP->cwdir);
SUP->cwdir = g_strdup (remote_path);
SUP->cwd_deferred = 0;
}
return r;
}
@ -2078,11 +2115,14 @@ ftpfs_rmdir (struct vfs_class *me, const char *path)
static int
ftpfs_fh_open (struct vfs_class *me, struct vfs_s_fh *fh, int flags, mode_t mode)
{
ftp_fh_data_t *ftp;
(void) mode;
fh->u.ftp.append = 0;
fh->data = g_new0 (ftp_fh_data_t, 1);
ftp = (ftp_fh_data_t *) fh->data;
/* File will be written only, so no need to retrieve it from ftp server */
if (((flags & O_WRONLY) == O_WRONLY) && !(flags & (O_RDONLY | O_RDWR)))
if (((flags & O_WRONLY) == O_WRONLY) && ((flags & (O_RDONLY | O_RDWR)) == 0))
{
#ifdef HAVE_STRUCT_LINGER_L_LINGER
struct linger li;
@ -2092,32 +2132,32 @@ ftpfs_fh_open (struct vfs_class *me, struct vfs_s_fh *fh, int flags, mode_t mode
char *name;
/* ftpfs_linear_start() called, so data will be written
* to local temporary file and stored to ftp server
* to local temporary file and stored to ftp server
* by vfs_s_close later
*/
if (FH_SUPER->u.ftp.ctl_connection_busy)
if (((ftp_super_data_t *) (FH_SUPER->data))->ctl_connection_busy)
{
if (!fh->ino->localname)
{
int handle = vfs_mkstemps (&fh->ino->localname, me->name,
fh->ino->ent->name);
if (handle == -1)
return -1;
goto fail;
close (handle);
fh->u.ftp.append = flags & O_APPEND;
ftp->append = flags & O_APPEND;
}
return 0;
}
name = vfs_s_fullpath (me, fh->ino);
if (!name)
return -1;
if (name == NULL)
goto fail;
fh->handle =
ftpfs_open_data_connection (me, fh->ino->super,
(flags & O_APPEND) ? "APPE" : "STOR", name, TYPE_BINARY, 0);
g_free (name);
if (fh->handle < 0)
return -1;
goto fail;
#ifdef HAVE_STRUCT_LINGER_L_LINGER
li.l_onoff = 1;
li.l_linger = 120;
@ -2133,12 +2173,15 @@ ftpfs_fh_open (struct vfs_class *me, struct vfs_s_fh *fh, int flags, mode_t mode
return 0;
}
if (!fh->ino->localname)
if (vfs_s_retrieve_file (me, fh->ino) == -1)
return -1;
if (!fh->ino->localname && vfs_s_retrieve_file (me, fh->ino) == -1)
goto fail;
if (!fh->ino->localname)
vfs_die ("retrieve_file failed to fill in localname");
return 0;
fail:
g_free (fh->data);
return -1;
}
/* --------------------------------------------------------------------------------------------- */
@ -2148,16 +2191,21 @@ ftpfs_fh_close (struct vfs_class *me, struct vfs_s_fh *fh)
{
if (fh->handle != -1 && !fh->ino->localname)
{
ftp_super_data_t *ftp = (ftp_super_data_t *) fh->ino->super->data;
close (fh->handle);
fh->handle = -1;
/* File is stored to destination already, so
* we prevent MEDATA->ftpfs_file_store() call from vfs_s_close ()
*/
fh->changed = 0;
if (ftpfs_get_reply (me, fh->ino->SUP.sock, NULL, 0) != COMPLETE)
if (ftpfs_get_reply (me, ftp->sock, NULL, 0) != COMPLETE)
ERRNOR (EIO, -1);
vfs_s_invalidate (me, FH_SUPER);
}
g_free (fh->data);
return 0;
}
@ -2187,7 +2235,7 @@ ftpfs_fill_names (struct vfs_class *me, fill_names_f func)
const struct vfs_s_super *super = (const struct vfs_s_super *) iter->data;
char *name;
name = g_strconcat ("/#ftp:", SUP.user, "@", SUP.host, "/", SUP.cwdir, (char *) NULL);
name = g_strconcat ("/#ftp:", SUP->user, "@", SUP->host, "/", SUP->cwdir, (char *) NULL);
func (name);
g_free (name);
}

View File

@ -47,7 +47,7 @@
#include "lib/vfs/vfs.h"
#include "lib/vfs/utilvfs.h"
#include "lib/vfs/xdirentry.h"
#include "lib/vfs/gc.h" /* vfs_rmstamp */
#include "lib/vfs/gc.h" /* vfs_rmstamp */
#include "tar.h"
@ -207,6 +207,13 @@ typedef enum
STATUS_EOF
} ReadStatus;
typedef struct
{
int fd;
struct stat st;
int type; /* Type of the archive */
} tar_super_data_t;
/*** file scope variables ************************************************************************/
static struct vfs_class vfs_tarfs_ops;
@ -254,8 +261,14 @@ tar_free_archive (struct vfs_class *me, struct vfs_s_super *archive)
{
(void) me;
if (archive->u.arch.fd != -1)
mc_close (archive->u.arch.fd);
if (archive->data != NULL)
{
tar_super_data_t *arch = (tar_super_data_t *) archive->data;
if (arch->fd != -1)
mc_close (arch->fd);
g_free (archive->data);
}
}
/* --------------------------------------------------------------------------------------------- */
@ -265,6 +278,7 @@ static int
tar_open_archive_int (struct vfs_class *me, const char *name, struct vfs_s_super *archive)
{
int result, type;
tar_super_data_t *arch;
mode_t mode;
struct vfs_s_inode *root;
@ -276,9 +290,11 @@ tar_open_archive_int (struct vfs_class *me, const char *name, struct vfs_s_super
}
archive->name = g_strdup (name);
mc_stat (name, &(archive->u.arch.st));
archive->u.arch.fd = -1;
archive->u.arch.type = TAR_UNKNOWN;
archive->data = g_new (tar_super_data_t, 1);
arch = (tar_super_data_t *) archive->data;
mc_stat (name, &arch->st);
arch->fd = -1;
arch->type = TAR_UNKNOWN;
/* Find out the method to handle this tar file */
type = get_compression_type (result, name);
@ -296,8 +312,8 @@ tar_open_archive_int (struct vfs_class *me, const char *name, struct vfs_s_super
ERRNOR (ENOENT, -1);
}
archive->u.arch.fd = result;
mode = archive->u.arch.st.st_mode & 07777;
arch->fd = result;
mode = arch->st.st_mode & 07777;
if (mode & 0400)
mode |= 0100;
if (mode & 0040)
@ -306,7 +322,7 @@ tar_open_archive_int (struct vfs_class *me, const char *name, struct vfs_s_super
mode |= 0001;
mode |= S_IFDIR;
root = vfs_s_new_inode (me, archive, &archive->u.arch.st);
root = vfs_s_new_inode (me, archive, &arch->st);
root->st.st_mode = mode;
root->data_offset = -1;
root->st.st_nlink++;
@ -349,6 +365,8 @@ tar_skip_n_records (struct vfs_s_super *archive, int tard, int n)
static void
tar_fill_stat (struct vfs_s_super *archive, struct stat *st, union record *header, size_t h_size)
{
tar_super_data_t *arch = (tar_super_data_t *) archive->data;
st->st_mode = tar_from_oct (8, header->header.mode);
/* Adjust st->st_mode because there are tar-files with
@ -357,30 +375,20 @@ tar_fill_stat (struct vfs_s_super *archive, struct stat *st, union record *heade
* problem when I adjust them, too. -- Norbert.
*/
if (header->header.linkflag == LF_DIR)
{
st->st_mode |= S_IFDIR;
}
else if (header->header.linkflag == LF_SYMLINK)
{
st->st_mode |= S_IFLNK;
}
else if (header->header.linkflag == LF_CHR)
{
st->st_mode |= S_IFCHR;
}
else if (header->header.linkflag == LF_BLK)
{
st->st_mode |= S_IFBLK;
}
else if (header->header.linkflag == LF_FIFO)
{
st->st_mode |= S_IFIFO;
}
else
st->st_mode |= S_IFREG;
st->st_rdev = 0;
switch (archive->u.arch.type)
switch (arch->type)
{
case TAR_USTAR:
case TAR_POSIX:
@ -409,7 +417,7 @@ tar_fill_stat (struct vfs_s_super *archive, struct stat *st, union record *heade
st->st_mtime = tar_from_oct (1 + 12, header->header.mtime);
st->st_atime = 0;
st->st_ctime = 0;
if (archive->u.arch.type == TAR_GNU)
if (arch->type == TAR_GNU)
{
st->st_atime = tar_from_oct (1 + 12, header->header.unused.oldgnu.atime);
st->st_ctime = tar_from_oct (1 + 12, header->header.unused.oldgnu.ctime);
@ -425,6 +433,8 @@ tar_fill_stat (struct vfs_s_super *archive, struct stat *st, union record *heade
static ReadStatus
tar_read_header (struct vfs_class *me, struct vfs_s_super *archive, int tard, size_t * h_size)
{
tar_super_data_t *arch = (tar_super_data_t *) archive->data;
register int i;
register long sum, signed_sum, recsum;
register char *p;
@ -474,19 +484,17 @@ tar_read_header (struct vfs_class *me, struct vfs_s_super *archive, int tard, si
/*
* Try to determine the archive format.
*/
if (archive->u.arch.type == TAR_UNKNOWN)
if (arch->type == TAR_UNKNOWN)
{
if (!strcmp (header->header.magic, TMAGIC))
if (strcmp (header->header.magic, TMAGIC) == 0)
{
if (header->header.linkflag == LF_GLOBAL_EXTHDR)
archive->u.arch.type = TAR_POSIX;
arch->type = TAR_POSIX;
else
archive->u.arch.type = TAR_USTAR;
}
else if (!strcmp (header->header.magic, OLDGNU_MAGIC))
{
archive->u.arch.type = TAR_GNU;
arch->type = TAR_USTAR;
}
else if (strcmp (header->header.magic, OLDGNU_MAGIC) == 0)
arch->type = TAR_GNU;
}
/*
@ -494,12 +502,14 @@ tar_read_header (struct vfs_class *me, struct vfs_s_super *archive, int tard, si
*/
if (header->header.linkflag == '\000')
{
if (header->header.arch_name[NAMSIZ - 1] != '\0')
i = NAMSIZ;
else
i = strlen (header->header.arch_name);
size_t len;
if (i && header->header.arch_name[i - 1] == '/')
if (header->header.arch_name[NAMSIZ - 1] != '\0')
len = NAMSIZ;
else
len = strlen (header->header.arch_name);
if (len != 0 && header->header.arch_name[len - 1] == '/')
header->header.linkflag = LF_DIR;
}
@ -517,8 +527,8 @@ tar_read_header (struct vfs_class *me, struct vfs_s_super *archive, int tard, si
*/
if (header->header.linkflag == LF_DUMPDIR)
{
if (archive->u.arch.type == TAR_UNKNOWN)
archive->u.arch.type = TAR_GNU;
if (arch->type == TAR_UNKNOWN)
arch->type = TAR_GNU;
return STATUS_SUCCESS;
}
@ -528,8 +538,8 @@ tar_read_header (struct vfs_class *me, struct vfs_s_super *archive, int tard, si
*/
if (header->header.linkflag == LF_EXTHDR || header->header.linkflag == LF_GLOBAL_EXTHDR)
{
if (archive->u.arch.type == TAR_UNKNOWN)
archive->u.arch.type = TAR_POSIX;
if (arch->type == TAR_UNKNOWN)
arch->type = TAR_POSIX;
return STATUS_SUCCESS;
}
@ -539,8 +549,8 @@ tar_read_header (struct vfs_class *me, struct vfs_s_super *archive, int tard, si
char *bp, *data;
int size, written;
if (archive->u.arch.type == TAR_UNKNOWN)
archive->u.arch.type = TAR_GNU;
if (arch->type == TAR_UNKNOWN)
arch->type = TAR_GNU;
if (*h_size > MC_MAXPATHLEN)
{
@ -598,7 +608,7 @@ tar_read_header (struct vfs_class *me, struct vfs_s_super *archive, int tard, si
current_link_name[len - 1] = 0;
current_file_name = NULL;
switch (archive->u.arch.type)
switch (arch->type)
{
case TAR_USTAR:
case TAR_POSIX:
@ -701,9 +711,10 @@ tar_read_header (struct vfs_class *me, struct vfs_s_super *archive, int tard, si
done:
next_long_link = next_long_name = NULL;
if (archive->u.arch.type == TAR_GNU && header->header.unused.oldgnu.isextended)
if (arch->type == TAR_GNU && header->header.unused.oldgnu.isextended)
{
while (tar_get_next_record (archive, tard)->ext_hdr.isextended);
while (tar_get_next_record (archive, tard)->ext_hdr.isextended != 0)
;
inode->data_offset = current_tar_position;
}
return STATUS_SUCCESS;
@ -814,7 +825,7 @@ tar_super_same (struct vfs_class *me, struct vfs_s_super *parc,
return 0;
/* Has the cached archive been changed on the disk? */
if (parc->u.arch.st.st_mtime < archive_stat->st_mtime)
if (((tar_super_data_t *) parc->data)->st.st_mtime < archive_stat->st_mtime)
{
/* Yes, reload! */
(*vfs_tarfs_ops.free) ((vfsid) parc);
@ -832,7 +843,7 @@ static ssize_t
tar_read (void *fh, char *buffer, size_t count)
{
off_t begin = FH->ino->data_offset;
int fd = FH_SUPER->u.arch.fd;
int fd = ((tar_super_data_t *) FH_SUPER->data)->fd;
struct vfs_class *me = FH_SUPER->me;
ssize_t res;