mirror of
https://github.com/MidnightCommander/mc
synced 2024-12-22 20:36:50 +03:00
O_LINEAR option added, tar fixed to handle bzip/bzip2 files correctly.
This commit is contained in:
parent
004d818a54
commit
a57c127f2d
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
200
vfs/fish.c
200
vfs/fish.c
@ -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
|
||||
|
@ -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
|
||||
|
243
vfs/ftpfs.c
243
vfs/ftpfs.c
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
13
vfs/vfs.c
13
vfs/vfs.c
@ -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)
|
||||
|
14
vfs/vfs.h
14
vfs/vfs.h
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user