From ad9c1daad88d4972f81fd73ab06fb8b90027cb7a Mon Sep 17 00:00:00 2001 From: Andrew Borodin Date: Wed, 27 Jan 2010 16:59:21 +0000 Subject: [PATCH 1/8] Ticket #1909: easy plugable EXTFS VFS. Reimplemented EXTFS VFS to be friendly to package-based systems. Currently, MC requires to edit extfs.ini file to add new plugin to MC VFS. After upgrade, all changes to this files will be lost. To solve that problem, MC configuration system should support ".d" pattern. Initial step: refactoring of current extfs code: cleanup, type accuracy, indentation. Signed-off-by: Andrew Borodin --- lib/vfs/mc-vfs/extfs.c | 763 ++++++++++++++++++++++------------------- 1 file changed, 402 insertions(+), 361 deletions(-) diff --git a/lib/vfs/mc-vfs/extfs.c b/lib/vfs/mc-vfs/extfs.c index a92d8d540..ec6a8a227 100644 --- a/lib/vfs/mc-vfs/extfs.c +++ b/lib/vfs/mc-vfs/extfs.c @@ -1,7 +1,7 @@ /* Virtual File System: External file system. Copyright (C) 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009 Free Software Foundation, Inc. - + Written by: 1995 Jakub Jelinek Rewritten by: 1998 Pavel Machek Additional changes by: 1999 Andrew T. Veliath @@ -87,7 +87,7 @@ struct entry { struct pseudofile { struct archive *archive; - unsigned int has_changed:1; + gboolean has_changed; int local_handle; struct entry *entry; }; @@ -104,12 +104,19 @@ struct archive { struct archive *next; }; -static struct entry *extfs_find_entry (struct entry *dir, char *name, - int make_dirs, int make_file); -static int extfs_which (struct vfs_class *me, const char *path); +struct loop_protect { + struct entry *entry; + struct loop_protect *next; +}; + +static gboolean errloop; +static gboolean notadir; + static void extfs_remove_entry (struct entry *e); static void extfs_free (vfsid id); static void extfs_free_entry (struct entry *e); +static struct entry * extfs_resolve_symlinks_int (struct entry *entry, + struct loop_protect *list); static struct vfs_class vfs_extfs_ops; static struct archive *first_archive = NULL; @@ -121,29 +128,12 @@ static char extfs_need_archive [MAXEXTFS]; static int extfs_no = 0; static void -extfs_fill_names (struct vfs_class *me, fill_names_f func) -{ - struct archive *a = first_archive; - char *name; - - (void) me; - - while (a) { - name = - g_strconcat (a->name ? a->name : "", "#", - extfs_prefixes[a->fstype], (char *) NULL); - (*func) (name); - g_free (name); - a = a->next; - } -} - -static void extfs_make_dots (struct entry *ent) +extfs_make_dots (struct entry *ent) { struct entry *entry = g_new (struct entry, 1); struct entry *parentry = ent->dir; struct inode *inode = ent->inode, *parent; - + parent = (parentry != NULL) ? parentry->inode : NULL; entry->name = g_strdup ("."); entry->inode = inode; @@ -151,6 +141,7 @@ static void extfs_make_dots (struct entry *ent) inode->local_filename = NULL; inode->first_in_subdir = entry; inode->nlink++; + entry->next_in_dir = g_new (struct entry, 1); entry = entry->next_in_dir; entry->name = g_strdup (".."); @@ -161,14 +152,15 @@ static void extfs_make_dots (struct entry *ent) entry->dir = parentry; parent->nlink++; } else { - entry->inode = inode; - entry->dir = ent; - inode->nlink++; + entry->inode = inode; + entry->dir = ent; + inode->nlink++; } } -static struct entry *extfs_generate_entry (struct archive *archive, - const char *name, struct entry *parentry, mode_t mode) +static struct entry * +extfs_generate_entry (struct archive *archive, + const char *name, struct entry *parentry, mode_t mode) { mode_t myumask; struct inode *inode, *parent; @@ -176,13 +168,13 @@ static struct entry *extfs_generate_entry (struct archive *archive, parent = (parentry != NULL) ? parentry->inode : NULL; entry = g_new (struct entry, 1); - + entry->name = g_strdup (name); entry->next_in_dir = NULL; entry->dir = parentry; if (parent != NULL) { - parent->last_in_subdir->next_in_dir = entry; - parent->last_in_subdir = entry; + parent->last_in_subdir->next_in_dir = entry; + parent->last_in_subdir = entry; } inode = g_new (struct inode, 1); entry->inode = inode; @@ -209,20 +201,123 @@ static struct entry *extfs_generate_entry (struct archive *archive, return entry; } -#if 0 -static void extfs_free_entries (struct entry *entry) +static struct entry * +extfs_find_entry_int (struct entry *dir, char *name, struct loop_protect *list, + gboolean make_dirs, gboolean make_file) { - (void) entry; - return; -} -#endif + struct entry *pent, *pdir; + char *p, *q, *name_end; + char c = PATH_SEP; -static void extfs_free_archive (struct archive *archive) + if (*name == '/') { /* Handle absolute paths */ + name++; + dir = dir->inode->archive->root_entry; + } + + pent = dir; + p = name; + name_end = name + strlen (name); + + q = strchr (p, '/'); + if (q == '\0') + q = strchr (p, '\0'); + + while ((pent != NULL) && (c != '\0') && (*p != '\0')) { + c = *q; + *q = '\0'; + + if (strcmp (p, ".") != 0) { + if (strcmp (p, "..") == 0) + pent = pent->dir; + else { + pent = extfs_resolve_symlinks_int (pent, list); + if (pent == NULL) { + *q = c; + return NULL; + } + if (!S_ISDIR (pent->inode->mode)) { + *q = c; + notadir = TRUE; + return NULL; + } + + pdir = pent; + for (pent = pent->inode->first_in_subdir; pent != NULL; pent = pent->next_in_dir) + /* Hack: I keep the original semanthic unless + q+1 would break in the strchr */ + if (strcmp (pent->name, p) == 0) { + if (q + 1 > name_end) { + *q = c; + notadir = !S_ISDIR (pent->inode->mode); + return pent; + } + break; + } + + /* When we load archive, we create automagically + * non-existant directories + */ + if (pent == NULL && make_dirs) + pent = extfs_generate_entry (dir->inode->archive, p, pdir, S_IFDIR | 0777); + if (pent == NULL && make_file) + pent = extfs_generate_entry (dir->inode->archive, p, pdir, S_IFREG | 0666); + } + } + /* Next iteration */ + *q = c; + p = q + 1; + q = strchr (p, '/'); + if (q == '\0') + q = strchr (p, '\0'); + } + if (pent == NULL) + my_errno = ENOENT; + return pent; +} + +static struct entry * +extfs_find_entry (struct entry *dir, char *name, gboolean make_dirs, gboolean make_file) +{ + struct entry *res; + + errloop = FALSE; + notadir = FALSE; + + res = extfs_find_entry_int (dir, name, NULL, make_dirs, make_file); + if (res == NULL) { + if (errloop) + my_errno = ELOOP; + else if (notadir) + my_errno = ENOTDIR; + } + return res; +} + +static void +extfs_fill_names (struct vfs_class *me, fill_names_f func) +{ + struct archive *a = first_archive; + + (void) me; + + while (a != NULL) { + char *name; + + name = g_strconcat (a->name ? a->name : "", "#", + extfs_prefixes[a->fstype], (char *) NULL); + func (name); + g_free (name); + a = a->next; + } +} + +static void +extfs_free_archive (struct archive *archive) { extfs_free_entry (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); @@ -243,10 +338,11 @@ extfs_open_archive (int fstype, const char *name, struct archive **pparc) struct stat mystat; struct archive *current_archive; struct entry *root_entry; - char *local_name = NULL, *tmp = 0; - int uses_archive = extfs_need_archive[fstype]; + char *local_name = NULL, *tmp = NULL; + int uses_archive; - if (uses_archive) { + uses_archive = extfs_need_archive[fstype]; + if (uses_archive != 0) { if (mc_stat (name, &mystat) == -1) return NULL; if (!vfs_file_is_local (name)) { @@ -258,9 +354,8 @@ extfs_open_archive (int fstype, const char *name, struct archive **pparc) } mc_extfsdir = concat_dir_and_file (mc_home_alt, "extfs" PATH_SEP_STR); - cmd = - g_strconcat (mc_extfsdir, extfs_prefixes[fstype], " list ", - local_name ? local_name : tmp, (char *) NULL); + cmd = g_strconcat (mc_extfsdir, extfs_prefixes[fstype], " list ", + local_name != NULL ? local_name : tmp, (char *) NULL); g_free (tmp); g_free (mc_extfsdir); open_error_pipe (); @@ -268,15 +363,16 @@ extfs_open_archive (int fstype, const char *name, struct archive **pparc) g_free (cmd); if (result == NULL) { close_error_pipe (D_ERROR, NULL); - if (local_name) { + if (local_name != NULL) { mc_ungetlocalcopy (name, local_name, 0); g_free(local_name); } return NULL; - } -#ifdef ___QNXNTO__ + } + +#ifdef ___QNXNTO__ setvbuf (result, NULL, _IONBF, 0); -#endif +#endif current_archive = g_new (struct archive, 1); current_archive->fstype = fstype; @@ -323,44 +419,43 @@ extfs_read_archive (int fstype, const char *name, struct archive **pparc) struct archive *current_archive; char *current_file_name, *current_link_name; - if ((extfsd = - extfs_open_archive (fstype, name, ¤t_archive)) == NULL) { + extfsd = extfs_open_archive (fstype, name, ¤t_archive); + if (extfsd == NULL) { message (D_ERROR, MSG_ERROR, _("Cannot open %s archive\n%s"), extfs_prefixes[fstype], name); return -1; } - buffer = g_malloc (4096); - while (fgets (buffer, 4096, extfsd) != NULL) { + buffer = g_malloc (BUF_4K); + while (fgets (buffer, BUF_4K, extfsd) != NULL) { struct stat hstat; current_link_name = NULL; - if (vfs_parse_ls_lga - (buffer, &hstat, ¤t_file_name, ¤t_link_name)) { + if (vfs_parse_ls_lga (buffer, &hstat, + ¤t_file_name, ¤t_link_name)) { struct entry *entry, *pent; struct inode *inode; char *p, *q, *cfn = current_file_name; - if (*cfn) { + if (*cfn != '\0') { if (*cfn == '/') cfn++; - p = strchr (cfn, 0); + p = strchr (cfn, '\0'); if (p != cfn && *(p - 1) == '/') - *(p - 1) = 0; + *(p - 1) = '\0'; p = strrchr (cfn, '/'); if (p == NULL) { p = cfn; - q = strchr (cfn, 0); + q = strchr (cfn, '\0'); } else { - *(p++) = 0; + *(p++) = '\0'; q = cfn; } if (S_ISDIR (hstat.st_mode) - && (!strcmp (p, ".") || !strcmp (p, ".."))) + && (strcmp (p, ".") || !strcmp (p, "..") == 0)) goto read_extfs_continue; - pent = - extfs_find_entry (current_archive->root_entry, q, 1, - 0); + pent = extfs_find_entry (current_archive->root_entry, + q, TRUE, FALSE); if (pent == NULL) { /* FIXME: Should clean everything one day */ g_free (buffer); @@ -376,10 +471,9 @@ extfs_read_archive (int fstype, const char *name, struct archive **pparc) 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 (!S_ISLNK (hstat.st_mode) && (current_link_name != NULL)) { + pent = extfs_find_entry (current_archive->root_entry, + current_link_name, FALSE, FALSE); if (pent == NULL) { /* FIXME: Should clean everything one day */ g_free (buffer); @@ -387,10 +481,10 @@ extfs_read_archive (int fstype, const char *name, struct archive **pparc) close_error_pipe (D_ERROR, _("Inconsistent extfs archive")); return -1; - } else { - entry->inode = pent->inode; - pent->inode->nlink++; } + + entry->inode = pent->inode; + pent->inode->nlink++; } else { inode = g_new (struct inode, 1); entry->inode = inode; @@ -426,7 +520,7 @@ extfs_read_archive (int fstype, const char *name, struct archive **pparc) extfs_make_dots (entry); } } - read_extfs_continue: +read_extfs_continue: g_free (current_file_name); g_free (current_link_name); } @@ -445,13 +539,26 @@ extfs_read_archive (int fstype, const char *name, struct archive **pparc) return 0; } +static int +extfs_which (struct vfs_class *me, const char *path) +{ + int i; + + (void) me; + + for (i = 0; i < extfs_no; i++) + if (!strcmp (path, extfs_prefixes [i])) + return i; + return -1; +} + /* * Dissect the path and create corresponding superblock. Note that inname * can be changed and the result may point inside the original string. */ static char * extfs_get_path_mangle (struct vfs_class *me, char *inname, struct archive **archive, - int do_not_open) + gboolean do_not_open) { char *local, *op; const char *archive_name; @@ -466,7 +573,7 @@ extfs_get_path_mangle (struct vfs_class *me, char *inname, struct archive **arch if (fstype == -1) return NULL; - if (!local) + if (local == NULL) local = inname + strlen (inname); /* @@ -474,45 +581,43 @@ extfs_get_path_mangle (struct vfs_class *me, char *inname, struct archive **arch * it can be '/'. */ for (parc = first_archive; parc != NULL; parc = parc->next) - if (parc->name) { - if (!strcmp (parc->name, archive_name)) { + if (parc->name != NULL) { + if (strcmp (parc->name, archive_name) == 0) { vfs_stamp (&vfs_extfs_ops, (vfsid) parc); goto return_success; } } - result = - do_not_open ? -1 : extfs_read_archive (fstype, archive_name, - &parc); + result = do_not_open ? -1 : extfs_read_archive (fstype, archive_name, + &parc); if (result == -1) ERRNOR (EIO, NULL); - return_success: +return_success: *archive = parc; return local; } - /* * Dissect the path and create corresponding superblock. * The result should be freed. */ static char * -extfs_get_path (struct vfs_class *me, const char *inname, struct archive **archive, - int do_not_open) +extfs_get_path (struct vfs_class *me, const char *inname, + struct archive **archive, gboolean do_not_open) { - char *buf = g_strdup (inname); - char *res = extfs_get_path_mangle (me, buf, archive, do_not_open); - char *res2 = NULL; - if (res) - res2 = g_strdup (res); + char *buf, *res, *res2; + + buf = g_strdup (inname); + res = extfs_get_path_mangle (me, buf, archive, do_not_open); + res2 = g_strdup (res); g_free (buf); return res2; } - /* Return allocated path (without leading slash) inside the archive */ -static char *extfs_get_path_from_entry (struct entry *entry) +static char * +extfs_get_path_from_entry (struct entry *entry) { struct list { struct list *next; @@ -520,7 +625,7 @@ static char *extfs_get_path_from_entry (struct entry *entry) } *head, *p; char *localpath; size_t len; - + for (len = 0, head = 0; entry->dir; entry = entry->dir) { p = g_new (struct list, 1); p->next = head; @@ -531,7 +636,7 @@ static char *extfs_get_path_from_entry (struct entry *entry) if (len == 0) return g_strdup (""); - + localpath = g_malloc (len); *localpath = '\0'; while (head) { @@ -545,54 +650,47 @@ static char *extfs_get_path_from_entry (struct entry *entry) return (localpath); } - -struct loop_protect { - struct entry *entry; - struct loop_protect *next; -}; -static int errloop; -static int notadir; - static struct entry * -extfs_find_entry_int (struct entry *dir, char *name, - struct loop_protect *list, int make_dirs, int make_file); - -static struct entry * -extfs_resolve_symlinks_int (struct entry *entry, - struct loop_protect *list) +extfs_resolve_symlinks_int (struct entry *entry, struct loop_protect *list) { struct entry *pent; struct loop_protect *looping; - + if (!S_ISLNK (entry->inode->mode)) - return entry; + 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; - } + if (entry == looping->entry) { + /* Here we protect us against symlink looping */ + errloop = TRUE; + return NULL; + } + looping = g_new (struct loop_protect, 1); looping->entry = entry; looping->next = list; - pent = extfs_find_entry_int (entry->dir, entry->inode->linkname, looping, 0, 0); + pent = extfs_find_entry_int (entry->dir, entry->inode->linkname, + looping, FALSE, FALSE); g_free (looping); + if (pent == NULL) - my_errno = ENOENT; + my_errno = ENOENT; return pent; } -static struct entry *extfs_resolve_symlinks (struct entry *entry) +static struct entry * +extfs_resolve_symlinks (struct entry *entry) { struct entry *res; - - errloop = 0; - notadir = 0; + + errloop = FALSE; + notadir = FALSE; res = extfs_resolve_symlinks_int (entry, NULL); if (res == NULL) { - if (errloop) - my_errno = ELOOP; - else if (notadir) - my_errno = ENOTDIR; + if (errloop) + my_errno = ELOOP; + else if (notadir) + my_errno = ENOTDIR; } return res; } @@ -606,7 +704,7 @@ extfs_get_archive_name (struct archive *archive) archive_name = archive->local_name; else archive_name = archive->name; - + if (!archive_name || !*archive_name) return "no_archive_name"; else @@ -655,7 +753,8 @@ extfs_run (struct vfs_class *me, const char *file) char *p, *q, *archive_name, *mc_extfsdir; char *cmd; - if ((p = extfs_get_path (me, file, &archive, 0)) == NULL) + p = extfs_get_path (me, file, &archive, FALSE); + if (p == NULL) return; q = name_quote (p, 0); g_free (p); @@ -663,7 +762,7 @@ extfs_run (struct vfs_class *me, const char *file) archive_name = name_quote (extfs_get_archive_name (archive), 0); mc_extfsdir = concat_dir_and_file (mc_home_alt, "extfs" PATH_SEP_STR); cmd = g_strconcat (mc_extfsdir, extfs_prefixes[archive->fstype], - " run ", archive_name, " ", q, (char *) NULL); + " run ", archive_name, " ", q, (char *) NULL); g_free (mc_extfsdir); g_free (archive_name); g_free (q); @@ -679,21 +778,23 @@ extfs_open (struct vfs_class *me, const char *file, int flags, int mode) char *q; struct entry *entry; int local_handle; - int created = 0; + gboolean created = FALSE; - if ((q = extfs_get_path (me, file, &archive, 0)) == NULL) + q = extfs_get_path (me, file, &archive, FALSE); + if (q == NULL) return NULL; - entry = extfs_find_entry (archive->root_entry, q, 0, 0); - if (entry == NULL && (flags & O_CREAT)) { + entry = extfs_find_entry (archive->root_entry, q, FALSE, FALSE); + if ((entry == NULL) && ((flags & O_CREAT) != 0)) { /* Create new entry */ - entry = extfs_find_entry (archive->root_entry, q, 0, 1); + entry = extfs_find_entry (archive->root_entry, q, FALSE, TRUE); created = (entry != NULL); } g_free (q); if (entry == NULL) return NULL; - if ((entry = extfs_resolve_symlinks (entry)) == NULL) + entry = extfs_resolve_symlinks (entry); + if (entry == NULL) return NULL; if (S_ISDIR (entry->inode->mode)) @@ -708,7 +809,7 @@ extfs_open (struct vfs_class *me, const char *file, int flags, int mode) return NULL; close (local_handle); - if (!created && !(flags & O_TRUNC) + if (!created && ((flags & O_TRUNC) == 0) && extfs_cmd (" copyout ", archive, entry, local_filename)) { unlink (local_filename); g_free (local_filename); @@ -718,13 +819,12 @@ extfs_open (struct vfs_class *me, const char *file, int flags, int mode) entry->inode->local_filename = local_filename; } - local_handle = - open (entry->inode->local_filename, NO_LINEAR (flags), mode); + local_handle = open (entry->inode->local_filename, NO_LINEAR (flags), mode); if (local_handle == -1) { /* file exists(may be). Need to drop O_CREAT flag and truncate file content */ flags = ~O_CREAT & (NO_LINEAR (flags)|O_TRUNC); - local_handle = open (entry->inode->local_filename, flags , mode); + local_handle = open (entry->inode->local_filename, flags, mode); } if (local_handle == -1) @@ -742,9 +842,10 @@ extfs_open (struct vfs_class *me, const char *file, int flags, int mode) return extfs_info; } -static ssize_t extfs_read (void *data, char *buffer, int count) +static ssize_t +extfs_read (void *data, char *buffer, int count) { - struct pseudofile *file = (struct pseudofile *)data; + struct pseudofile *file = (struct pseudofile *) data; return read (file->local_handle, buffer, count); } @@ -760,148 +861,56 @@ extfs_close (void *data) /* Commit the file if it has changed */ if (file->has_changed) { - if (extfs_cmd - (" copyin ", file->archive, file->entry, - file->entry->inode->local_filename)) + struct stat file_status; + + if (extfs_cmd (" copyin ", file->archive, file->entry, + file->entry->inode->local_filename)) errno_code = EIO; - { - 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; - } + + 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) + if (--file->archive->fd_usage == 0) vfs_stamp_create (&vfs_extfs_ops, file->archive); g_free (data); - if (errno_code) + if (errno_code != 0) ERRNOR (EIO, -1); return 0; } -#define RECORDSIZE 512 - -static struct entry* -extfs_find_entry_int (struct entry *dir, char *name, - struct loop_protect *list, int make_dirs, int make_file) -{ - struct entry *pent, *pdir; - char *p, *q, *name_end; - char c; - - if (*name == '/') { /* Handle absolute paths */ - name++; - dir = dir->inode->archive->root_entry; - } - - pent = dir; - p = name; - name_end = name + strlen (name); - q = strchr (p, '/'); - c = '/'; - if (!q) - q = strchr (p, 0); - - for (; pent != NULL && c && *p; ){ - c = *q; - *q = 0; - - if (strcmp (p, ".")){ - if (!strcmp (p, "..")) - pent = pent->dir; - else { - if ((pent = extfs_resolve_symlinks_int (pent, list))==NULL){ - *q = c; - return NULL; - } - if (!S_ISDIR (pent->inode->mode)){ - *q = c; - notadir = 1; - return NULL; - } - pdir = pent; - for (pent = pent->inode->first_in_subdir; pent; pent = pent->next_in_dir) - /* Hack: I keep the original semanthic unless - q+1 would break in the strchr */ - if (!strcmp (pent->name, p)){ - if (q + 1 > name_end){ - *q = c; - notadir = !S_ISDIR (pent->inode->mode); - return pent; - } - break; - } - - /* When we load archive, we create automagically - * non-existant directories - */ - if (pent == NULL && make_dirs) { - pent = extfs_generate_entry (dir->inode->archive, p, pdir, S_IFDIR | 0777); - } - if (pent == NULL && make_file) { - pent = extfs_generate_entry (dir->inode->archive, p, pdir, S_IFREG | 0666); - } - } - } - /* Next iteration */ - *q = c; - p = q + 1; - q = strchr (p, '/'); - if (!q) - q = strchr (p, 0); - } - if (pent == NULL) - my_errno = ENOENT; - return pent; -} - -static struct entry *extfs_find_entry (struct entry *dir, char *name, int make_dirs, int make_file) -{ - struct entry *res; - - errloop = 0; - notadir = 0; - res = extfs_find_entry_int (dir, name, NULL, make_dirs, make_file); - if (res == NULL) { - if (errloop) - my_errno = ELOOP; - else if (notadir) - my_errno = ENOTDIR; - } - return res; -} - - -static int extfs_errno (struct vfs_class *me) +static int +extfs_errno (struct vfs_class *me) { (void) me; - return my_errno; } -static void * extfs_opendir (struct vfs_class *me, const char *dirname) +static void * +extfs_opendir (struct vfs_class *me, const char *dirname) { struct archive *archive = NULL; char *q; struct entry *entry; struct entry **info; - if ((q = extfs_get_path (me, dirname, &archive, 0)) == NULL) + q = extfs_get_path (me, dirname, &archive, FALSE); + if (q == NULL) return NULL; - entry = extfs_find_entry (archive->root_entry, q, 0, 0); + entry = extfs_find_entry (archive->root_entry, q, FALSE, FALSE); g_free (q); if (entry == NULL) - return NULL; - if ((entry = extfs_resolve_symlinks (entry)) == NULL) return NULL; - if (!S_ISDIR (entry->inode->mode)) ERRNOR (ENOTDIR, NULL); + entry = extfs_resolve_symlinks (entry); + if (entry == NULL) + return NULL; + if (!S_ISDIR (entry->inode->mode)) + ERRNOR (ENOTDIR, NULL); info = g_new (struct entry *, 2); info[0] = entry->inode->first_in_subdir; @@ -910,29 +919,34 @@ static void * extfs_opendir (struct vfs_class *me, const char *dirname) return info; } -static void * extfs_readdir(void *data) +static void * +extfs_readdir(void *data) { static union vfs_dirent dir; struct entry **info = (struct entry **) data; - if (!*info) + if (*info == NULL) return NULL; - g_strlcpy(dir.dent.d_name, (*info)->name, MC_MAXPATHLEN); + g_strlcpy (dir.dent.d_name, (*info)->name, MC_MAXPATHLEN); - compute_namelen(&dir.dent); + compute_namelen (&dir.dent); *info = (*info)->next_in_dir; return (void *) &dir; } -static int extfs_closedir (void *data) +static int +extfs_closedir (void *data) { g_free (data); return 0; } -static void extfs_stat_move (struct stat *buf, const struct inode *inode) +#define RECORDSIZE 512 + +static void +extfs_stat_move (struct stat *buf, const struct inode *inode) { buf->st_dev = inode->dev; buf->st_ino = inode->inode; @@ -957,42 +971,50 @@ static void extfs_stat_move (struct stat *buf, const struct inode *inode) static int extfs_internal_stat (struct vfs_class *me, const char *path, struct stat *buf, - int resolve) + gboolean resolve) { struct archive *archive; - char *q; + char *q, *mpath; struct entry *entry; - char *path2 = g_strdup (path); int result = -1; - if ((q = extfs_get_path_mangle (me, path2, &archive, 0)) == NULL) + mpath = g_strdup (path); + + q = extfs_get_path_mangle (me, mpath, &archive, FALSE); + if (q == NULL) goto cleanup; - entry = extfs_find_entry (archive->root_entry, q, 0, 0); + entry = extfs_find_entry (archive->root_entry, q, FALSE, FALSE); if (entry == NULL) goto cleanup; - if (resolve && (entry = extfs_resolve_symlinks (entry)) == NULL) - goto cleanup; + if (resolve) { + entry = extfs_resolve_symlinks (entry); + if (entry == NULL) + goto cleanup; + } extfs_stat_move (buf, entry->inode); result = 0; cleanup: - g_free (path2); + g_free (mpath); return result; } -static int extfs_stat (struct vfs_class *me, const char *path, struct stat *buf) +static int +extfs_stat (struct vfs_class *me, const char *path, struct stat *buf) { - return extfs_internal_stat (me, path, buf, 1); + return extfs_internal_stat (me, path, buf, TRUE); } -static int extfs_lstat (struct vfs_class *me, const char *path, struct stat *buf) +static int +extfs_lstat (struct vfs_class *me, const char *path, struct stat *buf) { - return extfs_internal_stat (me, path, buf, 0); + return extfs_internal_stat (me, path, buf, FALSE); } -static int extfs_fstat (void *data, struct stat *buf) +static int +extfs_fstat (void *data, struct stat *buf) { - struct pseudofile *file = (struct pseudofile *)data; - + struct pseudofile *file = (struct pseudofile *) data; + extfs_stat_move (buf, file->entry->inode); return 0; } @@ -1001,32 +1023,36 @@ static int extfs_readlink (struct vfs_class *me, const char *path, char *buf, size_t size) { struct archive *archive; - char *q; + char *q, *mpath; size_t len; struct entry *entry; - char *mpath = g_strdup (path); int result = -1; - if ((q = extfs_get_path_mangle (me, mpath, &archive, 0)) == NULL) + mpath = g_strdup (path); + + q = extfs_get_path_mangle (me, mpath, &archive, FALSE); + if (q == NULL) goto cleanup; - entry = extfs_find_entry (archive->root_entry, q, 0, 0); + entry = extfs_find_entry (archive->root_entry, q, FALSE, FALSE); if (entry == NULL) goto cleanup; if (!S_ISLNK (entry->inode->mode)) { - me->verrno = EINVAL; - goto cleanup; + me->verrno = EINVAL; + goto cleanup; } len = strlen (entry->inode->linkname); if (size < len) len = size; /* readlink() does not append a NUL character to buf */ - memcpy (buf, entry->inode->linkname, result = len); + result = len; + memcpy (buf, entry->inode->linkname, result); cleanup: g_free (mpath); return result; } -static int extfs_chown (struct vfs_class *me, const char *path, int owner, int group) +static int +extfs_chown (struct vfs_class *me, const char *path, int owner, int group) { (void) me; (void) path; @@ -1035,7 +1061,8 @@ static int extfs_chown (struct vfs_class *me, const char *path, int owner, int g return 0; } -static int extfs_chmod (struct vfs_class *me, const char *path, int mode) +static int +extfs_chmod (struct vfs_class *me, const char *path, int mode) { (void) me; (void) path; @@ -1043,33 +1070,39 @@ static int extfs_chmod (struct vfs_class *me, const char *path, int mode) return 0; } -static ssize_t extfs_write (void *data, const char *buf, int nbyte) +static ssize_t +extfs_write (void *data, const char *buf, int nbyte) { - struct pseudofile *file = (struct pseudofile *)data; + struct pseudofile *file = (struct pseudofile *) data; - file->has_changed = 1; + file->has_changed = TRUE; return write (file->local_handle, buf, nbyte); } -static int extfs_unlink (struct vfs_class *me, const char *file) +static int +extfs_unlink (struct vfs_class *me, const char *file) { struct archive *archive; - char *q, *mpath = g_strdup (file); + char *q, *mpath; struct entry *entry; int result = -1; - if ((q = extfs_get_path_mangle (me, mpath, &archive, 0)) == NULL) + mpath = g_strdup (file); + + q = extfs_get_path_mangle (me, mpath, &archive, FALSE); + if (q == NULL) goto cleanup; - entry = extfs_find_entry (archive->root_entry, q, 0, 0); + entry = extfs_find_entry (archive->root_entry, q, FALSE, FALSE); if (entry == NULL) goto cleanup; - if ((entry = extfs_resolve_symlinks (entry)) == NULL) + entry = extfs_resolve_symlinks (entry); + if (entry == NULL) goto cleanup; if (S_ISDIR (entry->inode->mode)) { - me->verrno = EISDIR; - goto cleanup; + me->verrno = EISDIR; + goto cleanup; } - if (extfs_cmd (" rm ", archive, entry, "")){ + if (extfs_cmd (" rm ", archive, entry, "")) { my_errno = EIO; goto cleanup; } @@ -1080,33 +1113,38 @@ cleanup: return result; } -static int extfs_mkdir (struct vfs_class *me, const char *path, mode_t mode) +static int +extfs_mkdir (struct vfs_class *me, const char *path, mode_t mode) { struct archive *archive; - char *q, *mpath = g_strdup(path); + char *q, *mpath; struct entry *entry; int result = -1; (void) mode; - if ((q = extfs_get_path_mangle (me, mpath, &archive, 0)) == NULL) + mpath = g_strdup (path); + + q = extfs_get_path_mangle (me, mpath, &archive, FALSE); + if (q == NULL) goto cleanup; - entry = extfs_find_entry (archive->root_entry, q, 0, 0); + entry = extfs_find_entry (archive->root_entry, q, FALSE, FALSE); if (entry != NULL) { - me->verrno = EEXIST; - goto cleanup; + me->verrno = EEXIST; + goto cleanup; } - entry = extfs_find_entry (archive->root_entry, q, 1, 0); + entry = extfs_find_entry (archive->root_entry, q, TRUE, FALSE); if (entry == NULL) goto cleanup; - if ((entry = extfs_resolve_symlinks (entry)) == NULL) + entry = extfs_resolve_symlinks (entry); + if (entry == NULL) goto cleanup; if (!S_ISDIR (entry->inode->mode)) { - me->verrno = ENOTDIR; - goto cleanup; + me->verrno = ENOTDIR; + goto cleanup; } - if (extfs_cmd (" mkdir ", archive, entry, "")){ + if (extfs_cmd (" mkdir ", archive, entry, "")) { my_errno = EIO; extfs_remove_entry (entry); goto cleanup; @@ -1117,26 +1155,31 @@ cleanup: return result; } -static int extfs_rmdir (struct vfs_class *me, const char *path) +static int +extfs_rmdir (struct vfs_class *me, const char *path) { struct archive *archive; - char *q, *mpath = g_strdup(path); + char *q, *mpath; struct entry *entry; int result = -1; - if ((q = extfs_get_path_mangle (me, mpath, &archive, 0)) == NULL) + mpath = g_strdup (path); + + q = extfs_get_path_mangle (me, mpath, &archive, FALSE); + if (q == NULL) goto cleanup; - entry = extfs_find_entry (archive->root_entry, q, 0, 0); + entry = extfs_find_entry (archive->root_entry, q, FALSE, FALSE); + if (entry == NULL) + goto cleanup; + entry = extfs_resolve_symlinks (entry); if (entry == NULL) - goto cleanup; - if ((entry = extfs_resolve_symlinks (entry)) == NULL) goto cleanup; if (!S_ISDIR (entry->inode->mode)) { - me->verrno = ENOTDIR; - goto cleanup; + me->verrno = ENOTDIR; + goto cleanup; } - if (extfs_cmd (" rmdir ", archive, entry, "")){ + if (extfs_cmd (" rmdir ", archive, entry, "")) { my_errno = EIO; goto cleanup; } @@ -1155,20 +1198,22 @@ extfs_chdir (struct vfs_class *me, const char *path) struct entry *entry; my_errno = ENOTDIR; - if ((q = extfs_get_path (me, path, &archive, 0)) == NULL) + q = extfs_get_path (me, path, &archive, FALSE); + if (q == NULL) return -1; - entry = extfs_find_entry (archive->root_entry, q, 0, 0); + entry = extfs_find_entry (archive->root_entry, q, FALSE, FALSE); g_free (q); - if (!entry) + if (entry == NULL) return -1; entry = extfs_resolve_symlinks (entry); - if ((!entry) || (!S_ISDIR (entry->inode->mode))) + if ((entry == NULL) || (!S_ISDIR (entry->inode->mode))) return -1; my_errno = 0; return 0; } -static off_t extfs_lseek (void *data, off_t offset, int whence) +static off_t +extfs_lseek (void *data, off_t offset, int whence) { struct pseudofile *file = (struct pseudofile *) data; @@ -1181,22 +1226,23 @@ extfs_getid (struct vfs_class *me, const char *path) struct archive *archive = NULL; char *p; - if (!(p = extfs_get_path (me, path, &archive, 1))) + p = extfs_get_path (me, path, &archive, TRUE); + if (p == NULL) return NULL; g_free (p); return (vfsid) archive; } -static int extfs_nothingisopen (vfsid id) +static int +extfs_nothingisopen (vfsid id) { - if (((struct archive *)id)->fd_usage <= 0) - return 1; - return 0; + return (((struct archive *) id)->fd_usage <= 0); } -static void extfs_remove_entry (struct entry *e) +static void +extfs_remove_entry (struct entry *e) { - int i = --(e->inode->nlink); + int i = --e->inode->nlink; struct entry *pe, *ent, *prev; if (S_ISDIR (e->inode->mode) && e->inode->first_in_subdir != NULL) { @@ -1233,9 +1279,11 @@ static void extfs_remove_entry (struct entry *e) g_free (e); } -static void extfs_free_entry (struct entry *e) +static void +extfs_free_entry (struct entry *e) { - int i = --(e->inode->nlink); + int i = --e->inode->nlink; + if (S_ISDIR (e->inode->mode) && e->inode->first_in_subdir != NULL) { struct entry *f = e->inode->first_in_subdir; @@ -1256,14 +1304,15 @@ static void extfs_free_entry (struct entry *e) g_free (e); } -static void extfs_free (vfsid id) +static void +extfs_free (vfsid id) { - struct archive *parc; - struct archive *archive = (struct archive *)id; + struct archive *archive = (struct archive *) id; if (archive == first_archive) { first_archive = archive->next; } else { + struct archive *parc; for (parc = first_archive; parc != NULL; parc = parc->next) if (parc->next == archive) { parc->next = archive->next; @@ -1276,10 +1325,10 @@ static void extfs_free (vfsid id) static char * extfs_getlocalcopy (struct vfs_class *me, const char *path) { - struct pseudofile *fp = - (struct pseudofile *) extfs_open (me, path, O_RDONLY, 0); + struct pseudofile *fp; char *p; + fp = (struct pseudofile *) extfs_open (me, path, O_RDONLY, 0); if (fp == NULL) return NULL; if (fp->entry->inode->local_filename == NULL) { @@ -1296,14 +1345,16 @@ static int extfs_ungetlocalcopy (struct vfs_class *me, const char *path, const char *local, int has_changed) { - struct pseudofile *fp = - (struct pseudofile *) extfs_open (me, path, O_RDONLY, 0); + struct pseudofile *fp; + fp = (struct pseudofile *) extfs_open (me, path, O_RDONLY, 0); if (fp == NULL) return 0; - if (!strcmp (fp->entry->inode->local_filename, local)) { + + if (strcmp (fp->entry->inode->local_filename, local) == 0) { fp->archive->fd_usage--; - fp->has_changed |= has_changed; + if (has_changed != 0) + fp->has_changed = TRUE; extfs_close ((void *) fp); return 0; } else { @@ -1313,8 +1364,8 @@ extfs_ungetlocalcopy (struct vfs_class *me, const char *path, } } - -static int extfs_init (struct vfs_class *me) +static int +extfs_init (struct vfs_class *me) { FILE *cfg; char *mc_extfsini; @@ -1328,7 +1379,7 @@ static int extfs_init (struct vfs_class *me) /* We may not use vfs_die() message or message or similar, * UI is not initialized at this time and message would not * appear on screen. */ - if (!cfg) { + if (cfg == NULL) { fprintf (stderr, _("Warning: file %s not found\n"), mc_extfsini); g_free (mc_extfsini); return 0; @@ -1345,44 +1396,34 @@ static int extfs_init (struct vfs_class *me) if (*key == '[') { fprintf(stderr, "Warning: You need to update your %s file.\n", mc_extfsini); - fclose(cfg); + fclose (cfg); g_free (mc_extfsini); return 0; } if (*key == '#' || *key == '\n') continue; - if ((c = strchr (key, '\n'))){ - *c-- = 0; - } else { /* Last line without newline or strlen (key) > 255 */ + c = strchr (key, '\n'); + if (c != '\0') + *c-- = '\0'; + else /* Last line without newline or strlen (key) > 255 */ c = &key [strlen (key) - 1]; - } + extfs_need_archive [extfs_no] = !(*c == ':'); if (*c == ':') - *c = 0; - if (!(*key)) + *c = '\0'; + if (*key == '\0') continue; extfs_prefixes [extfs_no++] = g_strdup (key); } - fclose(cfg); + fclose (cfg); g_free (mc_extfsini); return 1; } -static int extfs_which (struct vfs_class *me, const char *path) -{ - int i; - - (void) me; - - for (i = 0; i < extfs_no; i++) - if (!strcmp (path, extfs_prefixes [i])) - return i; - return -1; -} - -static void extfs_done (struct vfs_class *me) +static void +extfs_done (struct vfs_class *me) { int i; struct archive *ar; From 5b96caa5f0ceb13a889918e457b79e937d490620 Mon Sep 17 00:00:00 2001 From: Andrew Borodin Date: Thu, 28 Jan 2010 15:20:41 +0000 Subject: [PATCH 2/8] Optimization of extfs_get_path_from_entry() function. Signed-off-by: Andrew Borodin --- lib/vfs/mc-vfs/extfs.c | 35 +++++++++-------------------------- 1 file changed, 9 insertions(+), 26 deletions(-) diff --git a/lib/vfs/mc-vfs/extfs.c b/lib/vfs/mc-vfs/extfs.c index ec6a8a227..7d0ff8ea9 100644 --- a/lib/vfs/mc-vfs/extfs.c +++ b/lib/vfs/mc-vfs/extfs.c @@ -619,35 +619,18 @@ extfs_get_path (struct vfs_class *me, const char *inname, static char * extfs_get_path_from_entry (struct entry *entry) { - struct list { - struct list *next; - char *name; - } *head, *p; - char *localpath; - size_t len; + GString *localpath; - for (len = 0, head = 0; entry->dir; entry = entry->dir) { - p = g_new (struct list, 1); - p->next = head; - p->name = entry->name; - head = p; - len += strlen (entry->name) + 1; + localpath = g_string_new (""); + + while (entry->dir != NULL) { + g_string_prepend (localpath, entry->name); + if (entry->dir->dir != NULL) + g_string_prepend_c (localpath, PATH_SEP); + entry = entry->dir; } - if (len == 0) - return g_strdup (""); - - localpath = g_malloc (len); - *localpath = '\0'; - while (head) { - strcat (localpath, head->name); - if (head->next) - strcat (localpath, "/"); - p = head; - head = head->next; - g_free (p); - } - return (localpath); + return g_string_free (localpath, FALSE); } static struct entry * From 6e1c61da0e3e951e7af7b19b3628e289b416912a Mon Sep 17 00:00:00 2001 From: Andrew Borodin Date: Thu, 28 Jan 2010 16:09:26 +0000 Subject: [PATCH 3/8] Optimization of symbolic link loop protection. Signed-off-by: Andrew Borodin --- lib/vfs/mc-vfs/extfs.c | 42 +++++++++++++++++------------------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/lib/vfs/mc-vfs/extfs.c b/lib/vfs/mc-vfs/extfs.c index 7d0ff8ea9..91da15e48 100644 --- a/lib/vfs/mc-vfs/extfs.c +++ b/lib/vfs/mc-vfs/extfs.c @@ -104,19 +104,13 @@ struct archive { struct archive *next; }; -struct loop_protect { - struct entry *entry; - struct loop_protect *next; -}; - static gboolean errloop; static gboolean notadir; static void extfs_remove_entry (struct entry *e); static void extfs_free (vfsid id); static void extfs_free_entry (struct entry *e); -static struct entry * extfs_resolve_symlinks_int (struct entry *entry, - struct loop_protect *list); +static struct entry * extfs_resolve_symlinks_int (struct entry *entry, GSList *list); static struct vfs_class vfs_extfs_ops; static struct archive *first_archive = NULL; @@ -202,7 +196,7 @@ extfs_generate_entry (struct archive *archive, } static struct entry * -extfs_find_entry_int (struct entry *dir, char *name, struct loop_protect *list, +extfs_find_entry_int (struct entry *dir, char *name, GSList *list, gboolean make_dirs, gboolean make_file) { struct entry *pent, *pdir; @@ -634,30 +628,28 @@ extfs_get_path_from_entry (struct entry *entry) } static struct entry * -extfs_resolve_symlinks_int (struct entry *entry, struct loop_protect *list) +extfs_resolve_symlinks_int (struct entry *entry, GSList *list) { - struct entry *pent; - struct loop_protect *looping; + struct entry *pent = NULL; 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 = TRUE; - return NULL; - } + if (g_slist_find (list, entry) != NULL) { + /* Here we protect us against symlink looping */ + errloop = TRUE; + } else { + GSList *looping; - looping = g_new (struct loop_protect, 1); - looping->entry = entry; - looping->next = list; - pent = extfs_find_entry_int (entry->dir, entry->inode->linkname, - looping, FALSE, FALSE); - g_free (looping); + looping = g_slist_prepend (list, entry); + pent = extfs_find_entry_int (entry->dir, entry->inode->linkname, + looping, FALSE, FALSE); + g_free (looping); /* It is OK here, no any leaks */ + + if (pent == NULL) + my_errno = ENOENT; + } - if (pent == NULL) - my_errno = ENOENT; return pent; } From 2d43ad1bb4674cef8a69bc5cc11291eee68fff94 Mon Sep 17 00:00:00 2001 From: Andrew Borodin Date: Thu, 28 Jan 2010 17:02:10 +0000 Subject: [PATCH 4/8] Reimplemented work with plugin info. Signed-off-by: Andrew Borodin --- lib/vfs/mc-vfs/extfs.c | 90 +++++++++++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 32 deletions(-) diff --git a/lib/vfs/mc-vfs/extfs.c b/lib/vfs/mc-vfs/extfs.c index 91da15e48..1c0ff92fa 100644 --- a/lib/vfs/mc-vfs/extfs.c +++ b/lib/vfs/mc-vfs/extfs.c @@ -104,6 +104,11 @@ struct archive { struct archive *next; }; +typedef struct { + char *prefix; + gboolean need_archive; +} extfs_plugin_info_t; + static gboolean errloop; static gboolean notadir; @@ -116,10 +121,7 @@ static struct vfs_class vfs_extfs_ops; static struct archive *first_archive = NULL; static int my_errno = 0; -#define MAXEXTFS 32 -static char *extfs_prefixes [MAXEXTFS]; -static char extfs_need_archive [MAXEXTFS]; -static int extfs_no = 0; +GArray *extfs_plugins = NULL; static void extfs_make_dots (struct entry *ent) @@ -295,10 +297,11 @@ extfs_fill_names (struct vfs_class *me, fill_names_f func) (void) me; while (a != NULL) { + extfs_plugin_info_t *info; char *name; - name = g_strconcat (a->name ? a->name : "", "#", - extfs_prefixes[a->fstype], (char *) NULL); + info = &g_array_index (extfs_plugins, extfs_plugin_info_t, a->fstype); + name = g_strconcat (a->name ? a->name : "", "#", info->prefix, (char *) NULL); func (name); g_free (name); a = a->next; @@ -324,6 +327,7 @@ extfs_free_archive (struct archive *archive) static FILE * extfs_open_archive (int fstype, const char *name, struct archive **pparc) { + const extfs_plugin_info_t *info; static dev_t archive_counter = 0; FILE *result; mode_t mode; @@ -333,25 +337,28 @@ extfs_open_archive (int fstype, const char *name, struct archive **pparc) struct archive *current_archive; struct entry *root_entry; char *local_name = NULL, *tmp = NULL; - int uses_archive; - uses_archive = extfs_need_archive[fstype]; - if (uses_archive != 0) { + info = &g_array_index (extfs_plugins, extfs_plugin_info_t, fstype); + + if (info->need_archive) { 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); } mc_extfsdir = concat_dir_and_file (mc_home_alt, "extfs" PATH_SEP_STR); - cmd = g_strconcat (mc_extfsdir, extfs_prefixes[fstype], " list ", + cmd = g_strconcat (mc_extfsdir, info->prefix, " list ", local_name != NULL ? local_name : tmp, (char *) NULL); g_free (tmp); g_free (mc_extfsdir); + open_error_pipe (); result = popen (cmd, "r"); g_free (cmd); @@ -359,7 +366,7 @@ extfs_open_archive (int fstype, const char *name, struct archive **pparc) close_error_pipe (D_ERROR, NULL); if (local_name != NULL) { mc_ungetlocalcopy (name, local_name, 0); - g_free(local_name); + g_free (local_name); } return NULL; } @@ -409,14 +416,18 @@ static int extfs_read_archive (int fstype, const char *name, struct archive **pparc) { FILE *extfsd; + const extfs_plugin_info_t *info; char *buffer; struct archive *current_archive; char *current_file_name, *current_link_name; - extfsd = extfs_open_archive (fstype, name, ¤t_archive); + info = &g_array_index (extfs_plugins, extfs_plugin_info_t, fstype); + + extfsd = extfs_open_archive (fstype, name, ¤t_archive); + if (extfsd == NULL) { message (D_ERROR, MSG_ERROR, _("Cannot open %s archive\n%s"), - extfs_prefixes[fstype], name); + info->prefix, name); return -1; } @@ -536,13 +547,17 @@ read_extfs_continue: static int extfs_which (struct vfs_class *me, const char *path) { - int i; + size_t i; (void) me; - for (i = 0; i < extfs_no; i++) - if (!strcmp (path, extfs_prefixes [i])) + for (i = 0; i < extfs_plugins->len; i++) { + extfs_plugin_info_t *info; + + info = &g_array_index (extfs_plugins, extfs_plugin_info_t, i); + if (strcmp (path, info->prefix) == 0) return i; + } return -1; } @@ -695,6 +710,7 @@ extfs_cmd (const char *str_extfs_cmd, struct archive *archive, char *quoted_file; char *quoted_localname; char *archive_name; + const extfs_plugin_info_t *info; char *mc_extfsdir; char *cmd; int retval; @@ -702,13 +718,14 @@ extfs_cmd (const char *str_extfs_cmd, struct archive *archive, file = extfs_get_path_from_entry (entry); quoted_file = name_quote (file, 0); g_free (file); + archive_name = name_quote (extfs_get_archive_name (archive), 0); quoted_localname = name_quote (localname, 0); - + info = &g_array_index (extfs_plugins, extfs_plugin_info_t, archive->fstype); mc_extfsdir = concat_dir_and_file (mc_home_alt, "extfs" PATH_SEP_STR); - cmd = g_strconcat (mc_extfsdir, extfs_prefixes[archive->fstype], - str_extfs_cmd, archive_name, " ", quoted_file, " ", - quoted_localname, (char *) NULL); + cmd = g_strconcat (mc_extfsdir, info->prefix, str_extfs_cmd, + archive_name, " ", quoted_file, " ", + quoted_localname, (char *) NULL); g_free (quoted_file); g_free (quoted_localname); g_free (mc_extfsdir); @@ -727,6 +744,7 @@ extfs_run (struct vfs_class *me, const char *file) struct archive *archive = NULL; char *p, *q, *archive_name, *mc_extfsdir; char *cmd; + const extfs_plugin_info_t *info; p = extfs_get_path (me, file, &archive, FALSE); if (p == NULL) @@ -736,7 +754,8 @@ extfs_run (struct vfs_class *me, const char *file) archive_name = name_quote (extfs_get_archive_name (archive), 0); mc_extfsdir = concat_dir_and_file (mc_home_alt, "extfs" PATH_SEP_STR); - cmd = g_strconcat (mc_extfsdir, extfs_prefixes[archive->fstype], + info = &g_array_index (extfs_plugins, extfs_plugin_info_t, archive->fstype); + cmd = g_strconcat (mc_extfsdir, info->prefix, " run ", archive_name, " ", q, (char *) NULL); g_free (mc_extfsdir); g_free (archive_name); @@ -1360,8 +1379,10 @@ extfs_init (struct vfs_class *me) return 0; } - extfs_no = 0; - while (extfs_no < MAXEXTFS && fgets (key, sizeof (key), cfg)) { + extfs_plugins = g_array_sized_new (FALSE, TRUE, sizeof (extfs_plugin_info_t), 32); + + while (fgets (key, sizeof (key), cfg) != NULL) { + extfs_plugin_info_t info; char *c; /* Handle those with a trailing ':', those flag that the @@ -1369,12 +1390,13 @@ extfs_init (struct vfs_class *me) */ if (*key == '[') { - fprintf(stderr, "Warning: You need to update your %s file.\n", + fprintf (stderr, "Warning: You need to update your %s file.\n", mc_extfsini); fclose (cfg); g_free (mc_extfsini); return 0; } + if (*key == '#' || *key == '\n') continue; @@ -1384,13 +1406,13 @@ extfs_init (struct vfs_class *me) else /* Last line without newline or strlen (key) > 255 */ c = &key [strlen (key) - 1]; - extfs_need_archive [extfs_no] = !(*c == ':'); + info.need_archive = !(*c == ':'); if (*c == ':') *c = '\0'; - if (*key == '\0') - continue; + if (*key != '\0') + info.prefix = g_strdup (key); - extfs_prefixes [extfs_no++] = g_strdup (key); + g_array_append_val (extfs_plugins, info); } fclose (cfg); g_free (mc_extfsini); @@ -1400,7 +1422,7 @@ extfs_init (struct vfs_class *me) static void extfs_done (struct vfs_class *me) { - int i; + size_t i; struct archive *ar; (void) me; @@ -1410,9 +1432,13 @@ extfs_done (struct vfs_class *me) ar = first_archive; } - for (i = 0; i < extfs_no; i++ ) - g_free (extfs_prefixes [i]); - extfs_no = 0; + for (i = 0; i < extfs_plugins->len; i++) { + extfs_plugin_info_t *info; + + info = &g_array_index (extfs_plugins, extfs_plugin_info_t, i); + g_free (info->prefix); + } + g_array_free (extfs_plugins, TRUE); } static int From ba1d909a7a80badfc931fca97d78f3db4b66f8a7 Mon Sep 17 00:00:00 2001 From: Andrew Borodin Date: Wed, 27 Jan 2010 16:22:56 +0000 Subject: [PATCH 5/8] extfs.ini file is replaced to extfs.d directory. Signed-off-by: Andrew Borodin --- configure.ac | 12 +- lib/fileloc.h | 1 + lib/vfs/mc-vfs/Makefile.am | 2 + lib/vfs/mc-vfs/extfs.c | 107 +++++++++++------- lib/vfs/mc-vfs/extfs/Makefile.am | 32 +++--- .../mc-vfs/extfs/{extfs.ini => README.extfs} | 25 ++-- lib/vfs/mc-vfs/extfs/{a.in => a+.in} | 0 lib/vfs/mc-vfs/extfs/{apt.in => apt+.in} | 0 lib/vfs/mc-vfs/extfs/{dpkg.in => dpkg+.in} | 0 lib/vfs/mc-vfs/extfs/{hp48.in => hp48+.in} | 0 lib/vfs/mc-vfs/extfs/{rpms.in => rpms+.in} | 0 lib/vfs/mc-vfs/extfs/{s3.in => s3+.in} | 0 lib/vfs/mc-vfs/sfs.c | 4 +- 13 files changed, 102 insertions(+), 81 deletions(-) rename lib/vfs/mc-vfs/extfs/{extfs.ini => README.extfs} (66%) rename lib/vfs/mc-vfs/extfs/{a.in => a+.in} (100%) rename lib/vfs/mc-vfs/extfs/{apt.in => apt+.in} (100%) rename lib/vfs/mc-vfs/extfs/{dpkg.in => dpkg+.in} (100%) rename lib/vfs/mc-vfs/extfs/{hp48.in => hp48+.in} (100%) rename lib/vfs/mc-vfs/extfs/{rpms.in => rpms+.in} (100%) rename lib/vfs/mc-vfs/extfs/{s3.in => s3+.in} (100%) diff --git a/configure.ac b/configure.ac index 4c7fb9cf9..7c820c418 100644 --- a/configure.ac +++ b/configure.ac @@ -589,20 +589,20 @@ lib/tty/Makefile lib/vfs/Makefile lib/vfs/mc-vfs/Makefile lib/vfs/mc-vfs/extfs/Makefile -lib/vfs/mc-vfs/extfs/a -lib/vfs/mc-vfs/extfs/apt +lib/vfs/mc-vfs/extfs/a+ +lib/vfs/mc-vfs/extfs/apt+ lib/vfs/mc-vfs/extfs/audio lib/vfs/mc-vfs/extfs/deb lib/vfs/mc-vfs/extfs/deba lib/vfs/mc-vfs/extfs/debd -lib/vfs/mc-vfs/extfs/dpkg +lib/vfs/mc-vfs/extfs/dpkg+ lib/vfs/mc-vfs/extfs/iso9660 -lib/vfs/mc-vfs/extfs/hp48 +lib/vfs/mc-vfs/extfs/hp48+ lib/vfs/mc-vfs/extfs/lslR lib/vfs/mc-vfs/extfs/mailfs lib/vfs/mc-vfs/extfs/patchfs -lib/vfs/mc-vfs/extfs/rpms -lib/vfs/mc-vfs/extfs/s3 +lib/vfs/mc-vfs/extfs/rpms+ +lib/vfs/mc-vfs/extfs/s3+ lib/vfs/mc-vfs/extfs/uace lib/vfs/mc-vfs/extfs/ualz lib/vfs/mc-vfs/extfs/uar diff --git a/lib/fileloc.h b/lib/fileloc.h index 12f000769..0ff7f7bac 100644 --- a/lib/fileloc.h +++ b/lib/fileloc.h @@ -29,6 +29,7 @@ #define CHARSETS_INDEX "mc.charsets" #define MC_LIB_EXT "mc.ext" +#define MC_EXTFS_DIR "extfs.d" #define MC_BASHRC_FILE "bashrc" #define MC_CONFIG_FILE "ini" diff --git a/lib/vfs/mc-vfs/Makefile.am b/lib/vfs/mc-vfs/Makefile.am index f981a0313..4e621ff36 100644 --- a/lib/vfs/mc-vfs/Makefile.am +++ b/lib/vfs/mc-vfs/Makefile.am @@ -8,6 +8,8 @@ DIST_SUBDIRS = extfs SUBDIRS = extfs $(SAMBA_SUBDIRS) AM_CFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir) $(SAMBA_CFLAGS) +AM_CPPFLAGS = -DLIBEXECDIR=\""$(libexecdir)/@PACKAGE@/"\" + BASICFILES = \ cpio.c \ direntry.c \ diff --git a/lib/vfs/mc-vfs/extfs.c b/lib/vfs/mc-vfs/extfs.c index 1c0ff92fa..b31336f37 100644 --- a/lib/vfs/mc-vfs/extfs.c +++ b/lib/vfs/mc-vfs/extfs.c @@ -44,11 +44,13 @@ #include #include #include +#include #include "lib/global.h" +#include "lib/fileloc.h" -#include "src/wtools.h" /* message() */ -#include "src/main.h" /* print_vfs_message */ +#include "src/wtools.h" /* message() */ +#include "src/main.h" /* print_vfs_message */ #include "src/execute.h" /* For shell_execute */ #include "utilvfs.h" @@ -353,7 +355,7 @@ extfs_open_archive (int fstype, const char *name, struct archive **pparc) tmp = name_quote (name, 0); } - mc_extfsdir = concat_dir_and_file (mc_home_alt, "extfs" PATH_SEP_STR); + mc_extfsdir = g_build_path (PATH_SEP_STR, LIBEXECDIR, MC_EXTFS_DIR PATH_SEP_STR, (char *) NULL); cmd = g_strconcat (mc_extfsdir, info->prefix, " list ", local_name != NULL ? local_name : tmp, (char *) NULL); g_free (tmp); @@ -722,7 +724,7 @@ extfs_cmd (const char *str_extfs_cmd, struct archive *archive, archive_name = name_quote (extfs_get_archive_name (archive), 0); quoted_localname = name_quote (localname, 0); info = &g_array_index (extfs_plugins, extfs_plugin_info_t, archive->fstype); - mc_extfsdir = concat_dir_and_file (mc_home_alt, "extfs" PATH_SEP_STR); + mc_extfsdir = g_build_path (PATH_SEP_STR, LIBEXECDIR, MC_EXTFS_DIR PATH_SEP_STR, (char *) NULL); cmd = g_strconcat (mc_extfsdir, info->prefix, str_extfs_cmd, archive_name, " ", quoted_file, " ", quoted_localname, (char *) NULL); @@ -753,7 +755,7 @@ extfs_run (struct vfs_class *me, const char *file) g_free (p); archive_name = name_quote (extfs_get_archive_name (archive), 0); - mc_extfsdir = concat_dir_and_file (mc_home_alt, "extfs" PATH_SEP_STR); + mc_extfsdir = g_build_path (PATH_SEP_STR, LIBEXECDIR, MC_EXTFS_DIR PATH_SEP_STR, (char *) NULL); info = &g_array_index (extfs_plugins, extfs_plugin_info_t, archive->fstype); cmd = g_strconcat (mc_extfsdir, info->prefix, " run ", archive_name, " ", q, (char *) NULL); @@ -1361,61 +1363,78 @@ extfs_ungetlocalcopy (struct vfs_class *me, const char *path, static int extfs_init (struct vfs_class *me) { - FILE *cfg; - char *mc_extfsini; - char key[256]; + char *dirname; + GDir *dir; + const char *filename; (void) me; - mc_extfsini = concat_dir_and_file (mc_home, "extfs" PATH_SEP_STR "extfs.ini"); - cfg = fopen (mc_extfsini, "r"); + dirname = g_build_path (PATH_SEP_STR, LIBEXECDIR, MC_EXTFS_DIR, (char *) NULL); + dir = g_dir_open (dirname, 0, NULL); /* We may not use vfs_die() message or message or similar, * UI is not initialized at this time and message would not * appear on screen. */ - if (cfg == NULL) { - fprintf (stderr, _("Warning: file %s not found\n"), mc_extfsini); - g_free (mc_extfsini); + if (dir == NULL) { + fprintf (stderr, _("Warning: cannot open %s directory\n"), dirname); + g_free (dirname); return 0; } extfs_plugins = g_array_sized_new (FALSE, TRUE, sizeof (extfs_plugin_info_t), 32); - while (fgets (key, sizeof (key), cfg) != NULL) { - extfs_plugin_info_t info; - char *c; + while ((filename = g_dir_read_name (dir)) != NULL) { + char fullname[MC_MAXPATHLEN]; + struct stat s; - /* Handle those with a trailing ':', those flag that the - * file system does not require an archive to work - */ + g_snprintf (fullname, sizeof (fullname), "%s" PATH_SEP_STR "%s", dirname, filename); - if (*key == '[') { - fprintf (stderr, "Warning: You need to update your %s file.\n", - mc_extfsini); - fclose (cfg); - g_free (mc_extfsini); - return 0; + if ((stat (fullname, &s) == 0) + && S_ISREG (s.st_mode) && !S_ISDIR (s.st_mode) + && (((s.st_mode & S_IXOTH) != 0) || + ((s.st_mode & S_IXUSR) != 0) || + ((s.st_mode & S_IXGRP) != 0))) { + int f; + + f = open (fullname, O_RDONLY); + + if (f > 0) { + size_t len; + extfs_plugin_info_t info; + + close (f); + + /* Handle those with a trailing '+', those flag that the + * file system does not require an archive to work + */ + len = strlen (filename); + if (filename [len - 1] != '+') + info.need_archive = TRUE; + else { + info.need_archive = FALSE; + len--; + } + info.prefix = g_strndup (filename, len); + g_array_append_val (extfs_plugins, info); + } } - - if (*key == '#' || *key == '\n') - continue; - - c = strchr (key, '\n'); - if (c != '\0') - *c-- = '\0'; - else /* Last line without newline or strlen (key) > 255 */ - c = &key [strlen (key) - 1]; - - info.need_archive = !(*c == ':'); - if (*c == ':') - *c = '\0'; - if (*key != '\0') - info.prefix = g_strdup (key); - - g_array_append_val (extfs_plugins, info); } - fclose (cfg); - g_free (mc_extfsini); + + g_dir_close (dir); + g_free (dirname); + +#if 0 + { + size_t i; + + for (i = 0; i < extfs_plugins->len; i++) { + extfs_plugin_info_t *info; + info = &g_array_index (extfs_plugins, extfs_plugin_info_t, i); + mc_log ("%s %d\n", info->prefix, info->need_archive ? 1 : 0); + } + } +#endif + return 1; } diff --git a/lib/vfs/mc-vfs/extfs/Makefile.am b/lib/vfs/mc-vfs/extfs/Makefile.am index d955a2c07..d48699fe5 100644 --- a/lib/vfs/mc-vfs/extfs/Makefile.am +++ b/lib/vfs/mc-vfs/extfs/Makefile.am @@ -1,29 +1,29 @@ -extfsdir = $(pkgdatadir)/extfs +extfsdir = $(libexecdir)/@PACKAGE@/extfs.d -EXTFSCONFFILES = extfs.ini sfs.ini +EXTFSCONFFILES = sfs.ini # Files to install and distribute other than extfs scripts -EXTFS_MISC = README +EXTFS_MISC = README README.extfs # Scripts hat don't need adaptation to the local system EXTFS_CONST = bpp rpm trpm u7z ucab # Scripts that need adaptation to the local system - source files EXTFS_IN = \ - a.in \ - apt.in \ + a+.in \ + apt+.in \ audio.in \ deb.in \ deba.in \ debd.in \ - dpkg.in \ + dpkg+.in \ iso9660.in \ - hp48.in \ + hp48+.in \ lslR.in \ mailfs.in \ patchfs.in \ - rpms.in \ - s3.in \ + rpms+.in \ + s3+.in \ uace.in \ ualz.in \ uar.in \ @@ -38,20 +38,20 @@ EXTFS_IN = \ # Scripts that need adaptation to the local system - files to install EXTFS_OUT = \ - a \ - apt \ + a+ \ + apt+ \ audio \ deb \ deba \ debd \ - dpkg \ + dpkg+ \ iso9660 \ - hp48 \ + hp48+ \ lslR \ mailfs \ patchfs \ - rpms \ - s3 \ + rpms+ \ + s3+ \ uace \ ualz \ uar \ @@ -68,7 +68,7 @@ if ENABLE_VFS extfs_DATA = $(EXTFS_MISC) extfs_SCRIPTS = $(EXTFS_CONST) $(EXTFS_OUT) -extfsconfdir = $(sysconfdir)/@PACKAGE@/extfs +extfsconfdir = $(sysconfdir)/@PACKAGE@ extfsconf_DATA = $(EXTFSCONFFILES) endif diff --git a/lib/vfs/mc-vfs/extfs/extfs.ini b/lib/vfs/mc-vfs/extfs/README.extfs similarity index 66% rename from lib/vfs/mc-vfs/extfs/extfs.ini rename to lib/vfs/mc-vfs/extfs/README.extfs index f4d04a2cf..b4509414c 100644 --- a/lib/vfs/mc-vfs/extfs/extfs.ini +++ b/lib/vfs/mc-vfs/extfs/README.extfs @@ -1,7 +1,7 @@ -# Each external VFS type must be registered here if you want to use it -# Trailing colon means that the filesystem is not tied to a certain file +# Each external VFS type must be registered in extfs.d directory if you want to use it. +# Trailing plus means that the filesystem is not tied to a certain file. -# Popular pc archivers +# Popular PC archivers uzip uzoo ulha @@ -9,7 +9,7 @@ urar uha u7z ualz -# For arj usage you need a special patch to unarj (see unarj.diff) +# FIXME: for arj usage you need a special patch to unarj (see unarj.diff) uarj uarc uace @@ -24,14 +24,14 @@ uar rpm deb -# a: - mtools filesystem -a: +# a+ - mtools filesystem +a+ # For browsing lslR listings (found on many ftp sites) lslR # Hewlett Packard calculator -hp48: +hp48+ # Commodore 64/128 d64/D64 files uc1541 @@ -43,18 +43,18 @@ patchfs mailfs # List all installed RPM packages on the system -rpms: +rpms+ trpm # dpkg frontend -dpkg: +dpkg+ debd # apt frontend -apt: +apt+ deba -# Simple filesystem for audio cdroms. Use /dev/cdrom#audio (or /#audio). +# Simple filesystem for audio cdroms. Use /dev/cdrom#audio (or /#audio) audio # Package of Bad Penguin (an Italian GNU/Linux distribution) @@ -64,5 +64,4 @@ bpp iso9660 # Amazon S3 -s3: - +s3+ diff --git a/lib/vfs/mc-vfs/extfs/a.in b/lib/vfs/mc-vfs/extfs/a+.in similarity index 100% rename from lib/vfs/mc-vfs/extfs/a.in rename to lib/vfs/mc-vfs/extfs/a+.in diff --git a/lib/vfs/mc-vfs/extfs/apt.in b/lib/vfs/mc-vfs/extfs/apt+.in similarity index 100% rename from lib/vfs/mc-vfs/extfs/apt.in rename to lib/vfs/mc-vfs/extfs/apt+.in diff --git a/lib/vfs/mc-vfs/extfs/dpkg.in b/lib/vfs/mc-vfs/extfs/dpkg+.in similarity index 100% rename from lib/vfs/mc-vfs/extfs/dpkg.in rename to lib/vfs/mc-vfs/extfs/dpkg+.in diff --git a/lib/vfs/mc-vfs/extfs/hp48.in b/lib/vfs/mc-vfs/extfs/hp48+.in similarity index 100% rename from lib/vfs/mc-vfs/extfs/hp48.in rename to lib/vfs/mc-vfs/extfs/hp48+.in diff --git a/lib/vfs/mc-vfs/extfs/rpms.in b/lib/vfs/mc-vfs/extfs/rpms+.in similarity index 100% rename from lib/vfs/mc-vfs/extfs/rpms.in rename to lib/vfs/mc-vfs/extfs/rpms+.in diff --git a/lib/vfs/mc-vfs/extfs/s3.in b/lib/vfs/mc-vfs/extfs/s3+.in similarity index 100% rename from lib/vfs/mc-vfs/extfs/s3.in rename to lib/vfs/mc-vfs/extfs/s3+.in diff --git a/lib/vfs/mc-vfs/sfs.c b/lib/vfs/mc-vfs/sfs.c index e39640182..a5a242382 100644 --- a/lib/vfs/mc-vfs/sfs.c +++ b/lib/vfs/mc-vfs/sfs.c @@ -344,10 +344,10 @@ static int sfs_init (struct vfs_class *me) (void) me; - mc_sfsini = concat_dir_and_file (mc_home, "extfs" PATH_SEP_STR "sfs.ini"); + mc_sfsini = g_build_filename (mc_home, "sfs.ini", (char *) NULL); cfg = fopen (mc_sfsini, "r"); - if (!cfg){ + if (cfg == NULL) { fprintf (stderr, _("Warning: file %s not found\n"), mc_sfsini); g_free (mc_sfsini); return 0; From b7d5a5852c5f61a46e84f4b861fe2f4ad922a947 Mon Sep 17 00:00:00 2001 From: Andrew Borodin Date: Tue, 9 Feb 2010 17:33:06 +0000 Subject: [PATCH 6/8] 2-level extfs plugin structure. extfs vfs plugins are read from following places: 1. ~/.mc/extfs.d directory. 2. /usr/libexec/mc/extfs.d direcotry. Priority of plugins installed in user home directory is highest. If there are two plugins with same names exist in user home and system directories, the plugin from user home is used. Signed-off-by: Andrew Borodin --- lib/vfs/mc-vfs/extfs.c | 89 ++++++++++++++++++++++++++---------------- 1 file changed, 56 insertions(+), 33 deletions(-) diff --git a/lib/vfs/mc-vfs/extfs.c b/lib/vfs/mc-vfs/extfs.c index b31336f37..a7bcd15f8 100644 --- a/lib/vfs/mc-vfs/extfs.c +++ b/lib/vfs/mc-vfs/extfs.c @@ -107,6 +107,7 @@ struct archive { }; typedef struct { + char *path; char *prefix; gboolean need_archive; } extfs_plugin_info_t; @@ -334,7 +335,6 @@ extfs_open_archive (int fstype, const char *name, struct archive **pparc) FILE *result; mode_t mode; char *cmd; - char *mc_extfsdir; struct stat mystat; struct archive *current_archive; struct entry *root_entry; @@ -355,11 +355,9 @@ extfs_open_archive (int fstype, const char *name, struct archive **pparc) tmp = name_quote (name, 0); } - mc_extfsdir = g_build_path (PATH_SEP_STR, LIBEXECDIR, MC_EXTFS_DIR PATH_SEP_STR, (char *) NULL); - cmd = g_strconcat (mc_extfsdir, info->prefix, " list ", + cmd = g_strconcat (info->path, info->prefix, " list ", local_name != NULL ? local_name : tmp, (char *) NULL); g_free (tmp); - g_free (mc_extfsdir); open_error_pipe (); result = popen (cmd, "r"); @@ -713,7 +711,6 @@ extfs_cmd (const char *str_extfs_cmd, struct archive *archive, char *quoted_localname; char *archive_name; const extfs_plugin_info_t *info; - char *mc_extfsdir; char *cmd; int retval; @@ -724,13 +721,11 @@ extfs_cmd (const char *str_extfs_cmd, struct archive *archive, archive_name = name_quote (extfs_get_archive_name (archive), 0); quoted_localname = name_quote (localname, 0); info = &g_array_index (extfs_plugins, extfs_plugin_info_t, archive->fstype); - mc_extfsdir = g_build_path (PATH_SEP_STR, LIBEXECDIR, MC_EXTFS_DIR PATH_SEP_STR, (char *) NULL); - cmd = g_strconcat (mc_extfsdir, info->prefix, str_extfs_cmd, + cmd = g_strconcat (info->path, info->prefix, str_extfs_cmd, archive_name, " ", quoted_file, " ", quoted_localname, (char *) NULL); g_free (quoted_file); g_free (quoted_localname); - g_free (mc_extfsdir); g_free (archive_name); open_error_pipe (); @@ -744,7 +739,7 @@ static void extfs_run (struct vfs_class *me, const char *file) { struct archive *archive = NULL; - char *p, *q, *archive_name, *mc_extfsdir; + char *p, *q, *archive_name; char *cmd; const extfs_plugin_info_t *info; @@ -755,11 +750,9 @@ extfs_run (struct vfs_class *me, const char *file) g_free (p); archive_name = name_quote (extfs_get_archive_name (archive), 0); - mc_extfsdir = g_build_path (PATH_SEP_STR, LIBEXECDIR, MC_EXTFS_DIR PATH_SEP_STR, (char *) NULL); info = &g_array_index (extfs_plugins, extfs_plugin_info_t, archive->fstype); - cmd = g_strconcat (mc_extfsdir, info->prefix, + cmd = g_strconcat (info->path, info->prefix, " run ", archive_name, " ", q, (char *) NULL); - g_free (mc_extfsdir); g_free (archive_name); g_free (q); shell_execute (cmd, 0); @@ -1360,28 +1353,28 @@ extfs_ungetlocalcopy (struct vfs_class *me, const char *path, } } -static int -extfs_init (struct vfs_class *me) +static gboolean +extfs_get_plugins (const char *where, gboolean silent) { char *dirname; GDir *dir; const char *filename; - (void) me; - - dirname = g_build_path (PATH_SEP_STR, LIBEXECDIR, MC_EXTFS_DIR, (char *) NULL); + dirname = g_build_path (PATH_SEP_STR, where, MC_EXTFS_DIR, (char *) NULL); dir = g_dir_open (dirname, 0, NULL); /* We may not use vfs_die() message or message or similar, * UI is not initialized at this time and message would not * appear on screen. */ if (dir == NULL) { - fprintf (stderr, _("Warning: cannot open %s directory\n"), dirname); + if (!silent) + fprintf (stderr, _("Warning: cannot open %s directory\n"), dirname); g_free (dirname); - return 0; + return FALSE; } - extfs_plugins = g_array_sized_new (FALSE, TRUE, sizeof (extfs_plugin_info_t), 32); + if (extfs_plugins == NULL) + extfs_plugins = g_array_sized_new (FALSE, TRUE, sizeof (extfs_plugin_info_t), 32); while ((filename = g_dir_read_name (dir)) != NULL) { char fullname[MC_MAXPATHLEN]; @@ -1399,8 +1392,9 @@ extfs_init (struct vfs_class *me) f = open (fullname, O_RDONLY); if (f > 0) { - size_t len; + size_t len, i; extfs_plugin_info_t info; + gboolean found = FALSE; close (f); @@ -1414,8 +1408,29 @@ extfs_init (struct vfs_class *me) info.need_archive = FALSE; len--; } + + info.path = g_strconcat (dirname, PATH_SEP_STR, (char *) NULL); info.prefix = g_strndup (filename, len); - g_array_append_val (extfs_plugins, info); + + /* don't overload already found plugin */ + for (i = 0; i < extfs_plugins->len; i++) { + extfs_plugin_info_t *p; + + p = &g_array_index (extfs_plugins, extfs_plugin_info_t, i); + + /* 2 files with same names cannot be in a directory */ + if ((strcmp (info.path, p->path) != 0) + && (strcmp (info.prefix, p->prefix) == 0)) { + found = TRUE; + break; + } + } + + if (found) { + g_free (info.path); + g_free (info.prefix); + } else + g_array_append_val (extfs_plugins, info); } } } @@ -1423,19 +1438,26 @@ extfs_init (struct vfs_class *me) g_dir_close (dir); g_free (dirname); -#if 0 - { - size_t i; + return TRUE; +} - for (i = 0; i < extfs_plugins->len; i++) { - extfs_plugin_info_t *info; - info = &g_array_index (extfs_plugins, extfs_plugin_info_t, i); - mc_log ("%s %d\n", info->prefix, info->need_archive ? 1 : 0); - } - } -#endif - return 1; +static int +extfs_init (struct vfs_class *me) +{ + gboolean d1, d2; + char *dirname; + + (void) me; + + /* 1st: scan user directory */ + dirname = g_build_path (PATH_SEP_STR, home_dir, MC_USERCONF_DIR, (char *) NULL); + d1 = extfs_get_plugins (dirname, TRUE); /* silent about user dir */ + g_free (dirname); + /* 2nd: scan system dir */ + d2 = extfs_get_plugins (LIBEXECDIR, d1); + + return (d1 || d2 ? 1 : 0); } static void @@ -1455,6 +1477,7 @@ extfs_done (struct vfs_class *me) extfs_plugin_info_t *info; info = &g_array_index (extfs_plugins, extfs_plugin_info_t, i); + g_free (info->path); g_free (info->prefix); } g_array_free (extfs_plugins, TRUE); From aa6f8e45e7455ee85fe7ad579ba1146086496dda Mon Sep 17 00:00:00 2001 From: Andrew Borodin Date: Tue, 9 Feb 2010 21:39:50 +0300 Subject: [PATCH 7/8] Fixed file list in RPM spec file. Signed-off-by: Andrew Borodin --- contrib/dist/redhat/mc.spec.in | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/contrib/dist/redhat/mc.spec.in b/contrib/dist/redhat/mc.spec.in index e6edf724c..572d49ba7 100644 --- a/contrib/dist/redhat/mc.spec.in +++ b/contrib/dist/redhat/mc.spec.in @@ -122,8 +122,13 @@ rm -rf $RPM_BUILD_ROOT %{_bindir}/mcedit %{_bindir}/mcview %{_bindir}/mcmfmt + +%dir %{_libexecdir}/mc +%dir %{_libexecdir}/mc/extfs.d %attr(4511, vcsa, tty) %{_libexecdir}/mc/cons.saver %{_libexecdir}/mc/mc*sh +%{_libexecdir}/mc/extfs.d/* + %{_mandir}/man1/* %lang(es) %{_mandir}/es/man1/mc.1* %lang(hu) %{_mandir}/hu/man1/mc.1* @@ -142,17 +147,18 @@ rm -rf $RPM_BUILD_ROOT %config(noreplace) %{_sysconfdir}/mc/mc.ext %config(noreplace) %{_sysconfdir}/mc/mc.menu %config(noreplace) %{_sysconfdir}/mc/mc.menu.* -%config(noreplace) %{_sysconfdir}/mc/extfs/extfs.ini -%config(noreplace) %{_sysconfdir}/mc/extfs/sfs.ini +%config(noreplace) %{_sysconfdir}/mc/sfs.ini %config(noreplace) %{_sysconfdir}/mc/mc.keymap %config(noreplace) %{_sysconfdir}/mc/mc.keymap.* %dir %{_datadir}/mc %{_datadir}/mc/* -%dir %{_libexecdir}/mc %changelog +* Tue Feb 09 2010 Andrew Borodin +- Fixed file list because of EXTFS VFS reorganizing. + * Wed Dec 30 2009 Yury V. Zaytsev - Bumped the epoch again and changed the versioning scheme. - Thanks to Slava Zanko for all his hard work on m4 vodoo! From d5d15896657301b4ad9bb445046f755cb33046ae Mon Sep 17 00:00:00 2001 From: Andrew Borodin Date: Tue, 9 Feb 2010 22:02:17 +0300 Subject: [PATCH 8/8] Replaced hardcoded '/' symbols. Symbolic names and GLib functions are used instead of hardcoded '/' symbols. Signed-off-by: Andrew Borodin --- lib/vfs/mc-vfs/extfs.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/lib/vfs/mc-vfs/extfs.c b/lib/vfs/mc-vfs/extfs.c index a7bcd15f8..a8f086c4b 100644 --- a/lib/vfs/mc-vfs/extfs.c +++ b/lib/vfs/mc-vfs/extfs.c @@ -208,8 +208,9 @@ extfs_find_entry_int (struct entry *dir, char *name, GSList *list, char *p, *q, *name_end; char c = PATH_SEP; - if (*name == '/') { /* Handle absolute paths */ - name++; + if (g_path_is_absolute (name)) { + /* Handle absolute paths */ + name = g_path_skip_root (name); dir = dir->inode->archive->root_entry; } @@ -217,7 +218,7 @@ extfs_find_entry_int (struct entry *dir, char *name, GSList *list, p = name; name_end = name + strlen (name); - q = strchr (p, '/'); + q = strchr (p, PATH_SEP); if (q == '\0') q = strchr (p, '\0'); @@ -265,7 +266,7 @@ extfs_find_entry_int (struct entry *dir, char *name, GSList *list, /* Next iteration */ *q = c; p = q + 1; - q = strchr (p, '/'); + q = strchr (p, PATH_SEP); if (q == '\0') q = strchr (p, '\0'); } @@ -395,7 +396,7 @@ extfs_open_archive (int fstype, const char *name, struct archive **pparc) if (mode & 0004) mode |= 0001; mode |= S_IFDIR; - root_entry = extfs_generate_entry (current_archive, "/", NULL, mode); + root_entry = extfs_generate_entry (current_archive, PATH_SEP_STR, NULL, mode); root_entry->inode->uid = mystat.st_uid; root_entry->inode->gid = mystat.st_gid; root_entry->inode->atime = mystat.st_atime; @@ -443,12 +444,12 @@ extfs_read_archive (int fstype, const char *name, struct archive **pparc) char *p, *q, *cfn = current_file_name; if (*cfn != '\0') { - if (*cfn == '/') + if (*cfn == PATH_SEP) cfn++; p = strchr (cfn, '\0'); - if (p != cfn && *(p - 1) == '/') + if (p != cfn && *(p - 1) == PATH_SEP) *(p - 1) = '\0'; - p = strrchr (cfn, '/'); + p = strrchr (cfn, PATH_SEP); if (p == NULL) { p = cfn; q = strchr (cfn, '\0'); @@ -587,7 +588,7 @@ extfs_get_path_mangle (struct vfs_class *me, char *inname, struct archive **arch /* * All filesystems should have some local archive, at least - * it can be '/'. + * it can be PATH_SEP ('/'). */ for (parc = first_archive; parc != NULL; parc = parc->next) if (parc->name != NULL) {