O_LINEAR option added, tar fixed to handle bzip/bzip2 files correctly.

This commit is contained in:
Pavel Machek 1998-09-21 09:52:07 +00:00
parent 004d818a54
commit a57c127f2d
14 changed files with 251 additions and 402 deletions

View File

@ -1,3 +1,11 @@
Mon Sep 21 11:40:30 1998 Pavel Machek <pavel@ucw.cz>
* ftpfs.c, fish.c: added O_LINEAR mode to handle linear read of
files in sane way. copy_file_file will make temporary files for a
while (fix pending).
* tar.c: fixed bzip/bzip2 compressed archives
Wed Sep 18 12:51:51 1998 Pavel Machek <pavel@ucw.cz>
* fish.c, vfs.c: created aliases /#ssh: and /#rsh:

View File

@ -29,7 +29,7 @@ VFSHDRS = vfs.h mcfs.h tcputil.h tar.h container.h ftpfs.h names.h \
VFSOBJS = $(NONETFILES) @NETFILES@
EXTFS_MISC = README extfs.ini
EXTFS_CONST = a rpm hp48 mailfs patchfs
EXTFS_CONST = a rpm hp48 mailfs patchfs sfs.ini
EXTFS_IN = deb.in lslR.in ucpio.in urar.in uzoo.in ftplist.in uar.in \
ulha.in uzip.in
EXTFS_OUT = deb lslR ucpio urar uzoo ftplist uar ulha uzip

View File

