Adding fish, cleanups, and small updates everywhere to support fish.
Этот коммит содержится в:
родитель
6af6c687c5
Коммит
f45e5aa3fc
@ -1,3 +1,12 @@
|
|||||||
|
Fri Sep 11 22:36:38 1998 Pavel Machek <pavel@ucw.cz>
|
||||||
|
* sfs.c: memory leak fixed
|
||||||
|
|
||||||
|
* vfs.c: split parse_ls_lga into more functions
|
||||||
|
|
||||||
|
* fish.c added, now you can access files over rsh/ssh connection
|
||||||
|
|
||||||
|
* shared*.c: reworked a bit not to include so many of ugly X_'s
|
||||||
|
|
||||||
Wed Sep 2 13:59:47 1998 Pavel Machek <pavel@ucw.cz>
|
Wed Sep 2 13:59:47 1998 Pavel Machek <pavel@ucw.cz>
|
||||||
|
|
||||||
* ftpfs.c: cleanup of code, few static's added
|
* ftpfs.c: cleanup of code, few static's added
|
||||||
|
@ -18,10 +18,10 @@ AR = @AR@
|
|||||||
# VFS code
|
# VFS code
|
||||||
#
|
#
|
||||||
NETFILES = tcputil.o ftpfs.o mcfs.o utilvfs.o
|
NETFILES = tcputil.o ftpfs.o mcfs.o utilvfs.o
|
||||||
NONETFILES = local.o vfs.o tar.o names.o container.o extfs.o sfs.o @undelfs_o@
|
NONETFILES = local.o vfs.o tar.o names.o container.o extfs.o sfs.o fish.o @undelfs_o@
|
||||||
|
|
||||||
VFSSRCS = local.c vfs.c mcfs.c tcputil.c tar.c names.c \
|
VFSSRCS = local.c vfs.c mcfs.c tcputil.c tar.c names.c \
|
||||||
ftpfs.c container.c mcserv.c extfs.c undelfs.c utilvfs.c sfs.c
|
ftpfs.c container.c mcserv.c extfs.c undelfs.c utilvfs.c sfs.c fish.c
|
||||||
|
|
||||||
VFSHDRS = vfs.h mcfs.h tcputil.h tar.h container.h ftpfs.h names.h \
|
VFSHDRS = vfs.h mcfs.h tcputil.h tar.h container.h ftpfs.h names.h \
|
||||||
extfs.h
|
extfs.h
|
||||||
@ -40,7 +40,7 @@ EXTFSSTUFF = $(EXTFS_MISC) $(EXTFS_CONST) $(EXTFS_IN)
|
|||||||
# Commands to build standalone version (.so)
|
# Commands to build standalone version (.so)
|
||||||
#
|
#
|
||||||
|
|
||||||
VFSSOOBJS = tcputil.so ftpfs.so mcfs.so utilvfs.so local.so vfs.so tar.so names.so container.so extfs.so util-alone.so util.sor utilunix.sor sfs.so
|
VFSSOOBJS = tcputil.so ftpfs.so mcfs.so utilvfs.so local.so vfs.so tar.so names.so container.so extfs.so util-alone.so util.sor utilunix.sor sfs.so fish.so
|
||||||
|
|
||||||
%.sor: ../src/%.c
|
%.sor: ../src/%.c
|
||||||
$(CC) -c $(CPPFLAGS) $(DEFS) $(CFLAGS) -DVFS_STANDALONE $< -o $@
|
$(CC) -c $(CPPFLAGS) $(DEFS) $(CFLAGS) -DVFS_STANDALONE $< -o $@
|
||||||
@ -48,8 +48,8 @@ VFSSOOBJS = tcputil.so ftpfs.so mcfs.so utilvfs.so local.so vfs.so tar.so names.
|
|||||||
%.so: %.c
|
%.so: %.c
|
||||||
$(CC) -c $(CPPFLAGS) $(DEFS) $(CFLAGS) -DVFS_STANDALONE $< -o $@
|
$(CC) -c $(CPPFLAGS) $(DEFS) $(CFLAGS) -DVFS_STANDALONE $< -o $@
|
||||||
|
|
||||||
libvfs.so: $(VFSSOOBJS) libvfs.o
|
libvfs.so: $(VFSSOOBJS)
|
||||||
gcc $(VFSSOOBJS) libvfs.o -shared -o libvfs.so
|
gcc $(VFSSOOBJS) -shared -o libvfs.so
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -96,7 +96,7 @@ TAGS: $(VFSSRCS)
|
|||||||
etags $(VFSSRCS)
|
etags $(VFSSRCS)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(RMF) mcserv *.o core a.out libvfs-mc.a mcservx libvfs.so
|
$(RMF) mcserv *.o core a.out libvfs-mc.a mcservx *.so
|
||||||
|
|
||||||
realclean: clean
|
realclean: clean
|
||||||
$(RMF) .depend
|
$(RMF) .depend
|
||||||
|
178
vfs/README.fish
Обычный файл
178
vfs/README.fish
Обычный файл
@ -0,0 +1,178 @@
|
|||||||
|
|
||||||
|
FIles transferred over SHell protocol (V 0.0.2)
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
This protocol was designed for transferring files over secureshell
|
||||||
|
(ssh) connection. It can be as well used for transfers over rsh, and
|
||||||
|
there may be other uses.
|
||||||
|
|
||||||
|
Client sends requests of following form:
|
||||||
|
|
||||||
|
#FISH_COMMAND
|
||||||
|
equivalent shell commands,
|
||||||
|
which may be multiline
|
||||||
|
|
||||||
|
Only fish commands are defined here, shell equivalents are for your
|
||||||
|
information only and will probably vary from implementation to
|
||||||
|
implementation. Fish commands always have priority: server is
|
||||||
|
expected to execute fish command if it understands it. If it does not,
|
||||||
|
however, it can try the luck and execute shell command.
|
||||||
|
|
||||||
|
Server's reply is multiline, but alwyas ends with
|
||||||
|
|
||||||
|
### 000<optional text>
|
||||||
|
|
||||||
|
line. ### is prefix to mark this line, 000 is return code. Return
|
||||||
|
codes are superset to those used in ftp.
|
||||||
|
|
||||||
|
There are few new exit codes defined:
|
||||||
|
|
||||||
|
000 don't know; if there were no previous lines, this marks COMPLETE
|
||||||
|
success, if they were, it marks failure.
|
||||||
|
|
||||||
|
001 don't know; if there were no previous lines, this marks
|
||||||
|
PRELIMinary success, if they were, it marks failure
|
||||||
|
|
||||||
|
Connecting
|
||||||
|
~~~~~~~~~~
|
||||||
|
Client uses "echo FISH:;/bin/sh" as command executed on remote
|
||||||
|
machine. This should make it possible for server to distinguish FISH
|
||||||
|
connections from normal rsh/ssh.
|
||||||
|
|
||||||
|
Commands
|
||||||
|
~~~~~~~~
|
||||||
|
#FISH
|
||||||
|
echo; start_fish_server; echo '### 200'
|
||||||
|
|
||||||
|
This command is sent at the begining. It marks that client wishes to
|
||||||
|
talk via FISH protocol. #VER command must follow. If server
|
||||||
|
understands FISH protocol, it has option to put FISH server somewhere
|
||||||
|
on system path and name it start_fish_server.
|
||||||
|
|
||||||
|
#VER 0.0.2 <feature1> <feature2> <...>
|
||||||
|
echo '### 000'
|
||||||
|
|
||||||
|
This command is the second one. It sends client version and extensions
|
||||||
|
to the server. Server should reply with protocol version to be used,
|
||||||
|
and list of extensions accepted.
|
||||||
|
|
||||||
|
VER 0.0.0 <feature2>
|
||||||
|
### 200
|
||||||
|
|
||||||
|
#PWD
|
||||||
|
pwd; echo '### 200'
|
||||||
|
|
||||||
|
Server should reply with current directory (in form /abc/def/ghi)
|
||||||
|
followed by line indicating success.
|
||||||
|
|
||||||
|
#LIST /directory
|
||||||
|
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 -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
|
||||||
|
"; done )
|
||||||
|
echo '### 200'
|
||||||
|
|
||||||
|
This allows client to list directory or get status information about
|
||||||
|
single file. Output is in following form (any line except :<filename>
|
||||||
|
may be ommited):
|
||||||
|
|
||||||
|
P<unix permissions> <owner>.<group>
|
||||||
|
S<size>
|
||||||
|
d<3-letters month name> <day> <year or HH:MM>
|
||||||
|
D<year> <month> <day> <hour> <minute> <second>[.1234]
|
||||||
|
E<major-of-device>,<minor>
|
||||||
|
:<filename>
|
||||||
|
L<filename symlink points to>
|
||||||
|
<blank line to separate items>
|
||||||
|
|
||||||
|
Unix permissions are of form X--------- where X is type of
|
||||||
|
file. Currently, '-' means regular file, 'd' means directory, 'c', 'b'
|
||||||
|
means character and block device, 'l' means symbolic link, 'p' means
|
||||||
|
FIFO and 's' means socket.
|
||||||
|
|
||||||
|
'd' has three fields: month (one of strings Jan Feb Mar Apr May Jun
|
||||||
|
Jul Aug Sep Oct Nov Dec), day of month, and third is either single
|
||||||
|
number indicating year, or HH:MM field (assume current year in such
|
||||||
|
case). As you've probably noticed, this is pretty broken; it is for
|
||||||
|
compatibility with ls listing.
|
||||||
|
|
||||||
|
#RETR /some/name
|
||||||
|
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
|
||||||
|
filesize bytes) and follows them with (with no preceeding newline) ###
|
||||||
|
200.
|
||||||
|
|
||||||
|
Note that there's no way to abort running RETR command - except
|
||||||
|
closing the connection.
|
||||||
|
|
||||||
|
#STOR <size> /file/name
|
||||||
|
> /file/name; echo '### 001'; ( dd bs=4096 count=<size/4096>; dd bs=<size%4096> count=1 ) 2>/dev/null | ( cat > %s; cat > /dev/null ); echo '### 200'
|
||||||
|
|
||||||
|
This command is for storing /file/name, which is exactly size bytes
|
||||||
|
big. You probably think I went crazy. Well, I did not: that strange
|
||||||
|
cat > /dev/null has purpose to discard any extra data which was not
|
||||||
|
written to disk (due to for example out of space condition).
|
||||||
|
|
||||||
|
[Why? Imagine uploading file with "rm -rf /" line in it.]
|
||||||
|
|
||||||
|
#CWD /somewhere
|
||||||
|
cd /somewhere; echo '### 000'
|
||||||
|
|
||||||
|
It is specified here, but I'm not sure how wise idea is to use this
|
||||||
|
one: it breaks stateless-ness of the protocol.
|
||||||
|
|
||||||
|
Following commands should be rather self-explanatory:
|
||||||
|
|
||||||
|
#CHMOD 1234 file
|
||||||
|
chmod 1234 file; echo '### 000'
|
||||||
|
|
||||||
|
#DELE /some/path
|
||||||
|
rm -f /some/path; echo '### 000'
|
||||||
|
|
||||||
|
#MKD /some/path
|
||||||
|
mkdir /some/path; echo '### 000'
|
||||||
|
|
||||||
|
#RMD /some/path
|
||||||
|
rmdir /some/path; echo '### 000'
|
||||||
|
|
||||||
|
#RENAME /path/a /path/b
|
||||||
|
mv /path/a /path/b; echo '### 000'
|
||||||
|
|
||||||
|
#LINK /path/a /path/b
|
||||||
|
ln /path/a /path/b; echo '### 000'
|
||||||
|
|
||||||
|
#SYMLINK /path/a /path/b
|
||||||
|
ln -s /path/a /path/b; echo '### 000'
|
||||||
|
|
||||||
|
#CHOWN user /file/name
|
||||||
|
chown user /file/name; echo '### 000'
|
||||||
|
|
||||||
|
#CHGRP group /file/name
|
||||||
|
chgrp group /file/name; echo '### 000'
|
||||||
|
|
||||||
|
#READ <offset> <size> /path/and/filename
|
||||||
|
cat /path/and/filename | ( dd bs=4096 count=<offset/4096> > /dev/null;
|
||||||
|
dd bs=<offset%4096> count=1 > /dev/null;
|
||||||
|
dd bs=4096 count=<offset/4096>;
|
||||||
|
dd bs=<offset%4096> count=1; )
|
||||||
|
|
||||||
|
Returns ### 200 on successfull exit, ### 291 on successfull exit when
|
||||||
|
reading ended at eof, ### 292 on successfull exit when reading did not
|
||||||
|
end at eof.
|
||||||
|
|
||||||
|
#WRITE <offset> <size> /path/and/filename
|
||||||
|
|
||||||
|
Hmm, shall we define these ones if we know our client is not going to
|
||||||
|
use them?
|
||||||
|
|
||||||
|
|
||||||
|
That's all, folks!
|
||||||
|
pavel@ucw.cz
|
226
vfs/extfs.c
226
vfs/extfs.c
@ -46,11 +46,11 @@
|
|||||||
#include "vfs.h"
|
#include "vfs.h"
|
||||||
#include "extfs.h"
|
#include "extfs.h"
|
||||||
|
|
||||||
static struct extfs_entry *
|
static struct entry *
|
||||||
extfs_find_entry (struct extfs_entry *dir, char *name, int make_dirs, int make_file);
|
find_entry (struct entry *dir, char *name, int make_dirs, int make_file);
|
||||||
|
|
||||||
static struct extfs_archive *first_archive = NULL;
|
static struct archive *first_archive = NULL;
|
||||||
static int extfserrno = 0;
|
static int my_errno = 0;
|
||||||
static struct stat hstat; /* Stat struct corresponding */
|
static struct stat hstat; /* Stat struct corresponding */
|
||||||
static char *current_file_name, *current_link_name;
|
static char *current_file_name, *current_link_name;
|
||||||
static char *extfs_current_dir;
|
static char *extfs_current_dir;
|
||||||
@ -62,7 +62,7 @@ static int extfs_no = 0;
|
|||||||
|
|
||||||
void extfs_fill_names (void (*func)(char *))
|
void extfs_fill_names (void (*func)(char *))
|
||||||
{
|
{
|
||||||
struct extfs_archive *a = first_archive;
|
struct archive *a = first_archive;
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
while (a){
|
while (a){
|
||||||
@ -75,12 +75,12 @@ void extfs_fill_names (void (*func)(char *))
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void make_dot_doubledot (struct extfs_entry *ent)
|
static void make_dot_doubledot (struct entry *ent)
|
||||||
{
|
{
|
||||||
struct extfs_entry *entry = (struct extfs_entry *)
|
struct entry *entry = (struct entry *)
|
||||||
xmalloc (sizeof (struct extfs_entry), "Extfs: extfs_entry");
|
xmalloc (sizeof (struct entry), "Extfs: entry");
|
||||||
struct extfs_entry *parentry = ent->dir;
|
struct entry *parentry = ent->dir;
|
||||||
struct extfs_inode *inode = ent->inode, *parent;
|
struct inode *inode = ent->inode, *parent;
|
||||||
|
|
||||||
parent = (parentry != NULL) ? parentry->inode : NULL;
|
parent = (parentry != NULL) ? parentry->inode : NULL;
|
||||||
entry->name = strdup (".");
|
entry->name = strdup (".");
|
||||||
@ -91,8 +91,8 @@ static void make_dot_doubledot (struct extfs_entry *ent)
|
|||||||
inode->first_in_subdir = entry;
|
inode->first_in_subdir = entry;
|
||||||
inode->last_in_subdir = entry;
|
inode->last_in_subdir = entry;
|
||||||
inode->nlink++;
|
inode->nlink++;
|
||||||
entry->next_in_dir = (struct extfs_entry *)
|
entry->next_in_dir = (struct entry *)
|
||||||
xmalloc (sizeof (struct extfs_entry), "Extfs: extfs_entry");
|
xmalloc (sizeof (struct entry), "Extfs: entry");
|
||||||
entry=entry->next_in_dir;
|
entry=entry->next_in_dir;
|
||||||
entry->name = strdup ("..");
|
entry->name = strdup ("..");
|
||||||
entry->has_changed = 0;
|
entry->has_changed = 0;
|
||||||
@ -109,16 +109,16 @@ static void make_dot_doubledot (struct extfs_entry *ent)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct extfs_entry *generate_entry (struct extfs_archive *archive,
|
static struct entry *generate_entry (struct archive *archive,
|
||||||
char *name, struct extfs_entry *parentry, mode_t mode)
|
char *name, struct entry *parentry, mode_t mode)
|
||||||
{
|
{
|
||||||
mode_t myumask;
|
mode_t myumask;
|
||||||
struct extfs_inode *inode, *parent;
|
struct inode *inode, *parent;
|
||||||
struct extfs_entry *entry;
|
struct entry *entry;
|
||||||
|
|
||||||
parent = (parentry != NULL) ? parentry->inode : NULL;
|
parent = (parentry != NULL) ? parentry->inode : NULL;
|
||||||
entry = (struct extfs_entry *)
|
entry = (struct entry *)
|
||||||
xmalloc (sizeof (struct extfs_entry), "Extfs: extfs_entry");
|
xmalloc (sizeof (struct entry), "Extfs: entry");
|
||||||
|
|
||||||
entry->name = strdup (name);
|
entry->name = strdup (name);
|
||||||
entry->has_changed = 0;
|
entry->has_changed = 0;
|
||||||
@ -128,8 +128,8 @@ static struct extfs_entry *generate_entry (struct extfs_archive *archive,
|
|||||||
parent->last_in_subdir->next_in_dir = entry;
|
parent->last_in_subdir->next_in_dir = entry;
|
||||||
parent->last_in_subdir = entry;
|
parent->last_in_subdir = entry;
|
||||||
}
|
}
|
||||||
inode = (struct extfs_inode *)
|
inode = (struct inode *)
|
||||||
xmalloc (sizeof (struct extfs_inode), "Extfs: extfs_inode");
|
xmalloc (sizeof (struct inode), "Extfs: inode");
|
||||||
entry->inode = inode;
|
entry->inode = inode;
|
||||||
inode->has_changed = 0;
|
inode->has_changed = 0;
|
||||||
inode->local_filename = NULL;
|
inode->local_filename = NULL;
|
||||||
@ -154,12 +154,12 @@ static struct extfs_entry *generate_entry (struct extfs_archive *archive,
|
|||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_entries (struct extfs_entry *entry)
|
static void free_entries (struct entry *entry)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_archive (struct extfs_archive *archive)
|
static void free_archive (struct archive *archive)
|
||||||
{
|
{
|
||||||
free_entries (archive->root_entry);
|
free_entries (archive->root_entry);
|
||||||
if (archive->local_name != NULL) {
|
if (archive->local_name != NULL) {
|
||||||
@ -175,7 +175,7 @@ static void free_archive (struct extfs_archive *archive)
|
|||||||
free (archive);
|
free (archive);
|
||||||
}
|
}
|
||||||
|
|
||||||
static FILE *open_extfs_archive (int fstype, char *name, struct extfs_archive **pparc)
|
static FILE *open_archive (int fstype, char *name, struct archive **pparc)
|
||||||
{
|
{
|
||||||
static dev_t __extfs_no = 0;
|
static dev_t __extfs_no = 0;
|
||||||
FILE *result;
|
FILE *result;
|
||||||
@ -183,8 +183,8 @@ static FILE *open_extfs_archive (int fstype, char *name, struct extfs_archive **
|
|||||||
char *cmd;
|
char *cmd;
|
||||||
char *mc_extfsdir;
|
char *mc_extfsdir;
|
||||||
struct stat mystat;
|
struct stat mystat;
|
||||||
struct extfs_archive *current_archive;
|
struct archive *current_archive;
|
||||||
struct extfs_entry *root_entry;
|
struct entry *root_entry;
|
||||||
char *local_name = NULL, *tmp = 0;
|
char *local_name = NULL, *tmp = 0;
|
||||||
int uses_archive = extfs_need_archive [fstype];
|
int uses_archive = extfs_need_archive [fstype];
|
||||||
char *tmpfile;
|
char *tmpfile;
|
||||||
@ -221,8 +221,8 @@ static FILE *open_extfs_archive (int fstype, char *name, struct extfs_archive **
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
current_archive = (struct extfs_archive *)
|
current_archive = (struct archive *)
|
||||||
xmalloc (sizeof (struct extfs_archive), "Extfs archive");
|
xmalloc (sizeof (struct archive), "Extfs archive");
|
||||||
current_archive->fstype = fstype;
|
current_archive->fstype = fstype;
|
||||||
current_archive->name = name ? strdup (name): name;
|
current_archive->name = name ? strdup (name): name;
|
||||||
current_archive->local_name = local_name;
|
current_archive->local_name = local_name;
|
||||||
@ -261,13 +261,13 @@ static FILE *open_extfs_archive (int fstype, char *name, struct extfs_archive **
|
|||||||
* Main loop for reading an archive.
|
* Main loop for reading an archive.
|
||||||
* Returns 0 on success, -1 on error.
|
* Returns 0 on success, -1 on error.
|
||||||
*/
|
*/
|
||||||
int read_extfs_archive (int fstype, char *name, struct extfs_archive **pparc)
|
int read_archive (int fstype, char *name, struct archive **pparc)
|
||||||
{
|
{
|
||||||
FILE *extfsd;
|
FILE *extfsd;
|
||||||
char *buffer;
|
char *buffer;
|
||||||
struct extfs_archive *current_archive;
|
struct archive *current_archive;
|
||||||
|
|
||||||
if ((extfsd = open_extfs_archive (fstype, name, ¤t_archive)) == NULL) {
|
if ((extfsd = open_archive (fstype, name, ¤t_archive)) == NULL) {
|
||||||
message_3s (1, MSG_ERROR, _("Couldn't open %s archive\n%s"),
|
message_3s (1, MSG_ERROR, _("Couldn't open %s archive\n%s"),
|
||||||
extfs_prefixes [fstype], name);
|
extfs_prefixes [fstype], name);
|
||||||
return -1;
|
return -1;
|
||||||
@ -277,8 +277,8 @@ int read_extfs_archive (int fstype, char *name, struct extfs_archive **pparc)
|
|||||||
while (fgets (buffer, 4096, extfsd) != NULL) {
|
while (fgets (buffer, 4096, extfsd) != NULL) {
|
||||||
current_link_name = NULL;
|
current_link_name = NULL;
|
||||||
if (parse_ls_lga (buffer, &hstat, ¤t_file_name, ¤t_link_name)) {
|
if (parse_ls_lga (buffer, &hstat, ¤t_file_name, ¤t_link_name)) {
|
||||||
struct extfs_entry *entry, *pent;
|
struct entry *entry, *pent;
|
||||||
struct extfs_inode *inode;
|
struct inode *inode;
|
||||||
char *p, *q, *cfn = current_file_name;
|
char *p, *q, *cfn = current_file_name;
|
||||||
|
|
||||||
if (*cfn) {
|
if (*cfn) {
|
||||||
@ -298,7 +298,7 @@ int read_extfs_archive (int fstype, char *name, struct extfs_archive **pparc)
|
|||||||
if (S_ISDIR (hstat.st_mode) &&
|
if (S_ISDIR (hstat.st_mode) &&
|
||||||
(!strcmp (p, ".") || !strcmp (p, "..")))
|
(!strcmp (p, ".") || !strcmp (p, "..")))
|
||||||
goto read_extfs_continue;
|
goto read_extfs_continue;
|
||||||
pent = extfs_find_entry (current_archive->root_entry, q, 1, 0) ;
|
pent = find_entry (current_archive->root_entry, q, 1, 0) ;
|
||||||
if (pent == NULL) {
|
if (pent == NULL) {
|
||||||
message_1s (1, MSG_ERROR, _("Inconsistent extfs archive"));
|
message_1s (1, MSG_ERROR, _("Inconsistent extfs archive"));
|
||||||
/* FIXME: Should clean everything one day */
|
/* FIXME: Should clean everything one day */
|
||||||
@ -306,7 +306,7 @@ int read_extfs_archive (int fstype, char *name, struct extfs_archive **pparc)
|
|||||||
pclose (extfsd);
|
pclose (extfsd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
entry = (struct extfs_entry *) xmalloc (sizeof (struct extfs_entry), "Extfs: extfs_entry");
|
entry = (struct entry *) xmalloc (sizeof (struct entry), "Extfs: entry");
|
||||||
entry->name = strdup (p);
|
entry->name = strdup (p);
|
||||||
entry->has_changed = 0;
|
entry->has_changed = 0;
|
||||||
entry->next_in_dir = NULL;
|
entry->next_in_dir = NULL;
|
||||||
@ -318,7 +318,7 @@ int read_extfs_archive (int fstype, char *name, struct extfs_archive **pparc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!S_ISLNK (hstat.st_mode) && current_link_name != NULL) {
|
if (!S_ISLNK (hstat.st_mode) && current_link_name != NULL) {
|
||||||
pent = extfs_find_entry (current_archive->root_entry, current_link_name, 0, 0);
|
pent = find_entry (current_archive->root_entry, current_link_name, 0, 0);
|
||||||
if (pent == NULL) {
|
if (pent == NULL) {
|
||||||
message_1s (1, MSG_ERROR, _("Inconsistent extfs archive"));
|
message_1s (1, MSG_ERROR, _("Inconsistent extfs archive"));
|
||||||
/* FIXME: Should clean everything one day */
|
/* FIXME: Should clean everything one day */
|
||||||
@ -330,7 +330,7 @@ int read_extfs_archive (int fstype, char *name, struct extfs_archive **pparc)
|
|||||||
pent->inode->nlink++;
|
pent->inode->nlink++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
inode = (struct extfs_inode *) xmalloc (sizeof (struct extfs_inode), "Extfs: extfs_inode");
|
inode = (struct inode *) xmalloc (sizeof (struct inode), "Extfs: inode");
|
||||||
entry->inode = inode;
|
entry->inode = inode;
|
||||||
inode->local_filename = NULL;
|
inode->local_filename = NULL;
|
||||||
inode->has_changed = 0;
|
inode->has_changed = 0;
|
||||||
@ -377,18 +377,18 @@ int read_extfs_archive (int fstype, char *name, struct extfs_archive **pparc)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *extfs_get_path (char *inname, struct extfs_archive **archive, int is_dir,
|
static char *get_path (char *inname, struct archive **archive, int is_dir,
|
||||||
int do_not_open);
|
int do_not_open);
|
||||||
|
|
||||||
/* Returns path inside argument. Returned char* is inside inname, which is mangled
|
/* Returns path inside argument. Returned char* is inside inname, which is mangled
|
||||||
* by this operation (so you must not free it's return value)
|
* by this operation (so you must not free it's return value)
|
||||||
*/
|
*/
|
||||||
static char *extfs_get_path_mangle (char *inname, struct extfs_archive **archive, int is_dir,
|
static char *get_path_mangle (char *inname, struct archive **archive, int is_dir,
|
||||||
int do_not_open)
|
int do_not_open)
|
||||||
{
|
{
|
||||||
char *local, *archive_name, *op;
|
char *local, *archive_name, *op;
|
||||||
int result = -1;
|
int result = -1;
|
||||||
struct extfs_archive *parc;
|
struct archive *parc;
|
||||||
struct vfs_stamping *parent;
|
struct vfs_stamping *parent;
|
||||||
vfs *v;
|
vfs *v;
|
||||||
int fstype;
|
int fstype;
|
||||||
@ -424,9 +424,9 @@ static char *extfs_get_path_mangle (char *inname, struct extfs_archive **archive
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result = do_not_open ? -1 : read_extfs_archive (fstype, archive_name, &parc);
|
result = do_not_open ? -1 : read_archive (fstype, archive_name, &parc);
|
||||||
if (result == -1) {
|
if (result == -1) {
|
||||||
extfserrno = EIO;
|
my_errno = EIO;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -449,7 +449,7 @@ static char *extfs_get_path_mangle (char *inname, struct extfs_archive **archive
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Returns allocated path (without leading slash) inside the archive */
|
/* Returns allocated path (without leading slash) inside the archive */
|
||||||
static char *extfs_get_path_from_entry (struct extfs_entry *entry)
|
static char *get_path_from_entry (struct entry *entry)
|
||||||
{
|
{
|
||||||
struct list {
|
struct list {
|
||||||
struct list *next;
|
struct list *next;
|
||||||
@ -480,23 +480,23 @@ static char *extfs_get_path_from_entry (struct extfs_entry *entry)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct extfs_loop_protect {
|
struct loop_protect {
|
||||||
struct extfs_entry *entry;
|
struct entry *entry;
|
||||||
struct extfs_loop_protect *next;
|
struct loop_protect *next;
|
||||||
};
|
};
|
||||||
static int errloop;
|
static int errloop;
|
||||||
static int notadir;
|
static int notadir;
|
||||||
|
|
||||||
static struct extfs_entry *
|
static struct entry *
|
||||||
__extfs_find_entry (struct extfs_entry *dir, char *name,
|
__find_entry (struct entry *dir, char *name,
|
||||||
struct extfs_loop_protect *list, int make_dirs, int make_file);
|
struct loop_protect *list, int make_dirs, int make_file);
|
||||||
|
|
||||||
static struct extfs_entry *
|
static struct entry *
|
||||||
__extfs_resolve_symlinks (struct extfs_entry *entry,
|
__resolve_symlinks (struct entry *entry,
|
||||||
struct extfs_loop_protect *list)
|
struct loop_protect *list)
|
||||||
{
|
{
|
||||||
struct extfs_entry *pent;
|
struct entry *pent;
|
||||||
struct extfs_loop_protect *looping;
|
struct loop_protect *looping;
|
||||||
|
|
||||||
if (!S_ISLNK (entry->inode->mode))
|
if (!S_ISLNK (entry->inode->mode))
|
||||||
return entry;
|
return entry;
|
||||||
@ -505,42 +505,42 @@ __extfs_resolve_symlinks (struct extfs_entry *entry,
|
|||||||
errloop = 1;
|
errloop = 1;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
looping = (struct extfs_loop_protect *)
|
looping = (struct loop_protect *)
|
||||||
xmalloc (sizeof (struct extfs_loop_protect),
|
xmalloc (sizeof (struct loop_protect),
|
||||||
"Extfs: symlink looping protection");
|
"Extfs: symlink looping protection");
|
||||||
looping->entry = entry;
|
looping->entry = entry;
|
||||||
looping->next = list;
|
looping->next = list;
|
||||||
pent = __extfs_find_entry (entry->dir, entry->inode->linkname, looping, 0, 0);
|
pent = __find_entry (entry->dir, entry->inode->linkname, looping, 0, 0);
|
||||||
free (looping);
|
free (looping);
|
||||||
if (pent == NULL)
|
if (pent == NULL)
|
||||||
extfserrno = ENOENT;
|
my_errno = ENOENT;
|
||||||
return pent;
|
return pent;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct extfs_entry *extfs_resolve_symlinks (struct extfs_entry *entry)
|
static struct entry *my_resolve_symlinks (struct entry *entry)
|
||||||
{
|
{
|
||||||
struct extfs_entry *res;
|
struct entry *res;
|
||||||
|
|
||||||
errloop = 0;
|
errloop = 0;
|
||||||
notadir = 0;
|
notadir = 0;
|
||||||
res = __extfs_resolve_symlinks (entry, NULL);
|
res = __resolve_symlinks (entry, NULL);
|
||||||
if (res == NULL) {
|
if (res == NULL) {
|
||||||
if (errloop)
|
if (errloop)
|
||||||
extfserrno = ELOOP;
|
my_errno = ELOOP;
|
||||||
else if (notadir)
|
else if (notadir)
|
||||||
extfserrno = ENOTDIR;
|
my_errno = ENOTDIR;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct extfs_pseudofile {
|
struct pseudofile {
|
||||||
struct extfs_archive *archive;
|
struct archive *archive;
|
||||||
unsigned int has_changed:1;
|
unsigned int has_changed:1;
|
||||||
int local_handle;
|
int local_handle;
|
||||||
struct extfs_entry *entry;
|
struct entry *entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
static char *get_archive_name (struct extfs_archive *archive)
|
static char *get_archive_name (struct archive *archive)
|
||||||
{
|
{
|
||||||
char *archive_name;
|
char *archive_name;
|
||||||
|
|
||||||
@ -557,10 +557,10 @@ static char *get_archive_name (struct extfs_archive *archive)
|
|||||||
|
|
||||||
void extfs_run (char *file)
|
void extfs_run (char *file)
|
||||||
{
|
{
|
||||||
struct extfs_archive *archive;
|
struct archive *archive;
|
||||||
char *p, *q, *cmd, *archive_name, *mc_extfsdir;
|
char *p, *q, *cmd, *archive_name, *mc_extfsdir;
|
||||||
|
|
||||||
if ((p = extfs_get_path (file, &archive, 0, 0)) == NULL)
|
if ((p = get_path (file, &archive, 0, 0)) == NULL)
|
||||||
return;
|
return;
|
||||||
q = name_quote (p, 0);
|
q = name_quote (p, 0);
|
||||||
|
|
||||||
@ -582,30 +582,30 @@ void extfs_run (char *file)
|
|||||||
|
|
||||||
static void *extfs_open (char *file, int flags, int mode)
|
static void *extfs_open (char *file, int flags, int mode)
|
||||||
{
|
{
|
||||||
struct extfs_pseudofile *extfs_info;
|
struct pseudofile *extfs_info;
|
||||||
struct extfs_archive *archive;
|
struct archive *archive;
|
||||||
char *q;
|
char *q;
|
||||||
char *mc_extfsdir;
|
char *mc_extfsdir;
|
||||||
struct extfs_entry *entry;
|
struct entry *entry;
|
||||||
int local_handle;
|
int local_handle;
|
||||||
const int do_create = (flags & O_ACCMODE) != O_RDONLY;
|
const int do_create = (flags & O_ACCMODE) != O_RDONLY;
|
||||||
|
|
||||||
if ((q = extfs_get_path_mangle (file, &archive, 0, 0)) == NULL)
|
if ((q = get_path_mangle (file, &archive, 0, 0)) == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
entry = extfs_find_entry (archive->root_entry, q, 0, do_create);
|
entry = find_entry (archive->root_entry, q, 0, do_create);
|
||||||
if (entry == NULL)
|
if (entry == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if ((entry = extfs_resolve_symlinks (entry)) == NULL)
|
if ((entry = my_resolve_symlinks (entry)) == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (S_ISDIR (entry->inode->mode)) {
|
if (S_ISDIR (entry->inode->mode)) {
|
||||||
extfserrno = EISDIR;
|
my_errno = EISDIR;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (entry->inode->local_filename == NULL) {
|
if (entry->inode->local_filename == NULL) {
|
||||||
char *cmd, *archive_name, *p;
|
char *cmd, *archive_name, *p;
|
||||||
|
|
||||||
entry->inode->local_filename = strdup (tempnam (NULL, "extfs"));
|
entry->inode->local_filename = strdup (tempnam (NULL, "extfs"));
|
||||||
p = extfs_get_path_from_entry (entry);
|
p = get_path_from_entry (entry);
|
||||||
q = name_quote (p, 0);
|
q = name_quote (p, 0);
|
||||||
free (p);
|
free (p);
|
||||||
archive_name = name_quote (get_archive_name (archive), 0);
|
archive_name = name_quote (get_archive_name (archive), 0);
|
||||||
@ -623,7 +623,7 @@ static void *extfs_open (char *file, int flags, int mode)
|
|||||||
entry->inode->local_filename = NULL;
|
entry->inode->local_filename = NULL;
|
||||||
free (cmd);
|
free (cmd);
|
||||||
free (mc_extfsdir);
|
free (mc_extfsdir);
|
||||||
extfserrno = EIO;
|
my_errno = EIO;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
free (cmd);
|
free (cmd);
|
||||||
@ -632,11 +632,11 @@ static void *extfs_open (char *file, int flags, int mode)
|
|||||||
|
|
||||||
local_handle = open (entry->inode->local_filename, flags, mode);
|
local_handle = open (entry->inode->local_filename, flags, mode);
|
||||||
if (local_handle == -1) {
|
if (local_handle == -1) {
|
||||||
extfserrno = EIO;
|
my_errno = EIO;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
extfs_info = (struct extfs_pseudofile *) xmalloc (sizeof (struct extfs_pseudofile), "Extfs: extfs_open");
|
extfs_info = (struct pseudofile *) xmalloc (sizeof (struct pseudofile), "Extfs: extfs_open");
|
||||||
extfs_info->archive = archive;
|
extfs_info->archive = archive;
|
||||||
extfs_info->entry = entry;
|
extfs_info->entry = entry;
|
||||||
extfs_info->has_changed = 0;
|
extfs_info->has_changed = 0;
|
||||||
@ -650,22 +650,22 @@ static void *extfs_open (char *file, int flags, int mode)
|
|||||||
|
|
||||||
static int extfs_read (void *data, char *buffer, int count)
|
static int extfs_read (void *data, char *buffer, int count)
|
||||||
{
|
{
|
||||||
struct extfs_pseudofile *file = (struct extfs_pseudofile *)data;
|
struct pseudofile *file = (struct pseudofile *)data;
|
||||||
|
|
||||||
return read (file->local_handle, buffer, count);
|
return read (file->local_handle, buffer, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int extfs_close (void *data)
|
static int extfs_close (void *data)
|
||||||
{
|
{
|
||||||
struct extfs_pseudofile *file;
|
struct pseudofile *file;
|
||||||
int errno_code = 0;
|
int errno_code = 0;
|
||||||
file = (struct extfs_pseudofile *)data;
|
file = (struct pseudofile *)data;
|
||||||
|
|
||||||
close (file->local_handle);
|
close (file->local_handle);
|
||||||
|
|
||||||
/* Commit the file if it has changed */
|
/* Commit the file if it has changed */
|
||||||
if (file->has_changed){
|
if (file->has_changed){
|
||||||
struct extfs_archive *archive;
|
struct archive *archive;
|
||||||
char *archive_name, *file_name;
|
char *archive_name, *file_name;
|
||||||
char *cmd;
|
char *cmd;
|
||||||
char *mc_extfsdir;
|
char *mc_extfsdir;
|
||||||
@ -673,7 +673,7 @@ static int extfs_close (void *data)
|
|||||||
|
|
||||||
archive = file->archive;
|
archive = file->archive;
|
||||||
archive_name = name_quote (get_archive_name (archive), 0);
|
archive_name = name_quote (get_archive_name (archive), 0);
|
||||||
p = extfs_get_path_from_entry (file->entry);
|
p = get_path_from_entry (file->entry);
|
||||||
file_name = name_quote (p, 0);
|
file_name = name_quote (p, 0);
|
||||||
free (p);
|
free (p);
|
||||||
|
|
||||||
@ -718,28 +718,14 @@ static int extfs_close (void *data)
|
|||||||
|
|
||||||
free (data);
|
free (data);
|
||||||
if (errno_code){
|
if (errno_code){
|
||||||
extfserrno = EIO; /* Non standard, but who cares? */
|
my_errno = EIO; /* Non standard, but who cares? */
|
||||||
return -1;
|
return -1;
|
||||||
} else
|
} else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define RECORDSIZE 512
|
#define RECORDSIZE 512
|
||||||
#define X_pseudofile extfs_pseudofile
|
#include "shared_tar_ext.c"
|
||||||
#define Xerrno extfserrno
|
|
||||||
|
|
||||||
#define X_entry extfs_entry
|
|
||||||
#define X_archive extfs_archive
|
|
||||||
#define X_get_path extfs_get_path
|
|
||||||
#define X_get_path_mangle extfs_get_path_mangle
|
|
||||||
#define X_find_entry extfs_find_entry
|
|
||||||
#define X_resolve_symlinks extfs_resolve_symlinks
|
|
||||||
#define X_inode extfs_inode
|
|
||||||
#define __X_find_entry __extfs_find_entry
|
|
||||||
#define __X_resolve_symlinks __extfs_resolve_symlinks
|
|
||||||
#define X_loop_protect extfs_loop_protect
|
|
||||||
|
|
||||||
#include "shared.c"
|
|
||||||
|
|
||||||
static int extfs_chmod (char *path, int mode)
|
static int extfs_chmod (char *path, int mode)
|
||||||
{
|
{
|
||||||
@ -748,7 +734,7 @@ static int extfs_chmod (char *path, int mode)
|
|||||||
|
|
||||||
static int extfs_write (void *data, char *buf, int nbyte)
|
static int extfs_write (void *data, char *buf, int nbyte)
|
||||||
{
|
{
|
||||||
struct extfs_pseudofile *file = (struct extfs_pseudofile *)data;
|
struct pseudofile *file = (struct pseudofile *)data;
|
||||||
|
|
||||||
file->has_changed = 1;
|
file->has_changed = 1;
|
||||||
return write (file->local_handle, buf, nbyte);
|
return write (file->local_handle, buf, nbyte);
|
||||||
@ -756,24 +742,24 @@ static int extfs_write (void *data, char *buf, int nbyte)
|
|||||||
|
|
||||||
static int extfs_chdir (char *path)
|
static int extfs_chdir (char *path)
|
||||||
{
|
{
|
||||||
struct extfs_archive *archive;
|
struct archive *archive;
|
||||||
char *q, *res;
|
char *q, *res;
|
||||||
struct extfs_entry *entry;
|
struct entry *entry;
|
||||||
|
|
||||||
extfserrno = ENOTDIR;
|
my_errno = ENOTDIR;
|
||||||
if ((q = extfs_get_path_mangle (path, &archive, 1, 0)) == NULL)
|
if ((q = get_path_mangle (path, &archive, 1, 0)) == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
entry = extfs_find_entry (archive->root_entry, q, 0, 0);
|
entry = find_entry (archive->root_entry, q, 0, 0);
|
||||||
if (!entry)
|
if (!entry)
|
||||||
return -1;
|
return -1;
|
||||||
entry = extfs_resolve_symlinks (entry);
|
entry = my_resolve_symlinks (entry);
|
||||||
if ((!entry) || (!S_ISDIR (entry->inode->mode)))
|
if ((!entry) || (!S_ISDIR (entry->inode->mode)))
|
||||||
return -1;
|
return -1;
|
||||||
entry->inode->archive->current_dir = entry;
|
entry->inode->archive->current_dir = entry;
|
||||||
res = copy_strings (
|
res = copy_strings (
|
||||||
entry->inode->archive->name, "#", extfs_prefixes [entry->inode->archive->fstype],
|
entry->inode->archive->name, "#", extfs_prefixes [entry->inode->archive->fstype],
|
||||||
"/", q, NULL);
|
"/", q, NULL);
|
||||||
extfserrno = 0;
|
my_errno = 0;
|
||||||
if (extfs_current_dir)
|
if (extfs_current_dir)
|
||||||
free (extfs_current_dir);
|
free (extfs_current_dir);
|
||||||
extfs_current_dir = res;
|
extfs_current_dir = res;
|
||||||
@ -782,21 +768,21 @@ static int extfs_chdir (char *path)
|
|||||||
|
|
||||||
static int extfs_lseek (void *data, off_t offset, int whence)
|
static int extfs_lseek (void *data, off_t offset, int whence)
|
||||||
{
|
{
|
||||||
struct extfs_pseudofile *file = (struct extfs_pseudofile *) data;
|
struct pseudofile *file = (struct pseudofile *) data;
|
||||||
|
|
||||||
return lseek (file->local_handle, offset, whence);
|
return lseek (file->local_handle, offset, whence);
|
||||||
}
|
}
|
||||||
|
|
||||||
static vfsid extfs_getid (char *path, struct vfs_stamping **parent)
|
static vfsid extfs_getid (char *path, struct vfs_stamping **parent)
|
||||||
{
|
{
|
||||||
struct extfs_archive *archive;
|
struct archive *archive;
|
||||||
vfs *v;
|
vfs *v;
|
||||||
vfsid id;
|
vfsid id;
|
||||||
struct vfs_stamping *par;
|
struct vfs_stamping *par;
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
*parent = NULL;
|
*parent = NULL;
|
||||||
if (!(p = extfs_get_path (path, &archive, 1, 1)))
|
if (!(p = get_path (path, &archive, 1, 1)))
|
||||||
return (vfsid) -1;
|
return (vfsid) -1;
|
||||||
free(p);
|
free(p);
|
||||||
if (archive->name){
|
if (archive->name){
|
||||||
@ -815,17 +801,17 @@ static vfsid extfs_getid (char *path, struct vfs_stamping **parent)
|
|||||||
|
|
||||||
static int extfs_nothingisopen (vfsid id)
|
static int extfs_nothingisopen (vfsid id)
|
||||||
{
|
{
|
||||||
if (((struct extfs_archive *)id)->fd_usage <= 0)
|
if (((struct archive *)id)->fd_usage <= 0)
|
||||||
return 1;
|
return 1;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_entry (struct extfs_entry *e)
|
static void free_entry (struct entry *e)
|
||||||
{
|
{
|
||||||
int i = --(e->inode->nlink);
|
int i = --(e->inode->nlink);
|
||||||
if (S_ISDIR (e->inode->mode) && e->inode->first_in_subdir != NULL) {
|
if (S_ISDIR (e->inode->mode) && e->inode->first_in_subdir != NULL) {
|
||||||
struct extfs_entry *f = e->inode->first_in_subdir;
|
struct entry *f = e->inode->first_in_subdir;
|
||||||
|
|
||||||
e->inode->first_in_subdir = NULL;
|
e->inode->first_in_subdir = NULL;
|
||||||
free_entry (f);
|
free_entry (f);
|
||||||
@ -847,8 +833,8 @@ static void free_entry (struct extfs_entry *e)
|
|||||||
|
|
||||||
static void extfs_free (vfsid id)
|
static void extfs_free (vfsid id)
|
||||||
{
|
{
|
||||||
struct extfs_archive *parc;
|
struct archive *parc;
|
||||||
struct extfs_archive *archive = (struct extfs_archive *)id;
|
struct archive *archive = (struct archive *)id;
|
||||||
|
|
||||||
free_entry (archive->root_entry);
|
free_entry (archive->root_entry);
|
||||||
if (archive == first_archive) {
|
if (archive == first_archive) {
|
||||||
@ -865,8 +851,8 @@ static void extfs_free (vfsid id)
|
|||||||
|
|
||||||
static char *extfs_getlocalcopy (char *path)
|
static char *extfs_getlocalcopy (char *path)
|
||||||
{
|
{
|
||||||
struct extfs_pseudofile *fp =
|
struct pseudofile *fp =
|
||||||
(struct extfs_pseudofile *) extfs_open (path, O_RDONLY, 0);
|
(struct pseudofile *) extfs_open (path, O_RDONLY, 0);
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
if (fp == NULL)
|
if (fp == NULL)
|
||||||
@ -883,8 +869,8 @@ static char *extfs_getlocalcopy (char *path)
|
|||||||
|
|
||||||
static void extfs_ungetlocalcopy (char *path, char *local, int has_changed)
|
static void extfs_ungetlocalcopy (char *path, char *local, int has_changed)
|
||||||
{
|
{
|
||||||
struct extfs_pseudofile *fp =
|
struct pseudofile *fp =
|
||||||
(struct extfs_pseudofile *) extfs_open (path, O_WRONLY, 0);
|
(struct pseudofile *) extfs_open (path, O_WRONLY, 0);
|
||||||
|
|
||||||
if (fp == NULL)
|
if (fp == NULL)
|
||||||
return;
|
return;
|
||||||
|
30
vfs/extfs.h
30
vfs/extfs.h
@ -20,26 +20,26 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
struct extfs_inode;
|
struct inode;
|
||||||
|
|
||||||
struct extfs_entry {
|
struct entry {
|
||||||
int has_changed;
|
int has_changed;
|
||||||
struct extfs_entry *next_in_dir;
|
struct entry *next_in_dir;
|
||||||
struct extfs_entry *dir;
|
struct entry *dir;
|
||||||
char *name;
|
char *name;
|
||||||
struct extfs_inode *inode;
|
struct inode *inode;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct extfs_archive;
|
struct archive;
|
||||||
|
|
||||||
struct extfs_inode {
|
struct inode {
|
||||||
int has_changed;
|
int has_changed;
|
||||||
nlink_t nlink;
|
nlink_t nlink;
|
||||||
struct extfs_entry *first_in_subdir; /* only used if this is a directory */
|
struct entry *first_in_subdir; /* only used if this is a directory */
|
||||||
struct extfs_entry *last_in_subdir;
|
struct entry *last_in_subdir;
|
||||||
ino_t inode; /* This is inode # */
|
ino_t inode; /* This is inode # */
|
||||||
dev_t dev; /* This is an internal identification of the extfs archive */
|
dev_t dev; /* This is an internal identification of the extfs archive */
|
||||||
struct extfs_archive *archive; /* And this is an archive structure */
|
struct archive *archive; /* And this is an archive structure */
|
||||||
dev_t rdev;
|
dev_t rdev;
|
||||||
umode_t mode;
|
umode_t mode;
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
@ -53,7 +53,7 @@ struct extfs_inode {
|
|||||||
char *local_filename;
|
char *local_filename;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct extfs_archive {
|
struct archive {
|
||||||
int fstype;
|
int fstype;
|
||||||
char *name;
|
char *name;
|
||||||
char *local_name;
|
char *local_name;
|
||||||
@ -62,9 +62,9 @@ struct extfs_archive {
|
|||||||
dev_t rdev;
|
dev_t rdev;
|
||||||
int fd_usage;
|
int fd_usage;
|
||||||
ino_t __inode_counter;
|
ino_t __inode_counter;
|
||||||
struct extfs_entry *root_entry;
|
struct entry *root_entry;
|
||||||
struct extfs_entry *current_dir;
|
struct entry *current_dir;
|
||||||
struct extfs_archive *next;
|
struct archive *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
void extfs_init (void);
|
void extfs_init (void);
|
||||||
@ -74,3 +74,5 @@ char *extfs_get_prefix (int fstype);
|
|||||||
char *extfs_analysis (char *path, char **arc_name, int *fstype, int is_dir);
|
char *extfs_analysis (char *path, char **arc_name, int *fstype, int is_dir);
|
||||||
void extfs_run (char *path);
|
void extfs_run (char *path);
|
||||||
void extfs_done (void);
|
void extfs_done (void);
|
||||||
|
|
||||||
|
typedef struct archive extfs_archive; /* Do _not_ use this inside extfs.c */
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
# Each external VFS type must be registered here if you want to use it
|
# Each external VFS type must be registered here if you want to use it
|
||||||
|
|
||||||
# Popular pc archivers, for arj usage you need special patch to unarj
|
# Popular pc archivers
|
||||||
uzip
|
uzip
|
||||||
uzoo
|
uzoo
|
||||||
ulha
|
ulha
|
||||||
urar
|
urar
|
||||||
|
# For arj usage you need special patch to unarj
|
||||||
uarj
|
uarj
|
||||||
|
|
||||||
# ar is used for static libraries
|
# ar is used for static libraries
|
||||||
|
1025
vfs/fish.c
Обычный файл
1025
vfs/fish.c
Обычный файл
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
74
vfs/fish.h
Обычный файл
74
vfs/fish.h
Обычный файл
@ -0,0 +1,74 @@
|
|||||||
|
/* fish.h */
|
||||||
|
|
||||||
|
#if !defined(__FISH_H)
|
||||||
|
#define __FISH_H
|
||||||
|
|
||||||
|
struct direntry
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
int count;
|
||||||
|
char *linkname;
|
||||||
|
char *local_filename;
|
||||||
|
int local_is_temp:1;
|
||||||
|
int freshly_created:1;
|
||||||
|
struct stat local_stat;
|
||||||
|
char *remote_filename;
|
||||||
|
struct stat s;
|
||||||
|
struct stat *l_stat;
|
||||||
|
struct connection *bucket;
|
||||||
|
int tmp_reget;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dir
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
struct timeval timestamp;
|
||||||
|
char *remote_path;
|
||||||
|
struct linklist *file_list;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct connection {
|
||||||
|
char *host;
|
||||||
|
char *user;
|
||||||
|
char *current_directory;
|
||||||
|
char *home;
|
||||||
|
char *updir;
|
||||||
|
char *password;
|
||||||
|
int flags;
|
||||||
|
int sockr, sockw;
|
||||||
|
struct linklist *dcache;
|
||||||
|
ino_t __inode_counter;
|
||||||
|
int lock;
|
||||||
|
int failed_on_login; /* used to pass the failure reason to upper levels */
|
||||||
|
int use_proxy; /* use a proxy server */
|
||||||
|
int result_pending;
|
||||||
|
int use_source_route;
|
||||||
|
int use_passive_connection;
|
||||||
|
int isbinary;
|
||||||
|
int cwd_defered; /* current_directory was changed but CWD command hasn't
|
||||||
|
been sent yet */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define qhost(b) (b)->host
|
||||||
|
#define quser(b) (b)->user
|
||||||
|
#define qcdir(b) (b)->current_directory
|
||||||
|
#define qflags(b) (b)->flags
|
||||||
|
#define qsockr(b) (b)->sockr
|
||||||
|
#define qsockw(b) (b)->sockw
|
||||||
|
#define qlock(b) (b)->lock
|
||||||
|
#define qdcache(b) (b)->dcache
|
||||||
|
#define qhome(b) (b)->home
|
||||||
|
#define qupdir(b) (b)->updir
|
||||||
|
#define qproxy(b) (b)->use_proxy
|
||||||
|
|
||||||
|
/* Increased since now we may use C-r to reread the contents */
|
||||||
|
#define FISH_DIRECTORY_TIMEOUT 30 * 60
|
||||||
|
|
||||||
|
#define DO_RESOLVE_SYMLINK 1
|
||||||
|
#define DO_OPEN 2
|
||||||
|
#define DO_FREE_RESOURCE 4
|
||||||
|
|
||||||
|
#define FISH_FLAG_COMPRESSED 1
|
||||||
|
#define FISH_FLAG_RSH 2
|
||||||
|
|
||||||
|
#endif
|
1213
vfs/ftpfs.c
1213
vfs/ftpfs.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
14
vfs/ftpfs.h
14
vfs/ftpfs.h
@ -3,7 +3,7 @@
|
|||||||
#if !defined(__FTPFS_H)
|
#if !defined(__FTPFS_H)
|
||||||
#define __FTPFS_H
|
#define __FTPFS_H
|
||||||
|
|
||||||
struct ftpentry
|
struct direntry
|
||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
int count;
|
int count;
|
||||||
@ -16,10 +16,10 @@ struct ftpentry
|
|||||||
char *remote_filename;
|
char *remote_filename;
|
||||||
struct stat s;
|
struct stat s;
|
||||||
struct stat *l_stat;
|
struct stat *l_stat;
|
||||||
struct ftpfs_connection *bucket;
|
struct connection *bucket;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ftpfs_dir
|
struct dir
|
||||||
{
|
{
|
||||||
int count;
|
int count;
|
||||||
struct timeval timestamp;
|
struct timeval timestamp;
|
||||||
@ -27,7 +27,7 @@ struct ftpfs_dir
|
|||||||
struct linklist *file_list;
|
struct linklist *file_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ftpfs_connection {
|
struct connection {
|
||||||
char *host;
|
char *host;
|
||||||
char *user;
|
char *user;
|
||||||
char *current_directory;
|
char *current_directory;
|
||||||
@ -63,9 +63,9 @@ struct ftpfs_connection {
|
|||||||
/* Increased since now we may use C-r to reread the contents */
|
/* Increased since now we may use C-r to reread the contents */
|
||||||
#define FTPFS_DIRECTORY_TIMEOUT 30 * 60
|
#define FTPFS_DIRECTORY_TIMEOUT 30 * 60
|
||||||
|
|
||||||
#define FTPFS_RESOLVE_SYMLINK 1
|
#define DO_RESOLVE_SYMLINK 1
|
||||||
#define FTPFS_OPEN 2
|
#define DO_OPEN 2
|
||||||
#define FTPFS_FREE_RESOURCE 4
|
#define DO_FREE_RESOURCE 4
|
||||||
|
|
||||||
extern char *ftpfs_anonymous_passwd;
|
extern char *ftpfs_anonymous_passwd;
|
||||||
extern char *ftpfs_proxy_host;
|
extern char *ftpfs_proxy_host;
|
||||||
|
26
vfs/libvfs.c
26
vfs/libvfs.c
@ -1,26 +0,0 @@
|
|||||||
/*
|
|
||||||
* These are functions that miss from vfs.c to make it complete library
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
|
|
||||||
void vfs_init( void );
|
|
||||||
void ftpfs_init_passwd( void );
|
|
||||||
|
|
||||||
char *mc_home = LIBDIR;
|
|
||||||
|
|
||||||
void
|
|
||||||
mc_vfs_init( void )
|
|
||||||
{
|
|
||||||
vfs_init();
|
|
||||||
ftpfs_init_passwd();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
mc_vfs_done( void )
|
|
||||||
{
|
|
||||||
vfs_shut();
|
|
||||||
}
|
|
856
vfs/shared_ftp_fish.c
Обычный файл
856
vfs/shared_ftp_fish.c
Обычный файл
@ -0,0 +1,856 @@
|
|||||||
|
|
||||||
|
static struct dir *retrieve_dir(struct connection *bucket, char *remote_path);
|
||||||
|
static int store_file(struct direntry *fe);
|
||||||
|
static int retrieve_file_start(struct direntry *fe);
|
||||||
|
static int retrieve_file(struct direntry *fe);
|
||||||
|
|
||||||
|
static int
|
||||||
|
select_on_two (int fd1, int fd2)
|
||||||
|
{
|
||||||
|
fd_set set;
|
||||||
|
struct timeval timeout;
|
||||||
|
int v;
|
||||||
|
int maxfd = (fd1 > fd2 ? fd1 : fd2) + 1;
|
||||||
|
|
||||||
|
timeout.tv_sec = 1;
|
||||||
|
timeout.tv_usec = 0;
|
||||||
|
FD_ZERO(&set);
|
||||||
|
FD_SET(fd1, &set);
|
||||||
|
FD_SET(fd2, &set);
|
||||||
|
v = select (maxfd, &set, 0, 0, &timeout);
|
||||||
|
if (v <= 0)
|
||||||
|
return v;
|
||||||
|
if (FD_ISSET (fd1, &set))
|
||||||
|
return 1;
|
||||||
|
if (FD_ISSET (fd2, &set))
|
||||||
|
return 2;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
get_line (int sock, char *buf, int buf_len, char term)
|
||||||
|
{
|
||||||
|
int i, status;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
for (i = 0; i < buf_len; i++, buf++) {
|
||||||
|
if (read(sock, buf, sizeof(char)) <= 0)
|
||||||
|
return 0;
|
||||||
|
if (logfile){
|
||||||
|
fwrite (buf, 1, 1, logfile);
|
||||||
|
fflush (logfile);
|
||||||
|
}
|
||||||
|
if (*buf == term) {
|
||||||
|
*buf = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*buf = 0;
|
||||||
|
while ((status = read(sock, &c, sizeof(c))) > 0){
|
||||||
|
if (logfile){
|
||||||
|
fwrite (&c, 1, 1, logfile);
|
||||||
|
fflush (logfile);
|
||||||
|
}
|
||||||
|
if (c == '\n')
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
direntry_destructor (void *data)
|
||||||
|
{
|
||||||
|
struct direntry *fe = data;
|
||||||
|
|
||||||
|
fe->count--;
|
||||||
|
if ((fe->tmp_reget == 1 && fe->local_filename)){
|
||||||
|
unlink (fe->local_filename);
|
||||||
|
fe->tmp_reget = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fe->count > 0)
|
||||||
|
return;
|
||||||
|
free(fe->name);
|
||||||
|
if (fe->linkname)
|
||||||
|
free(fe->linkname);
|
||||||
|
if (fe->local_filename) {
|
||||||
|
if (fe->local_is_temp) {
|
||||||
|
if (!fe->local_stat.st_mtime)
|
||||||
|
unlink(fe->local_filename);
|
||||||
|
else {
|
||||||
|
struct stat sb;
|
||||||
|
|
||||||
|
if (stat (fe->local_filename, &sb) >=0 &&
|
||||||
|
fe->local_stat.st_mtime == sb.st_mtime)
|
||||||
|
unlink (fe->local_filename); /* Delete only if it hasn't changed */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(fe->local_filename);
|
||||||
|
fe->local_filename = 0;
|
||||||
|
}
|
||||||
|
if (fe->remote_filename)
|
||||||
|
free(fe->remote_filename);
|
||||||
|
if (fe->l_stat)
|
||||||
|
free(fe->l_stat);
|
||||||
|
free(fe);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dir_destructor(void *data)
|
||||||
|
{
|
||||||
|
struct dir *fd = data;
|
||||||
|
|
||||||
|
fd->count--;
|
||||||
|
if (fd->count > 0)
|
||||||
|
return;
|
||||||
|
free(fd->remote_path);
|
||||||
|
linklist_destroy(fd->file_list, direntry_destructor);
|
||||||
|
free(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
get_line_interruptible (char *buffer, int size, int fd)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < size-1; i++) {
|
||||||
|
n = read (fd, buffer+i, 1);
|
||||||
|
if (n == -1 && errno == EINTR){
|
||||||
|
buffer [i] = 0;
|
||||||
|
return EINTR;
|
||||||
|
}
|
||||||
|
if (n == 0){
|
||||||
|
buffer [i] = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (buffer [i] == '\n'){
|
||||||
|
buffer [i] = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buffer [size-1] = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
free_bucket (void *data)
|
||||||
|
{
|
||||||
|
struct connection *bucket = data;
|
||||||
|
|
||||||
|
free(qhost(bucket));
|
||||||
|
free(quser(bucket));
|
||||||
|
if (qcdir(bucket))
|
||||||
|
free(qcdir(bucket));
|
||||||
|
if (qhome(bucket))
|
||||||
|
free(qhome(bucket));
|
||||||
|
if (qupdir(bucket))
|
||||||
|
free(qupdir(bucket));
|
||||||
|
if (bucket->password)
|
||||||
|
wipe_password (bucket->password);
|
||||||
|
linklist_destroy(qdcache(bucket), dir_destructor);
|
||||||
|
free(bucket);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
connection_destructor(void *data)
|
||||||
|
{
|
||||||
|
connection_close (data);
|
||||||
|
free_bucket (data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
flush_all_directory(struct connection *bucket)
|
||||||
|
{
|
||||||
|
linklist_delete_all(qdcache(bucket), dir_destructor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void X_fill_names (void (*func)(char *))
|
||||||
|
{
|
||||||
|
struct linklist *lptr;
|
||||||
|
char *path_name;
|
||||||
|
struct connection *bucket;
|
||||||
|
|
||||||
|
if (!connections_list)
|
||||||
|
return;
|
||||||
|
lptr = connections_list;
|
||||||
|
do {
|
||||||
|
if ((bucket = lptr->data) != 0){
|
||||||
|
|
||||||
|
path_name = copy_strings ( X_myname, quser (bucket),
|
||||||
|
"@", qhost (bucket),
|
||||||
|
qcdir(bucket), 0);
|
||||||
|
(*func)(path_name);
|
||||||
|
free (path_name);
|
||||||
|
}
|
||||||
|
lptr = lptr->next;
|
||||||
|
} 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.
|
||||||
|
*/
|
||||||
|
static char*
|
||||||
|
get_path (struct connection **bucket, char *path)
|
||||||
|
{
|
||||||
|
char *user, *host, *remote_path, *pass;
|
||||||
|
int port;
|
||||||
|
|
||||||
|
#ifndef BROKEN_PATHS
|
||||||
|
if (strncmp (path, X_myname, strlen (X_myname)))
|
||||||
|
return NULL; /* Normal: consider cd /bla/#ftp */
|
||||||
|
#else
|
||||||
|
if (!(path = strstr (path, X_myname)))
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
|
path += strlen (X_myname);
|
||||||
|
|
||||||
|
if (!(remote_path = my_get_host_and_username (path, &host, &user, &port, &pass)))
|
||||||
|
my_errno = ENOENT;
|
||||||
|
else {
|
||||||
|
if ((*bucket = open_link (host, user, port, pass)) == NULL) {
|
||||||
|
free (remote_path);
|
||||||
|
remote_path = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free (host);
|
||||||
|
free (user);
|
||||||
|
if (pass)
|
||||||
|
wipe_password (pass);
|
||||||
|
|
||||||
|
if (!remote_path)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* NOTE: Usage of tildes is deprecated, consider:
|
||||||
|
* cd /#ftp:pavel@hobit
|
||||||
|
* cd ~
|
||||||
|
* And now: what do I want to do? Do I want to go to /home/pavel or to
|
||||||
|
* /#ftp:hobit/home/pavel? I think first has better sense...
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
int f = !strcmp( remote_path, "/~" );
|
||||||
|
if (f || !strncmp( remote_path, "/~/", 3 )) {
|
||||||
|
char *s;
|
||||||
|
s = concat_dir_and_file( qhome (*bucket), remote_path +3-f );
|
||||||
|
free (remote_path);
|
||||||
|
remote_path = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return remote_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
void X_flushdir (void)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct direntry *
|
||||||
|
_get_file_entry(struct connection *bucket, char *file_name,
|
||||||
|
int op, int flags)
|
||||||
|
{
|
||||||
|
char *p, q;
|
||||||
|
struct direntry *ent;
|
||||||
|
struct linklist *file_list, *lptr;
|
||||||
|
struct dir *dcache;
|
||||||
|
struct stat sb;
|
||||||
|
|
||||||
|
p = strrchr(file_name, '/');
|
||||||
|
q = *p;
|
||||||
|
*p = '\0';
|
||||||
|
dcache = retrieve_dir(bucket, *file_name ? file_name : "/");
|
||||||
|
if (dcache == NULL)
|
||||||
|
return NULL;
|
||||||
|
file_list = dcache->file_list;
|
||||||
|
*p++ = q;
|
||||||
|
if (!*p)
|
||||||
|
p = ".";
|
||||||
|
for (lptr = file_list->next; lptr != file_list; lptr = lptr->next) {
|
||||||
|
ent = lptr->data;
|
||||||
|
if (strcmp(p, ent->name) == 0) {
|
||||||
|
if (S_ISLNK(ent->s.st_mode) && (op & DO_RESOLVE_SYMLINK)) {
|
||||||
|
if (ent->l_stat == NULL) {
|
||||||
|
my_errno = ENOENT;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (S_ISLNK(ent->l_stat->st_mode)) {
|
||||||
|
my_errno = ELOOP;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ent && (op & DO_OPEN)) {
|
||||||
|
mode_t fmode;
|
||||||
|
|
||||||
|
fmode = S_ISLNK(ent->s.st_mode)
|
||||||
|
? ent->l_stat->st_mode
|
||||||
|
: ent->s.st_mode;
|
||||||
|
if (S_ISDIR(fmode)) {
|
||||||
|
my_errno = EISDIR;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!S_ISREG(fmode)) {
|
||||||
|
my_errno = EPERM;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if ((flags & O_EXCL) && (flags & O_CREAT)) {
|
||||||
|
my_errno = EEXIST;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (ent->remote_filename == NULL) {
|
||||||
|
ent->remote_filename = strdup(file_name);
|
||||||
|
if (ent->remote_filename == NULL) {
|
||||||
|
my_errno = ENOMEM;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ent->local_filename == NULL ||
|
||||||
|
!ent->local_stat.st_mtime ||
|
||||||
|
stat (ent->local_filename, &sb) < 0 ||
|
||||||
|
sb.st_mtime != ent->local_stat.st_mtime) {
|
||||||
|
int handle;
|
||||||
|
|
||||||
|
if (ent->local_filename){
|
||||||
|
free (ent->local_filename);
|
||||||
|
ent->local_filename = 0;
|
||||||
|
}
|
||||||
|
if (flags & O_TRUNC) {
|
||||||
|
ent->local_filename = tempnam (NULL, X "fs");
|
||||||
|
if (ent->local_filename == NULL) {
|
||||||
|
my_errno = ENOMEM;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
handle = open(ent->local_filename, O_CREAT | O_TRUNC | O_RDWR | O_EXCL, 0600);
|
||||||
|
if (handle < 0) {
|
||||||
|
my_errno = EIO;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
close(handle);
|
||||||
|
if (stat (ent->local_filename, &ent->local_stat) < 0)
|
||||||
|
ent->local_stat.st_mtime = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (localname != NULL) {
|
||||||
|
isremotecopy = 1;
|
||||||
|
ent->local_is_temp = 0;
|
||||||
|
ent->local_stat.st_mtime = 0;
|
||||||
|
ent->local_filename = strdup (localname);
|
||||||
|
if (!retrieve_file_start (ent)) {
|
||||||
|
isremotecopy = 0;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return ent;
|
||||||
|
}
|
||||||
|
if (!retrieve_file(ent))
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (flags & O_TRUNC) {
|
||||||
|
truncate(ent->local_filename, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((op & DO_OPEN) && (flags & O_CREAT)) {
|
||||||
|
int handle;
|
||||||
|
|
||||||
|
ent = xmalloc(sizeof(struct direntry), "struct direntry");
|
||||||
|
ent->freshly_created = 0;
|
||||||
|
ent->tmp_reget = 0;
|
||||||
|
if (ent == NULL) {
|
||||||
|
my_errno = ENOMEM;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ent->count = 1;
|
||||||
|
ent->linkname = NULL;
|
||||||
|
ent->l_stat = NULL;
|
||||||
|
ent->bucket = bucket;
|
||||||
|
ent->name = strdup(p);
|
||||||
|
ent->remote_filename = strdup(file_name);
|
||||||
|
ent->local_filename = tempnam (NULL, X "fs");
|
||||||
|
if (!ent->name && !ent->remote_filename && !ent->local_filename) {
|
||||||
|
direntry_destructor(ent);
|
||||||
|
my_errno = ENOMEM;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
handle = creat(ent->local_filename, 0700);
|
||||||
|
if (handle == -1) {
|
||||||
|
my_errno = EIO;
|
||||||
|
direntry_destructor(ent);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
fstat(handle, &ent->s);
|
||||||
|
close(handle);
|
||||||
|
#if 0
|
||||||
|
/* This is very wrong - like this a zero length file will be always created
|
||||||
|
and usually preclude uploading anything more desirable */
|
||||||
|
#if defined(UPLOAD_ZERO_LENGTH_FILE)
|
||||||
|
if (!store_file(ent)) {
|
||||||
|
direntry_destructor(ent);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
if (!linklist_insert(file_list, ent)) {
|
||||||
|
my_errno = ENOMEM;
|
||||||
|
direntry_destructor(ent);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ent->freshly_created = 1;
|
||||||
|
return ent;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
my_errno = ENOENT;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
char *p, q;
|
||||||
|
struct connection *bucket;
|
||||||
|
struct direntry *ent;
|
||||||
|
struct linklist *file_list, *lptr;
|
||||||
|
struct dir *dcache;
|
||||||
|
|
||||||
|
if (!(file_name = get_path (&bucket, file_name)))
|
||||||
|
return -1;
|
||||||
|
p = strrchr (file_name, '/');
|
||||||
|
q = *p;
|
||||||
|
*p = '\0';
|
||||||
|
dcache = retrieve_dir (bucket, *file_name ? file_name : "/");
|
||||||
|
if (dcache == NULL)
|
||||||
|
return -1;
|
||||||
|
file_list = dcache->file_list;
|
||||||
|
*p++ = q;
|
||||||
|
if (!*p)
|
||||||
|
p = ".";
|
||||||
|
for (lptr = file_list->next; lptr != file_list; lptr = lptr->next) {
|
||||||
|
ent = lptr->data;
|
||||||
|
if (strcmp (p, ent->name) == 0) {
|
||||||
|
if (ent->local_filename) {
|
||||||
|
unlink (ent->local_filename);
|
||||||
|
free (ent->local_filename);
|
||||||
|
ent->local_filename = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct direntry *
|
||||||
|
get_file_entry(char *path, int op, int flags)
|
||||||
|
{
|
||||||
|
struct connection *bucket;
|
||||||
|
struct direntry *fe;
|
||||||
|
char *remote_path;
|
||||||
|
|
||||||
|
if (!(remote_path = get_path (&bucket, path)))
|
||||||
|
return NULL;
|
||||||
|
isremotecopy = 0;
|
||||||
|
fe = _get_file_entry(bucket, remote_path, op,
|
||||||
|
flags);
|
||||||
|
free(remote_path);
|
||||||
|
#if 0
|
||||||
|
if (op & DO_FREE_RESOURCE)
|
||||||
|
vfs_add_noncurrent_stamps (&X_vfs_ops, (vfsid) bucket, NULL);
|
||||||
|
#endif
|
||||||
|
return fe;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define OPT_FLUSH 1
|
||||||
|
#define OPT_IGNORE_ERROR 2
|
||||||
|
|
||||||
|
static int normal_flush = 1;
|
||||||
|
|
||||||
|
void X_hint_reread(int reread)
|
||||||
|
{
|
||||||
|
if (reread)
|
||||||
|
normal_flush++;
|
||||||
|
else
|
||||||
|
normal_flush--;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* The callbacks */
|
||||||
|
|
||||||
|
struct filp {
|
||||||
|
unsigned int has_changed:1;
|
||||||
|
struct direntry *fe;
|
||||||
|
int local_handle;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void *s_open (char *file, int flags, int mode)
|
||||||
|
{
|
||||||
|
struct filp *fp;
|
||||||
|
struct direntry *fe;
|
||||||
|
|
||||||
|
fp = xmalloc(sizeof(struct filp), "struct filp");
|
||||||
|
if (fp == NULL) {
|
||||||
|
my_errno = ENOMEM;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
fe = get_file_entry(file, DO_OPEN | DO_RESOLVE_SYMLINK, flags);
|
||||||
|
if (fe == NULL) {
|
||||||
|
free(fp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!isremotecopy) {
|
||||||
|
fp->local_handle = open(fe->local_filename, flags, mode);
|
||||||
|
if (fp->local_handle < 0) {
|
||||||
|
my_errno = errno;
|
||||||
|
free(fp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
fp->local_handle = -1;
|
||||||
|
#ifdef UPLOAD_ZERO_LENGTH_FILE
|
||||||
|
fp->has_changed = fe->freshly_created;
|
||||||
|
#else
|
||||||
|
fp->has_changed = 0;
|
||||||
|
#endif
|
||||||
|
fp->fe = fe;
|
||||||
|
qlock(fe->bucket)++;
|
||||||
|
fe->count++;
|
||||||
|
return fp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_read (void *data, char *buffer, int count)
|
||||||
|
{
|
||||||
|
struct filp *fp;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
fp = data;
|
||||||
|
n = read(fp->local_handle, buffer, count);
|
||||||
|
if (n < 0)
|
||||||
|
my_errno = errno;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_write (void *data, char *buf, int nbyte)
|
||||||
|
{
|
||||||
|
struct filp *fp;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
fp = data;
|
||||||
|
n = write(fp->local_handle, buf, nbyte);
|
||||||
|
if (n < 0)
|
||||||
|
my_errno = errno;
|
||||||
|
fp->has_changed = 1;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_close (void *data)
|
||||||
|
{
|
||||||
|
struct filp *fp = data;
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
if (fp->has_changed) {
|
||||||
|
if (!store_file(fp->fe))
|
||||||
|
result = -1;
|
||||||
|
if (normal_flush)
|
||||||
|
flush_all_directory(fp->fe->bucket);
|
||||||
|
}
|
||||||
|
if (fp->local_handle >= 0)
|
||||||
|
close(fp->local_handle);
|
||||||
|
qlock(fp->fe->bucket)--;
|
||||||
|
direntry_destructor(fp->fe);
|
||||||
|
free(fp);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_errno (void)
|
||||||
|
{
|
||||||
|
return my_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Explanation:
|
||||||
|
* On some operating systems (Slowaris 2 for example)
|
||||||
|
* the d_name member is just a char long (nice trick that break everything),
|
||||||
|
* so we need to set up some space for the filename.
|
||||||
|
*/
|
||||||
|
struct my_dirent {
|
||||||
|
struct dirent dent;
|
||||||
|
#ifdef NEED_EXTRA_DIRENT_BUFFER
|
||||||
|
char extra_buffer [MC_MAXPATHLEN];
|
||||||
|
#endif
|
||||||
|
struct linklist *pos;
|
||||||
|
struct dir *dcache;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Possible FIXME: what happens if one directory is opened twice ? */
|
||||||
|
|
||||||
|
static void *s_opendir (char *dirname)
|
||||||
|
{
|
||||||
|
struct connection *bucket;
|
||||||
|
char *remote_path;
|
||||||
|
struct my_dirent *dirp;
|
||||||
|
|
||||||
|
if (!(remote_path = get_path (&bucket, dirname)))
|
||||||
|
return NULL;
|
||||||
|
dirp = xmalloc(sizeof(struct my_dirent), "struct my_dirent");
|
||||||
|
if (dirp == NULL) {
|
||||||
|
my_errno = ENOMEM;
|
||||||
|
goto error_return;
|
||||||
|
}
|
||||||
|
dirp->dcache = retrieve_dir(bucket, remote_path);
|
||||||
|
if (dirp->dcache == NULL)
|
||||||
|
goto error_return;
|
||||||
|
dirp->pos = dirp->dcache->file_list->next;
|
||||||
|
free(remote_path);
|
||||||
|
dirp->dcache->count++;
|
||||||
|
return (void *)dirp;
|
||||||
|
error_return:
|
||||||
|
vfs_add_noncurrent_stamps (&X_vfs_ops, (vfsid) bucket, NULL);
|
||||||
|
free(remote_path);
|
||||||
|
free(dirp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *s_readdir (void *data)
|
||||||
|
{
|
||||||
|
struct direntry *fe;
|
||||||
|
struct my_dirent *dirp = data;
|
||||||
|
|
||||||
|
if (dirp->pos == dirp->dcache->file_list)
|
||||||
|
return NULL;
|
||||||
|
fe = dirp->pos->data;
|
||||||
|
strcpy (&(dirp->dent.d_name [0]), fe->name);
|
||||||
|
#ifndef DIRENT_LENGTH_COMPUTED
|
||||||
|
dirp->d_namlen = strlen (dirp->d_name);
|
||||||
|
#endif
|
||||||
|
dirp->pos = dirp->pos->next;
|
||||||
|
return (void *) &dirp->dent;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_telldir (void *data)
|
||||||
|
{
|
||||||
|
struct my_dirent *dirp = data;
|
||||||
|
struct linklist *pos;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
pos = dirp->dcache->file_list->next;
|
||||||
|
while( pos!=dirp->dcache->file_list) {
|
||||||
|
if (pos == dirp->pos)
|
||||||
|
return i;
|
||||||
|
pos = pos->next;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void s_seekdir (void *data, int pos)
|
||||||
|
{
|
||||||
|
struct my_dirent *dirp = data;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
dirp->pos = dirp->dcache->file_list->next;
|
||||||
|
for (i=0; i<pos; i++)
|
||||||
|
s_readdir(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_closedir (void *info)
|
||||||
|
{
|
||||||
|
struct my_dirent *dirp = info;
|
||||||
|
dir_destructor(dirp->dcache);
|
||||||
|
free(dirp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_lstat (char *path, struct stat *buf)
|
||||||
|
{
|
||||||
|
struct direntry *fe;
|
||||||
|
|
||||||
|
fe = get_file_entry(path, DO_FREE_RESOURCE, 0);
|
||||||
|
if (fe) {
|
||||||
|
*buf = fe->s;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_stat (char *path, struct stat *buf)
|
||||||
|
{
|
||||||
|
struct direntry *fe;
|
||||||
|
|
||||||
|
fe = get_file_entry(path, DO_RESOLVE_SYMLINK | DO_FREE_RESOURCE, 0);
|
||||||
|
if (fe) {
|
||||||
|
if (!S_ISLNK(fe->s.st_mode))
|
||||||
|
*buf = fe->s;
|
||||||
|
else
|
||||||
|
*buf = *fe->l_stat;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_fstat (void *data, struct stat *buf)
|
||||||
|
{
|
||||||
|
struct filp *fp = data;
|
||||||
|
|
||||||
|
if (!S_ISLNK(fp->fe->s.st_mode))
|
||||||
|
*buf = fp->fe->s;
|
||||||
|
else
|
||||||
|
*buf = *fp->fe->l_stat;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int s_readlink (char *path, char *buf, int size)
|
||||||
|
{
|
||||||
|
struct direntry *fe;
|
||||||
|
|
||||||
|
fe = get_file_entry(path, DO_FREE_RESOURCE, 0);
|
||||||
|
if (!fe)
|
||||||
|
return -1;
|
||||||
|
if (!S_ISLNK(fe->s.st_mode)) {
|
||||||
|
my_errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (fe->linkname == NULL) {
|
||||||
|
my_errno = EACCES;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (strlen(fe->linkname) >= size) {
|
||||||
|
my_errno = ERANGE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
strncpy(buf, fe->linkname, size);
|
||||||
|
return strlen(fe->linkname);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int s_chdir (char *path)
|
||||||
|
{
|
||||||
|
char *remote_path;
|
||||||
|
struct connection *bucket;
|
||||||
|
|
||||||
|
if (!(remote_path = get_path(&bucket, path)))
|
||||||
|
return -1;
|
||||||
|
if (qcdir(bucket))
|
||||||
|
free(qcdir(bucket));
|
||||||
|
qcdir(bucket) = remote_path;
|
||||||
|
bucket->cwd_defered = 1;
|
||||||
|
|
||||||
|
vfs_add_noncurrent_stamps (&X_vfs_ops, (vfsid) bucket, NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_lseek (void *data, off_t offset, int whence)
|
||||||
|
{
|
||||||
|
struct filp *fp = data;
|
||||||
|
|
||||||
|
return lseek(fp->local_handle, offset, whence);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static vfsid s_getid (char *p, struct vfs_stamping **parent)
|
||||||
|
{
|
||||||
|
struct connection *bucket;
|
||||||
|
char *remote_path;
|
||||||
|
|
||||||
|
*parent = NULL; /* We are not enclosed in any other fs */
|
||||||
|
|
||||||
|
if (!(remote_path = get_path (&bucket, p)))
|
||||||
|
return (vfsid) -1;
|
||||||
|
else {
|
||||||
|
free(remote_path);
|
||||||
|
return (vfsid) bucket;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_nothingisopen (vfsid id)
|
||||||
|
{
|
||||||
|
return qlock((struct connection *)id) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void s_free (vfsid id)
|
||||||
|
{
|
||||||
|
struct connection *bucket = (struct connection *) id;
|
||||||
|
|
||||||
|
connection_destructor(bucket);
|
||||||
|
linklist_delete(connections_list, bucket);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *s_getlocalcopy (char *path)
|
||||||
|
{
|
||||||
|
struct filp *fp = (struct filp *) s_open (path, O_RDONLY, 0);
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if (fp == NULL)
|
||||||
|
return NULL;
|
||||||
|
if (fp->fe->local_filename == NULL) {
|
||||||
|
s_close ((void *) fp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
p = strdup (fp->fe->local_filename);
|
||||||
|
qlock(fp->fe->bucket)++;
|
||||||
|
fp->fe->count++;
|
||||||
|
s_close ((void *) fp);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void s_ungetlocalcopy (char *path, char *local, int has_changed)
|
||||||
|
{
|
||||||
|
struct filp *fp = (struct filp *) s_open (path, O_WRONLY, 0);
|
||||||
|
|
||||||
|
if (fp == NULL)
|
||||||
|
return;
|
||||||
|
if (!strcmp (fp->fe->local_filename, local)) {
|
||||||
|
fp->has_changed = has_changed;
|
||||||
|
qlock(fp->fe->bucket)--;
|
||||||
|
direntry_destructor(fp->fe);
|
||||||
|
s_close ((void *) fp);
|
||||||
|
} else {
|
||||||
|
/* Should not happen */
|
||||||
|
s_close ((void *) fp);
|
||||||
|
mc_def_ungetlocalcopy (path, local, has_changed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
X_done(void)
|
||||||
|
{
|
||||||
|
linklist_destroy(connections_list, connection_destructor);
|
||||||
|
connections_list = NULL;
|
||||||
|
if (logfile)
|
||||||
|
fclose (logfile);
|
||||||
|
logfile = NULL;
|
||||||
|
}
|
@ -5,11 +5,11 @@
|
|||||||
* 1998 Pavel Machek
|
* 1998 Pavel Machek
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static char *X_get_path (char *inname, struct X_archive **archive, int is_dir,
|
static char *get_path (char *inname, struct archive **archive, int is_dir,
|
||||||
int do_not_open)
|
int do_not_open)
|
||||||
{
|
{
|
||||||
char *buf = strdup( inname );
|
char *buf = strdup( inname );
|
||||||
char *res = X_get_path_mangle( buf, archive, is_dir, do_not_open );
|
char *res = get_path_mangle( buf, archive, is_dir, do_not_open );
|
||||||
char *res2 = NULL;
|
char *res2 = NULL;
|
||||||
if (res)
|
if (res)
|
||||||
res2 = strdup(res);
|
res2 = strdup(res);
|
||||||
@ -17,11 +17,11 @@ static char *X_get_path (char *inname, struct X_archive **archive, int is_dir,
|
|||||||
return res2;
|
return res2;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct X_entry*
|
static struct entry*
|
||||||
__X_find_entry (struct X_entry *dir, char *name,
|
__find_entry (struct entry *dir, char *name,
|
||||||
struct X_loop_protect *list, int make_dirs, int make_file)
|
struct loop_protect *list, int make_dirs, int make_file)
|
||||||
{
|
{
|
||||||
struct X_entry *pent, *pdir;
|
struct entry *pent, *pdir;
|
||||||
char *p, *q, *name_end;
|
char *p, *q, *name_end;
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ __X_find_entry (struct X_entry *dir, char *name,
|
|||||||
if (!strcmp (p, ".."))
|
if (!strcmp (p, ".."))
|
||||||
pent = pent->dir;
|
pent = pent->dir;
|
||||||
else {
|
else {
|
||||||
if ((pent = __X_resolve_symlinks (pent, list))==NULL){
|
if ((pent = __resolve_symlinks (pent, list))==NULL){
|
||||||
*q = c;
|
*q = c;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -87,22 +87,22 @@ __X_find_entry (struct X_entry *dir, char *name,
|
|||||||
q = strchr (p, 0);
|
q = strchr (p, 0);
|
||||||
}
|
}
|
||||||
if (pent == NULL)
|
if (pent == NULL)
|
||||||
Xerrno = ENOENT;
|
my_errno = ENOENT;
|
||||||
return pent;
|
return pent;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct X_entry *X_find_entry (struct X_entry *dir, char *name, int make_dirs, int make_file)
|
static struct entry *find_entry (struct entry *dir, char *name, int make_dirs, int make_file)
|
||||||
{
|
{
|
||||||
struct X_entry *res;
|
struct entry *res;
|
||||||
|
|
||||||
errloop = 0;
|
errloop = 0;
|
||||||
notadir = 0;
|
notadir = 0;
|
||||||
res = __X_find_entry (dir, name, NULL, make_dirs, make_file);
|
res = __find_entry (dir, name, NULL, make_dirs, make_file);
|
||||||
if (res == NULL) {
|
if (res == NULL) {
|
||||||
if (errloop)
|
if (errloop)
|
||||||
Xerrno = ELOOP;
|
my_errno = ELOOP;
|
||||||
else if (notadir)
|
else if (notadir)
|
||||||
Xerrno = ENOTDIR;
|
my_errno = ENOTDIR;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -110,29 +110,29 @@ static struct X_entry *X_find_entry (struct X_entry *dir, char *name, int make_d
|
|||||||
|
|
||||||
static int s_errno (void)
|
static int s_errno (void)
|
||||||
{
|
{
|
||||||
return Xerrno;
|
return my_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void * s_opendir (char *dirname)
|
static void * s_opendir (char *dirname)
|
||||||
{
|
{
|
||||||
struct X_archive *archive;
|
struct archive *archive;
|
||||||
char *q;
|
char *q;
|
||||||
struct X_entry *entry;
|
struct entry *entry;
|
||||||
struct X_entry **info;
|
struct entry **info;
|
||||||
|
|
||||||
if ((q = X_get_path_mangle (dirname, &archive, 1, 0)) == NULL)
|
if ((q = get_path_mangle (dirname, &archive, 1, 0)) == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
entry = X_find_entry (archive->root_entry, q, 0, 0);
|
entry = find_entry (archive->root_entry, q, 0, 0);
|
||||||
if (entry == NULL)
|
if (entry == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if ((entry = X_resolve_symlinks (entry)) == NULL)
|
if ((entry = my_resolve_symlinks (entry)) == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (!S_ISDIR (entry->inode->mode)) {
|
if (!S_ISDIR (entry->inode->mode)) {
|
||||||
Xerrno = ENOTDIR;
|
my_errno = ENOTDIR;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
info = (struct X_entry **) xmalloc (2*sizeof (struct X_entry *), "shared opendir");
|
info = (struct entry **) xmalloc (2*sizeof (struct entry *), "shared opendir");
|
||||||
info[0] = entry->inode->first_in_subdir;
|
info[0] = entry->inode->first_in_subdir;
|
||||||
info[1] = entry->inode->first_in_subdir;
|
info[1] = entry->inode->first_in_subdir;
|
||||||
|
|
||||||
@ -148,7 +148,7 @@ static void * s_readdir (void *data)
|
|||||||
#endif
|
#endif
|
||||||
} dir;
|
} dir;
|
||||||
|
|
||||||
struct X_entry **info = (struct X_entry **) data;
|
struct entry **info = (struct entry **) data;
|
||||||
|
|
||||||
if (!*info)
|
if (!*info)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -165,8 +165,8 @@ static void * s_readdir (void *data)
|
|||||||
|
|
||||||
static int s_telldir (void *data)
|
static int s_telldir (void *data)
|
||||||
{
|
{
|
||||||
struct X_entry **info = (struct X_entry **) data;
|
struct entry **info = (struct entry **) data;
|
||||||
struct X_entry *cur;
|
struct entry *cur;
|
||||||
int num = 0;
|
int num = 0;
|
||||||
|
|
||||||
cur = info[1];
|
cur = info[1];
|
||||||
@ -180,7 +180,7 @@ static int s_telldir (void *data)
|
|||||||
|
|
||||||
static void s_seekdir (void *data, int offset)
|
static void s_seekdir (void *data, int offset)
|
||||||
{
|
{
|
||||||
struct X_entry **info = (struct X_entry **) data;
|
struct entry **info = (struct entry **) data;
|
||||||
int i;
|
int i;
|
||||||
info[0] = info[1];
|
info[0] = info[1];
|
||||||
for (i=0; i<offset; i++)
|
for (i=0; i<offset; i++)
|
||||||
@ -193,7 +193,7 @@ static int s_closedir (void *data)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stat_move( struct stat *buf, struct X_inode *inode )
|
static void stat_move( struct stat *buf, struct inode *inode )
|
||||||
{
|
{
|
||||||
buf->st_dev = inode->dev;
|
buf->st_dev = inode->dev;
|
||||||
buf->st_ino = inode->inode;
|
buf->st_ino = inode->inode;
|
||||||
@ -218,20 +218,20 @@ static void stat_move( struct stat *buf, struct X_inode *inode )
|
|||||||
|
|
||||||
static int s_internal_stat (char *path, struct stat *buf, int resolve)
|
static int s_internal_stat (char *path, struct stat *buf, int resolve)
|
||||||
{
|
{
|
||||||
struct X_archive *archive;
|
struct archive *archive;
|
||||||
char *q;
|
char *q;
|
||||||
struct X_entry *entry;
|
struct entry *entry;
|
||||||
struct X_inode *inode;
|
struct inode *inode;
|
||||||
char debugbuf[10240];
|
char debugbuf[10240];
|
||||||
strcpy( debugbuf, path );
|
strcpy( debugbuf, path );
|
||||||
|
|
||||||
|
|
||||||
if ((q = X_get_path_mangle (path, &archive, 0, 0)) == NULL)
|
if ((q = get_path_mangle (path, &archive, 0, 0)) == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
entry = X_find_entry (archive->root_entry, q, 0, 0);
|
entry = find_entry (archive->root_entry, q, 0, 0);
|
||||||
if (entry == NULL)
|
if (entry == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
if (resolve && (entry = X_resolve_symlinks (entry)) == NULL)
|
if (resolve && (entry = my_resolve_symlinks (entry)) == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
inode = entry->inode;
|
inode = entry->inode;
|
||||||
stat_move( buf, inode );
|
stat_move( buf, inode );
|
||||||
@ -250,8 +250,8 @@ static int s_lstat (char *path, struct stat *buf)
|
|||||||
|
|
||||||
static int s_fstat (void *data, struct stat *buf)
|
static int s_fstat (void *data, struct stat *buf)
|
||||||
{
|
{
|
||||||
struct X_pseudofile *file = (struct X_pseudofile *)data;
|
struct pseudofile *file = (struct pseudofile *)data;
|
||||||
struct X_inode *inode;
|
struct inode *inode;
|
||||||
|
|
||||||
inode = file->entry->inode;
|
inode = file->entry->inode;
|
||||||
stat_move( buf, inode );
|
stat_move( buf, inode );
|
||||||
@ -260,18 +260,18 @@ static int s_fstat (void *data, struct stat *buf)
|
|||||||
|
|
||||||
static int s_readlink (char *path, char *buf, int size)
|
static int s_readlink (char *path, char *buf, int size)
|
||||||
{
|
{
|
||||||
struct X_archive *archive;
|
struct archive *archive;
|
||||||
char *q;
|
char *q;
|
||||||
int i;
|
int i;
|
||||||
struct X_entry *entry;
|
struct entry *entry;
|
||||||
|
|
||||||
if ((q = X_get_path_mangle (path, &archive, 0, 0)) == NULL)
|
if ((q = get_path_mangle (path, &archive, 0, 0)) == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
entry = X_find_entry (archive->root_entry, q, 0, 0);
|
entry = find_entry (archive->root_entry, q, 0, 0);
|
||||||
if (entry == NULL)
|
if (entry == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
if (!S_ISLNK (entry->inode->mode)) {
|
if (!S_ISLNK (entry->inode->mode)) {
|
||||||
Xerrno = EINVAL;
|
my_errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (size > (i = strlen (entry->inode->linkname))) {
|
if (size > (i = strlen (entry->inode->linkname))) {
|
291
vfs/tar.c
291
vfs/tar.c
@ -41,6 +41,7 @@
|
|||||||
#include "../src/dialog.h" /* For MSG_ERROR */
|
#include "../src/dialog.h" /* For MSG_ERROR */
|
||||||
#include "../src/mem.h"
|
#include "../src/mem.h"
|
||||||
#include "../src/mad.h"
|
#include "../src/mad.h"
|
||||||
|
#include "../src/main.h"
|
||||||
#include "vfs.h"
|
#include "vfs.h"
|
||||||
#include "tar.h"
|
#include "tar.h"
|
||||||
#include "names.h"
|
#include "names.h"
|
||||||
@ -78,15 +79,15 @@ long from_oct (int digs, char *where)
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct tarfs_archive *first_archive = NULL;
|
static struct archive *first_archive = NULL;
|
||||||
static int tarerrno = 0;
|
static int my_errno = 0;
|
||||||
static struct stat hstat; /* Stat struct corresponding */
|
static struct stat hstat; /* Stat struct corresponding */
|
||||||
static char *current_file_name, *current_link_name;
|
static char *current_file_name, *current_link_name;
|
||||||
static struct tarfs_entry *tarfs_find_entry (struct tarfs_entry *dir, char *name, int make_dirs, int make_file);
|
static struct entry *find_entry (struct entry *dir, char *name, int make_dirs, int make_file);
|
||||||
|
|
||||||
void tarfs_fill_names (void (*func)(char *))
|
void tarfs_fill_names (void (*func)(char *))
|
||||||
{
|
{
|
||||||
struct tarfs_archive *a = first_archive;
|
struct archive *a = first_archive;
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
while (a){
|
while (a){
|
||||||
@ -98,12 +99,12 @@ void tarfs_fill_names (void (*func)(char *))
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void make_dot_doubledot (struct tarfs_entry *ent)
|
static void make_dot_doubledot (struct entry *ent)
|
||||||
{
|
{
|
||||||
struct tarfs_entry *entry = (struct tarfs_entry *)
|
struct entry *entry = (struct entry *)
|
||||||
xmalloc (sizeof (struct tarfs_entry), "Tar: tarfs_entry");
|
xmalloc (sizeof (struct entry), "Tar: entry");
|
||||||
struct tarfs_entry *parentry = ent->dir;
|
struct entry *parentry = ent->dir;
|
||||||
struct tarfs_inode *inode = ent->inode, *parent;
|
struct inode *inode = ent->inode, *parent;
|
||||||
|
|
||||||
parent = (parentry != NULL) ? parentry->inode : NULL;
|
parent = (parentry != NULL) ? parentry->inode : NULL;
|
||||||
entry->name = strdup (".");
|
entry->name = strdup (".");
|
||||||
@ -117,8 +118,8 @@ static void make_dot_doubledot (struct tarfs_entry *ent)
|
|||||||
inode->first_in_subdir = entry;
|
inode->first_in_subdir = entry;
|
||||||
inode->last_in_subdir = entry;
|
inode->last_in_subdir = entry;
|
||||||
inode->nlink++;
|
inode->nlink++;
|
||||||
entry->next_in_dir = (struct tarfs_entry *)
|
entry->next_in_dir = (struct entry *)
|
||||||
xmalloc (sizeof (struct tarfs_entry), "Tar: tarfs_entry");
|
xmalloc (sizeof (struct entry), "Tar: entry");
|
||||||
entry=entry->next_in_dir;
|
entry=entry->next_in_dir;
|
||||||
entry->name = strdup ("..");
|
entry->name = strdup ("..");
|
||||||
entry->has_changed = 0;
|
entry->has_changed = 0;
|
||||||
@ -139,16 +140,16 @@ static void make_dot_doubledot (struct tarfs_entry *ent)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct tarfs_entry *generate_entry (struct tarfs_archive *archive,
|
static struct entry *generate_entry (struct archive *archive,
|
||||||
char *name, struct tarfs_entry *parentry, mode_t mode)
|
char *name, struct entry *parentry, mode_t mode)
|
||||||
{
|
{
|
||||||
mode_t myumask;
|
mode_t myumask;
|
||||||
struct tarfs_inode *inode, *parent;
|
struct inode *inode, *parent;
|
||||||
struct tarfs_entry *entry;
|
struct entry *entry;
|
||||||
|
|
||||||
parent = (parentry != NULL) ? parentry->inode : NULL;
|
parent = (parentry != NULL) ? parentry->inode : NULL;
|
||||||
entry = (struct tarfs_entry *)
|
entry = (struct entry *)
|
||||||
xmalloc (sizeof (struct tarfs_entry), "Tar: tarfs_entry");
|
xmalloc (sizeof (struct entry), "Tar: entry");
|
||||||
|
|
||||||
entry->name = strdup (name);
|
entry->name = strdup (name);
|
||||||
entry->has_changed = 0;
|
entry->has_changed = 0;
|
||||||
@ -162,8 +163,8 @@ static struct tarfs_entry *generate_entry (struct tarfs_archive *archive,
|
|||||||
parent->last_in_subdir->next_in_dir = entry;
|
parent->last_in_subdir->next_in_dir = entry;
|
||||||
parent->last_in_subdir = entry;
|
parent->last_in_subdir = entry;
|
||||||
}
|
}
|
||||||
inode = (struct tarfs_inode *)
|
inode = (struct inode *)
|
||||||
xmalloc (sizeof (struct tarfs_inode), "Tar: tarfs_inode");
|
xmalloc (sizeof (struct inode), "Tar: inode");
|
||||||
entry->inode = inode;
|
entry->inode = inode;
|
||||||
inode->local_filename = NULL;
|
inode->local_filename = NULL;
|
||||||
inode->has_changed = 0;
|
inode->has_changed = 0;
|
||||||
@ -203,12 +204,12 @@ static struct tarfs_entry *generate_entry (struct tarfs_archive *archive,
|
|||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_entries (struct tarfs_entry *entry)
|
static void free_entries (struct entry *entry)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_archive (struct tarfs_archive *archive)
|
static void free_archive (struct archive *archive)
|
||||||
{
|
{
|
||||||
long l;
|
long l;
|
||||||
|
|
||||||
@ -220,10 +221,8 @@ static void free_archive (struct tarfs_archive *archive)
|
|||||||
free (archive->block_ptr);
|
free (archive->block_ptr);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (archive->is_gzipped == tar_uncompressed_local) {
|
if (archive->tmpname)
|
||||||
mc_unlink (archive->tmpname);
|
|
||||||
free (archive->tmpname);
|
free (archive->tmpname);
|
||||||
}
|
|
||||||
if (archive->fd != -1)
|
if (archive->fd != -1)
|
||||||
mc_close(archive->fd);
|
mc_close(archive->fd);
|
||||||
}
|
}
|
||||||
@ -246,7 +245,7 @@ static INLINE int gzip_limit_ok (int size)
|
|||||||
*
|
*
|
||||||
* Returns: 0 on failure
|
* Returns: 0 on failure
|
||||||
*/
|
*/
|
||||||
static INLINE int load_compressed_tar (struct tarfs_archive *current_archive,
|
static INLINE int load_compressed_tar (struct archive *current_archive,
|
||||||
int size, int fd, int type)
|
int size, int fd, int type)
|
||||||
{
|
{
|
||||||
int pipehandle, i;
|
int pipehandle, i;
|
||||||
@ -337,76 +336,39 @@ static INLINE int load_compressed_tar (struct tarfs_archive *current_archive,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Returns a file handle of the opened local tar file or -1 on error */
|
/* Returns a file handle of the opened local tar file or -1 on error */
|
||||||
static INLINE int uncompress_tar_file (struct tarfs_archive *current_archive,
|
static INLINE int uncompress_tar_file (struct archive *current_archive,
|
||||||
int size, int fd, int type)
|
int size, int fd, int type)
|
||||||
{
|
{
|
||||||
FILE *f;
|
int result;
|
||||||
char *command;
|
|
||||||
int i, result;
|
|
||||||
int dash_number = 0;
|
|
||||||
char buffer [8192]; /* Changed to 8K: better transfer size */
|
|
||||||
|
|
||||||
current_archive->is_gzipped = tar_uncompressed_local;
|
|
||||||
current_archive->tmpname = strdup (tempnam (NULL, "tarfs"));
|
|
||||||
|
|
||||||
/* Some security is sometimes neccessary :) */
|
|
||||||
command = copy_strings ("touch ", current_archive->tmpname,
|
|
||||||
" ; chmod 0600 ", current_archive->tmpname, " ; ",
|
|
||||||
decompress_command (type),
|
|
||||||
"2>/dev/null >", current_archive->tmpname, NULL);
|
|
||||||
|
|
||||||
if ((f = popen (command, "w")) == NULL) {
|
|
||||||
mc_close (fd);
|
|
||||||
free_archive (current_archive);
|
|
||||||
free (command);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
free (command);
|
|
||||||
|
|
||||||
while ((i = mc_read (fd, buffer, sizeof (buffer))) > 0){
|
|
||||||
if ((dash_number++ % 64) == 0)
|
|
||||||
rotate_dash ();
|
|
||||||
fwrite (buffer, 1, i, f);
|
|
||||||
if (ferror (f)) {
|
|
||||||
pclose (f);
|
|
||||||
#ifdef SCO_FLAVOR
|
|
||||||
waitpid(-1,NULL,WNOHANG);
|
|
||||||
#endif /* SCO_FLAVOR */
|
|
||||||
mc_close (fd);
|
|
||||||
free_archive (current_archive);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pclose (f);
|
/* From time we have sfs this function is pretty trivial */
|
||||||
#ifdef SCO_FLAVOR
|
current_archive->is_gzipped = tar_uncompressed_local;
|
||||||
waitpid(-1,NULL,WNOHANG);
|
current_archive->tmpname = copy_strings( current_archive->name, "#ugz", NULL );
|
||||||
#endif /* SCO_FLAVOR */
|
|
||||||
mc_close (fd);
|
|
||||||
result = mc_open (current_archive->tmpname, O_RDONLY);
|
result = mc_open (current_archive->tmpname, O_RDONLY);
|
||||||
if (result == -1){
|
if (result == -1)
|
||||||
free_archive (current_archive);
|
free_archive (current_archive);
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns fd of the open tar file */
|
/* Returns fd of the open tar file */
|
||||||
static int open_tar_archive (char *name, struct tarfs_archive **pparc)
|
static int open_tar_archive (char *name, struct archive **pparc)
|
||||||
{
|
{
|
||||||
static dev_t __tar_no = 0;
|
static dev_t __tar_no = 0;
|
||||||
int result, type;
|
int result, type;
|
||||||
long size;
|
long size;
|
||||||
mode_t mode;
|
mode_t mode;
|
||||||
struct tarfs_archive *current_archive;
|
struct archive *current_archive;
|
||||||
static struct tarfs_entry *root_entry;
|
static struct entry *root_entry;
|
||||||
|
|
||||||
result = mc_open (name, O_RDONLY);
|
result = mc_open (name, O_RDONLY);
|
||||||
if (result == -1)
|
if (result == -1) {
|
||||||
|
message_2s (1, MSG_ERROR, _("Couldn't open tar archive\n%s"), name);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
current_archive = (struct tarfs_archive *)
|
current_archive = (struct archive *)
|
||||||
xmalloc (sizeof (struct tarfs_archive), "Tar archive");
|
xmalloc (sizeof (struct archive), "Tar archive");
|
||||||
current_archive->current_tar_position = 0;
|
current_archive->current_tar_position = 0;
|
||||||
current_archive->name = strdup (name);
|
current_archive->name = strdup (name);
|
||||||
current_archive->__inode_counter = 0;
|
current_archive->__inode_counter = 0;
|
||||||
@ -415,18 +377,23 @@ static int open_tar_archive (char *name, struct tarfs_archive **pparc)
|
|||||||
current_archive->next = first_archive;
|
current_archive->next = first_archive;
|
||||||
current_archive->fd_usage = 0;
|
current_archive->fd_usage = 0;
|
||||||
current_archive->fd = -1;
|
current_archive->fd = -1;
|
||||||
|
current_archive->tmpname = NULL;
|
||||||
size = is_gunzipable (result, &type);
|
size = is_gunzipable (result, &type);
|
||||||
mc_lseek (result, 0, SEEK_SET);
|
mc_lseek (result, 0, SEEK_SET);
|
||||||
|
|
||||||
/* Find out the method to handle this tar file */
|
/* Find out the method to handle this tar file */
|
||||||
if (size > 0 && gzip_limit_ok (size)) {
|
if (size > 0 && gzip_limit_ok (size)) {
|
||||||
if (load_compressed_tar (current_archive, size, result, type) == 0)
|
if (load_compressed_tar (current_archive, size, result, type) == 0) {
|
||||||
|
message_2s (1, MSG_ERROR, _("Couldn't load compressed tar\n%s"), name);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
result = 0;
|
result = 0;
|
||||||
} else if (size > 0) {
|
} else if (size > 0) {
|
||||||
result = uncompress_tar_file (current_archive, size, result, type);
|
result = uncompress_tar_file (current_archive, size, result, type);
|
||||||
if (result == -1)
|
if (result == -1) {
|
||||||
|
message_2s (1, MSG_ERROR, _("Couldn't uncompress tar archive\n%s"), name);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
current_archive->is_gzipped = tar_normal;
|
current_archive->is_gzipped = tar_normal;
|
||||||
}
|
}
|
||||||
@ -455,12 +422,12 @@ static int open_tar_archive (char *name, struct tarfs_archive **pparc)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_current_position (struct tarfs_archive *archive, int tard)
|
static int get_current_position (struct archive *archive, int tard)
|
||||||
{
|
{
|
||||||
return archive->current_tar_position;
|
return archive->current_tar_position;
|
||||||
}
|
}
|
||||||
|
|
||||||
static union record *find_current_record (struct tarfs_archive *archive, long pos)
|
static union record *find_current_record (struct archive *archive, long pos)
|
||||||
{
|
{
|
||||||
long l, l2;
|
long l, l2;
|
||||||
static union record *ur;
|
static union record *ur;
|
||||||
@ -477,7 +444,7 @@ static union record *find_current_record (struct tarfs_archive *archive, long po
|
|||||||
|
|
||||||
static union record rec_buf;
|
static union record rec_buf;
|
||||||
|
|
||||||
static union record *get_next_record (struct tarfs_archive *archive, int tard)
|
static union record *get_next_record (struct archive *archive, int tard)
|
||||||
{
|
{
|
||||||
if (archive->is_gzipped == targz_growing) {
|
if (archive->is_gzipped == targz_growing) {
|
||||||
bcopy (archive->current_record, rec_buf.charptr, RECORDSIZE);
|
bcopy (archive->current_record, rec_buf.charptr, RECORDSIZE);
|
||||||
@ -488,7 +455,7 @@ static union record *get_next_record (struct tarfs_archive *archive, int tard)
|
|||||||
return &rec_buf;
|
return &rec_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void skip_n_records (struct tarfs_archive *archive, int tard, int n)
|
static void skip_n_records (struct archive *archive, int tard, int n)
|
||||||
{
|
{
|
||||||
if (archive->is_gzipped == targz_growing)
|
if (archive->is_gzipped == targz_growing)
|
||||||
archive->current_record = find_current_record (archive, archive->current_tar_position + n * RECORDSIZE);
|
archive->current_record = find_current_record (archive, archive->current_tar_position + n * RECORDSIZE);
|
||||||
@ -502,7 +469,7 @@ static void skip_n_records (struct tarfs_archive *archive, int tard, int n)
|
|||||||
* 2 for a record full of zeros (EOF marker).
|
* 2 for a record full of zeros (EOF marker).
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static int read_header (struct tarfs_archive *archive, int tard)
|
static int read_header (struct archive *archive, int tard)
|
||||||
{
|
{
|
||||||
register int i;
|
register int i;
|
||||||
register long sum, signed_sum, recsum;
|
register long sum, signed_sum, recsum;
|
||||||
@ -599,8 +566,8 @@ static int read_header (struct tarfs_archive *archive, int tard)
|
|||||||
#endif
|
#endif
|
||||||
goto recurse;
|
goto recurse;
|
||||||
} else {
|
} else {
|
||||||
struct tarfs_entry *entry, *pent;
|
struct entry *entry, *pent;
|
||||||
struct tarfs_inode *inode;
|
struct inode *inode;
|
||||||
long data_position;
|
long data_position;
|
||||||
char *p, *q;
|
char *p, *q;
|
||||||
int len;
|
int len;
|
||||||
@ -635,12 +602,12 @@ static int read_header (struct tarfs_archive *archive, int tard)
|
|||||||
q = current_file_name;
|
q = current_file_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
pent = tarfs_find_entry (archive->root_entry, q, 1, 0);
|
pent = find_entry (archive->root_entry, q, 1, 0);
|
||||||
if (pent == NULL) {
|
if (pent == NULL) {
|
||||||
message_1s (1, MSG_ERROR, _("Inconsistent tar archive"));
|
message_1s (1, MSG_ERROR, _("Inconsistent tar archive"));
|
||||||
}
|
}
|
||||||
|
|
||||||
entry = (struct tarfs_entry *) xmalloc (sizeof (struct tarfs_entry), "Tar: tarfs_entry");
|
entry = (struct entry *) xmalloc (sizeof (struct entry), "Tar: entry");
|
||||||
entry->name = strdup (p);
|
entry->name = strdup (p);
|
||||||
entry->has_changed = 0;
|
entry->has_changed = 0;
|
||||||
entry->header_offset = header_position;
|
entry->header_offset = header_position;
|
||||||
@ -656,7 +623,7 @@ static int read_header (struct tarfs_archive *archive, int tard)
|
|||||||
free (current_file_name);
|
free (current_file_name);
|
||||||
|
|
||||||
if (header->header.linkflag == LF_LINK) {
|
if (header->header.linkflag == LF_LINK) {
|
||||||
pent = tarfs_find_entry (archive->root_entry, current_link_name, 0, 0);
|
pent = find_entry (archive->root_entry, current_link_name, 0, 0);
|
||||||
if (pent == NULL) {
|
if (pent == NULL) {
|
||||||
message_1s (1, MSG_ERROR, _("Inconsistent tar archive"));
|
message_1s (1, MSG_ERROR, _("Inconsistent tar archive"));
|
||||||
} else {
|
} else {
|
||||||
@ -672,7 +639,7 @@ static int read_header (struct tarfs_archive *archive, int tard)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inode = (struct tarfs_inode *) xmalloc (sizeof (struct tarfs_inode), "Tar: tarfs_inode");
|
inode = (struct inode *) xmalloc (sizeof (struct inode), "Tar: inode");
|
||||||
entry->inode = inode;
|
entry->inode = inode;
|
||||||
inode->local_filename = NULL;
|
inode->local_filename = NULL;
|
||||||
inode->has_changed = 0;
|
inode->has_changed = 0;
|
||||||
@ -750,12 +717,12 @@ static int read_header (struct tarfs_archive *archive, int tard)
|
|||||||
* Main loop for reading an archive.
|
* Main loop for reading an archive.
|
||||||
* Returns 0 on success, -1 on error.
|
* Returns 0 on success, -1 on error.
|
||||||
*/
|
*/
|
||||||
int read_tar_archive (char *name, struct tarfs_archive **pparc)
|
int read_tar_archive (char *name, struct archive **pparc)
|
||||||
{
|
{
|
||||||
int status = 3; /* Initial status at start of archive */
|
int status = 3; /* Initial status at start of archive */
|
||||||
int prev_status;
|
int prev_status;
|
||||||
int tard;
|
int tard;
|
||||||
struct tarfs_archive *archive;
|
struct archive *archive;
|
||||||
|
|
||||||
if ((tard = open_tar_archive (name, &archive)) == -1) { /* Open for reading */
|
if ((tard = open_tar_archive (name, &archive)) == -1) { /* Open for reading */
|
||||||
message_2s (1, MSG_ERROR, _("Couldn't open tar archive\n%s"), name);
|
message_2s (1, MSG_ERROR, _("Couldn't open tar archive\n%s"), name);
|
||||||
@ -801,18 +768,18 @@ int read_tar_archive (char *name, struct tarfs_archive **pparc)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *tarfs_get_path (char *inname, struct tarfs_archive **archive, int is_dir,
|
static char *get_path (char *inname, struct archive **archive, int is_dir,
|
||||||
int do_not_open);
|
int do_not_open);
|
||||||
|
|
||||||
/* Returns path inside argument. Returned char* is inside inname, which is mangled
|
/* Returns path inside argument. Returned char* is inside inname, which is mangled
|
||||||
* by this operation (so you must not free it's return value)
|
* by this operation (so you must not free it's return value)
|
||||||
*/
|
*/
|
||||||
static char *tarfs_get_path_mangle (char *inname, struct tarfs_archive **archive, int is_dir,
|
static char *get_path_mangle (char *inname, struct archive **archive, int is_dir,
|
||||||
int do_not_open)
|
int do_not_open)
|
||||||
{
|
{
|
||||||
char *local, *archive_name;
|
char *local, *archive_name;
|
||||||
int result = -1;
|
int result = -1;
|
||||||
struct tarfs_archive *parc;
|
struct archive *parc;
|
||||||
struct vfs_stamping *parent;
|
struct vfs_stamping *parent;
|
||||||
vfs *v;
|
vfs *v;
|
||||||
struct stat stat_buf;
|
struct stat stat_buf;
|
||||||
@ -845,7 +812,7 @@ static char *tarfs_get_path_mangle (char *inname, struct tarfs_archive **archive
|
|||||||
else
|
else
|
||||||
result = read_tar_archive (archive_name, &parc);
|
result = read_tar_archive (archive_name, &parc);
|
||||||
if (result == -1) {
|
if (result == -1) {
|
||||||
tarerrno = EIO;
|
my_errno = EIO;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
v = vfs_type (archive_name);
|
v = vfs_type (archive_name);
|
||||||
@ -864,23 +831,23 @@ return_success:
|
|||||||
return local;
|
return local;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct tarfs_loop_protect {
|
struct loop_protect {
|
||||||
struct tarfs_entry *entry;
|
struct entry *entry;
|
||||||
struct tarfs_loop_protect *next;
|
struct loop_protect *next;
|
||||||
};
|
};
|
||||||
static int errloop;
|
static int errloop;
|
||||||
static int notadir;
|
static int notadir;
|
||||||
|
|
||||||
static struct tarfs_entry *
|
static struct entry *
|
||||||
__tarfs_find_entry (struct tarfs_entry *dir, char *name,
|
__find_entry (struct entry *dir, char *name,
|
||||||
struct tarfs_loop_protect *list, int make_dirs, int make_file);
|
struct loop_protect *list, int make_dirs, int make_file);
|
||||||
|
|
||||||
static struct tarfs_entry *
|
static struct entry *
|
||||||
__tarfs_resolve_symlinks (struct tarfs_entry *entry,
|
__resolve_symlinks (struct entry *entry,
|
||||||
struct tarfs_loop_protect *list)
|
struct loop_protect *list)
|
||||||
{
|
{
|
||||||
struct tarfs_entry *pent;
|
struct entry *pent;
|
||||||
struct tarfs_loop_protect *looping;
|
struct loop_protect *looping;
|
||||||
|
|
||||||
if (!S_ISLNK (entry->inode->mode))
|
if (!S_ISLNK (entry->inode->mode))
|
||||||
return entry;
|
return entry;
|
||||||
@ -889,68 +856,68 @@ __tarfs_resolve_symlinks (struct tarfs_entry *entry,
|
|||||||
errloop = 1;
|
errloop = 1;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
looping = (struct tarfs_loop_protect *)
|
looping = (struct loop_protect *)
|
||||||
xmalloc (sizeof (struct tarfs_loop_protect),
|
xmalloc (sizeof (struct loop_protect),
|
||||||
"Tar: symlink looping protection");
|
"Tar: symlink looping protection");
|
||||||
looping->entry = entry;
|
looping->entry = entry;
|
||||||
looping->next = list;
|
looping->next = list;
|
||||||
pent = __tarfs_find_entry (entry->dir, entry->inode->linkname, looping, 0, 0);
|
pent = __find_entry (entry->dir, entry->inode->linkname, looping, 0, 0);
|
||||||
free (looping);
|
free (looping);
|
||||||
if (pent == NULL)
|
if (pent == NULL)
|
||||||
tarerrno = ENOENT;
|
my_errno = ENOENT;
|
||||||
return pent;
|
return pent;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct tarfs_entry *tarfs_resolve_symlinks (struct tarfs_entry *entry)
|
static struct entry *my_resolve_symlinks (struct entry *entry)
|
||||||
{
|
{
|
||||||
struct tarfs_entry *res;
|
struct entry *res;
|
||||||
|
|
||||||
errloop = 0;
|
errloop = 0;
|
||||||
notadir = 0;
|
notadir = 0;
|
||||||
res = __tarfs_resolve_symlinks (entry, NULL);
|
res = __resolve_symlinks (entry, NULL);
|
||||||
if (res == NULL) {
|
if (res == NULL) {
|
||||||
if (errloop)
|
if (errloop)
|
||||||
tarerrno = ELOOP;
|
my_errno = ELOOP;
|
||||||
else if (notadir)
|
else if (notadir)
|
||||||
tarerrno = ENOTDIR;
|
my_errno = ENOTDIR;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct tar_pseudofile {
|
struct pseudofile {
|
||||||
struct tarfs_archive *archive;
|
struct archive *archive;
|
||||||
long pos;
|
long pos;
|
||||||
long begin;
|
long begin;
|
||||||
long end;
|
long end;
|
||||||
struct tarfs_entry *entry;
|
struct entry *entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct tarfs_entry *tarfs_find_entry (struct tarfs_entry *dir, char *name, int make_dirs, int make_file);
|
static struct entry *find_entry (struct entry *dir, char *name, int make_dirs, int make_file);
|
||||||
|
|
||||||
static void *tar_open (char *file, int flags, int mode)
|
static void *tar_open (char *file, int flags, int mode)
|
||||||
{
|
{
|
||||||
struct tar_pseudofile *tar_info;
|
struct pseudofile *tar_info;
|
||||||
struct tarfs_archive *archive;
|
struct archive *archive;
|
||||||
char *q;
|
char *q;
|
||||||
struct tarfs_entry *entry;
|
struct entry *entry;
|
||||||
|
|
||||||
if ((q = tarfs_get_path_mangle (file, &archive, 0, 0)) == NULL)
|
if ((q = get_path_mangle (file, &archive, 0, 0)) == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
entry = tarfs_find_entry (archive->root_entry, q, 0, 0);
|
entry = find_entry (archive->root_entry, q, 0, 0);
|
||||||
if (entry == NULL)
|
if (entry == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if ((entry = tarfs_resolve_symlinks (entry)) == NULL)
|
if ((entry = my_resolve_symlinks (entry)) == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (S_ISDIR (entry->inode->mode)) {
|
if (S_ISDIR (entry->inode->mode)) {
|
||||||
tarerrno = EISDIR;
|
my_errno = EISDIR;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if ((flags & O_ACCMODE) != O_RDONLY) {
|
if ((flags & O_ACCMODE) != O_RDONLY) {
|
||||||
tarerrno = EROFS; /* At the moment we are RO */
|
my_errno = EROFS; /* At the moment we are RO */
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
tar_info = (struct tar_pseudofile *) xmalloc (sizeof (struct tar_pseudofile), "Tar: tar_open");
|
tar_info = (struct pseudofile *) xmalloc (sizeof (struct pseudofile), "Tar: tar_open");
|
||||||
tar_info->archive = archive;
|
tar_info->archive = archive;
|
||||||
tar_info->pos = 0;
|
tar_info->pos = 0;
|
||||||
tar_info->begin = entry->inode->data_offset;
|
tar_info->begin = entry->inode->data_offset;
|
||||||
@ -966,12 +933,12 @@ static void *tar_open (char *file, int flags, int mode)
|
|||||||
|
|
||||||
static int tar_read (void *data, char *buffer, int count)
|
static int tar_read (void *data, char *buffer, int count)
|
||||||
{
|
{
|
||||||
struct tar_pseudofile *file = (struct tar_pseudofile *)data;
|
struct pseudofile *file = (struct pseudofile *)data;
|
||||||
|
|
||||||
if (file->archive->is_gzipped != targz_growing &&
|
if (file->archive->is_gzipped != targz_growing &&
|
||||||
mc_lseek (file->archive->fd, file->begin + file->pos, SEEK_SET) !=
|
mc_lseek (file->archive->fd, file->begin + file->pos, SEEK_SET) !=
|
||||||
file->begin + file->pos) {
|
file->begin + file->pos) {
|
||||||
tarerrno = EIO;
|
my_errno = EIO;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1005,7 +972,7 @@ static int tar_read (void *data, char *buffer, int count)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((count = mc_read (file->archive->fd, buffer, count)) == -1) {
|
else if ((count = mc_read (file->archive->fd, buffer, count)) == -1) {
|
||||||
tarerrno = errno;
|
my_errno = errno;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
file->pos += count;
|
file->pos += count;
|
||||||
@ -1014,9 +981,9 @@ static int tar_read (void *data, char *buffer, int count)
|
|||||||
|
|
||||||
static int tar_close (void *data)
|
static int tar_close (void *data)
|
||||||
{
|
{
|
||||||
struct tar_pseudofile *file;
|
struct pseudofile *file;
|
||||||
|
|
||||||
file = (struct tar_pseudofile *)data;
|
file = (struct pseudofile *)data;
|
||||||
|
|
||||||
file->archive->fd_usage--;
|
file->archive->fd_usage--;
|
||||||
if (!file->archive->fd_usage) {
|
if (!file->archive->fd_usage) {
|
||||||
@ -1041,21 +1008,7 @@ static int tar_close (void *data)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define X_pseudofile tar_pseudofile
|
#include "shared_tar_ext.c"
|
||||||
#define Xerrno tarerrno
|
|
||||||
|
|
||||||
#define X_entry tarfs_entry
|
|
||||||
#define X_archive tarfs_archive
|
|
||||||
#define X_get_path tarfs_get_path
|
|
||||||
#define X_get_path_mangle tarfs_get_path_mangle
|
|
||||||
#define X_find_entry tarfs_find_entry
|
|
||||||
#define X_resolve_symlinks tarfs_resolve_symlinks
|
|
||||||
#define X_inode tarfs_inode
|
|
||||||
#define __X_find_entry __tarfs_find_entry
|
|
||||||
#define __X_resolve_symlinks __tarfs_resolve_symlinks
|
|
||||||
#define X_loop_protect tarfs_loop_protect
|
|
||||||
|
|
||||||
#include "shared.c"
|
|
||||||
|
|
||||||
static int tar_chmod (char *path, int mode)
|
static int tar_chmod (char *path, int mode)
|
||||||
{ /* Fixme: are you sure? IMO this is guaranteed to fail */
|
{ /* Fixme: are you sure? IMO this is guaranteed to fail */
|
||||||
@ -1069,27 +1022,27 @@ static int tar_chown (char *path, int owner, int group)
|
|||||||
|
|
||||||
static int tar_chdir (char *path)
|
static int tar_chdir (char *path)
|
||||||
{
|
{
|
||||||
struct tarfs_archive *archive;
|
struct archive *archive;
|
||||||
char *q;
|
char *q;
|
||||||
struct tarfs_entry *entry;
|
struct entry *entry;
|
||||||
|
|
||||||
tarerrno = ENOTDIR;
|
my_errno = ENOTDIR;
|
||||||
if ((q = tarfs_get_path_mangle (path, &archive, 1, 0)) == NULL)
|
if ((q = get_path_mangle (path, &archive, 1, 0)) == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
entry = tarfs_find_entry (archive->root_entry, q, 0, 0);
|
entry = find_entry (archive->root_entry, q, 0, 0);
|
||||||
if (!entry)
|
if (!entry)
|
||||||
return -1;
|
return -1;
|
||||||
entry = tarfs_resolve_symlinks (entry);
|
entry = my_resolve_symlinks (entry);
|
||||||
if ((!entry) || (!S_ISDIR (entry->inode->mode)))
|
if ((!entry) || (!S_ISDIR (entry->inode->mode)))
|
||||||
return -1;
|
return -1;
|
||||||
entry->inode->archive->current_dir = entry;
|
entry->inode->archive->current_dir = entry;
|
||||||
tarerrno = 0;
|
my_errno = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tar_lseek (void *data, off_t offset, int whence)
|
static int tar_lseek (void *data, off_t offset, int whence)
|
||||||
{
|
{
|
||||||
struct tar_pseudofile *file = (struct tar_pseudofile *) data;
|
struct pseudofile *file = (struct pseudofile *) data;
|
||||||
|
|
||||||
switch (whence) {
|
switch (whence) {
|
||||||
case SEEK_CUR:
|
case SEEK_CUR:
|
||||||
@ -1108,14 +1061,14 @@ static int tar_lseek (void *data, off_t offset, int whence)
|
|||||||
|
|
||||||
static vfsid tar_getid (char *path, struct vfs_stamping **parent)
|
static vfsid tar_getid (char *path, struct vfs_stamping **parent)
|
||||||
{
|
{
|
||||||
struct tarfs_archive *archive;
|
struct archive *archive;
|
||||||
vfs *v;
|
vfs *v;
|
||||||
char *p;
|
char *p;
|
||||||
vfsid id;
|
vfsid id;
|
||||||
struct vfs_stamping *par;
|
struct vfs_stamping *par;
|
||||||
|
|
||||||
*parent = NULL;
|
*parent = NULL;
|
||||||
if (!(p = tarfs_get_path (path, &archive, 0, 1)))
|
if (!(p = get_path (path, &archive, 0, 1)))
|
||||||
return (vfsid) -1;
|
return (vfsid) -1;
|
||||||
free(p);
|
free(p);
|
||||||
v = vfs_type (archive->name);
|
v = vfs_type (archive->name);
|
||||||
@ -1132,17 +1085,17 @@ static vfsid tar_getid (char *path, struct vfs_stamping **parent)
|
|||||||
|
|
||||||
static int tar_nothingisopen (vfsid id)
|
static int tar_nothingisopen (vfsid id)
|
||||||
{
|
{
|
||||||
if (((struct tarfs_archive *)id)->fd_usage <= 0)
|
if (((struct archive *)id)->fd_usage <= 0)
|
||||||
return 1;
|
return 1;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_entry (struct tarfs_entry *e)
|
static void free_entry (struct entry *e)
|
||||||
{
|
{
|
||||||
int i = --(e->inode->nlink);
|
int i = --(e->inode->nlink);
|
||||||
if (S_ISDIR (e->inode->mode) && e->inode->first_in_subdir != NULL) {
|
if (S_ISDIR (e->inode->mode) && e->inode->first_in_subdir != NULL) {
|
||||||
struct tarfs_entry *f = e->inode->first_in_subdir;
|
struct entry *f = e->inode->first_in_subdir;
|
||||||
|
|
||||||
e->inode->first_in_subdir = NULL;
|
e->inode->first_in_subdir = NULL;
|
||||||
free_entry (f);
|
free_entry (f);
|
||||||
@ -1164,8 +1117,8 @@ static void free_entry (struct tarfs_entry *e)
|
|||||||
|
|
||||||
static void tar_free (vfsid id)
|
static void tar_free (vfsid id)
|
||||||
{
|
{
|
||||||
struct tarfs_archive *parc;
|
struct archive *parc;
|
||||||
struct tarfs_archive *archive = (struct tarfs_archive *)id;
|
struct archive *archive = (struct archive *)id;
|
||||||
|
|
||||||
free_entry (archive->root_entry);
|
free_entry (archive->root_entry);
|
||||||
if (archive == first_archive) {
|
if (archive == first_archive) {
|
||||||
@ -1182,18 +1135,18 @@ static void tar_free (vfsid id)
|
|||||||
|
|
||||||
static char *tar_getlocalcopy (char *path)
|
static char *tar_getlocalcopy (char *path)
|
||||||
{
|
{
|
||||||
struct tarfs_archive *archive;
|
struct archive *archive;
|
||||||
char *p, *q;
|
char *p, *q;
|
||||||
struct tarfs_entry *entry;
|
struct entry *entry;
|
||||||
char buf[MC_MAXPATHLEN];
|
char buf[MC_MAXPATHLEN];
|
||||||
|
|
||||||
strcpy( buf, path );
|
strcpy( buf, path );
|
||||||
if ((q = tarfs_get_path_mangle (path, &archive, 1, 0)) == NULL)
|
if ((q = get_path_mangle (path, &archive, 1, 0)) == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
entry = tarfs_find_entry (archive->root_entry, q, 0, 0);
|
entry = find_entry (archive->root_entry, q, 0, 0);
|
||||||
if (entry == NULL)
|
if (entry == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if ((entry = tarfs_resolve_symlinks (entry)) == NULL)
|
if ((entry = my_resolve_symlinks (entry)) == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (entry->inode->local_filename != NULL)
|
if (entry->inode->local_filename != NULL)
|
||||||
|
28
vfs/tar.h
28
vfs/tar.h
@ -157,34 +157,34 @@ union record {
|
|||||||
|
|
||||||
#ifndef TAR_NAMES
|
#ifndef TAR_NAMES
|
||||||
|
|
||||||
struct tarfs_inode;
|
struct inode;
|
||||||
|
|
||||||
struct tarfs_entry {
|
struct entry {
|
||||||
int has_changed;
|
int has_changed;
|
||||||
long header_offset; /* -1 if not in stored in archive */
|
long header_offset; /* -1 if not in stored in archive */
|
||||||
int header_size;
|
int header_size;
|
||||||
struct tarfs_entry *next_in_dir;
|
struct entry *next_in_dir;
|
||||||
struct tarfs_entry *dir;
|
struct entry *dir;
|
||||||
long extended_offset; /* -1 if not present */
|
long extended_offset; /* -1 if not present */
|
||||||
int extended_size;
|
int extended_size;
|
||||||
|
|
||||||
char *name;
|
char *name;
|
||||||
struct tarfs_inode *inode;
|
struct inode *inode;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tarfs_archive;
|
struct archive;
|
||||||
|
|
||||||
struct tarfs_inode {
|
struct inode {
|
||||||
int has_changed;
|
int has_changed;
|
||||||
int is_open;
|
int is_open;
|
||||||
nlink_t nlink;
|
nlink_t nlink;
|
||||||
struct tarfs_entry *first_in_subdir; /* only used if linkflag == L_DIR */
|
struct entry *first_in_subdir; /* only used if linkflag == L_DIR */
|
||||||
struct tarfs_entry *last_in_subdir;
|
struct entry *last_in_subdir;
|
||||||
long data_offset;
|
long data_offset;
|
||||||
char *local_filename;
|
char *local_filename;
|
||||||
ino_t inode; /* This is inode # */
|
ino_t inode; /* This is inode # */
|
||||||
dev_t dev; /* This is an internal identification of the tar archive */
|
dev_t dev; /* This is an internal identification of the tar archive */
|
||||||
struct tarfs_archive *archive; /* And this is an archive structure */
|
struct archive *archive; /* And this is an archive structure */
|
||||||
dev_t rdev;
|
dev_t rdev;
|
||||||
int std; /* 0 if old Unix inode */
|
int std; /* 0 if old Unix inode */
|
||||||
|
|
||||||
@ -199,15 +199,15 @@ struct tarfs_inode {
|
|||||||
time_t ctime;
|
time_t ctime;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tarfs_archive {
|
struct archive {
|
||||||
char *name;
|
char *name;
|
||||||
struct stat tarstat;
|
struct stat tarstat;
|
||||||
int is_gzipped;
|
int is_gzipped;
|
||||||
dev_t rdev;
|
dev_t rdev;
|
||||||
ino_t __inode_counter;
|
ino_t __inode_counter;
|
||||||
struct tarfs_entry *root_entry;
|
struct entry *root_entry;
|
||||||
struct tarfs_entry *current_dir;
|
struct entry *current_dir;
|
||||||
struct tarfs_archive *next;
|
struct archive *next;
|
||||||
long current_tar_position;
|
long current_tar_position;
|
||||||
int fd;
|
int fd;
|
||||||
int fd_usage; /* Zero means fd is invalid, otherwise is number of
|
int fd_usage; /* Zero means fd is invalid, otherwise is number of
|
||||||
|
@ -178,12 +178,24 @@ char *get_host_and_username (char *path, char **host, char **user, int *port,
|
|||||||
/* Check if the host comes with a port spec, if so, chop it */
|
/* Check if the host comes with a port spec, if so, chop it */
|
||||||
colon = strchr (rest, ':');
|
colon = strchr (rest, ':');
|
||||||
if (colon){
|
if (colon){
|
||||||
*port = atoi (colon+1);
|
|
||||||
|
|
||||||
if (*port <= 0 || *port >= 65536)
|
|
||||||
*port = 21;
|
|
||||||
*colon = 0;
|
*colon = 0;
|
||||||
|
if (sscanf(colon+1, "%d", port)==1) {
|
||||||
|
if (*port <= 0 || *port >= 65536)
|
||||||
|
*port = default_port;
|
||||||
|
} else {
|
||||||
|
while(1) {
|
||||||
|
colon++;
|
||||||
|
switch(*colon) {
|
||||||
|
case 'C': *port = 1;
|
||||||
|
break;
|
||||||
|
case 'r': *port = 2;
|
||||||
|
break;
|
||||||
|
case 0: goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
done:
|
||||||
*host = strdup (rest);
|
*host = strdup (rest);
|
||||||
|
|
||||||
free (pcopy);
|
free (pcopy);
|
||||||
|
350
vfs/vfs.c
350
vfs/vfs.c
@ -19,6 +19,10 @@
|
|||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
|
/* Warning: funtions like extfs_lstat() have right to destroy any
|
||||||
|
* strings you pass to them. This is acutally ok as you strdup what
|
||||||
|
* you are passing to them, anyway; still, beware. */
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h> /* For atol() */
|
#include <stdlib.h> /* For atol() */
|
||||||
@ -86,7 +90,7 @@ static struct {
|
|||||||
vfs *operations;
|
vfs *operations;
|
||||||
} vfs_file_table [MAX_VFS_FILES];
|
} vfs_file_table [MAX_VFS_FILES];
|
||||||
|
|
||||||
static int get_bucket ()
|
static int get_bucket (void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -95,8 +99,7 @@ static int get_bucket ()
|
|||||||
if (!vfs_file_table [i].fs_info)
|
if (!vfs_file_table [i].fs_info)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
fprintf (stderr, "No more virtual file handles\n");
|
vfs_die ("No more virtual file handles");
|
||||||
exit (1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vfs *vfs_type_from_op (char *path)
|
vfs *vfs_type_from_op (char *path)
|
||||||
@ -111,6 +114,8 @@ vfs *vfs_type_from_op (char *path)
|
|||||||
if (!(vfs_flags & FL_NO_UNDELFS) && !strncmp (path, "undel:", 6))
|
if (!(vfs_flags & FL_NO_UNDELFS) && !strncmp (path, "undel:", 6))
|
||||||
return &undelfs_vfs_ops;
|
return &undelfs_vfs_ops;
|
||||||
#endif
|
#endif
|
||||||
|
if (!(vfs_flags & FL_NO_FISH) && !strncmp (path, "sh:", 3))
|
||||||
|
return &fish_vfs_ops;
|
||||||
if (!(vfs_flags & FL_NO_TARFS) && !strcmp (path, "utar"))
|
if (!(vfs_flags & FL_NO_TARFS) && !strcmp (path, "utar"))
|
||||||
return &tarfs_vfs_ops;
|
return &tarfs_vfs_ops;
|
||||||
if (!(vfs_flags & FL_NO_EXTFS) && extfs_which (path) != -1)
|
if (!(vfs_flags & FL_NO_EXTFS) && extfs_which (path) != -1)
|
||||||
@ -122,12 +127,12 @@ vfs *vfs_type_from_op (char *path)
|
|||||||
|
|
||||||
int path_magic( char *path )
|
int path_magic( char *path )
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
res = !strncmp( path, "/#/", 3 );
|
res = !strncmp( path, "/#/", 3 );
|
||||||
if (res)
|
if (res)
|
||||||
path[1] = '/';
|
path[1] = '/';
|
||||||
return res || (vfs_flags & FL_ALWAYS_MAGIC);
|
return res || (vfs_flags & FL_ALWAYS_MAGIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -742,7 +747,7 @@ void vfs_add_noncurrent_stamps (vfs * oldvfs, vfsid oldvfsid, struct vfs_stampin
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((*oldvfs->nothingisopen) (oldvfsid)){
|
if ((*oldvfs->nothingisopen) (oldvfsid)){
|
||||||
if (oldvfs == &extfs_vfs_ops && ((struct extfs_archive *) oldvfsid)->name == 0){
|
if (oldvfs == &extfs_vfs_ops && ((extfs_archive *) oldvfsid)->name == 0){
|
||||||
/* Free the resources immediatly when we leave a mtools fs
|
/* Free the resources immediatly when we leave a mtools fs
|
||||||
('cd a:') instead of waiting for the vfs-timeout */
|
('cd a:') instead of waiting for the vfs-timeout */
|
||||||
(oldvfs->free) (oldvfsid);
|
(oldvfs->free) (oldvfsid);
|
||||||
@ -755,7 +760,7 @@ void vfs_add_noncurrent_stamps (vfs * oldvfs, vfsid oldvfsid, struct vfs_stampin
|
|||||||
stamp->id == (vfsid) - 1 ||
|
stamp->id == (vfsid) - 1 ||
|
||||||
!(*stamp->v->nothingisopen) (stamp->id))
|
!(*stamp->v->nothingisopen) (stamp->id))
|
||||||
break;
|
break;
|
||||||
if (stamp->v == &extfs_vfs_ops && ((struct extfs_archive *) stamp->id)->name == 0){
|
if (stamp->v == &extfs_vfs_ops && ((extfs_archive *) stamp->id)->name == 0){
|
||||||
(stamp->v->free) (stamp->id);
|
(stamp->v->free) (stamp->id);
|
||||||
vfs_rmstamp (stamp->v, stamp->id, 0);
|
vfs_rmstamp (stamp->v, stamp->id, 0);
|
||||||
} else
|
} else
|
||||||
@ -888,7 +893,8 @@ char *vfs_get_current_dir (void)
|
|||||||
void vfs_setup_wd (void)
|
void vfs_setup_wd (void)
|
||||||
{
|
{
|
||||||
current_dir = strdup ("/");
|
current_dir = strdup ("/");
|
||||||
mc_return_cwd(); /* mc_return_cwd will fixup current_dir for us */
|
if (!(vfs_flags & FL_NO_CWDSETUP))
|
||||||
|
mc_return_cwd();
|
||||||
|
|
||||||
if (strlen(current_dir)>MC_MAXPATHLEN-2)
|
if (strlen(current_dir)>MC_MAXPATHLEN-2)
|
||||||
vfs_die ("Current dir too long.\n");
|
vfs_die ("Current dir too long.\n");
|
||||||
@ -1084,6 +1090,7 @@ void vfs_init (void)
|
|||||||
tcp_init();
|
tcp_init();
|
||||||
ftpfs_init();
|
ftpfs_init();
|
||||||
#endif
|
#endif
|
||||||
|
fish_init ();
|
||||||
extfs_init ();
|
extfs_init ();
|
||||||
sfs_init ();
|
sfs_init ();
|
||||||
vfs_setup_wd ();
|
vfs_setup_wd ();
|
||||||
@ -1134,11 +1141,11 @@ void vfs_shut (void)
|
|||||||
free (current_dir);
|
free (current_dir);
|
||||||
|
|
||||||
extfs_done ();
|
extfs_done ();
|
||||||
|
sfs_done();
|
||||||
#ifdef USE_NETCODE
|
#ifdef USE_NETCODE
|
||||||
|
fish_done();
|
||||||
ftpfs_done();
|
ftpfs_done();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* These ones grab information from the VFS
|
/* These ones grab information from the VFS
|
||||||
@ -1149,6 +1156,7 @@ void vfs_fill_names (void (*func)(char *))
|
|||||||
#ifdef USE_NETCODE
|
#ifdef USE_NETCODE
|
||||||
mcfs_fill_names (func);
|
mcfs_fill_names (func);
|
||||||
ftpfs_fill_names (func);
|
ftpfs_fill_names (func);
|
||||||
|
fish_fill_names (func);
|
||||||
#endif
|
#endif
|
||||||
tarfs_fill_names (func);
|
tarfs_fill_names (func);
|
||||||
extfs_fill_names (func);
|
extfs_fill_names (func);
|
||||||
@ -1161,7 +1169,7 @@ void vfs_fill_names (void (*func)(char *))
|
|||||||
static char *columns [MAXCOLS]; /* Points to the string in column n */
|
static char *columns [MAXCOLS]; /* Points to the string in column n */
|
||||||
static int column_ptr [MAXCOLS]; /* Index from 0 to the starting positions of the columns */
|
static int column_ptr [MAXCOLS]; /* Index from 0 to the starting positions of the columns */
|
||||||
|
|
||||||
static int split_text (char *p)
|
int split_text (char *p)
|
||||||
{
|
{
|
||||||
char *original = p;
|
char *original = p;
|
||||||
int numcols;
|
int numcols;
|
||||||
@ -1182,7 +1190,7 @@ static int split_text (char *p)
|
|||||||
|
|
||||||
static int is_num (int idx)
|
static int is_num (int idx)
|
||||||
{
|
{
|
||||||
if (columns [idx][0] < '0' || columns [idx][0] > '9')
|
if (!columns [idx] || columns [idx][0] < '0' || columns [idx][0] > '9')
|
||||||
return 0;
|
return 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -1230,37 +1238,173 @@ static int is_year(char *str, struct tm *tim)
|
|||||||
where "2904 1234" is filename. Well, this code decodes it as year :-(.
|
where "2904 1234" is filename. Well, this code decodes it as year :-(.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
int parse_filetype (char c)
|
||||||
|
{
|
||||||
|
switch (c){
|
||||||
|
case 'd': return S_IFDIR;
|
||||||
|
case 'b': return S_IFBLK;
|
||||||
|
case 'c': return S_IFCHR;
|
||||||
|
case 'l': return S_IFLNK;
|
||||||
|
case 's':
|
||||||
|
#ifdef IS_IFSOCK /* And if not, we fall through to IFIFO, which is pretty close */
|
||||||
|
return S_IFSOCK;
|
||||||
|
#endif
|
||||||
|
case 'p': return S_IFIFO;
|
||||||
|
case 'm': case 'n': /* Don't know what these are :-) */
|
||||||
|
case '-': case '?': return S_IFREG;
|
||||||
|
default: return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int parse_filemode (char *p)
|
||||||
|
{ /* converts rw-rw-rw- into 0666 */
|
||||||
|
int res = 0;
|
||||||
|
switch (*(p++)){
|
||||||
|
case 'r': res |= 0400; break;
|
||||||
|
case '-': break;
|
||||||
|
default: return -1;
|
||||||
|
}
|
||||||
|
switch (*(p++)){
|
||||||
|
case 'w': res |= 0200; break;
|
||||||
|
case '-': break;
|
||||||
|
default: return -1;
|
||||||
|
}
|
||||||
|
switch (*(p++)){
|
||||||
|
case 'x': res |= 0100; break;
|
||||||
|
case 's': res |= 0100 | S_ISUID; break;
|
||||||
|
case 'S': res |= S_ISUID; break;
|
||||||
|
case '-': break;
|
||||||
|
default: return -1;
|
||||||
|
}
|
||||||
|
switch (*(p++)){
|
||||||
|
case 'r': res |= 0040; break;
|
||||||
|
case '-': break;
|
||||||
|
default: return -1;
|
||||||
|
}
|
||||||
|
switch (*(p++)){
|
||||||
|
case 'w': res |= 0020; break;
|
||||||
|
case '-': break;
|
||||||
|
default: return -1;
|
||||||
|
}
|
||||||
|
switch (*(p++)){
|
||||||
|
case 'x': res |= 0010; break;
|
||||||
|
case 's': res |= 0010 | S_ISGID; break;
|
||||||
|
case 'S': res |= S_ISGID; break;
|
||||||
|
case '-': break;
|
||||||
|
default: return -1;
|
||||||
|
}
|
||||||
|
switch (*(p++)){
|
||||||
|
case 'r': res |= 0004; break;
|
||||||
|
case '-': break;
|
||||||
|
default: return -1;
|
||||||
|
}
|
||||||
|
switch (*(p++)){
|
||||||
|
case 'w': res |= 0002; break;
|
||||||
|
case '-': break;
|
||||||
|
default: return -1;
|
||||||
|
}
|
||||||
|
switch (*(p++)){
|
||||||
|
case 'x': res |= 0001; break;
|
||||||
|
case 't': res |= 0001 | S_ISVTX; break;
|
||||||
|
case 'T': res |= S_ISVTX; break;
|
||||||
|
case '-': break;
|
||||||
|
default: return -1;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int parse_filedate(int idx, time_t *t)
|
||||||
|
{ /* This thing parses from idx in columns[] array */
|
||||||
|
static char *month = "JanFebMarAprMayJunJulAugSepOctNovDec";
|
||||||
|
static char *week = "SunMonTueWedThuFriSat";
|
||||||
|
char *p, *pos;
|
||||||
|
int extfs_format_date = 0;
|
||||||
|
struct tm tim;
|
||||||
|
|
||||||
|
/* Let's setup default time values */
|
||||||
|
tim.tm_year = current_year;
|
||||||
|
tim.tm_mon = current_mon;
|
||||||
|
tim.tm_mday = current_mday;
|
||||||
|
tim.tm_hour = 0;
|
||||||
|
tim.tm_min = 0;
|
||||||
|
tim.tm_sec = 0;
|
||||||
|
tim.tm_isdst = 0;
|
||||||
|
|
||||||
|
p = columns [idx++];
|
||||||
|
|
||||||
|
if((pos=strstr(week, p)) != NULL){
|
||||||
|
tim.tm_wday = (pos - week)/3;
|
||||||
|
p = columns [idx++];
|
||||||
|
}
|
||||||
|
|
||||||
|
if((pos=strstr(month, p)) != NULL)
|
||||||
|
tim.tm_mon = (pos - month)/3;
|
||||||
|
else {
|
||||||
|
/* This case should not normaly happen, but in extfs we allow these
|
||||||
|
date formats:
|
||||||
|
Mon DD hh:mm
|
||||||
|
Mon DD YYYY
|
||||||
|
Mon DD YYYY hh:mm
|
||||||
|
Wek Mon DD hh:mm:ss YYYY
|
||||||
|
MM-DD-YY hh:mm
|
||||||
|
where Mon is Jan-Dec, DD, MM, YY two digit day, month, year,
|
||||||
|
YYYY four digit year, hh, mm two digit hour and minute. */
|
||||||
|
|
||||||
|
if (strlen (p) == 8 && p [2] == '-' && p [5] == '-'){
|
||||||
|
p [2] = 0;
|
||||||
|
p [5] = 0;
|
||||||
|
tim.tm_mon = (int) atol (p);
|
||||||
|
if (!tim.tm_mon)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
tim.tm_mon--;
|
||||||
|
tim.tm_mday = (int) atol (p + 3);
|
||||||
|
tim.tm_year = (int) atol (p + 6);
|
||||||
|
if (tim.tm_year < 70)
|
||||||
|
tim.tm_year += 70;
|
||||||
|
extfs_format_date = 1;
|
||||||
|
} else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!extfs_format_date){
|
||||||
|
if (!is_num (idx))
|
||||||
|
return 0;
|
||||||
|
tim.tm_mday = (int)atol (columns [idx++]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_num (idx)) {
|
||||||
|
if(is_time(columns[idx], &tim) || is_year(columns[idx], &tim)) {
|
||||||
|
idx++;
|
||||||
|
|
||||||
|
if(is_num (idx) &&
|
||||||
|
(is_year(columns[idx], &tim) || is_time(columns[idx], &tim)))
|
||||||
|
idx++; /* time & year or reverse */
|
||||||
|
} /* only time or date */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0; /* Nor time or date */
|
||||||
|
|
||||||
|
if ((*t = mktime(&tim)) ==-1)
|
||||||
|
*t = 0;
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
#define free_and_return(x) { free (p_copy); return (x); }
|
#define free_and_return(x) { free (p_copy); return (x); }
|
||||||
int parse_ls_lga (char *p, struct stat *s, char **filename, char **linkname)
|
int parse_ls_lga (char *p, struct stat *s, char **filename, char **linkname)
|
||||||
{
|
{
|
||||||
static char *month = "JanFebMarAprMayJunJulAugSepOctNovDec";
|
|
||||||
static char *week = "SunMonTueWedThuFriSat";
|
|
||||||
char *pos;
|
|
||||||
int idx, idx2, num_cols, isconc = 0;
|
int idx, idx2, num_cols, isconc = 0;
|
||||||
int i;
|
int i;
|
||||||
struct tm tim;
|
|
||||||
int extfs_format_date = 0;
|
|
||||||
char *p_copy;
|
char *p_copy;
|
||||||
|
|
||||||
s->st_mode = 0;
|
if (strncmp (p, "total", 5) == 0)
|
||||||
if (strncmp (p, "total", 5) == 0){
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
switch (*(p++)){
|
if ((i = parse_filetype(*(p++))) == -1)
|
||||||
case 'd': s->st_mode |= S_IFDIR; break;
|
return 0;
|
||||||
case 'b': s->st_mode |= S_IFBLK; break;
|
|
||||||
case 'c': s->st_mode |= S_IFCHR; break;
|
s->st_mode = i;
|
||||||
case 'm': s->st_mode |= S_IFREG; break; /* Don't know what it is :-) */
|
|
||||||
case 'n': s->st_mode |= S_IFREG; break; /* and this as well */
|
|
||||||
case 'l': s->st_mode |= S_IFLNK; break;
|
|
||||||
#ifdef IS_IFSOCK
|
|
||||||
case 's': s->st_mode |= S_IFSOCK; break;
|
|
||||||
#endif
|
|
||||||
case 'p': s->st_mode |= S_IFIFO; break;
|
|
||||||
case '-': s->st_mode |= S_IFREG; break;
|
|
||||||
case '?': s->st_mode |= S_IFREG; break;
|
|
||||||
default: return 0;
|
|
||||||
}
|
|
||||||
if (*p == '['){
|
if (*p == '['){
|
||||||
if (strlen (p) <= 8 || p [8] != ']')
|
if (strlen (p) <= 8 || p [8] != ']')
|
||||||
return 0;
|
return 0;
|
||||||
@ -1271,57 +1415,10 @@ int parse_ls_lga (char *p, struct stat *s, char **filename, char **linkname)
|
|||||||
s->st_mode |= (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR);
|
s->st_mode |= (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR);
|
||||||
p += 9;
|
p += 9;
|
||||||
} else {
|
} else {
|
||||||
switch (*(p++)){
|
if ((i = parse_filemode(p)) ==-1)
|
||||||
case 'r': s->st_mode |= 0400; break;
|
return 0;
|
||||||
case '-': break;
|
s->st_mode |= i;
|
||||||
default: return 0;
|
p += 9;
|
||||||
}
|
|
||||||
switch (*(p++)){
|
|
||||||
case 'w': s->st_mode |= 0200; break;
|
|
||||||
case '-': break;
|
|
||||||
default: return 0;
|
|
||||||
}
|
|
||||||
switch (*(p++)){
|
|
||||||
case 'x': s->st_mode |= 0100; break;
|
|
||||||
case 's': s->st_mode |= 0100 | S_ISUID; break;
|
|
||||||
case 'S': s->st_mode |= S_ISUID; break;
|
|
||||||
case '-': break;
|
|
||||||
default: return 0;
|
|
||||||
}
|
|
||||||
switch (*(p++)){
|
|
||||||
case 'r': s->st_mode |= 0040; break;
|
|
||||||
case '-': break;
|
|
||||||
default: return 0;
|
|
||||||
}
|
|
||||||
switch (*(p++)){
|
|
||||||
case 'w': s->st_mode |= 0020; break;
|
|
||||||
case '-': break;
|
|
||||||
default: return 0;
|
|
||||||
}
|
|
||||||
switch (*(p++)){
|
|
||||||
case 'x': s->st_mode |= 0010; break;
|
|
||||||
case 's': s->st_mode |= 0010 | S_ISGID; break;
|
|
||||||
case 'S': s->st_mode |= S_ISGID; break;
|
|
||||||
case '-': break;
|
|
||||||
default: return 0;
|
|
||||||
}
|
|
||||||
switch (*(p++)){
|
|
||||||
case 'r': s->st_mode |= 0004; break;
|
|
||||||
case '-': break;
|
|
||||||
default: return 0;
|
|
||||||
}
|
|
||||||
switch (*(p++)){
|
|
||||||
case 'w': s->st_mode |= 0002; break;
|
|
||||||
case '-': break;
|
|
||||||
default: return 0;
|
|
||||||
}
|
|
||||||
switch (*(p++)){
|
|
||||||
case 'x': s->st_mode |= 0001; break;
|
|
||||||
case 't': s->st_mode |= 0001 | S_ISVTX; break;
|
|
||||||
case 'T': s->st_mode |= S_ISVTX; break;
|
|
||||||
case '-': break;
|
|
||||||
default: return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p_copy = strdup (p);
|
p_copy = strdup (p);
|
||||||
@ -1391,76 +1488,11 @@ int parse_ls_lga (char *p, struct stat *s, char **filename, char **linkname)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Let's setup default time values */
|
idx = parse_filedate(idx, &s->st_mtime);
|
||||||
tim.tm_year = current_year;
|
if (!idx)
|
||||||
tim.tm_mon = current_mon;
|
free_and_return (0);
|
||||||
tim.tm_mday = current_mday;
|
/* Use resulting time value */
|
||||||
tim.tm_hour = 0;
|
s->st_atime = s->st_ctime = s->st_mtime;
|
||||||
tim.tm_min = 0;
|
|
||||||
tim.tm_sec = 0;
|
|
||||||
tim.tm_isdst = 0;
|
|
||||||
|
|
||||||
p = columns [idx++];
|
|
||||||
|
|
||||||
if((pos=strstr(week, p)) != NULL){
|
|
||||||
tim.tm_wday = (pos - week)/3;
|
|
||||||
p = columns [idx++];
|
|
||||||
}
|
|
||||||
|
|
||||||
if((pos=strstr(month, p)) != NULL)
|
|
||||||
tim.tm_mon = (pos - month)/3;
|
|
||||||
else {
|
|
||||||
/* This case should not normaly happen, but in extfs we allow these
|
|
||||||
date formats:
|
|
||||||
Mon DD hh:mm
|
|
||||||
Mon DD YYYY
|
|
||||||
Mon DD YYYY hh:mm
|
|
||||||
Wek Mon DD hh:mm:ss YYYY
|
|
||||||
MM-DD-YY hh:mm
|
|
||||||
where Mon is Jan-Dec, DD, MM, YY two digit day, month, year,
|
|
||||||
YYYY four digit year, hh, mm two digit hour and minute. */
|
|
||||||
|
|
||||||
if (strlen (p) == 8 && p [2] == '-' && p [5] == '-'){
|
|
||||||
p [2] = 0;
|
|
||||||
p [5] = 0;
|
|
||||||
tim.tm_mon = (int) atol (p);
|
|
||||||
if (!tim.tm_mon)
|
|
||||||
free_and_return (0)
|
|
||||||
else
|
|
||||||
tim.tm_mon--;
|
|
||||||
tim.tm_mday = (int) atol (p + 3);
|
|
||||||
tim.tm_year = (int) atol (p + 6);
|
|
||||||
if (tim.tm_year < 70)
|
|
||||||
tim.tm_year += 70;
|
|
||||||
extfs_format_date = 1;
|
|
||||||
} else
|
|
||||||
free_and_return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!extfs_format_date){
|
|
||||||
if (!is_num (idx))
|
|
||||||
free_and_return (0);
|
|
||||||
tim.tm_mday = (int)atol (columns [idx++]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_num (idx)) {
|
|
||||||
if(is_time(columns[idx], &tim) || is_year(columns[idx], &tim)) {
|
|
||||||
idx++;
|
|
||||||
|
|
||||||
if(is_num (idx) &&
|
|
||||||
(is_year(columns[idx], &tim) || is_time(columns[idx], &tim)))
|
|
||||||
idx++; /* time & year or reverse */
|
|
||||||
} /* only time or date */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
free_and_return (0); /* Nor time or date */
|
|
||||||
|
|
||||||
/* Use resultimg time value */
|
|
||||||
s->st_mtime = mktime (&tim);
|
|
||||||
if (s->st_mtime == -1)
|
|
||||||
s->st_mtime = 0;
|
|
||||||
s->st_atime = s->st_mtime;
|
|
||||||
s->st_ctime = s->st_mtime;
|
|
||||||
s->st_dev = 0;
|
s->st_dev = 0;
|
||||||
s->st_ino = 0;
|
s->st_ino = 0;
|
||||||
#ifdef HAVE_ST_BLKSIZE
|
#ifdef HAVE_ST_BLKSIZE
|
||||||
|
15
vfs/vfs.h
15
vfs/vfs.h
@ -6,9 +6,9 @@
|
|||||||
#else
|
#else
|
||||||
#define BROKEN_PATHS
|
#define BROKEN_PATHS
|
||||||
/*
|
/*
|
||||||
* We should really only allow /:ftp/ tree to export ftp, but midnight's users may
|
* We should really only allow /#ftp/ tree to export ftp, but midnight's users may
|
||||||
* like to be able to cd .. to get back where there were before ftp. How to solve?
|
* like to be able to cd .. to get back where there were before ftp. How to solve?
|
||||||
* Ok, we'll allow /any/path/:ftp/ to access ftp tree. Broken, yes.
|
* Ok, we'll allow /any/path/#ftp/ to access ftp tree. Broken, yes.
|
||||||
*/
|
*/
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -90,6 +90,7 @@ struct utimbuf {
|
|||||||
extern vfs tarfs_vfs_ops;
|
extern vfs tarfs_vfs_ops;
|
||||||
|
|
||||||
extern vfs ftpfs_vfs_ops;
|
extern vfs ftpfs_vfs_ops;
|
||||||
|
extern vfs fish_vfs_ops;
|
||||||
extern vfs mcfs_vfs_ops;
|
extern vfs mcfs_vfs_ops;
|
||||||
|
|
||||||
extern vfs extfs_vfs_ops;
|
extern vfs extfs_vfs_ops;
|
||||||
@ -316,8 +317,6 @@ extern int vfs_flags;
|
|||||||
extern uid_t vfs_uid;
|
extern uid_t vfs_uid;
|
||||||
extern gid_t vfs_gid;
|
extern gid_t vfs_gid;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define FL_ALWAYS_MAGIC 1
|
#define FL_ALWAYS_MAGIC 1
|
||||||
#define FL_NO_MCFS 2
|
#define FL_NO_MCFS 2
|
||||||
#define FL_NO_FTPFS 4
|
#define FL_NO_FTPFS 4
|
||||||
@ -325,6 +324,14 @@ extern gid_t vfs_gid;
|
|||||||
#define FL_NO_TARFS 16
|
#define FL_NO_TARFS 16
|
||||||
#define FL_NO_EXTFS 32
|
#define FL_NO_EXTFS 32
|
||||||
#define FL_NO_SFS 64
|
#define FL_NO_SFS 64
|
||||||
|
#define FL_NO_FISH 128
|
||||||
|
|
||||||
|
#define FL_NO_CWDSETUP 0x40000000
|
||||||
|
|
||||||
|
#ifdef VFS_STANDALONE
|
||||||
|
extern void mc_vfs_init( void );
|
||||||
|
extern void mc_vfs_done( void );
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* __VFS_H */
|
#endif /* __VFS_H */
|
||||||
|
|
||||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user