1
1

Adding fish, cleanups, and small updates everywhere to support fish.

Этот коммит содержится в:
Pavel Machek 1998-09-13 10:40:43 +00:00
родитель 6af6c687c5
Коммит f45e5aa3fc
18 изменённых файлов: 2868 добавлений и 1582 удалений

Просмотреть файл

@ -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>
* ftpfs.c: cleanup of code, few static's added

Просмотреть файл

@ -18,10 +18,10 @@ AR = @AR@
# VFS code
#
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 \
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 \
extfs.h
@ -40,7 +40,7 @@ EXTFSSTUFF = $(EXTFS_MISC) $(EXTFS_CONST) $(EXTFS_IN)
# 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
$(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
$(CC) -c $(CPPFLAGS) $(DEFS) $(CFLAGS) -DVFS_STANDALONE $< -o $@
libvfs.so: $(VFSSOOBJS) libvfs.o
gcc $(VFSSOOBJS) libvfs.o -shared -o libvfs.so
libvfs.so: $(VFSSOOBJS)
gcc $(VFSSOOBJS) -shared -o libvfs.so
#
@ -96,7 +96,7 @@ TAGS: $(VFSSRCS)
etags $(VFSSRCS)
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
$(RMF) .depend

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

Просмотреть файл

@ -46,11 +46,11 @@
#include "vfs.h"
#include "extfs.h"
static struct extfs_entry *
extfs_find_entry (struct extfs_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 struct extfs_archive *first_archive = NULL;
static int extfserrno = 0;
static struct archive *first_archive = NULL;
static int my_errno = 0;
static struct stat hstat; /* Stat struct corresponding */
static char *current_file_name, *current_link_name;
static char *extfs_current_dir;
@ -62,7 +62,7 @@ static int extfs_no = 0;
void extfs_fill_names (void (*func)(char *))
{
struct extfs_archive *a = first_archive;
struct archive *a = first_archive;
char *name;
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 *)
xmalloc (sizeof (struct extfs_entry), "Extfs: extfs_entry");
struct extfs_entry *parentry = ent->dir;
struct extfs_inode *inode = ent->inode, *parent;
struct entry *entry = (struct entry *)
xmalloc (sizeof (struct entry), "Extfs: entry");
struct entry *parentry = ent->dir;
struct inode *inode = ent->inode, *parent;
parent = (parentry != NULL) ? parentry->inode : NULL;
entry->name = strdup (".");
@ -91,8 +91,8 @@ static void make_dot_doubledot (struct extfs_entry *ent)
inode->first_in_subdir = entry;
inode->last_in_subdir = entry;
inode->nlink++;
entry->next_in_dir = (struct extfs_entry *)
xmalloc (sizeof (struct extfs_entry), "Extfs: extfs_entry");
entry->next_in_dir = (struct entry *)
xmalloc (sizeof (struct entry), "Extfs: entry");
entry=entry->next_in_dir;
entry->name = strdup ("..");
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,
char *name, struct extfs_entry *parentry, mode_t mode)
static struct entry *generate_entry (struct archive *archive,
char *name, struct entry *parentry, mode_t mode)
{
mode_t myumask;
struct extfs_inode *inode, *parent;
struct extfs_entry *entry;
struct inode *inode, *parent;
struct entry *entry;
parent = (parentry != NULL) ? parentry->inode : NULL;
entry = (struct extfs_entry *)
xmalloc (sizeof (struct extfs_entry), "Extfs: extfs_entry");
entry = (struct entry *)
xmalloc (sizeof (struct entry), "Extfs: entry");
entry->name = strdup (name);
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 = entry;
}
inode = (struct extfs_inode *)
xmalloc (sizeof (struct extfs_inode), "Extfs: extfs_inode");
inode = (struct inode *)
xmalloc (sizeof (struct inode), "Extfs: inode");
entry->inode = inode;
inode->has_changed = 0;
inode->local_filename = NULL;
@ -154,12 +154,12 @@ static struct extfs_entry *generate_entry (struct extfs_archive *archive,
return entry;
}
static void free_entries (struct extfs_entry *entry)
static void free_entries (struct entry *entry)
{
return;
}
static void free_archive (struct extfs_archive *archive)
static void free_archive (struct archive *archive)
{
free_entries (archive->root_entry);
if (archive->local_name != NULL) {
@ -175,7 +175,7 @@ static void free_archive (struct extfs_archive *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;
FILE *result;
@ -183,8 +183,8 @@ static FILE *open_extfs_archive (int fstype, char *name, struct extfs_archive **
char *cmd;
char *mc_extfsdir;
struct stat mystat;
struct extfs_archive *current_archive;
struct extfs_entry *root_entry;
struct archive *current_archive;
struct entry *root_entry;
char *local_name = NULL, *tmp = 0;
int uses_archive = extfs_need_archive [fstype];
char *tmpfile;
@ -221,8 +221,8 @@ static FILE *open_extfs_archive (int fstype, char *name, struct extfs_archive **
return NULL;
}
current_archive = (struct extfs_archive *)
xmalloc (sizeof (struct extfs_archive), "Extfs archive");
current_archive = (struct archive *)
xmalloc (sizeof (struct archive), "Extfs archive");
current_archive->fstype = fstype;
current_archive->name = name ? strdup (name): 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.
* 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;
char *buffer;
struct extfs_archive *current_archive;
struct archive *current_archive;
if ((extfsd = open_extfs_archive (fstype, name, &current_archive)) == NULL) {
if ((extfsd = open_archive (fstype, name, &current_archive)) == NULL) {
message_3s (1, MSG_ERROR, _("Couldn't open %s archive\n%s"),
extfs_prefixes [fstype], name);
return -1;
@ -277,8 +277,8 @@ int read_extfs_archive (int fstype, char *name, struct extfs_archive **pparc)
while (fgets (buffer, 4096, extfsd) != NULL) {
current_link_name = NULL;
if (parse_ls_lga (buffer, &hstat, &current_file_name, &current_link_name)) {
struct extfs_entry *entry, *pent;
struct extfs_inode *inode;
struct entry *entry, *pent;
struct inode *inode;
char *p, *q, *cfn = current_file_name;
if (*cfn) {
@ -298,7 +298,7 @@ int read_extfs_archive (int fstype, char *name, struct extfs_archive **pparc)
if (S_ISDIR (hstat.st_mode) &&
(!strcmp (p, ".") || !strcmp (p, "..")))
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) {
message_1s (1, MSG_ERROR, _("Inconsistent extfs archive"));
/* FIXME: Should clean everything one day */
@ -306,7 +306,7 @@ int read_extfs_archive (int fstype, char *name, struct extfs_archive **pparc)
pclose (extfsd);
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->has_changed = 0;
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) {
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) {
message_1s (1, MSG_ERROR, _("Inconsistent extfs archive"));
/* 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++;
}
} 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;
inode->local_filename = NULL;
inode->has_changed = 0;
@ -377,18 +377,18 @@ int read_extfs_archive (int fstype, char *name, struct extfs_archive **pparc)
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);
/* Returns path inside argument. Returned char* is inside inname, which is mangled
* 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)
{
char *local, *archive_name, *op;
int result = -1;
struct extfs_archive *parc;
struct archive *parc;
struct vfs_stamping *parent;
vfs *v;
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) {
extfserrno = EIO;
my_errno = EIO;
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 */
static char *extfs_get_path_from_entry (struct extfs_entry *entry)
static char *get_path_from_entry (struct entry *entry)
{
struct list {
struct list *next;
@ -480,23 +480,23 @@ static char *extfs_get_path_from_entry (struct extfs_entry *entry)
}
struct extfs_loop_protect {
struct extfs_entry *entry;
struct extfs_loop_protect *next;
struct loop_protect {
struct entry *entry;
struct loop_protect *next;
};
static int errloop;
static int notadir;
static struct extfs_entry *
__extfs_find_entry (struct extfs_entry *dir, char *name,
struct extfs_loop_protect *list, int make_dirs, int make_file);
static struct entry *
__find_entry (struct entry *dir, char *name,
struct loop_protect *list, int make_dirs, int make_file);
static struct extfs_entry *
__extfs_resolve_symlinks (struct extfs_entry *entry,
struct extfs_loop_protect *list)
static struct entry *
__resolve_symlinks (struct entry *entry,
struct loop_protect *list)
{
struct extfs_entry *pent;
struct extfs_loop_protect *looping;
struct entry *pent;
struct loop_protect *looping;
if (!S_ISLNK (entry->inode->mode))
return entry;
@ -505,42 +505,42 @@ __extfs_resolve_symlinks (struct extfs_entry *entry,
errloop = 1;
return NULL;
}
looping = (struct extfs_loop_protect *)
xmalloc (sizeof (struct extfs_loop_protect),
looping = (struct loop_protect *)
xmalloc (sizeof (struct loop_protect),
"Extfs: symlink looping protection");
looping->entry = entry;
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);
if (pent == NULL)
extfserrno = ENOENT;
my_errno = ENOENT;
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;
notadir = 0;
res = __extfs_resolve_symlinks (entry, NULL);
res = __resolve_symlinks (entry, NULL);
if (res == NULL) {
if (errloop)
extfserrno = ELOOP;
my_errno = ELOOP;
else if (notadir)
extfserrno = ENOTDIR;
my_errno = ENOTDIR;
}
return res;
}
struct extfs_pseudofile {
struct extfs_archive *archive;
struct pseudofile {
struct archive *archive;
unsigned int has_changed:1;
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;
@ -557,10 +557,10 @@ static char *get_archive_name (struct extfs_archive *archive)
void extfs_run (char *file)
{
struct extfs_archive *archive;
struct archive *archive;
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;
q = name_quote (p, 0);
@ -582,30 +582,30 @@ void extfs_run (char *file)
static void *extfs_open (char *file, int flags, int mode)
{
struct extfs_pseudofile *extfs_info;
struct extfs_archive *archive;
struct pseudofile *extfs_info;
struct archive *archive;
char *q;
char *mc_extfsdir;
struct extfs_entry *entry;
struct entry *entry;
int local_handle;
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;
entry = extfs_find_entry (archive->root_entry, q, 0, do_create);
entry = find_entry (archive->root_entry, q, 0, do_create);
if (entry == NULL)
return NULL;
if ((entry = extfs_resolve_symlinks (entry)) == NULL)
if ((entry = my_resolve_symlinks (entry)) == NULL)
return NULL;
if (S_ISDIR (entry->inode->mode)) {
extfserrno = EISDIR;
my_errno = EISDIR;
return NULL;
}
if (entry->inode->local_filename == NULL) {
char *cmd, *archive_name, *p;
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);
free (p);
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;
free (cmd);
free (mc_extfsdir);
extfserrno = EIO;
my_errno = EIO;
return NULL;
}
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);
if (local_handle == -1) {
extfserrno = EIO;
my_errno = EIO;
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->entry = entry;
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)
{
struct extfs_pseudofile *file = (struct extfs_pseudofile *)data;
struct pseudofile *file = (struct pseudofile *)data;
return read (file->local_handle, buffer, count);
}
static int extfs_close (void *data)
{
struct extfs_pseudofile *file;
struct pseudofile *file;
int errno_code = 0;
file = (struct extfs_pseudofile *)data;
file = (struct pseudofile *)data;
close (file->local_handle);
/* Commit the file if it has changed */
if (file->has_changed){
struct extfs_archive *archive;
struct archive *archive;
char *archive_name, *file_name;
char *cmd;
char *mc_extfsdir;
@ -673,7 +673,7 @@ static int extfs_close (void *data)
archive = file->archive;
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);
free (p);
@ -718,28 +718,14 @@ static int extfs_close (void *data)
free (data);
if (errno_code){
extfserrno = EIO; /* Non standard, but who cares? */
my_errno = EIO; /* Non standard, but who cares? */
return -1;
} else
return 0;
}
#define RECORDSIZE 512
#define X_pseudofile extfs_pseudofile
#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"
#include "shared_tar_ext.c"
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)
{
struct extfs_pseudofile *file = (struct extfs_pseudofile *)data;
struct pseudofile *file = (struct pseudofile *)data;
file->has_changed = 1;
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)
{
struct extfs_archive *archive;
struct archive *archive;
char *q, *res;
struct extfs_entry *entry;
struct entry *entry;
extfserrno = ENOTDIR;
if ((q = extfs_get_path_mangle (path, &archive, 1, 0)) == NULL)
my_errno = ENOTDIR;
if ((q = get_path_mangle (path, &archive, 1, 0)) == NULL)
return -1;
entry = extfs_find_entry (archive->root_entry, q, 0, 0);
entry = find_entry (archive->root_entry, q, 0, 0);
if (!entry)
return -1;
entry = extfs_resolve_symlinks (entry);
entry = my_resolve_symlinks (entry);
if ((!entry) || (!S_ISDIR (entry->inode->mode)))
return -1;
entry->inode->archive->current_dir = entry;
res = copy_strings (
entry->inode->archive->name, "#", extfs_prefixes [entry->inode->archive->fstype],
"/", q, NULL);
extfserrno = 0;
my_errno = 0;
if (extfs_current_dir)
free (extfs_current_dir);
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)
{
struct extfs_pseudofile *file = (struct extfs_pseudofile *) data;
struct pseudofile *file = (struct pseudofile *) data;
return lseek (file->local_handle, offset, whence);
}
static vfsid extfs_getid (char *path, struct vfs_stamping **parent)
{
struct extfs_archive *archive;
struct archive *archive;
vfs *v;
vfsid id;
struct vfs_stamping *par;
char *p;
*parent = NULL;
if (!(p = extfs_get_path (path, &archive, 1, 1)))
if (!(p = get_path (path, &archive, 1, 1)))
return (vfsid) -1;
free(p);
if (archive->name){
@ -815,17 +801,17 @@ static vfsid extfs_getid (char *path, struct vfs_stamping **parent)
static int extfs_nothingisopen (vfsid id)
{
if (((struct extfs_archive *)id)->fd_usage <= 0)
if (((struct archive *)id)->fd_usage <= 0)
return 1;
else
return 0;
}
static void free_entry (struct extfs_entry *e)
static void free_entry (struct entry *e)
{
int i = --(e->inode->nlink);
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;
free_entry (f);
@ -847,8 +833,8 @@ static void free_entry (struct extfs_entry *e)
static void extfs_free (vfsid id)
{
struct extfs_archive *parc;
struct extfs_archive *archive = (struct extfs_archive *)id;
struct archive *parc;
struct archive *archive = (struct archive *)id;
free_entry (archive->root_entry);
if (archive == first_archive) {
@ -865,8 +851,8 @@ static void extfs_free (vfsid id)
static char *extfs_getlocalcopy (char *path)
{
struct extfs_pseudofile *fp =
(struct extfs_pseudofile *) extfs_open (path, O_RDONLY, 0);
struct pseudofile *fp =
(struct pseudofile *) extfs_open (path, O_RDONLY, 0);
char *p;
if (fp == NULL)
@ -883,8 +869,8 @@ static char *extfs_getlocalcopy (char *path)
static void extfs_ungetlocalcopy (char *path, char *local, int has_changed)
{
struct extfs_pseudofile *fp =
(struct extfs_pseudofile *) extfs_open (path, O_WRONLY, 0);
struct pseudofile *fp =
(struct pseudofile *) extfs_open (path, O_WRONLY, 0);
if (fp == NULL)
return;

Просмотреть файл

@ -20,26 +20,26 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <sys/types.h>
struct extfs_inode;
struct inode;
struct extfs_entry {
struct entry {
int has_changed;
struct extfs_entry *next_in_dir;
struct extfs_entry *dir;
struct entry *next_in_dir;
struct entry *dir;
char *name;
struct extfs_inode *inode;
struct inode *inode;
};
struct extfs_archive;
struct archive;
struct extfs_inode {
struct inode {
int has_changed;
nlink_t nlink;
struct extfs_entry *first_in_subdir; /* only used if this is a directory */
struct extfs_entry *last_in_subdir;
struct entry *first_in_subdir; /* only used if this is a directory */
struct entry *last_in_subdir;
ino_t inode; /* This is inode # */
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;
umode_t mode;
uid_t uid;
@ -53,7 +53,7 @@ struct extfs_inode {
char *local_filename;
};
struct extfs_archive {
struct archive {
int fstype;
char *name;
char *local_name;
@ -62,9 +62,9 @@ struct extfs_archive {
dev_t rdev;
int fd_usage;
ino_t __inode_counter;
struct extfs_entry *root_entry;
struct extfs_entry *current_dir;
struct extfs_archive *next;
struct entry *root_entry;
struct entry *current_dir;
struct archive *next;
};
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);
void extfs_run (char *path);
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
# Popular pc archivers, for arj usage you need special patch to unarj
# Popular pc archivers
uzip
uzoo
ulha
urar
# For arj usage you need special patch to unarj
uarj
# ar is used for static libraries

1025
vfs/fish.c Обычный файл

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -3,7 +3,7 @@
#if !defined(__FTPFS_H)
#define __FTPFS_H
struct ftpentry
struct direntry
{
char *name;
int count;
@ -16,10 +16,10 @@ struct ftpentry
char *remote_filename;
struct stat s;
struct stat *l_stat;
struct ftpfs_connection *bucket;
struct connection *bucket;
};
struct ftpfs_dir
struct dir
{
int count;
struct timeval timestamp;
@ -27,7 +27,7 @@ struct ftpfs_dir
struct linklist *file_list;
};
struct ftpfs_connection {
struct connection {
char *host;
char *user;
char *current_directory;
@ -63,9 +63,9 @@ struct ftpfs_connection {
/* Increased since now we may use C-r to reread the contents */
#define FTPFS_DIRECTORY_TIMEOUT 30 * 60
#define FTPFS_RESOLVE_SYMLINK 1
#define FTPFS_OPEN 2
#define FTPFS_FREE_RESOURCE 4
#define DO_RESOLVE_SYMLINK 1
#define DO_OPEN 2
#define DO_FREE_RESOURCE 4
extern char *ftpfs_anonymous_passwd;
extern char *ftpfs_proxy_host;

Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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
*/
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)
{
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;
if (res)
res2 = strdup(res);
@ -17,11 +17,11 @@ static char *X_get_path (char *inname, struct X_archive **archive, int is_dir,
return res2;
}
static struct X_entry*
__X_find_entry (struct X_entry *dir, char *name,
struct X_loop_protect *list, int make_dirs, int make_file)
static struct entry*
__find_entry (struct entry *dir, char *name,
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 c;
@ -46,7 +46,7 @@ __X_find_entry (struct X_entry *dir, char *name,
if (!strcmp (p, ".."))
pent = pent->dir;
else {
if ((pent = __X_resolve_symlinks (pent, list))==NULL){
if ((pent = __resolve_symlinks (pent, list))==NULL){
*q = c;
return NULL;
}
@ -87,22 +87,22 @@ __X_find_entry (struct X_entry *dir, char *name,
q = strchr (p, 0);
}
if (pent == NULL)
Xerrno = ENOENT;
my_errno = ENOENT;
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;
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 (errloop)
Xerrno = ELOOP;
my_errno = ELOOP;
else if (notadir)
Xerrno = ENOTDIR;
my_errno = ENOTDIR;
}
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)
{
return Xerrno;
return my_errno;
}
static void * s_opendir (char *dirname)
{
struct X_archive *archive;
struct archive *archive;
char *q;
struct X_entry *entry;
struct X_entry **info;
struct entry *entry;
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;
entry = X_find_entry (archive->root_entry, q, 0, 0);
entry = find_entry (archive->root_entry, q, 0, 0);
if (entry == NULL)
return NULL;
if ((entry = X_resolve_symlinks (entry)) == NULL)
if ((entry = my_resolve_symlinks (entry)) == NULL)
return NULL;
if (!S_ISDIR (entry->inode->mode)) {
Xerrno = ENOTDIR;
my_errno = ENOTDIR;
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[1] = entry->inode->first_in_subdir;
@ -148,7 +148,7 @@ static void * s_readdir (void *data)
#endif
} dir;
struct X_entry **info = (struct X_entry **) data;
struct entry **info = (struct entry **) data;
if (!*info)
return NULL;
@ -165,8 +165,8 @@ static void * s_readdir (void *data)
static int s_telldir (void *data)
{
struct X_entry **info = (struct X_entry **) data;
struct X_entry *cur;
struct entry **info = (struct entry **) data;
struct entry *cur;
int num = 0;
cur = info[1];
@ -180,7 +180,7 @@ static int s_telldir (void *data)
static void s_seekdir (void *data, int offset)
{
struct X_entry **info = (struct X_entry **) data;
struct entry **info = (struct entry **) data;
int i;
info[0] = info[1];
for (i=0; i<offset; i++)
@ -193,7 +193,7 @@ static int s_closedir (void *data)
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_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)
{
struct X_archive *archive;
struct archive *archive;
char *q;
struct X_entry *entry;
struct X_inode *inode;
struct entry *entry;
struct inode *inode;
char debugbuf[10240];
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;
entry = X_find_entry (archive->root_entry, q, 0, 0);
entry = find_entry (archive->root_entry, q, 0, 0);
if (entry == NULL)
return -1;
if (resolve && (entry = X_resolve_symlinks (entry)) == NULL)
if (resolve && (entry = my_resolve_symlinks (entry)) == NULL)
return -1;
inode = entry->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)
{
struct X_pseudofile *file = (struct X_pseudofile *)data;
struct X_inode *inode;
struct pseudofile *file = (struct pseudofile *)data;
struct inode *inode;
inode = file->entry->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)
{
struct X_archive *archive;
struct archive *archive;
char *q;
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;
entry = X_find_entry (archive->root_entry, q, 0, 0);
entry = find_entry (archive->root_entry, q, 0, 0);
if (entry == NULL)
return -1;
if (!S_ISLNK (entry->inode->mode)) {
Xerrno = EINVAL;
my_errno = EINVAL;
return -1;
}
if (size > (i = strlen (entry->inode->linkname))) {

291
vfs/tar.c
Просмотреть файл

@ -41,6 +41,7 @@
#include "../src/dialog.h" /* For MSG_ERROR */
#include "../src/mem.h"
#include "../src/mad.h"
#include "../src/main.h"
#include "vfs.h"
#include "tar.h"
#include "names.h"
@ -78,15 +79,15 @@ long from_oct (int digs, char *where)
return value;
}
static struct tarfs_archive *first_archive = NULL;
static int tarerrno = 0;
static struct archive *first_archive = NULL;
static int my_errno = 0;
static struct stat hstat; /* Stat struct corresponding */
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 *))
{
struct tarfs_archive *a = first_archive;
struct archive *a = first_archive;
char *name;
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 *)
xmalloc (sizeof (struct tarfs_entry), "Tar: tarfs_entry");
struct tarfs_entry *parentry = ent->dir;
struct tarfs_inode *inode = ent->inode, *parent;
struct entry *entry = (struct entry *)
xmalloc (sizeof (struct entry), "Tar: entry");
struct entry *parentry = ent->dir;
struct inode *inode = ent->inode, *parent;
parent = (parentry != NULL) ? parentry->inode : NULL;
entry->name = strdup (".");
@ -117,8 +118,8 @@ static void make_dot_doubledot (struct tarfs_entry *ent)
inode->first_in_subdir = entry;
inode->last_in_subdir = entry;
inode->nlink++;
entry->next_in_dir = (struct tarfs_entry *)
xmalloc (sizeof (struct tarfs_entry), "Tar: tarfs_entry");
entry->next_in_dir = (struct entry *)
xmalloc (sizeof (struct entry), "Tar: entry");
entry=entry->next_in_dir;
entry->name = strdup ("..");
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,
char *name, struct tarfs_entry *parentry, mode_t mode)
static struct entry *generate_entry (struct archive *archive,
char *name, struct entry *parentry, mode_t mode)
{
mode_t myumask;
struct tarfs_inode *inode, *parent;
struct tarfs_entry *entry;
struct inode *inode, *parent;
struct entry *entry;
parent = (parentry != NULL) ? parentry->inode : NULL;
entry = (struct tarfs_entry *)
xmalloc (sizeof (struct tarfs_entry), "Tar: tarfs_entry");
entry = (struct entry *)
xmalloc (sizeof (struct entry), "Tar: entry");
entry->name = strdup (name);
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 = entry;
}
inode = (struct tarfs_inode *)
xmalloc (sizeof (struct tarfs_inode), "Tar: tarfs_inode");
inode = (struct inode *)
xmalloc (sizeof (struct inode), "Tar: inode");
entry->inode = inode;
inode->local_filename = NULL;
inode->has_changed = 0;
@ -203,12 +204,12 @@ static struct tarfs_entry *generate_entry (struct tarfs_archive *archive,
return entry;
}
static void free_entries (struct tarfs_entry *entry)
static void free_entries (struct entry *entry)
{
return;
}
static void free_archive (struct tarfs_archive *archive)
static void free_archive (struct archive *archive)
{
long l;
@ -220,10 +221,8 @@ static void free_archive (struct tarfs_archive *archive)
free (archive->block_ptr);
}
} else {
if (archive->is_gzipped == tar_uncompressed_local) {
mc_unlink (archive->tmpname);
if (archive->tmpname)
free (archive->tmpname);
}
if (archive->fd != -1)
mc_close(archive->fd);
}
@ -246,7 +245,7 @@ static INLINE int gzip_limit_ok (int size)
*
* 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 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 */
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)
{
FILE *f;
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;
}
}
int result;
pclose (f);
#ifdef SCO_FLAVOR
waitpid(-1,NULL,WNOHANG);
#endif /* SCO_FLAVOR */
mc_close (fd);
/* From time we have sfs this function is pretty trivial */
current_archive->is_gzipped = tar_uncompressed_local;
current_archive->tmpname = copy_strings( current_archive->name, "#ugz", NULL );
result = mc_open (current_archive->tmpname, O_RDONLY);
if (result == -1){
if (result == -1)
free_archive (current_archive);
return -1;
}
return result;
}
/* 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;
int result, type;
long size;
mode_t mode;
struct tarfs_archive *current_archive;
static struct tarfs_entry *root_entry;
struct archive *current_archive;
static struct entry *root_entry;
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;
}
current_archive = (struct tarfs_archive *)
xmalloc (sizeof (struct tarfs_archive), "Tar archive");
current_archive = (struct archive *)
xmalloc (sizeof (struct archive), "Tar archive");
current_archive->current_tar_position = 0;
current_archive->name = strdup (name);
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->fd_usage = 0;
current_archive->fd = -1;
current_archive->tmpname = NULL;
size = is_gunzipable (result, &type);
mc_lseek (result, 0, SEEK_SET);
/* Find out the method to handle this tar file */
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;
}
result = 0;
} else if (size > 0) {
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;
}
} else {
current_archive->is_gzipped = tar_normal;
}
@ -455,12 +422,12 @@ static int open_tar_archive (char *name, struct tarfs_archive **pparc)
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;
}
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;
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 *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) {
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;
}
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)
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).
*
*/
static int read_header (struct tarfs_archive *archive, int tard)
static int read_header (struct archive *archive, int tard)
{
register int i;
register long sum, signed_sum, recsum;
@ -599,8 +566,8 @@ static int read_header (struct tarfs_archive *archive, int tard)
#endif
goto recurse;
} else {
struct tarfs_entry *entry, *pent;
struct tarfs_inode *inode;
struct entry *entry, *pent;
struct inode *inode;
long data_position;
char *p, *q;
int len;
@ -635,12 +602,12 @@ static int read_header (struct tarfs_archive *archive, int tard)
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) {
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->has_changed = 0;
entry->header_offset = header_position;
@ -656,7 +623,7 @@ static int read_header (struct tarfs_archive *archive, int tard)
free (current_file_name);
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) {
message_1s (1, MSG_ERROR, _("Inconsistent tar archive"));
} else {
@ -672,7 +639,7 @@ static int read_header (struct tarfs_archive *archive, int tard)
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;
inode->local_filename = NULL;
inode->has_changed = 0;
@ -750,12 +717,12 @@ static int read_header (struct tarfs_archive *archive, int tard)
* Main loop for reading an archive.
* 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 prev_status;
int tard;
struct tarfs_archive *archive;
struct archive *archive;
if ((tard = open_tar_archive (name, &archive)) == -1) { /* Open for reading */
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;
}
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);
/* Returns path inside argument. Returned char* is inside inname, which is mangled
* 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)
{
char *local, *archive_name;
int result = -1;
struct tarfs_archive *parc;
struct archive *parc;
struct vfs_stamping *parent;
vfs *v;
struct stat stat_buf;
@ -845,7 +812,7 @@ static char *tarfs_get_path_mangle (char *inname, struct tarfs_archive **archive
else
result = read_tar_archive (archive_name, &parc);
if (result == -1) {
tarerrno = EIO;
my_errno = EIO;
return NULL;
}
v = vfs_type (archive_name);
@ -864,23 +831,23 @@ return_success:
return local;
}
struct tarfs_loop_protect {
struct tarfs_entry *entry;
struct tarfs_loop_protect *next;
struct loop_protect {
struct entry *entry;
struct loop_protect *next;
};
static int errloop;
static int notadir;
static struct tarfs_entry *
__tarfs_find_entry (struct tarfs_entry *dir, char *name,
struct tarfs_loop_protect *list, int make_dirs, int make_file);
static struct entry *
__find_entry (struct entry *dir, char *name,
struct loop_protect *list, int make_dirs, int make_file);
static struct tarfs_entry *
__tarfs_resolve_symlinks (struct tarfs_entry *entry,
struct tarfs_loop_protect *list)
static struct entry *
__resolve_symlinks (struct entry *entry,
struct loop_protect *list)
{
struct tarfs_entry *pent;
struct tarfs_loop_protect *looping;
struct entry *pent;
struct loop_protect *looping;
if (!S_ISLNK (entry->inode->mode))
return entry;
@ -889,68 +856,68 @@ __tarfs_resolve_symlinks (struct tarfs_entry *entry,
errloop = 1;
return NULL;
}
looping = (struct tarfs_loop_protect *)
xmalloc (sizeof (struct tarfs_loop_protect),
looping = (struct loop_protect *)
xmalloc (sizeof (struct loop_protect),
"Tar: symlink looping protection");
looping->entry = entry;
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);
if (pent == NULL)
tarerrno = ENOENT;
my_errno = ENOENT;
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;
notadir = 0;
res = __tarfs_resolve_symlinks (entry, NULL);
res = __resolve_symlinks (entry, NULL);
if (res == NULL) {
if (errloop)
tarerrno = ELOOP;
my_errno = ELOOP;
else if (notadir)
tarerrno = ENOTDIR;
my_errno = ENOTDIR;
}
return res;
}
struct tar_pseudofile {
struct tarfs_archive *archive;
struct pseudofile {
struct archive *archive;
long pos;
long begin;
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)
{
struct tar_pseudofile *tar_info;
struct tarfs_archive *archive;
struct pseudofile *tar_info;
struct archive *archive;
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;
entry = tarfs_find_entry (archive->root_entry, q, 0, 0);
entry = find_entry (archive->root_entry, q, 0, 0);
if (entry == NULL)
return NULL;
if ((entry = tarfs_resolve_symlinks (entry)) == NULL)
if ((entry = my_resolve_symlinks (entry)) == NULL)
return NULL;
if (S_ISDIR (entry->inode->mode)) {
tarerrno = EISDIR;
my_errno = EISDIR;
return NULL;
}
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;
}
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->pos = 0;
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)
{
struct tar_pseudofile *file = (struct tar_pseudofile *)data;
struct pseudofile *file = (struct pseudofile *)data;
if (file->archive->is_gzipped != targz_growing &&
mc_lseek (file->archive->fd, file->begin + file->pos, SEEK_SET) !=
file->begin + file->pos) {
tarerrno = EIO;
my_errno = EIO;
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) {
tarerrno = errno;
my_errno = errno;
return -1;
}
file->pos += count;
@ -1014,9 +981,9 @@ static int tar_read (void *data, char *buffer, int count)
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--;
if (!file->archive->fd_usage) {
@ -1041,21 +1008,7 @@ static int tar_close (void *data)
return 0;
}
#define X_pseudofile tar_pseudofile
#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"
#include "shared_tar_ext.c"
static int tar_chmod (char *path, int mode)
{ /* 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)
{
struct tarfs_archive *archive;
struct archive *archive;
char *q;
struct tarfs_entry *entry;
struct entry *entry;
tarerrno = ENOTDIR;
if ((q = tarfs_get_path_mangle (path, &archive, 1, 0)) == NULL)
my_errno = ENOTDIR;
if ((q = get_path_mangle (path, &archive, 1, 0)) == NULL)
return -1;
entry = tarfs_find_entry (archive->root_entry, q, 0, 0);
entry = find_entry (archive->root_entry, q, 0, 0);
if (!entry)
return -1;
entry = tarfs_resolve_symlinks (entry);
entry = my_resolve_symlinks (entry);
if ((!entry) || (!S_ISDIR (entry->inode->mode)))
return -1;
entry->inode->archive->current_dir = entry;
tarerrno = 0;
my_errno = 0;
return 0;
}
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) {
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)
{
struct tarfs_archive *archive;
struct archive *archive;
vfs *v;
char *p;
vfsid id;
struct vfs_stamping *par;
*parent = NULL;
if (!(p = tarfs_get_path (path, &archive, 0, 1)))
if (!(p = get_path (path, &archive, 0, 1)))
return (vfsid) -1;
free(p);
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)
{
if (((struct tarfs_archive *)id)->fd_usage <= 0)
if (((struct archive *)id)->fd_usage <= 0)
return 1;
else
return 0;
}
static void free_entry (struct tarfs_entry *e)
static void free_entry (struct entry *e)
{
int i = --(e->inode->nlink);
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;
free_entry (f);
@ -1164,8 +1117,8 @@ static void free_entry (struct tarfs_entry *e)
static void tar_free (vfsid id)
{
struct tarfs_archive *parc;
struct tarfs_archive *archive = (struct tarfs_archive *)id;
struct archive *parc;
struct archive *archive = (struct archive *)id;
free_entry (archive->root_entry);
if (archive == first_archive) {
@ -1182,18 +1135,18 @@ static void tar_free (vfsid id)
static char *tar_getlocalcopy (char *path)
{
struct tarfs_archive *archive;
struct archive *archive;
char *p, *q;
struct tarfs_entry *entry;
struct entry *entry;
char buf[MC_MAXPATHLEN];
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;
entry = tarfs_find_entry (archive->root_entry, q, 0, 0);
entry = find_entry (archive->root_entry, q, 0, 0);
if (entry == NULL)
return NULL;
if ((entry = tarfs_resolve_symlinks (entry)) == NULL)
if ((entry = my_resolve_symlinks (entry)) == NULL)
return NULL;
if (entry->inode->local_filename != NULL)

Просмотреть файл

@ -157,34 +157,34 @@ union record {
#ifndef TAR_NAMES
struct tarfs_inode;
struct inode;
struct tarfs_entry {
struct entry {
int has_changed;
long header_offset; /* -1 if not in stored in archive */
int header_size;
struct tarfs_entry *next_in_dir;
struct tarfs_entry *dir;
struct entry *next_in_dir;
struct entry *dir;
long extended_offset; /* -1 if not present */
int extended_size;
char *name;
struct tarfs_inode *inode;
struct inode *inode;
};
struct tarfs_archive;
struct archive;
struct tarfs_inode {
struct inode {
int has_changed;
int is_open;
nlink_t nlink;
struct tarfs_entry *first_in_subdir; /* only used if linkflag == L_DIR */
struct tarfs_entry *last_in_subdir;
struct entry *first_in_subdir; /* only used if linkflag == L_DIR */
struct entry *last_in_subdir;
long data_offset;
char *local_filename;
ino_t inode; /* This is inode # */
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;
int std; /* 0 if old Unix inode */
@ -199,15 +199,15 @@ struct tarfs_inode {
time_t ctime;
};
struct tarfs_archive {
struct archive {
char *name;
struct stat tarstat;
int is_gzipped;
dev_t rdev;
ino_t __inode_counter;
struct tarfs_entry *root_entry;
struct tarfs_entry *current_dir;
struct tarfs_archive *next;
struct entry *root_entry;
struct entry *current_dir;
struct archive *next;
long current_tar_position;
int fd;
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 */
colon = strchr (rest, ':');
if (colon){
*port = atoi (colon+1);
if (*port <= 0 || *port >= 65536)
*port = 21;
*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);
free (pcopy);

350
vfs/vfs.c
Просмотреть файл

@ -19,6 +19,10 @@
along with this program; if not, write to the Free Software
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 <stdio.h>
#include <stdlib.h> /* For atol() */
@ -86,7 +90,7 @@ static struct {
vfs *operations;
} vfs_file_table [MAX_VFS_FILES];
static int get_bucket ()
static int get_bucket (void)
{
int i;
@ -95,8 +99,7 @@ static int get_bucket ()
if (!vfs_file_table [i].fs_info)
return i;
}
fprintf (stderr, "No more virtual file handles\n");
exit (1);
vfs_die ("No more virtual file handles");
}
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))
return &undelfs_vfs_ops;
#endif
if (!(vfs_flags & FL_NO_FISH) && !strncmp (path, "sh:", 3))
return &fish_vfs_ops;
if (!(vfs_flags & FL_NO_TARFS) && !strcmp (path, "utar"))
return &tarfs_vfs_ops;
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 res;
int res;
res = !strncmp( path, "/#/", 3 );
if (res)
path[1] = '/';
return res || (vfs_flags & FL_ALWAYS_MAGIC);
res = !strncmp( path, "/#/", 3 );
if (res)
path[1] = '/';
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 == &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
('cd a:') instead of waiting for the vfs-timeout */
(oldvfs->free) (oldvfsid);
@ -755,7 +760,7 @@ void vfs_add_noncurrent_stamps (vfs * oldvfs, vfsid oldvfsid, struct vfs_stampin
stamp->id == (vfsid) - 1 ||
!(*stamp->v->nothingisopen) (stamp->id))
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);
vfs_rmstamp (stamp->v, stamp->id, 0);
} else
@ -888,7 +893,8 @@ char *vfs_get_current_dir (void)
void vfs_setup_wd (void)
{
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)
vfs_die ("Current dir too long.\n");
@ -1084,6 +1090,7 @@ void vfs_init (void)
tcp_init();
ftpfs_init();
#endif
fish_init ();
extfs_init ();
sfs_init ();
vfs_setup_wd ();
@ -1134,11 +1141,11 @@ void vfs_shut (void)
free (current_dir);
extfs_done ();
sfs_done();
#ifdef USE_NETCODE
fish_done();
ftpfs_done();
#endif
}
/* These ones grab information from the VFS
@ -1149,6 +1156,7 @@ void vfs_fill_names (void (*func)(char *))
#ifdef USE_NETCODE
mcfs_fill_names (func);
ftpfs_fill_names (func);
fish_fill_names (func);
#endif
tarfs_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 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;
int numcols;
@ -1182,7 +1190,7 @@ static int split_text (char *p)
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 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 :-(.
*/
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); }
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 i;
struct tm tim;
int extfs_format_date = 0;
char *p_copy;
s->st_mode = 0;
if (strncmp (p, "total", 5) == 0){
if (strncmp (p, "total", 5) == 0)
return 0;
}
switch (*(p++)){
case 'd': s->st_mode |= S_IFDIR; break;
case 'b': s->st_mode |= S_IFBLK; break;
case 'c': s->st_mode |= S_IFCHR; break;
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 ((i = parse_filetype(*(p++))) == -1)
return 0;
s->st_mode = i;
if (*p == '['){
if (strlen (p) <= 8 || p [8] != ']')
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);
p += 9;
} else {
switch (*(p++)){
case 'r': s->st_mode |= 0400; break;
case '-': break;
default: return 0;
}
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;
}
if ((i = parse_filemode(p)) ==-1)
return 0;
s->st_mode |= i;
p += 9;
}
p_copy = strdup (p);
@ -1391,76 +1488,11 @@ int parse_ls_lga (char *p, struct stat *s, char **filename, char **linkname)
#endif
}
/* 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)
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;
idx = parse_filedate(idx, &s->st_mtime);
if (!idx)
free_and_return (0);
/* Use resulting time value */
s->st_atime = s->st_ctime = s->st_mtime;
s->st_dev = 0;
s->st_ino = 0;
#ifdef HAVE_ST_BLKSIZE

Просмотреть файл

@ -6,9 +6,9 @@
#else
#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?
* 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
@ -90,6 +90,7 @@ struct utimbuf {
extern vfs tarfs_vfs_ops;
extern vfs ftpfs_vfs_ops;
extern vfs fish_vfs_ops;
extern vfs mcfs_vfs_ops;
extern vfs extfs_vfs_ops;
@ -316,8 +317,6 @@ extern int vfs_flags;
extern uid_t vfs_uid;
extern gid_t vfs_gid;
#define FL_ALWAYS_MAGIC 1
#define FL_NO_MCFS 2
#define FL_NO_FTPFS 4
@ -325,6 +324,14 @@ extern gid_t vfs_gid;
#define FL_NO_TARFS 16
#define FL_NO_EXTFS 32
#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 */