@ -66,12 +66,12 @@ Server should reply with current directory (in form /abc/def/ghi)
followed by line indicating success.
#LIST /directory
ls -lLga $1 | grep '^[^cbt]' | ( while read p x u g s m d y n; do echo "P$p $u.$g
ls -lLa $1 | grep '^[^cbt]' | ( while read p x u g s m d y n; do echo "P$p $u.$g
S$s
d$m $d $y
:$n
"; done )
ls -lLga $1 | grep '^[cb]' | ( while read p x u g a i m d y n; do echo "P$p $u.$g
ls -lLa $1 | grep '^[cb]' | ( while read p x u g a i m d y n; do echo "P$p $u.$g
E$a$i
dD$m $d $y
:$n
@ -103,7 +103,7 @@ case). As you've probably noticed, this is pretty broken; it is for
compatibility with ls listing.
#RETR /some/name
ls -lg /some/name | ( read a b c d x e; echo $x ); echo '### 100'; cat /some/name; echo '### 200'
ls -l /some/name | ( read a b c d x e; echo $x ); echo '### 100'; cat /some/name; echo '### 200'
Server sends line with filesize on it, followed by line with ### 100
indicating partial success, then it sends binary data (exactly

View File

@ -72,7 +72,6 @@ void extfs_fill_names (void (*func)(char *));
int extfs_prefix_to_type (char *path);
char *extfs_get_prefix (int fstype);
char *extfs_analysis (char *path, char **arc_name, int *fstype, int is_dir);
int extfs_which (char *path);
void extfs_run (char *path);
void extfs_done (void);

View File

@ -2,7 +2,11 @@
# This is config for Single File fileSystem
#
gz/1 gzip < %1 > %3
ugz/1 gzip -d < %1 > %3
ugz/1 gzip -cdf < %1 > %3
bz/1 bzip < %1 > %3
ubz/1 bzip -d < %1 > %3
bz2/1 bzip2 < %1 > %3
ubz2/1 bzip2 -d < %1 > %3
tar/1 tar cf %3 %1
tgz/1 tar czf %3 %1
uhtml/1 lynx -force_html -dump %1 > %3

View File

@ -628,187 +628,81 @@ error_return:
return 0;
}
/* For _ctl routine */
static int remotelocal_handle, remoten = 0, remotestat_size;
static int linear_start(struct direntry *fe)
{
fe->local_stat.st_mtime = 0;
if (command(fe->bucket, WANT_STRING,
"#RETR %s\nls -l %s | ( read var1 var2 var3 var4 var5 var6; echo $var5 ); echo '### 100'; cat %s; echo '### 200'\n",
fe->remote_filename, fe->remote_filename, fe->remote_filename )
!= PRELIM) ERRNOR (EACCES, 0);
fe->got = 0;
fe->total = atoi(reply_str);
return 1;
}
static void
fish_abort (struct connection *bucket)
linear_abort (struct direntry *fe)
{
char buffer[8192];
int n;
print_vfs_message( "Aborting transfer..." );
do {
n = remotestat_size - remotetotal;
n = (n>8192) ? 8192:n;
n = MIN(8192, fe->total - fe->got);
if (n)
if ((n = read(qsockr(remoteent->bucket), remotebuffer, n)) < 0)
if ((n = read(qsockr(fe->bucket), buffer, n)) < 0)
return;
} while (n);
if (get_reply (qsockr(remoteent->bucket), NULL, 0) != COMPLETE)
if (get_reply (qsockr(fe->bucket), NULL, 0) != COMPLETE)
print_vfs_message( "Error reported after abort." );
else
print_vfs_message( "Aborted transfer would be successfull." );
}
static int retrieve_file_start(struct direntry *fe)
static int
linear_read (struct direntry *fe, void *buf, int len)
{
if (fe->local_filename == NULL)
ERRNOR (ENOMEM, 0);
if (command(fe->bucket, WANT_STRING,
"#RETR %s\nls -l %s | ( read var1 var2 var3 var4 var5 var6; echo $var5 ); echo '### 100'; cat %s; echo '### 200'\n",
fe->remote_filename, fe->remote_filename, fe->remote_filename )
!= PRELIM) ERRNOR (EPERM, 0);
remotestat_size = atoi(reply_str);
remotetotal = 0;
remoteent = fe;
return 1;
}
static int retrieve_file_start2(struct direntry *fe)
{
remotebuffer = xmalloc (8192, "retrieve_file");
remotelocal_handle = open(fe->local_filename, O_RDWR | O_CREAT | O_TRUNC | O_EXCL, 0600);
if (remotelocal_handle == -1) {
fish_abort(remoteent->bucket);
free(remotebuffer);
free(fe->local_filename);
fe->local_filename = NULL;
fe->local_is_temp = 1;
ERRNOR (EIO, 0);
int n = 0;
len = MIN( fe->total - fe->got, len );
while (len && ((n = read (qsockr(fe->bucket), buf, len))<0)) {
if ((errno == EINTR) && !got_interrupt())
continue;
break;
}
return 1;
if (n>0) fe->got += n;
if (n<0) linear_abort(fe);
if ((!n) && ((get_reply (qsockr (fe->bucket), NULL, 0) != COMPLETE)))
ERRNOR (EIO, -1);
ERRNOR (errno, n);
}
static int
linear_close (struct direntry *fe)
{
if (fe->total != fe->got)
linear_abort(fe);
}
int fish_ctl (void *data, int ctlop, int arg)
{
int n = 0;
struct filp *fp = data;
int v;
switch (ctlop) {
case MCCTL_ISREMOTECOPY:
return isremotecopy;
case MCCTL_REMOTECOPYCHUNK:
if (!transfer_started)
if (!retrieve_file_start2 (remoteent)){
return MCERR_TARGETOPEN;
} else
transfer_started = 1;
enable_interrupt_key ();
if (!remoten) {
int v = select_on_two (qsockr(remoteent->bucket), 0);
case MCCTL_IS_NOTREADY:
{
int v = select_on_two (qsockr(fp->fe->bucket), 0);
if (((v < 0) && (errno == EINTR)) || v == 0){
disable_interrupt_key ();
return MCERR_DATA_ON_STDIN;
}
n = remotestat_size - remotetotal;
n = (n>8192) ? 8192:n;
if (n)
if ((n = read(qsockr(remoteent->bucket), remotebuffer, n)) < 0){
disable_interrupt_key ();
if (errno == EINTR)
return MCERR_DATA_ON_STDIN;
else
return MCERR_READ;
}
if (!n) {
if (get_reply (qsockr(remoteent->bucket), NULL, 0) != COMPLETE)
my_errno = EIO;
close(remotelocal_handle);
if (localname){
free (localname);
localname = NULL;
}
disable_interrupt_key ();
transfer_started = 0;
return MCERR_FINISH;
}
disable_interrupt_key ();
remotetotal += n;
remoten = n;
} else
n = remoten;
if (write(remotelocal_handle, remotebuffer, remoten) < 0)
return MCERR_WRITE;
remoten = 0;
return n;
/* We get this message if the transfer was aborted */
case MCCTL_FINISHREMOTE:
if (localname) {
free (localname);
localname = NULL;
if (((v < 0) && (errno == EINTR)) || v == 0)
return 1;
return 0;
}
if (!arg) { /* OK */
if (stat (remoteent->local_filename, &remoteent->local_stat) < 0)
remoteent->local_stat.st_mtime = 0;
} else
remoteent->local_stat.st_mtime = 0;
transfer_started = 0;
fish_abort (remoteent->bucket);
my_errno = EINTR;
default:
return 0;
}
return 0;
}
static int retrieve_file(struct direntry *fe)
{
if (fe->local_filename)
return 1;
fe->local_stat.st_mtime = 0;
fe->local_filename = tempnam (NULL, "fish");
fe->local_is_temp = 1;
isremotecopy = 0;
my_errno = ENOMEM;
if (!fe->local_filename ||
!retrieve_file_start(fe))
return 0;
/* Clear the interrupt status */
enable_interrupt_key ();
my_errno = 0;
while (1) {
int res;
res = fish_ctl(NULL, MCCTL_REMOTECOPYCHUNK, 0 );
if ((res == MCERR_TARGETOPEN) ||
(res == MCERR_WRITE) ||
(res == MCERR_DATA_ON_STDIN) ||
(res == MCERR_READ)) {
my_errno = EIO;
break;
}
if (res == MCERR_FINISH)
break;
if (remotestat_size == 0)
print_vfs_message ("fish: Getting file: %ld bytes transfered",
remotetotal);
else
print_vfs_message ("fish: Getting file: %3d%% (%ld bytes transfered)",
remotetotal*100/remotestat_size, remotetotal);
}
if (my_errno) {
disable_interrupt_key ();
fish_abort( remoteent->bucket );
unlink(fe->local_filename);
free(fe->local_filename);
fe->local_filename = NULL;
return 0;
}
if (stat (fe->local_filename, &fe->local_stat) < 0)
fe->local_stat.st_mtime = 0;
return 1;
}
static int

View File

@ -11,12 +11,16 @@ struct direntry
char *local_filename;
int local_is_temp:1;
int freshly_created:1;
int linear:1;
struct stat local_stat;
char *remote_filename;
struct stat s;
struct stat *l_stat;
struct connection *bucket;
int tmp_reget;
int got, total; /* Bytes transfered / bytes need to be transfered */
};
struct dir

View File

@ -994,7 +994,7 @@ open_data_connection (struct connection *bucket, char *cmd, char *remote,
}
static void
ftpfs_abort (struct connection *bucket, int dsock)
my_abort (struct connection *bucket, int dsock)
{
static unsigned char ipbuf[3] = { IAC, IP, IAC };
fd_set mask;
@ -1240,9 +1240,9 @@ retrieve_dir(struct connection *bucket, char *remote_path, int resolve_symlinks)
disable_interrupt_key();
print_vfs_message("ftpfs: reading FTP directory interrupt by user");
#ifdef OLD_READ
ftpfs_abort(bucket, fileno(fp));
my_abort(bucket, fileno(fp));
#else
ftpfs_abort(bucket, sock);
my_abort(bucket, sock);
#endif
close_this_sock(fp, sock);
my_errno = EINTR;
@ -1369,212 +1369,69 @@ error_return:
return 0;
}
/* For _ctl routine */
static int remotelocal_handle, remotesock, remoten, remotestat_size;
static int retrieve_file_start(struct direntry *fe)
static int
linear_start(struct direntry *fe)
{
if (fe->local_filename == NULL) ERRNOR (ENOMEM, 0);
remotesock = open_data_connection(fe->bucket, "RETR", fe->remote_filename, TYPE_BINARY);
if (remotesock == -1) {
my_errno = EACCES;
free (fe->local_filename);
fe->local_filename = NULL;
return 0;
}
remotetotal = 0;
remoteent = fe;
fe->local_stat.st_mtime = 0;
fe->data_sock = open_data_connection(fe->bucket, "RETR", fe->remote_filename, TYPE_BINARY);
if (fe->data_sock == -1)
ERRNOR (EACCES, 0);
return 1;
}
static int retrieve_file_start2(struct direntry *fe)
static int
linear_abort (struct direntry *fe)
{
remotelocal_handle = open(fe->local_filename, O_RDWR | O_CREAT | O_TRUNC, 0600);
if (remotelocal_handle == -1) {
my_errno = EIO;
free(fe->local_filename);
fe->local_filename = NULL;
fe->local_is_temp = 1;
close(remotesock);
return 0;
my_abort(fe->bucket, fe->data_sock);
fe->data_sock = -1;
}
static int
linear_read (struct direntry *fe, void *buf, int len)
{
int n;
while ((n = read (fe->data_sock, buf, len))<0) {
if ((errno == EINTR) && !got_interrupt())
continue;
break;
}
remotestat_size = fe->s.st_size;
remotebuffer = xmalloc (8192, "");
return 1;
if (n<0) linear_abort(fe);
if (!n) {
if ((get_reply (qsock (fe->bucket), NULL, 0) != COMPLETE)) {
my_errno = EIO;
n=-1;
}
fe->data_sock = -1;
}
ERRNOR (errno, n);
}
static int
linear_close (struct direntry *fe)
{
if (fe->data_sock != -1)
linear_abort(fe);
}
int ftpfs_ctl (void *data, int ctlop, int arg)
{
int n = 0;
struct filp *fp = data;
int v;
switch (ctlop) {
case MCCTL_ISREMOTECOPY:
return isremotecopy;
case MCCTL_REMOTECOPYCHUNK:
if (!transfer_started)
if (!retrieve_file_start2 (remoteent)){
return MCERR_TARGETOPEN;
} else
transfer_started = 1;
enable_interrupt_key ();
if (!remoten) {
int v = select_on_two (remotesock, 0);
case MCCTL_IS_NOTREADY:
{
int v = select_on_two (fp->fe->data_sock, 0);
if (((v < 0) && (errno == EINTR)) || v == 0){
disable_interrupt_key ();
return MCERR_DATA_ON_STDIN;
}
if ((n = read(remotesock, remotebuffer, 8192)) < 0){
disable_interrupt_key ();
if (errno == EINTR)
return MCERR_DATA_ON_STDIN;
else
return MCERR_READ;
}
if (n == 0) {
if (get_reply (qsock (remoteent->bucket), NULL, 0) != COMPLETE) {
my_errno = EIO;
}
close(remotelocal_handle);
close(remotesock);
if (localname){
free (localname);
localname = NULL;
}
disable_interrupt_key ();
transfer_started = 0;
return MCERR_FINISH;
}
disable_interrupt_key ();
remotetotal += n;
remoten = n;
} else
n = remoten;
if (write(remotelocal_handle, remotebuffer, remoten) < 0)
return MCERR_WRITE;
remoten = 0;
return n;
/* We get this message if the transfer was aborted */
case MCCTL_FINISHREMOTE:
if (localname) {
free (localname);
localname = NULL;
if (((v < 0) && (errno == EINTR)) || v == 0)
return 1;
return 0;
}
if (!arg) { /* OK */
if (stat (remoteent->local_filename, &remoteent->local_stat) < 0)
remoteent->local_stat.st_mtime = 0;
} else
remoteent->local_stat.st_mtime = 0;
transfer_started = 0;
ftpfs_abort (remoteent->bucket, remotesock);
my_errno = EINTR;
default:
return 0;
}
return 0;
}
static int retrieve_file(struct direntry *fe)
{
int total, tmp_reget = do_reget;
char buffer[8192];
int local_handle, sock, n;
if (fe->local_filename)
return 1;
fe->local_stat.st_mtime = 0;
fe->local_filename = tempnam (NULL, "ftpfs");
fe->local_is_temp = 1;
if (fe->local_filename == NULL) ERRNOR (ENOMEM, 0);
local_handle = open(fe->local_filename, O_RDWR | O_CREAT | O_TRUNC | O_EXCL, 0600);
if (local_handle == -1) {
my_errno = EIO;
free(fe->local_filename);
fe->local_filename = NULL;
return 0;
}
sock = open_data_connection(fe->bucket, "RETR", fe->remote_filename, TYPE_BINARY);
if (sock == -1) {
my_errno = EACCES;
goto error_3;
}
/* Clear the interrupt status */
enable_interrupt_key ();
total = 0;
if (tmp_reget > 0)
total = tmp_reget;
else
total = 0;
while (1) {
int stat_size = fe->s.st_size;
while ((n = read(sock, buffer, sizeof(buffer))) < 0) {
if (errno == EINTR) {
if (got_interrupt ()) {
disable_interrupt_key();
ftpfs_abort(fe->bucket, sock);
my_errno = EINTR;
goto error_2;
}
else
continue;
}
my_errno = errno;
disable_interrupt_key();
goto error_1;
}
if (n == 0)
break;
total += n;
if (stat_size == 0)
print_vfs_message ("ftpfs: Getting file: %ld bytes transfered",
total);
else
print_vfs_message ("ftpfs: Getting file: %3d%% (%ld bytes transfered)",
total*100/stat_size, total);
while (write(local_handle, buffer, n) < 0) {
if (errno == EINTR) {
if (got_interrupt()) {
ftpfs_abort(fe->bucket, sock);
my_errno = EINTR;
goto error_2;
}
else
continue;
}
my_errno = errno;
goto error_1;
}
}
close(local_handle);
close(sock);
if (get_reply (qsock (fe->bucket), NULL, 0) != COMPLETE) {
my_errno = EIO;
goto error_2;
}
if (stat (fe->local_filename, &fe->local_stat) < 0)
fe->local_stat.st_mtime = 0;
if (tmp_reget > 0)
fe->tmp_reget = 1;
return 1;
error_1:
get_reply(qsock(fe->bucket), NULL, 0);
error_2:
close(sock);
error_3:
disable_interrupt_key ();
close(local_handle);
unlink(fe->local_filename);
free(fe->local_filename);
fe->local_filename = NULL;
return 0;
}
static int

View File

@ -8,15 +8,17 @@ struct direntry
char *name;
int count;
char *linkname;
char *local_filename;
char *local_filename, *remote_filename;
int local_is_temp:1;
int freshly_created:1;
int linear:1; /* Did they promiss not to seek? */
int tmp_reget;
struct stat local_stat;
char *remote_filename;
struct stat s;
struct stat *l_stat;
struct connection *bucket;
int data_sock; /* For linear_ operations */
};
struct dir

View File

@ -23,7 +23,7 @@ static void *local_open (char *file, int flags, int mode)
int *local_info;
int fd;
fd = open (file, flags, mode);
fd = open (file, NO_LINEAR(flags), mode);
if (fd == -1)
return 0;

View File

@ -3,6 +3,7 @@ static struct dir *retrieve_dir(struct connection *bucket, char *remote_path, in
static int store_file(struct direntry *fe);
static int retrieve_file_start(struct direntry *fe);
static int retrieve_file(struct direntry *fe);
static int remove_temp_file (char *file_name);
static int
select_on_two (int fd1, int fd2)
@ -188,7 +189,6 @@ void X_fill_names (void (*func)(char *))
} while (lptr != connections_list);
}
/* get_path:
* makes BUCKET point to the connection bucket descriptor for PATH
* returns a malloced string with the pathname relative to BUCKET.
@ -244,31 +244,19 @@ s_get_path (struct connection **bucket, char *path, char *name)
return remote_path;
}
void X_flushdir (void)
void
X_flushdir (void)
{
force_expiration = 1;
force_expiration = 1;
}
/* These variables are for the _ctl routine */
static char *localname = NULL;
static struct direntry *remoteent;
static int remotetotal = 0;
static int transfer_started = 0;
static char *remotebuffer;
static int isremotecopy = 0;
static int remove_temp_file (char *file_name);
static int s_setctl (char *path, int ctlop, char *arg)
static int
s_setctl (char *path, int ctlop, char *arg)
{
switch (ctlop) {
case MCCTL_REMOVELOCALCOPY:
return remove_temp_file (path);
case MCCTL_SETREMOTECOPY: if (localname) free (localname);
localname = strdup (vfs_canon (arg));
return 1;
default:
return 0;
}
}
@ -310,10 +298,8 @@ _get_file_entry(struct connection *bucket, char *file_name,
if (S_ISDIR(fmode)) ERRNOR (EISDIR, NULL);
if (!S_ISREG(fmode)) ERRNOR (EPERM, NULL);
if ((flags & O_EXCL) && (flags & O_CREAT)) ERRNOR (EEXIST, NULL);
if (ent->remote_filename == NULL) {
ent->remote_filename = strdup(file_name);
if (ent->remote_filename == NULL) ERRNOR (ENOMEM, NULL);
}
if (ent->remote_filename == NULL)
if (!(ent->remote_filename = strdup(file_name))) ERRNOR (ENOMEM, NULL);
if (ent->local_filename == NULL ||
!ent->local_stat.st_mtime ||
stat (ent->local_filename, &sb) < 0 ||
@ -322,7 +308,7 @@ _get_file_entry(struct connection *bucket, char *file_name,
if (ent->local_filename){
free (ent->local_filename);
ent->local_filename = 0;
ent->local_filename = NULL;
}
if (flags & O_TRUNC) {
ent->local_filename = tempnam (NULL, X "fs");
@ -334,15 +320,11 @@ _get_file_entry(struct connection *bucket, char *file_name,
ent->local_stat.st_mtime = 0;
}
else {
if (localname != NULL) {
isremotecopy = 1;
if (IS_LINEAR(flags)) {
ent->local_is_temp = 0;
ent->local_stat.st_mtime = 0;
ent->local_filename = strdup (localname);
if (!retrieve_file_start (ent)) {
isremotecopy = 0;
ent->local_filename = NULL;
if (!linear_start (ent))
return NULL;
}
return ent;
}
if (!retrieve_file(ent))
@ -405,7 +387,8 @@ error:
/* this just free's the local temp file. I don't know if the
remote file can be used after this without crashing - paul
psheer@obsidian.co.za psheer@icon.co.za */
static int remove_temp_file (char *file_name)
static int
remove_temp_file (char *file_name)
{
char *p, q;
struct connection *bucket;
@ -439,7 +422,6 @@ static int remove_temp_file (char *file_name)
return -1;
}
static struct direntry *
get_file_entry(char *path, int op, int flags)
{
@ -449,7 +431,6 @@ get_file_entry(char *path, int op, int flags)
if (!(remote_path = get_path (&bucket, path)))
return NULL;
isremotecopy = 0;
fe = _get_file_entry(bucket, remote_path, op,
flags);
free(remote_path);
@ -490,24 +471,23 @@ static void *s_open (char *file, int flags, int mode)
fp = xmalloc(sizeof(struct filp), "struct filp");
if (fp == NULL) ERRNOR (ENOMEM, NULL);
fe = get_file_entry(file, DO_OPEN | DO_RESOLVE_SYMLINK, flags);
if (fe == NULL) {
if (!fe) {
free(fp);
return NULL;
}
if (!isremotecopy) {
fe->linear = IS_LINEAR(flags);
if (!fe->linear) {
fp->local_handle = open(fe->local_filename, flags, mode);
if (fp->local_handle < 0) {
my_errno = errno;
free(fp);
return NULL;
ERRNOR (errno, NULL);
}
} else
fp->local_handle = -1;
} else fp->local_handle = -1;
#ifdef UPLOAD_ZERO_LENGTH_FILE
fp->has_changed = fe->freshly_created;
#else
fp->has_changed = 0;
#endif
#endif
fp->fe = fe;
qlock(fe->bucket)++;
fe->count++;
@ -520,9 +500,12 @@ static int s_read (void *data, char *buffer, int count)
int n;
fp = data;
n = read(fp->local_handle, buffer, count);
if (fp->fe->linear)
return linear_read (fp->fe, buffer, count);
n = read (fp->local_handle, buffer, count);
if (n < 0)
my_errno = errno;
my_errno = errno;
return n;
}
@ -532,9 +515,9 @@ static int s_write (void *data, char *buf, int nbyte)
int n;
fp = data;
n = write(fp->local_handle, buf, nbyte);
n = write (fp->local_handle, buf, nbyte);
if (n < 0)
my_errno = errno;
my_errno = errno;
fp->has_changed = 1;
return n;
}
@ -550,6 +533,8 @@ static int s_close (void *data)
if (normal_flush)
flush_all_directory(fp->fe->bucket);
}
if (fp->fe->linear)
linear_close(fp->fe);
if (fp->local_handle >= 0)
close(fp->local_handle);
qlock(fp->fe->bucket)--;
@ -801,7 +786,6 @@ static void s_ungetlocalcopy (char *path, char *local, int has_changed)
}
}
void
X_done(void)
{
@ -811,3 +795,74 @@ X_done(void)
fclose (logfile);
logfile = NULL;
}
static int retrieve_file(struct direntry *fe)
{
int total, tmp_reget = 0; /* do_reget; -- I think it can not work: pavel@ucw.cz */
char buffer[8192];
int local_handle, n;
int stat_size = fe->s.st_size;
if (fe->local_filename)
return 1;
if (!(fe->local_filename = tempnam (NULL, X))) ERRNOR (ENOMEM, 0);
fe->local_is_temp = 1;
local_handle = open(fe->local_filename, O_RDWR | O_CREAT | O_TRUNC | O_EXCL, 0600);
if (local_handle == -1) {
my_errno = EIO;
goto error_4;
}
if (!linear_start (fe))
goto error_3;
/* Clear the interrupt status */
enable_interrupt_key ();
total = (tmp_reget > 0) ? tmp_reget : 0;
while (1) {
if ((n = linear_read(fe, buffer, sizeof(buffer))) < 0)
goto error_1;
if (!n)
break;
total += n;
print_vfs_stats (X, "Getting file", fe->remote_filename, total, stat_size);
while (write(local_handle, buffer, n) < 0) {
if (errno == EINTR) {
if (got_interrupt()) {
my_errno = EINTR;
goto error_2;
}
else
continue;
}
my_errno = errno;
goto error_1;
}
}
linear_close(fe);
disable_interrupt_key();
close(local_handle);
if (stat (fe->local_filename, &fe->local_stat) < 0)
fe->local_stat.st_mtime = 0;
if (tmp_reget > 0)
fe->tmp_reget = 1;
return 1;
error_1:
error_2:
linear_close(fe);
error_3:
disable_interrupt_key();
close(local_handle);
unlink(fe->local_filename);
error_4:
free(fe->local_filename);
fe->local_filename = NULL;
return 0;
}

View File

@ -343,7 +343,8 @@ static INLINE int uncompress_tar_file (struct archive *current_archive,
/* From time we have sfs this function is pretty trivial */
current_archive->is_gzipped = tar_uncompressed_local;
current_archive->tmpname = copy_strings( current_archive->name, "#ugz", NULL );
current_archive->tmpname = copy_strings( current_archive->name,
decompress_extension (type), NULL );
result = mc_open (current_archive->tmpname, O_RDONLY);
if (result == -1)

View File

@ -826,7 +826,7 @@ int mc_chdir (char *path)
current_dir = vfs_canon (path);
current_vfs = vfs_type (current_dir);
b = strdup (current_dir);
result = (*current_vfs->chdir)(vfs_name (b));
result = (*current_vfs->chdir) ? (*current_vfs->chdir)(vfs_name (b)) : -1;
free (b);
if (result == -1){
errno = ferrno (current_vfs);
@ -1580,6 +1580,17 @@ vfs_die (char *m)
exit (1);
}
void
print_vfs_stats (char *fs_name, char *action, char *file_name, int have, int need)
{
if (need)
print_vfs_message ("%s: %s: %s %3d%% (%ld bytes transfered)",
fs_name, action, file_name, have*100/need, have);
else
print_vfs_message ("%s: %s: %s %ld bytes transfered",
fs_name, action, file_name, have);
}
#ifndef VFS_STANDALONE
char *
vfs_get_password (char *msg)

View File

@ -360,4 +360,18 @@ extern void mc_vfs_done( void );
#define NO_LINEAR(a) (((a) == (O_RDONLY | O_LINEAR)) ? O_RDONLY : (a))
#endif
/* O_LINEAR is strange beast, be carefull. If you open file asserting
* O_RDONLY | O_LINEAR, you promise:
*
* a) to read file linearily from beggining to the end
* b) not to open another file before you close this one
* (this will likely go away in future)
*
* O_LINEAR allows filesystems not to create temporary file in some
* cases (ftp transfer). -- pavel@ucw.cz
*/
#define MIN(a,b) ((a)<(b) ? (a) : (b))
#define MAX(a,b) ((a)<(b) ? (b) : (a))
#endif /* __VFS_H */