mirror of
https://github.com/MidnightCommander/mc
synced 2025-01-22 03:02:06 +03:00
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:
parent
2e839a6ec6
commit
68628184b1
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user