1998-02-27 07:54:42 +03:00
|
|
|
/* Virtual File System: External file system.
|
|
|
|
Copyright (C) 1995 The Free Software Foundation
|
|
|
|
|
|
|
|
Written by: 1995 Jakub Jelinek
|
1998-05-26 04:53:24 +04:00
|
|
|
Rewritten by: 1998 Pavel Machek
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#ifdef HAVE_SYS_WAIT_H
|
|
|
|
#include <sys/wait.h>
|
|
|
|
#endif
|
|
|
|
#include <errno.h>
|
|
|
|
#ifdef SCO_FLAVOR
|
|
|
|
#include <sys/timeb.h> /* alex: for struct timeb definition */
|
|
|
|
#endif /* SCO_FLAVOR */
|
|
|
|
#include <time.h>
|
|
|
|
#include "../src/fs.h"
|
|
|
|
#include "../src/util.h"
|
1998-05-26 04:53:24 +04:00
|
|
|
#include "../src/dialog.h"
|
1998-02-27 07:54:42 +03:00
|
|
|
#include "../src/mem.h"
|
|
|
|
#include "../src/mad.h"
|
|
|
|
#include "../src/main.h" /* For shell_execute */
|
|
|
|
#define WANT_PARSE_LS_LGA
|
|
|
|
#include "vfs.h"
|
|
|
|
#include "extfs.h"
|
|
|
|
|
1998-04-17 04:59:58 +04:00
|
|
|
static struct extfs_entry *
|
|
|
|
extfs_find_entry (struct extfs_entry *dir, char *name, int make_dirs, int make_file);
|
|
|
|
|
1998-06-11 14:10:05 +04:00
|
|
|
static struct extfs_archive *first_archive = NULL;
|
1998-02-27 07:54:42 +03:00
|
|
|
static int extfserrno = 0;
|
|
|
|
static struct stat hstat; /* Stat struct corresponding */
|
|
|
|
static char *current_file_name, *current_link_name;
|
|
|
|
static char *extfs_current_dir;
|
|
|
|
|
|
|
|
#define MAXEXTFS 32
|
|
|
|
static char *extfs_prefixes [MAXEXTFS];
|
|
|
|
static char extfs_need_archive [MAXEXTFS];
|
|
|
|
static int extfs_no = 0;
|
|
|
|
|
|
|
|
void extfs_fill_names (void (*func)(char *))
|
|
|
|
{
|
|
|
|
struct extfs_archive *a = first_archive;
|
|
|
|
char *name;
|
|
|
|
|
|
|
|
while (a){
|
1998-05-26 04:53:24 +04:00
|
|
|
name = copy_strings (extfs_prefixes [a->fstype], "#",
|
1998-02-27 07:54:42 +03:00
|
|
|
(a->name ? a->name : ""), "/",
|
|
|
|
a->current_dir->name, 0);
|
|
|
|
(*func)(name);
|
|
|
|
free (name);
|
|
|
|
a = a->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void make_dot_doubledot (struct extfs_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;
|
|
|
|
|
|
|
|
parent = (parentry != NULL) ? parentry->inode : NULL;
|
|
|
|
entry->name = strdup (".");
|
|
|
|
entry->has_changed = 0;
|
|
|
|
entry->inode = inode;
|
|
|
|
entry->dir = ent;
|
|
|
|
inode->local_filename = NULL;
|
|
|
|
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=entry->next_in_dir;
|
|
|
|
entry->name = strdup ("..");
|
|
|
|
entry->has_changed = 0;
|
|
|
|
inode->last_in_subdir = entry;
|
|
|
|
entry->next_in_dir = NULL;
|
|
|
|
if (parent != NULL) {
|
|
|
|
entry->inode = parent;
|
|
|
|
entry->dir = parentry;
|
|
|
|
parent->nlink++;
|
|
|
|
} else {
|
|
|
|
entry->inode = inode;
|
|
|
|
entry->dir = ent;
|
|
|
|
inode->nlink++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct extfs_entry *generate_entry (struct extfs_archive *archive,
|
|
|
|
char *name, struct extfs_entry *parentry, mode_t mode)
|
|
|
|
{
|
|
|
|
mode_t myumask;
|
|
|
|
struct extfs_inode *inode, *parent;
|
|
|
|
struct extfs_entry *entry;
|
|
|
|
|
|
|
|
parent = (parentry != NULL) ? parentry->inode : NULL;
|
|
|
|
entry = (struct extfs_entry *)
|
|
|
|
xmalloc (sizeof (struct extfs_entry), "Extfs: extfs_entry");
|
|
|
|
|
|
|
|
entry->name = strdup (name);
|
|
|
|
entry->has_changed = 0;
|
|
|
|
entry->next_in_dir = NULL;
|
|
|
|
entry->dir = parentry;
|
|
|
|
if (parent != NULL) {
|
|
|
|
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");
|
|
|
|
entry->inode = inode;
|
|
|
|
inode->has_changed = 0;
|
|
|
|
inode->local_filename = NULL;
|
|
|
|
inode->linkname = 0;
|
|
|
|
inode->inode = (archive->__inode_counter)++;
|
|
|
|
inode->dev = archive->rdev;
|
|
|
|
inode->archive = archive;
|
|
|
|
myumask = umask (022);
|
|
|
|
umask (myumask);
|
|
|
|
inode->mode = mode & ~myumask;
|
|
|
|
mode = inode->mode;
|
|
|
|
inode->rdev = 0;
|
|
|
|
inode->uid = getuid ();
|
|
|
|
inode->gid = getgid ();
|
|
|
|
inode->size = 0;
|
|
|
|
inode->mtime = time (NULL);
|
|
|
|
inode->atime = inode->mtime;
|
|
|
|
inode->ctime = inode->mtime;
|
|
|
|
inode->nlink = 1;
|
|
|
|
if (S_ISDIR (mode))
|
|
|
|
make_dot_doubledot (entry);
|
|
|
|
return entry;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void free_entries (struct extfs_entry *entry)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void free_archive (struct extfs_archive *archive)
|
|
|
|
{
|
|
|
|
free_entries (archive->root_entry);
|
|
|
|
if (archive->local_name != NULL) {
|
|
|
|
struct stat my;
|
|
|
|
|
|
|
|
mc_stat (archive->local_name, &my);
|
|
|
|
mc_ungetlocalcopy (archive->name, archive->local_name,
|
|
|
|
archive->local_stat.st_mtime != my.st_mtime);
|
|
|
|
/* ungetlocalcopy frees local_name for us */
|
|
|
|
}
|
|
|
|
if (archive->name)
|
|
|
|
free (archive->name);
|
|
|
|
free (archive);
|
|
|
|
}
|
|
|
|
|
|
|
|
static FILE *open_extfs_archive (int fstype, char *name, struct extfs_archive **pparc)
|
|
|
|
{
|
|
|
|
static dev_t __extfs_no = 0;
|
|
|
|
FILE *result;
|
|
|
|
mode_t mode;
|
|
|
|
char *cmd;
|
|
|
|
struct stat mystat;
|
|
|
|
struct extfs_archive *current_archive;
|
|
|
|
struct extfs_entry *root_entry;
|
|
|
|
char *local_name = NULL, *tmp = 0;
|
1998-05-26 04:53:24 +04:00
|
|
|
int uses_archive = extfs_need_archive [fstype];
|
|
|
|
char *tmpfile;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
1998-05-26 04:53:24 +04:00
|
|
|
if (uses_archive){
|
1998-02-27 07:54:42 +03:00
|
|
|
if (mc_stat (name, &mystat) == -1)
|
|
|
|
return NULL;
|
|
|
|
if (!vfs_file_is_local (name)) {
|
|
|
|
local_name = mc_getlocalcopy (name);
|
|
|
|
if (local_name == NULL)
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
tmp = name_quote (name, 0);
|
|
|
|
}
|
|
|
|
|
1998-05-26 04:53:24 +04:00
|
|
|
#if 0
|
|
|
|
/* Sorry, what is this good for? */
|
1998-02-27 07:54:42 +03:00
|
|
|
if (uses_archive == EFS_NEED_ARG){
|
|
|
|
tmp = name_quote (name, 0);
|
|
|
|
}
|
1998-05-26 04:53:24 +04:00
|
|
|
#endif
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
cmd = copy_strings (LIBDIR "extfs/", extfs_prefixes [fstype],
|
|
|
|
" list ", local_name ? local_name : tmp, 0);
|
|
|
|
if (tmp)
|
|
|
|
free (tmp);
|
|
|
|
result = popen (cmd, "r");
|
|
|
|
free (cmd);
|
|
|
|
if (result == NULL) {
|
|
|
|
if (local_name != NULL && uses_archive)
|
|
|
|
mc_ungetlocalcopy (name, local_name, 0);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
current_archive = (struct extfs_archive *)
|
1998-05-26 04:53:24 +04:00
|
|
|
xmalloc (sizeof (struct extfs_archive), "Extfs archive");
|
1998-02-27 07:54:42 +03:00
|
|
|
current_archive->fstype = fstype;
|
|
|
|
current_archive->name = name ? strdup (name): name;
|
|
|
|
current_archive->local_name = local_name;
|
|
|
|
|
|
|
|
if (local_name != NULL)
|
|
|
|
mc_stat (local_name, ¤t_archive->local_stat);
|
|
|
|
current_archive->__inode_counter = 0;
|
|
|
|
current_archive->fd_usage = 0;
|
|
|
|
current_archive->extfsstat = mystat;
|
|
|
|
current_archive->rdev = __extfs_no++;
|
|
|
|
current_archive->next = first_archive;
|
|
|
|
first_archive = current_archive;
|
|
|
|
mode = current_archive->extfsstat.st_mode & 07777;
|
|
|
|
if (mode & 0400)
|
|
|
|
mode |= 0100;
|
|
|
|
if (mode & 0040)
|
|
|
|
mode |= 0010;
|
|
|
|
if (mode & 0004)
|
|
|
|
mode |= 0001;
|
|
|
|
mode |= S_IFDIR;
|
|
|
|
root_entry = generate_entry (current_archive, "/", NULL, mode);
|
|
|
|
root_entry->inode->uid = current_archive->extfsstat.st_uid;
|
|
|
|
root_entry->inode->gid = current_archive->extfsstat.st_gid;
|
|
|
|
root_entry->inode->atime = current_archive->extfsstat.st_atime;
|
|
|
|
root_entry->inode->ctime = current_archive->extfsstat.st_ctime;
|
|
|
|
root_entry->inode->mtime = current_archive->extfsstat.st_mtime;
|
|
|
|
current_archive->root_entry = root_entry;
|
|
|
|
current_archive->current_dir = root_entry;
|
|
|
|
|
|
|
|
*pparc = current_archive;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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)
|
|
|
|
{
|
|
|
|
FILE *extfsd;
|
|
|
|
char *buffer;
|
|
|
|
struct extfs_archive *current_archive;
|
|
|
|
|
|
|
|
if ((extfsd = open_extfs_archive (fstype, name, ¤t_archive)) == NULL) {
|
1998-05-26 04:53:24 +04:00
|
|
|
message_3s (1, MSG_ERROR, _("Couldn't open %s archive\n%s"),
|
1998-02-27 07:54:42 +03:00
|
|
|
extfs_prefixes [fstype], name);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
buffer = xmalloc (4096, "Extfs: buffer");
|
|
|
|
while (fgets (buffer, 4096, extfsd) != NULL) {
|
|
|
|
current_link_name = NULL;
|
|
|
|
if (parse_ls_lga (buffer, &hstat, ¤t_file_name, ¤t_link_name)) {
|
|
|
|
struct extfs_entry *entry, *pent;
|
|
|
|
struct extfs_inode *inode;
|
|
|
|
char *p, *q, *cfn = current_file_name;
|
|
|
|
|
|
|
|
if (*cfn) {
|
|
|
|
if (*cfn == '/')
|
|
|
|
cfn++;
|
|
|
|
p = strchr (cfn, 0);
|
|
|
|
if (p != NULL && p != cfn && *(p - 1) == '/')
|
|
|
|
*(p - 1) = 0;
|
|
|
|
p = strrchr (cfn, '/');
|
|
|
|
if (p == NULL) {
|
|
|
|
p = cfn;
|
|
|
|
q = strchr (cfn, 0);
|
|
|
|
} else {
|
|
|
|
*(p++) = 0;
|
|
|
|
q = cfn;
|
|
|
|
}
|
|
|
|
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) ;
|
|
|
|
if (pent == NULL) {
|
1998-05-26 04:53:24 +04:00
|
|
|
message_1s (1, MSG_ERROR, _("Inconsistent extfs archive"));
|
1998-02-27 07:54:42 +03:00
|
|
|
/* FIXME: Should clean everything one day */
|
|
|
|
free (buffer);
|
|
|
|
pclose (extfsd);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
entry = (struct extfs_entry *) xmalloc (sizeof (struct extfs_entry), "Extfs: extfs_entry");
|
|
|
|
entry->name = strdup (p);
|
|
|
|
entry->has_changed = 0;
|
|
|
|
entry->next_in_dir = NULL;
|
|
|
|
entry->dir = pent;
|
|
|
|
if (pent != NULL) {
|
|
|
|
if (pent->inode->last_in_subdir){
|
|
|
|
pent->inode->last_in_subdir->next_in_dir = entry;
|
|
|
|
pent->inode->last_in_subdir = entry;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!S_ISLNK (hstat.st_mode) && current_link_name != NULL) {
|
|
|
|
pent = extfs_find_entry (current_archive->root_entry, current_link_name, 0, 0);
|
|
|
|
if (pent == NULL) {
|
1998-05-26 04:53:24 +04:00
|
|
|
message_1s (1, MSG_ERROR, _("Inconsistent extfs archive"));
|
1998-02-27 07:54:42 +03:00
|
|
|
/* FIXME: Should clean everything one day */
|
|
|
|
free (buffer);
|
|
|
|
pclose (extfsd);
|
|
|
|
return -1;
|
|
|
|
} else {
|
|
|
|
entry->inode = pent->inode;
|
|
|
|
pent->inode->nlink++;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
inode = (struct extfs_inode *) xmalloc (sizeof (struct extfs_inode), "Extfs: extfs_inode");
|
|
|
|
entry->inode = inode;
|
|
|
|
inode->local_filename = NULL;
|
|
|
|
inode->has_changed = 0;
|
|
|
|
inode->inode = (current_archive->__inode_counter)++;
|
|
|
|
inode->nlink = 1;
|
|
|
|
inode->dev = current_archive->rdev;
|
|
|
|
inode->archive = current_archive;
|
|
|
|
inode->mode = hstat.st_mode;
|
|
|
|
#ifdef HAVE_ST_RDEV
|
|
|
|
inode->rdev = hstat.st_rdev;
|
|
|
|
#else
|
|
|
|
inode->rdev = 0;
|
|
|
|
#endif
|
|
|
|
inode->uid = hstat.st_uid;
|
|
|
|
inode->gid = hstat.st_gid;
|
|
|
|
inode->size = hstat.st_size;
|
|
|
|
inode->mtime = hstat.st_mtime;
|
|
|
|
inode->atime = hstat.st_atime;
|
|
|
|
inode->ctime = hstat.st_ctime;
|
|
|
|
if (current_link_name != NULL && S_ISLNK (hstat.st_mode)) {
|
|
|
|
inode->linkname = current_link_name;
|
|
|
|
current_link_name = NULL;
|
|
|
|
} else {
|
1998-05-26 04:53:24 +04:00
|
|
|
if (S_ISLNK( hstat.st_mode))
|
|
|
|
inode->mode &= ~S_IFLNK; /* You *DON'T* want to do this always */
|
1998-02-27 07:54:42 +03:00
|
|
|
inode->linkname = NULL;
|
|
|
|
}
|
|
|
|
if (S_ISDIR (hstat.st_mode))
|
|
|
|
make_dot_doubledot (entry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
read_extfs_continue:
|
|
|
|
free (current_file_name);
|
|
|
|
if (current_link_name != NULL)
|
|
|
|
free (current_link_name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pclose (extfsd);
|
|
|
|
#ifdef SCO_FLAVOR
|
|
|
|
waitpid(-1,NULL,WNOHANG);
|
|
|
|
#endif /* SCO_FLAVOR */
|
|
|
|
*pparc = current_archive;
|
|
|
|
free (buffer);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *extfs_get_path (char *inname, struct extfs_archive **archive, int is_dir,
|
1998-06-01 00:12:35 +04:00
|
|
|
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,
|
1998-02-27 07:54:42 +03:00
|
|
|
int do_not_open)
|
|
|
|
{
|
1998-05-26 04:53:24 +04:00
|
|
|
char *local, *archive_name, *op;
|
1998-02-27 07:54:42 +03:00
|
|
|
int result = -1;
|
|
|
|
struct extfs_archive *parc;
|
|
|
|
struct vfs_stamping *parent;
|
|
|
|
vfs *v;
|
|
|
|
int fstype;
|
|
|
|
|
1998-05-26 04:53:24 +04:00
|
|
|
archive_name = inname;
|
|
|
|
vfs_split( inname, &local, &op );
|
|
|
|
fstype = extfs_which( op );
|
|
|
|
if (!local)
|
|
|
|
local = "";
|
|
|
|
if (fstype == -1)
|
|
|
|
return NULL;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
1998-05-26 04:53:24 +04:00
|
|
|
/* All filesystems should have some local archive, at least
|
|
|
|
* it can be '/'.
|
1998-02-27 07:54:42 +03:00
|
|
|
*
|
|
|
|
* Actually, we should implement an alias mechanism that would
|
|
|
|
* translate: "a:" to "dos:a.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
for (parc = first_archive; parc != NULL; parc = parc->next)
|
1998-05-26 04:53:24 +04:00
|
|
|
if (parc->name) {
|
|
|
|
if (!strcmp (parc->name, archive_name)) {
|
|
|
|
vfs_stamp (&extfs_vfs_ops, (vfsid) parc);
|
1998-02-27 07:54:42 +03:00
|
|
|
goto return_success;
|
|
|
|
}
|
|
|
|
}
|
1998-05-26 04:53:24 +04:00
|
|
|
|
|
|
|
result = do_not_open ? -1 : read_extfs_archive (fstype, archive_name, &parc);
|
1998-02-27 07:54:42 +03:00
|
|
|
if (result == -1) {
|
|
|
|
extfserrno = EIO;
|
|
|
|
return NULL;
|
|
|
|
}
|
1998-05-26 04:53:24 +04:00
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
if (archive_name){
|
|
|
|
v = vfs_type (archive_name);
|
|
|
|
if (v == &local_vfs_ops) {
|
|
|
|
parent = NULL;
|
|
|
|
} else {
|
|
|
|
parent = xmalloc (sizeof (struct vfs_stamping), "vfs stamping");
|
|
|
|
parent->v = v;
|
|
|
|
parent->next = 0;
|
|
|
|
parent->id = (*v->getid) (archive_name, &(parent->parent));
|
|
|
|
}
|
|
|
|
vfs_add_noncurrent_stamps (&extfs_vfs_ops, (vfsid) parc, parent);
|
|
|
|
vfs_rm_parents (parent);
|
|
|
|
}
|
|
|
|
return_success:
|
|
|
|
*archive = parc;
|
|
|
|
return local;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Returns allocated path (without leading slash) inside the archive */
|
|
|
|
static char *extfs_get_path_from_entry (struct extfs_entry *entry)
|
|
|
|
{
|
|
|
|
struct list {
|
|
|
|
struct list *next;
|
|
|
|
char *name;
|
|
|
|
} *head, *p;
|
|
|
|
char *localpath;
|
|
|
|
size_t len;
|
|
|
|
|
|
|
|
for (len = 0, head = 0; entry->dir; entry = entry->dir) {
|
|
|
|
p = xmalloc (sizeof (struct list), "Extfs: list");
|
|
|
|
p->next = head;
|
|
|
|
p->name = entry->name;
|
|
|
|
head = p;
|
|
|
|
len += strlen (entry->name) + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
localpath = xmalloc (len, "Extfs: localpath");
|
|
|
|
*localpath = '\0';
|
|
|
|
for ( ; head; ) {
|
|
|
|
strcat (localpath, head->name);
|
|
|
|
if (head->next)
|
|
|
|
strcat (localpath, "/");
|
|
|
|
p = head;
|
|
|
|
head = head->next;
|
|
|
|
free (p);
|
|
|
|
}
|
|
|
|
return (localpath);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct extfs_loop_protect {
|
|
|
|
struct extfs_entry *entry;
|
|
|
|
struct extfs_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 extfs_entry *
|
|
|
|
__extfs_resolve_symlinks (struct extfs_entry *entry,
|
|
|
|
struct extfs_loop_protect *list)
|
|
|
|
{
|
|
|
|
struct extfs_entry *pent;
|
|
|
|
struct extfs_loop_protect *looping;
|
|
|
|
|
|
|
|
if (!S_ISLNK (entry->inode->mode))
|
|
|
|
return entry;
|
|
|
|
for (looping = list; looping != NULL; looping = looping->next)
|
|
|
|
if (entry == looping->entry) { /* Here we protect us against symlink looping */
|
|
|
|
errloop = 1;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
looping = (struct extfs_loop_protect *)
|
|
|
|
xmalloc (sizeof (struct extfs_loop_protect),
|
|
|
|
"Extfs: symlink looping protection");
|
|
|
|
looping->entry = entry;
|
|
|
|
looping->next = list;
|
|
|
|
pent = __extfs_find_entry (entry->dir, entry->inode->linkname, looping, 0, 0);
|
|
|
|
free (looping);
|
|
|
|
if (pent == NULL)
|
|
|
|
extfserrno = ENOENT;
|
|
|
|
return pent;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct extfs_entry *extfs_resolve_symlinks (struct extfs_entry *entry)
|
|
|
|
{
|
|
|
|
struct extfs_entry *res;
|
|
|
|
|
|
|
|
errloop = 0;
|
|
|
|
notadir = 0;
|
|
|
|
res = __extfs_resolve_symlinks (entry, NULL);
|
|
|
|
if (res == NULL) {
|
|
|
|
if (errloop)
|
|
|
|
extfserrno = ELOOP;
|
|
|
|
else if (notadir)
|
|
|
|
extfserrno = ENOTDIR;
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct extfs_pseudofile {
|
|
|
|
struct extfs_archive *archive;
|
|
|
|
unsigned int has_changed:1;
|
|
|
|
int local_handle;
|
|
|
|
struct extfs_entry *entry;
|
|
|
|
};
|
|
|
|
|
|
|
|
static char *get_archive_name (struct extfs_archive *archive)
|
|
|
|
{
|
|
|
|
char *archive_name;
|
|
|
|
|
|
|
|
if (archive->local_name)
|
|
|
|
archive_name = archive->local_name;
|
|
|
|
else
|
|
|
|
archive_name = archive->name;
|
|
|
|
|
|
|
|
if (!archive_name || !*archive_name)
|
|
|
|
return "no_archive_name";
|
|
|
|
else
|
|
|
|
return archive_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
void extfs_run (char *file)
|
|
|
|
{
|
|
|
|
struct extfs_archive *archive;
|
|
|
|
char *p, *q, *cmd, *archive_name;
|
|
|
|
|
|
|
|
if ((p = extfs_get_path (file, &archive, 0, 0)) == NULL)
|
|
|
|
return;
|
1998-05-26 04:53:24 +04:00
|
|
|
q = name_quote (p, 0);
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
archive_name = name_quote (get_archive_name(archive), 0);
|
|
|
|
cmd = copy_strings (LIBDIR "extfs/", extfs_prefixes [archive->fstype],
|
|
|
|
" run ", archive_name, " ", q, 0);
|
|
|
|
free (archive_name);
|
|
|
|
free (q);
|
1998-05-26 04:53:24 +04:00
|
|
|
#ifndef VFS_STANDALONE
|
1998-02-27 07:54:42 +03:00
|
|
|
shell_execute(cmd, 0);
|
1998-05-26 04:53:24 +04:00
|
|
|
#else
|
|
|
|
vfs_die( "shell_execute: implement me!" );
|
|
|
|
#endif
|
1998-02-27 07:54:42 +03:00
|
|
|
free(cmd);
|
|
|
|
free(p);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *extfs_open (char *file, int flags, int mode)
|
|
|
|
{
|
|
|
|
struct extfs_pseudofile *extfs_info;
|
|
|
|
struct extfs_archive *archive;
|
1998-05-26 04:53:24 +04:00
|
|
|
char *q;
|
1998-02-27 07:54:42 +03:00
|
|
|
struct extfs_entry *entry;
|
|
|
|
int local_handle;
|
|
|
|
const int do_create = (flags & O_ACCMODE) != O_RDONLY;
|
|
|
|
|
1998-06-01 00:12:35 +04:00
|
|
|
if ((q = extfs_get_path_mangle (file, &archive, 0, 0)) == NULL)
|
1998-02-27 07:54:42 +03:00
|
|
|
return NULL;
|
|
|
|
entry = extfs_find_entry (archive->root_entry, q, 0, do_create);
|
1998-05-26 04:53:24 +04:00
|
|
|
if (entry == NULL)
|
1998-02-27 07:54:42 +03:00
|
|
|
return NULL;
|
1998-05-26 04:53:24 +04:00
|
|
|
if ((entry = extfs_resolve_symlinks (entry)) == NULL)
|
1998-02-27 07:54:42 +03:00
|
|
|
return NULL;
|
|
|
|
if (S_ISDIR (entry->inode->mode)) {
|
|
|
|
extfserrno = EISDIR;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (entry->inode->local_filename == NULL) {
|
1998-05-26 04:53:24 +04:00
|
|
|
char *cmd, *archive_name, *p;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
entry->inode->local_filename = strdup (tmpnam (NULL));
|
|
|
|
p = extfs_get_path_from_entry (entry);
|
|
|
|
q = name_quote (p, 0);
|
|
|
|
free (p);
|
|
|
|
archive_name = name_quote (get_archive_name (archive), 0);
|
|
|
|
cmd = copy_strings (LIBDIR "extfs/", extfs_prefixes [archive->fstype],
|
|
|
|
" copyout ",
|
|
|
|
archive_name,
|
|
|
|
" ", q, " ", entry->inode->local_filename, 0);
|
|
|
|
free (q);
|
|
|
|
free (archive_name);
|
I improved the movement keys of the internal viewer a little bit.
Now in wrap mode the End key and cursor up key behave much better
(e.g. when viewing binary files with lots of wrapped lines).
It's not perfekt but it's better than it used to be.
Tue Apr 28 06:52:24 1998 Norbert Warmuth <k3190@fh-sw.de>
* gnome/gcmd.c (gnome_open_terminal): Changed my_system(1,...) to
my_system(EXECUTE_AS_SHELL,...)
Tue Apr 28 06:06:03 1998 Norbert Warmuth <k3190@fh-sw.de>
* vfs/extfs.c (extfs_open, extfs_close): Changed my_system(1,...)
to my_system(EXECUTE_AS_SHELL,...), this fixes the broken copyin and
copyout in 4.1.32.
Tue Apr 28 06:11:08 1998 Norbert Warmuth <k3190@fh-sw.de>
* view.c (toggle_wrap_mode, toggle_hex_mode): Force recalculation
of bottom_first (we mustn't use an already calculated and cached
value because it is invalid for the new mode and the End key would
not move to the end of the file).
* configure.in: Renamed the option `--with-our-slang' to
`--with-included-slang' (this one looks better because we also
have an `--with-included-gettext').
Make the option `--with-ext2undel' recognice a given path.
* cmd.c (view_file_at_line): In plain view (F13) set the default
magic flag to zero in order to view the file content unprocessed
(esp. don't uncompress files if they are compressed). The
view_simple_cmd got broken when the default magic flag in view.c
was changed from 0 to 1.
* view.c (do_view_init, goto_line): Set wrap mode temporary off
to make goto line number work, i.e. `line number' now always means
line number in file and not line number on screen (in wrap mode
one long line wrapped once is displayed in two lines on the screen).
That's important when the viewer is invoked from the find file
dialog to display even in wrap mode approxiamtly the part of the
file where we found the content we searched for.
(move_forward2): In wrap mode lines were sometimes counted wrong
causing cursor up to move more than one line.
(move_backward2): Fixed the movement in wrap mode.
(change_viewer): Always re-init viewer when we have a filename,
i. e. if the viewer is invoked with simple_view_cmd then we can switch
with the F8 key between unprocessed file content und uncompressed
file content.
(view_init): re-init view also when magic flag was altered
1998-04-28 18:19:48 +04:00
|
|
|
if (my_system (EXECUTE_AS_SHELL, shell, cmd) && !do_create){
|
1998-02-27 07:54:42 +03:00
|
|
|
free (entry->inode->local_filename);
|
|
|
|
entry->inode->local_filename = NULL;
|
|
|
|
free (cmd);
|
|
|
|
extfserrno = EIO;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
free (cmd);
|
|
|
|
}
|
|
|
|
|
|
|
|
local_handle = open (entry->inode->local_filename, flags, mode);
|
|
|
|
if (local_handle == -1) {
|
|
|
|
extfserrno = EIO;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
extfs_info = (struct extfs_pseudofile *) xmalloc (sizeof (struct extfs_pseudofile), "Extfs: extfs_open");
|
|
|
|
extfs_info->archive = archive;
|
|
|
|
extfs_info->entry = entry;
|
|
|
|
extfs_info->has_changed = 0;
|
|
|
|
extfs_info->local_handle = local_handle;
|
|
|
|
|
|
|
|
/* i.e. we had no open files and now we have one */
|
|
|
|
vfs_rmstamp (&extfs_vfs_ops, (vfsid) archive, 1);
|
|
|
|
archive->fd_usage++;
|
|
|
|
return extfs_info;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int extfs_read (void *data, char *buffer, int count)
|
|
|
|
{
|
|
|
|
struct extfs_pseudofile *file = (struct extfs_pseudofile *)data;
|
|
|
|
|
|
|
|
return read (file->local_handle, buffer, count);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int extfs_close (void *data)
|
|
|
|
{
|
|
|
|
struct extfs_pseudofile *file;
|
|
|
|
int errno_code = 0;
|
|
|
|
file = (struct extfs_pseudofile *)data;
|
|
|
|
|
|
|
|
close (file->local_handle);
|
|
|
|
|
|
|
|
/* Commit the file if it has changed */
|
|
|
|
if (file->has_changed){
|
|
|
|
struct extfs_archive *archive;
|
|
|
|
char *archive_name, *file_name;
|
|
|
|
char *cmd;
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
archive = file->archive;
|
|
|
|
archive_name = name_quote (get_archive_name (archive), 0);
|
|
|
|
p = extfs_get_path_from_entry (file->entry);
|
|
|
|
file_name = name_quote (p, 0);
|
|
|
|
free (p);
|
|
|
|
|
|
|
|
cmd = copy_strings (LIBDIR "extfs/",
|
|
|
|
extfs_prefixes [archive->fstype],
|
|
|
|
" copyin ", archive_name, " ",
|
|
|
|
file_name, " ",
|
|
|
|
file->entry->inode->local_filename, 0);
|
|
|
|
free (archive_name);
|
|
|
|
free (file_name);
|
I improved the movement keys of the internal viewer a little bit.
Now in wrap mode the End key and cursor up key behave much better
(e.g. when viewing binary files with lots of wrapped lines).
It's not perfekt but it's better than it used to be.
Tue Apr 28 06:52:24 1998 Norbert Warmuth <k3190@fh-sw.de>
* gnome/gcmd.c (gnome_open_terminal): Changed my_system(1,...) to
my_system(EXECUTE_AS_SHELL,...)
Tue Apr 28 06:06:03 1998 Norbert Warmuth <k3190@fh-sw.de>
* vfs/extfs.c (extfs_open, extfs_close): Changed my_system(1,...)
to my_system(EXECUTE_AS_SHELL,...), this fixes the broken copyin and
copyout in 4.1.32.
Tue Apr 28 06:11:08 1998 Norbert Warmuth <k3190@fh-sw.de>
* view.c (toggle_wrap_mode, toggle_hex_mode): Force recalculation
of bottom_first (we mustn't use an already calculated and cached
value because it is invalid for the new mode and the End key would
not move to the end of the file).
* configure.in: Renamed the option `--with-our-slang' to
`--with-included-slang' (this one looks better because we also
have an `--with-included-gettext').
Make the option `--with-ext2undel' recognice a given path.
* cmd.c (view_file_at_line): In plain view (F13) set the default
magic flag to zero in order to view the file content unprocessed
(esp. don't uncompress files if they are compressed). The
view_simple_cmd got broken when the default magic flag in view.c
was changed from 0 to 1.
* view.c (do_view_init, goto_line): Set wrap mode temporary off
to make goto line number work, i.e. `line number' now always means
line number in file and not line number on screen (in wrap mode
one long line wrapped once is displayed in two lines on the screen).
That's important when the viewer is invoked from the find file
dialog to display even in wrap mode approxiamtly the part of the
file where we found the content we searched for.
(move_forward2): In wrap mode lines were sometimes counted wrong
causing cursor up to move more than one line.
(move_backward2): Fixed the movement in wrap mode.
(change_viewer): Always re-init viewer when we have a filename,
i. e. if the viewer is invoked with simple_view_cmd then we can switch
with the F8 key between unprocessed file content und uncompressed
file content.
(view_init): re-init view also when magic flag was altered
1998-04-28 18:19:48 +04:00
|
|
|
if (my_system (EXECUTE_AS_SHELL, shell, cmd))
|
1998-02-27 07:54:42 +03:00
|
|
|
errno_code = EIO;
|
|
|
|
free (cmd);
|
|
|
|
{
|
|
|
|
struct stat file_status;
|
|
|
|
if( stat(file->entry->inode->local_filename,&file_status) != 0 )
|
|
|
|
errno_code = EIO;
|
|
|
|
else file->entry->inode->size = file_status.st_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
file->entry->inode->mtime = time (NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
file->archive->fd_usage--;
|
|
|
|
if (!file->archive->fd_usage) {
|
|
|
|
struct vfs_stamping *parent;
|
|
|
|
vfs *v;
|
|
|
|
|
|
|
|
if (!file->archive->name || !*file->archive->name || (v = vfs_type (file->archive->name)) == &local_vfs_ops) {
|
|
|
|
parent = NULL;
|
|
|
|
} else {
|
|
|
|
parent = xmalloc (sizeof (struct vfs_stamping), "vfs stamping");
|
|
|
|
parent->v = v;
|
|
|
|
parent->next = 0;
|
|
|
|
parent->id = (*v->getid) (file->archive->name, &(parent->parent));
|
|
|
|
}
|
|
|
|
vfs_add_noncurrent_stamps (&extfs_vfs_ops, (vfsid) (file->archive), parent);
|
|
|
|
vfs_rm_parents (parent);
|
|
|
|
}
|
|
|
|
|
|
|
|
free (data);
|
|
|
|
if (errno_code){
|
|
|
|
extfserrno = EIO; /* Non standard, but who cares? */
|
|
|
|
return -1;
|
|
|
|
} else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1998-05-26 04:53:24 +04:00
|
|
|
#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
|
1998-06-01 00:12:35 +04:00
|
|
|
#define X_get_path_mangle extfs_get_path_mangle
|
1998-05-26 04:53:24 +04:00
|
|
|
#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"
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
static int extfs_chmod (char *path, int mode)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int extfs_chown (char *path, int owner, int group)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int extfs_unlink (char *path)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int extfs_symlink (char *n1, char *n2)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int extfs_write (void *data, char *buf, int nbyte)
|
|
|
|
{
|
|
|
|
struct extfs_pseudofile *file = (struct extfs_pseudofile *)data;
|
|
|
|
|
|
|
|
file->has_changed = 1;
|
|
|
|
return write (file->local_handle, buf, nbyte);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int extfs_rename (char *a, char *b)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int extfs_chdir (char *path)
|
|
|
|
{
|
|
|
|
struct extfs_archive *archive;
|
1998-05-26 04:53:24 +04:00
|
|
|
char *q, *res;
|
1998-02-27 07:54:42 +03:00
|
|
|
struct extfs_entry *entry;
|
|
|
|
|
|
|
|
extfserrno = ENOTDIR;
|
1998-06-01 00:12:35 +04:00
|
|
|
if ((q = extfs_get_path_mangle (path, &archive, 1, 0)) == NULL)
|
1998-02-27 07:54:42 +03:00
|
|
|
return -1;
|
|
|
|
entry = extfs_find_entry (archive->root_entry, q, 0, 0);
|
1998-05-26 04:53:24 +04:00
|
|
|
if (!entry)
|
1998-02-27 07:54:42 +03:00
|
|
|
return -1;
|
|
|
|
entry = extfs_resolve_symlinks (entry);
|
1998-05-26 04:53:24 +04:00
|
|
|
if ((!entry) || (!S_ISDIR (entry->inode->mode)))
|
1998-02-27 07:54:42 +03:00
|
|
|
return -1;
|
|
|
|
entry->inode->archive->current_dir = entry;
|
1998-05-26 04:53:24 +04:00
|
|
|
res = copy_strings (
|
|
|
|
entry->inode->archive->name, "#", extfs_prefixes [entry->inode->archive->fstype],
|
|
|
|
"/", q, NULL);
|
1998-02-27 07:54:42 +03:00
|
|
|
extfserrno = 0;
|
|
|
|
if (extfs_current_dir)
|
|
|
|
free (extfs_current_dir);
|
|
|
|
extfs_current_dir = res;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int extfs_lseek (void *data, off_t offset, int whence)
|
|
|
|
{
|
|
|
|
struct extfs_pseudofile *file = (struct extfs_pseudofile *) data;
|
|
|
|
|
|
|
|
return lseek (file->local_handle, offset, whence);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int extfs_mknod (char *path, int mode, int dev)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int extfs_link (char *p1, char *p2)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int extfs_mkdir (char *path, mode_t mode)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int extfs_rmdir (char *path)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static vfsid extfs_getid (char *path, struct vfs_stamping **parent)
|
|
|
|
{
|
|
|
|
struct extfs_archive *archive;
|
|
|
|
vfs *v;
|
|
|
|
vfsid id;
|
|
|
|
struct vfs_stamping *par;
|
1998-06-01 00:12:35 +04:00
|
|
|
char *p;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
*parent = NULL;
|
1998-06-01 00:12:35 +04:00
|
|
|
if (!(p = extfs_get_path (path, &archive, 1, 1)))
|
1998-02-27 07:54:42 +03:00
|
|
|
return (vfsid) -1;
|
1998-06-01 00:12:35 +04:00
|
|
|
free(p);
|
1998-02-27 07:54:42 +03:00
|
|
|
if (archive->name){
|
|
|
|
v = vfs_type (archive->name);
|
|
|
|
id = (*v->getid) (archive->name, &par);
|
|
|
|
if (id != (vfsid)-1) {
|
|
|
|
*parent = xmalloc (sizeof (struct vfs_stamping), "vfs stamping");
|
|
|
|
(*parent)->v = v;
|
|
|
|
(*parent)->id = id;
|
|
|
|
(*parent)->parent = par;
|
|
|
|
(*parent)->next = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (vfsid) archive;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int extfs_nothingisopen (vfsid id)
|
|
|
|
{
|
|
|
|
if (((struct extfs_archive *)id)->fd_usage <= 0)
|
|
|
|
return 1;
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void free_entry (struct extfs_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;
|
|
|
|
|
|
|
|
e->inode->first_in_subdir = NULL;
|
|
|
|
free_entry (f);
|
|
|
|
}
|
|
|
|
if (i <= 0) {
|
|
|
|
if (e->inode->local_filename != NULL) {
|
|
|
|
unlink (e->inode->local_filename);
|
|
|
|
free (e->inode->local_filename);
|
|
|
|
}
|
|
|
|
if (e->inode->linkname != NULL)
|
|
|
|
free (e->inode->linkname);
|
|
|
|
free (e->inode);
|
|
|
|
}
|
|
|
|
if (e->next_in_dir != NULL)
|
|
|
|
free_entry (e->next_in_dir);
|
|
|
|
free (e->name);
|
|
|
|
free (e);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void extfs_free (vfsid id)
|
|
|
|
{
|
|
|
|
struct extfs_archive *parc;
|
|
|
|
struct extfs_archive *archive = (struct extfs_archive *)id;
|
|
|
|
|
|
|
|
free_entry (archive->root_entry);
|
|
|
|
if (archive == first_archive) {
|
|
|
|
first_archive = archive->next;
|
|
|
|
} else {
|
|
|
|
for (parc = first_archive; parc != NULL; parc = parc->next)
|
|
|
|
if (parc->next == archive)
|
|
|
|
break;
|
|
|
|
if (parc != NULL)
|
|
|
|
parc->next = archive->next;
|
|
|
|
}
|
|
|
|
free_archive (archive);
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *extfs_getlocalcopy (char *path)
|
|
|
|
{
|
|
|
|
struct extfs_pseudofile *fp =
|
|
|
|
(struct extfs_pseudofile *) extfs_open (path, O_RDONLY, 0);
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
if (fp == NULL)
|
|
|
|
return NULL;
|
|
|
|
if (fp->entry->inode->local_filename == NULL) {
|
|
|
|
extfs_close ((void *) fp);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
p = strdup (fp->entry->inode->local_filename);
|
|
|
|
fp->archive->fd_usage++;
|
|
|
|
extfs_close ((void *) fp);
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void extfs_ungetlocalcopy (char *path, char *local, int has_changed)
|
|
|
|
{
|
|
|
|
struct extfs_pseudofile *fp =
|
|
|
|
(struct extfs_pseudofile *) extfs_open (path, O_WRONLY, 0);
|
|
|
|
|
|
|
|
if (fp == NULL)
|
|
|
|
return;
|
|
|
|
if (!strcmp (fp->entry->inode->local_filename, local)) {
|
|
|
|
fp->entry->inode->has_changed = has_changed;
|
|
|
|
fp->archive->fd_usage--;
|
|
|
|
extfs_close ((void *) fp);
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
/* Should not happen */
|
|
|
|
extfs_close ((void *) fp);
|
|
|
|
mc_def_ungetlocalcopy (path, local, has_changed);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef HAVE_MMAP
|
|
|
|
caddr_t extfs_mmap (caddr_t addr, size_t len, int prot, int flags, void *data, off_t offset)
|
|
|
|
{
|
|
|
|
return (caddr_t)-1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int extfs_munmap (caddr_t addr, size_t len, void *data)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
vfs extfs_vfs_ops =
|
|
|
|
{
|
|
|
|
extfs_open,
|
|
|
|
extfs_close,
|
|
|
|
extfs_read,
|
|
|
|
extfs_write,
|
|
|
|
|
1998-05-26 04:53:24 +04:00
|
|
|
s_opendir,
|
|
|
|
s_readdir,
|
|
|
|
s_closedir,
|
|
|
|
s_telldir,
|
|
|
|
s_seekdir,
|
1998-02-27 07:54:42 +03:00
|
|
|
|
1998-05-26 04:53:24 +04:00
|
|
|
s_stat,
|
|
|
|
s_lstat,
|
|
|
|
s_fstat,
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
extfs_chmod, /* unimplemented */
|
|
|
|
extfs_chown, /* unimplemented */
|
|
|
|
NULL,
|
|
|
|
|
1998-05-26 04:53:24 +04:00
|
|
|
s_readlink,
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
extfs_symlink, /* unimplemented */
|
|
|
|
extfs_link, /* unimplemented */
|
|
|
|
extfs_unlink, /* unimplemented */
|
|
|
|
|
|
|
|
extfs_rename, /* unimplemented */
|
|
|
|
extfs_chdir,
|
1998-05-26 04:53:24 +04:00
|
|
|
s_errno,
|
1998-02-27 07:54:42 +03:00
|
|
|
extfs_lseek,
|
|
|
|
extfs_mknod, /* unimplemented */
|
|
|
|
|
|
|
|
extfs_getid,
|
|
|
|
extfs_nothingisopen,
|
|
|
|
extfs_free,
|
|
|
|
|
|
|
|
extfs_getlocalcopy,
|
|
|
|
extfs_ungetlocalcopy,
|
|
|
|
|
|
|
|
extfs_mkdir, /* unimplemented */
|
|
|
|
extfs_rmdir, /* unimplemented */
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL
|
1998-05-26 04:53:24 +04:00
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
#ifdef HAVE_MMAP
|
|
|
|
, extfs_mmap,
|
|
|
|
extfs_munmap
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
|
|
|
#include "../src/profile.h"
|
|
|
|
void extfs_init (void)
|
|
|
|
{
|
1998-05-26 04:53:24 +04:00
|
|
|
FILE *cfg = fopen( LIBDIR "extfs/extfs.ini", "r" );
|
|
|
|
if (!cfg) {
|
|
|
|
fprintf( stderr, "Warning: " LIBDIR "extfs/extfs.ini not found\n" );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
extfs_no = 0;
|
1998-05-26 04:53:24 +04:00
|
|
|
while ( extfs_no < MAXEXTFS ) {
|
|
|
|
char key[256];
|
|
|
|
char *c;
|
|
|
|
|
|
|
|
if (!fgets( key, 250, cfg ))
|
|
|
|
break;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
/* Handle those with a trailing ':', those flag that the
|
|
|
|
* file system does not require an archive to work
|
|
|
|
*/
|
|
|
|
|
1998-05-26 04:53:24 +04:00
|
|
|
if (*key == '[') {
|
|
|
|
/* We may not use vfs_die() message or message_1s or similar,
|
|
|
|
* UI is not initialized at this time and message would not
|
|
|
|
* appear on screen. */
|
|
|
|
fprintf( stderr, "Warning: You need to update your " LIBDIR "extfs/extfs.ini file.\n" );
|
|
|
|
fclose(cfg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (*key == '#')
|
|
|
|
continue;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
1998-05-26 04:53:24 +04:00
|
|
|
if ((c = strchr( key, '\n')))
|
|
|
|
*c = 0;
|
|
|
|
c = &key [strlen (key)-1];
|
|
|
|
extfs_need_archive [extfs_no] = !(*c==':');
|
|
|
|
if (*c==':') *c = 0;
|
|
|
|
if (!(*key))
|
|
|
|
continue;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
1998-05-26 04:53:24 +04:00
|
|
|
extfs_prefixes [extfs_no] = strdup (key);
|
|
|
|
extfs_no++;
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
1998-05-26 04:53:24 +04:00
|
|
|
fclose(cfg);
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
1998-05-26 04:53:24 +04:00
|
|
|
int extfs_which (char *path)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
1998-05-26 04:53:24 +04:00
|
|
|
int i;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
1998-05-26 04:53:24 +04:00
|
|
|
for (i = 0; i < extfs_no; i++)
|
|
|
|
if (!strcmp (path, extfs_prefixes [i]))
|
1998-02-27 07:54:42 +03:00
|
|
|
return i;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *extfs_get_prefix (int idx)
|
|
|
|
{
|
|
|
|
return extfs_prefixes [idx];
|
|
|
|
}
|
|
|
|
|
|
|
|
void extfs_done (void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
1998-05-26 04:53:24 +04:00
|
|
|
for (i = 0; i < extfs_no; i++ )
|
1998-02-27 07:54:42 +03:00
|
|
|
free (extfs_prefixes [i]);
|
|
|
|
extfs_no = 0;
|
|
|
|
if (extfs_current_dir)
|
|
|
|
free (extfs_current_dir);
|
|
|
|
extfs_current_dir = 0;
|
|
|
|
}
|
|
|
|
|