From 286c61a200e17d61f2220ceea74e66f210e54298 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Mon, 31 Aug 1998 10:02:52 +0000 Subject: [PATCH] Undelfs was too broken for too long. --- src/cmd.c | 18 ++++- vfs/ChangeLog | 15 ++++ vfs/undelfs.c | 162 +++++++++------------------------------- vfs/vfs.c | 203 ++++++++++++++++++++++++-------------------------- 4 files changed, 163 insertions(+), 235 deletions(-) diff --git a/src/cmd.c b/src/cmd.c index daefb2fa9..386fe5c30 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -272,6 +272,18 @@ void view_cmd (WPanel *panel) do_view_cmd (panel, 0); } +void view_file_cmd (WPanel *panel) +{ + char *filename; + + panel = get_a_panel (panel); + filename = input_dialog (_(" View file "), _(" Filename:"), selection (panel)->fname); + if (!filename) return; + + view_file (filename, 0, use_internal_view); + free (filename); +} + void view_simple_cmd (WPanel *panel) { do_view_cmd (panel, 1); @@ -1294,9 +1306,9 @@ void source_routing (void) void undelete_cmd (void) { nice_cd (_(" Undelete files on an ext2 file system "), - _(" Enter the file system name where you want to run the\n " - " undelete file system on: (F1 for details)"), - "[Undelete File System]", "/#undel/", 0); + _(" Enter device (without /dev/) to undelete\n " + " files on: (F1 for details)"), + "[Undelete File System]", "/#undel:", 0); } #endif diff --git a/vfs/ChangeLog b/vfs/ChangeLog index b5fe5e1bb..e8a197707 100644 --- a/vfs/ChangeLog +++ b/vfs/ChangeLog @@ -1,3 +1,18 @@ +Sun Aug 30 13:19:49 1998 Pavel Machek + + * undelfs.c: fixed, it has been broken for too long + + * vfs.c, ../src/cmd.c: neccessary minor fixes to make undelfs work + + * vfs.c: made more fields in *_vfs_ops optional, cleanup of errno + handling in case of NULL in *_vfs_ops. + + * extfs.c, ftpfs.c, tar.c: made use of above change + + * vfs.c: cleanup of macros generating mc_*() + + * libvfs.c: adding variable mc_home + Thu Aug 27 19:45:31 1998 Pavel Roskin * extfs.c: mc_extfsdir was not defined in extfs_open() diff --git a/vfs/undelfs.c b/vfs/undelfs.c index fa9bf75bf..98c65bace 100644 --- a/vfs/undelfs.c +++ b/vfs/undelfs.c @@ -26,7 +26,7 @@ /* Assumptions: * - * 1. We don't handle directories (thus undelfs_getpath is easy to write). + * 1. We don't handle directories (thus undelfs_get_path is easy to write). * 2. Files are on the local file system (we do not support vfs files * because we would have to provide an io_manager for the ext2fs tools, * and I don't think it would be too useful to undelete files @@ -86,7 +86,7 @@ static int undelfs_usage; #define READDIR_PTR_INIT 0 static void -undelfs_shutdown () +undelfs_shutdown (void) { if (fs) ext2fs_close (fs); @@ -107,33 +107,44 @@ undelfs_get_path (char *dirname, char **ext2_fname, char **file) { char *p; + /* To look like filesystem, we have virtual directories + /#undel:XXX, which have no subdirectories. XXX is replaced with + hda5, sdb8 etc, which is assumed to live under /dev. + -- pavel@ucw.cz */ + *ext2_fname = 0; - if (strncmp (dirname, "undel:", 6)) + if (strncmp (dirname, "/#undel:", 8)) return; else - dirname += 6; + dirname += 8; /* Since we don't allow subdirectories, it's easy to get a filename, - * just scan backwards for a slash - */ + * just scan backwards for a slash */ if (*dirname == 0) return; p = dirname + strlen (dirname); +#if 0 + /* Strip trailing ./ + */ if (p - dirname > 2 && *(p-1) == '/' && *(p-2) == '.') *(p = p-2) = 0; +#endif while (p > dirname){ if (*p == '/'){ *file = strdup (p+1); *p = 0; - *ext2_fname = strdup (dirname); + *ext2_fname = copy_strings ("/dev/", dirname, NULL); *p = '/'; return; } p--; } + *file = strdup (""); + *ext2_fname = copy_strings ("/dev/", dirname, NULL); + return; } static int @@ -159,7 +170,7 @@ lsdel_proc(ext2_filsys fs, blk_t *block_nr, int blockcnt, void *private) * if we don't have enough memory */ static int -undelfs_loaddel () +undelfs_loaddel (void) { int retval, count; ino_t ino; @@ -519,13 +530,6 @@ undelfs_read (void *vfs_info, char *buffer, int count) return p->dest_buffer - buffer; } -static int -undelfs_write (void *vfs_info, char *buf, int count) -{ - /* No writes allowed */ - return -1; -} - static long undelfs_getindex (char *path) { @@ -608,48 +612,6 @@ undelfs_fstat (void *vfs_info, struct stat *buf) return do_stat (p->f_index, buf); } -static int -undelfs_chmod(char *path, int mode) -{ - return -1; -} - -static int -undelfs_chown(char *path, int owner, int group) -{ - return -1; -} - -static int -undelfs_readlink(char *path, char *buf, int size) -{ - return -1; -} - -static int -undelfs_symlink(char *n1, char *n2) -{ - return -1; -} - -static int -undelfs_link(char *p1, char *p2) -{ - return -1; -} - -static int -undelfs_unlink(char *path) -{ - return -1; -} - -static int -undelfs_rename(char *p1, char *p2) -{ - return -1; -} - static int undelfs_chdir(char *path) { @@ -675,24 +637,13 @@ undelfs_chdir(char *path) return 0; } -static int -undelfs_ferrno(void) -{ - return -1; -} - +/* this has to stay here for now: vfs layer does not know how to emulate it */ static int undelfs_lseek(void *vfs_info, off_t offset, int whence) { return -1; } -static int -undelfs_mknod(char *path, int mode, int dev) -{ - return -1; -} - static vfsid undelfs_getid(char *path, struct vfs_stamping **parent) { @@ -721,50 +672,11 @@ undelfs_free(vfsid id) undelfs_shutdown (); } -static char * -undelfs_getlocalcopy(char *filename) -{ - return 0; -} - -static void -undelfs_ungetlocalcopy(char *filename, char *local, int has_changed) -{ -} - -static int -undelfs_mkdir(char *path, mode_t mode) -{ - return -1; -} - -static int -undelfs_rmdir(char *path) -{ - return -1; -} - - -#ifdef HAVE_MMAP -static caddr_t -undelfs_mmap(caddr_t addr, size_t len, int prot, int flags, void *vfs_info, off_t offset) -{ - return (caddr_t) -1; -} - -static int -undelfs_munmap(caddr_t addr, size_t len, void *vfs_info) -{ - return -1; -} -#endif - - vfs undelfs_vfs_ops = { undelfs_open, undelfs_close, undelfs_read, - undelfs_write, + NULL, undelfs_opendir, undelfs_readdir, @@ -776,35 +688,35 @@ vfs undelfs_vfs_ops = { undelfs_lstat, undelfs_fstat, - undelfs_chmod, - undelfs_chown, + NULL, + NULL, NULL, - undelfs_readlink, - undelfs_symlink, - undelfs_link, - undelfs_unlink, + NULL, /* readlink */ + NULL, + NULL, + NULL, - undelfs_rename, + NULL, undelfs_chdir, - undelfs_ferrno, - undelfs_lseek, - undelfs_mknod, + NULL, + undelfs_lseek, + NULL, undelfs_getid, undelfs_nothingisopen, undelfs_free, - undelfs_getlocalcopy, - undelfs_ungetlocalcopy, + NULL, /* get_local_copy */ + NULL, - undelfs_mkdir, - undelfs_rmdir, + NULL, + NULL, NULL, NULL, NULL #ifdef HAVE_MMAP - , undelfs_mmap, - undelfs_munmap + , NULL, + NULL #endif }; diff --git a/vfs/vfs.c b/vfs/vfs.c index 1a4555390..7bc6adae0 100644 --- a/vfs/vfs.c +++ b/vfs/vfs.c @@ -108,7 +108,7 @@ vfs *vfs_type_from_op (char *path) return &ftpfs_vfs_ops; #endif #ifdef USE_EXT2FSLIB - if (!(vfs_flags & FL_NO_UNDELFS) && !strcmp (path, "undel")) + if (!(vfs_flags & FL_NO_UNDELFS) && !strncmp (path, "undel:", 6)) return &undelfs_vfs_ops; #endif if (!(vfs_flags & FL_NO_TARFS) && !strcmp (path, "utar")) @@ -309,7 +309,7 @@ int mc_open (char *file, int flags, ...) va_end (ap); if (!vfs->open) - vfs_die( "VFS must support open\n" ); + vfs_die( "VFS must support open.\n" ); info = (*vfs->open) (file, flags, mode); /* open must be supported */ free (file); if (!info){ @@ -337,12 +337,14 @@ int mc_open (char *file, int flags, ...) result = vfs->name ? (*vfs->name)callarg : -1; \ post \ if (result == -1) \ - errno = ferrno (vfs); \ + errno = vfs->name ? ferrno (vfs) : EOPNOTSUPP; \ return result; \ } -#define MC_NAMEOP(name, inarg, callarg) MC_OP (name, inarg, callarg, path = vfs_canon (path); vfs = vfs_type (path);, free (path); ) -#define MC_HANDLEOP(name, inarg, callarg) MC_OP (name, inarg, callarg, if (handle == -1) return -1; vfs = vfs_op (handle);, ) +#define MC_NAMEOP(name, inarg, callarg) \ + MC_OP (name, inarg, callarg, path = vfs_canon (path); vfs = vfs_type (path);, free (path); ) +#define MC_HANDLEOP(name, inarg, callarg) \ + MC_OP (name, inarg, callarg, if (handle == -1) return -1; vfs = vfs_op (handle);, ) MC_HANDLEOP(read, (int handle, char *buffer, int count), (vfs_info (handle), buffer, count) ); @@ -380,7 +382,9 @@ int mc_close (int handle) if (handle < 3) return close (handle); - result = (*vfs->close)(vfs_info (handle)); /* close must be supported */ + if (!vfs->close) + vfs_die( "VFS must support close.\n" ); + result = (*vfs->close)(vfs_info (handle)); vfs_free_bucket (handle); if (result == -1) errno = ferrno (vfs); @@ -408,19 +412,16 @@ DIR *mc_opendir (char *dirname) info = vfs->opendir ? (*vfs->opendir)(dirname) : NULL; free (dirname); + if (p) + free (p); if (!info){ - errno = ferrno (vfs); - if (p) - free (p); + errno = vfs->opendir ? ferrno (vfs) : EOPNOTSUPP; return NULL; } handle = get_bucket (); vfs_file_table [handle].fs_info = info; vfs_file_table [handle].operations = vfs; - if (p) - free (p); - handlep = (int *) xmalloc (sizeof (int), "opendir handle"); *handlep = handle; return (DIR *) handlep; @@ -429,11 +430,29 @@ DIR *mc_opendir (char *dirname) /* This should strip the non needed part of a path name */ #define vfs_name(x) x -#define MC_DIROP(name, type, inarg, callarg, onerr ) \ -type mc_##name inarg \ +void mc_seekdir (DIR *dirp, int offset) +{ + int handle; + vfs *vfs; + + if (!dirp){ + errno = EFAULT; + return; + } + handle = *(int *) dirp; + vfs = vfs_op (handle); + if (vfs->seekdir) + (*vfs->seekdir) (vfs_info (handle), offset); + else + errno = EOPNOTSUPP; +} + +#define MC_DIROP(name, type, onerr ) \ +type mc_##name (DIR *dirp) \ { \ int handle; \ vfs *vfs; \ + type result; \ \ if (!dirp){ \ errno = EFAULT; \ @@ -441,28 +460,14 @@ type mc_##name inarg \ } \ handle = *(int *) dirp; \ vfs = vfs_op (handle); \ - return vfs->name ? (*vfs->name) callarg : onerr; \ + result = vfs->name ? (*vfs->name) (vfs_info (handle)) : onerr; \ + if (result == onerr) \ + errno = vfs->name ? ferrno(vfs) : EOPNOTSUPP; \ + return result; \ } -#define MC_DIROP_VOID(name, inarg, callarg ) \ -void mc_##name inarg \ -{ \ - int handle; \ - vfs *vfs; \ -\ - if (!dirp){ \ - errno = EFAULT; \ - return; \ - } \ - handle = *(int *) dirp; \ - vfs = vfs_op (handle); \ - if (vfs->name) \ - (*vfs->name) callarg; \ -} - -MC_DIROP (readdir, struct dirent *, (DIR *dirp), (vfs_info (handle)), NULL) -MC_DIROP_VOID (seekdir, (DIR *dirp, int offset), (vfs_info (handle), offset)) -MC_DIROP (telldir, int, (DIR *dirp), (vfs_info (handle)), -1) +MC_DIROP (readdir, struct dirent *, NULL) +MC_DIROP (telldir, int, -1) int mc_closedir (DIR *dirp) { @@ -514,7 +519,7 @@ char *mc_get_current_wd (char *buffer, int size) { char *cwd = mc_return_cwd(); if (strlen (cwd) > size){ - vfs_die ("Current_dir size overflow\n"); + vfs_die ("Current_dir size overflow.\n"); } strcpy (buffer, cwd); return buffer; @@ -527,73 +532,48 @@ MC_NAMEOP (readlink, (char *path, char *buf, int bufsiz), (vfs_name (path), buf, MC_NAMEOP (unlink, (char *path), (vfs_name (path))) MC_NAMEOP (symlink, (char *name1, char *path), (vfs_name (name1), vfs_name (path))) -int mc_link (char *name1, char *name2) -{ - vfs *vfs1; - vfs *vfs2; - int result; - - name1 = vfs_canon (name1); - vfs1 = vfs_type (name1); - name2 = vfs_canon (name2); - vfs2 = vfs_type (name2); - - if (vfs1 != vfs2){ - errno = EXDEV; - free (name1); - free (name2); - return -1; - } - - result = (*vfs1->link)(vfs_name (name1), vfs_name (name2)); - free (name1); - free (name2); - if (result == -1){ - errno = (*vfs1->ferrno)(); - return -1; - } - return result; +#define MC_RENAMEOP(name) \ +int mc_##name (char *name1, char *name2) \ +{ \ + vfs *vfs; \ + int result; \ +\ + name1 = vfs_canon (name1); \ + vfs = vfs_type (name1); \ + name2 = vfs_canon (name2); \ + if (vfs != vfs_type (name2)){ \ + errno = EXDEV; \ + free (name1); \ + free (name2); \ + return -1; \ + } \ +\ + result = vfs->name ? (*vfs->name)(vfs_name (name1), vfs_name (name2)) : -1; \ + free (name1); \ + free (name2); \ + if (result == -1) \ + errno = vfs->name ? ferrno (vfs) : EOPNOTSUPP; \ + return result; \ } +MC_RENAMEOP (link); +MC_RENAMEOP (rename); + MC_HANDLEOP (write, (int handle, char *buf, int nbyte), (vfs_info (handle), buf, nbyte)); -int mc_rename (char *path1, char *path2) -{ - vfs *vfs1; - vfs *vfs2; - int result; - - path1 = vfs_canon (path1); - vfs1 = vfs_type (path1); - path2 = vfs_canon (path2); - vfs2 = vfs_type (path2); - - if (vfs1 != vfs2){ - errno = EXDEV; - free (path1); - free (path2); - return -1; - } - - result = (*vfs1->rename)(vfs_name (path1), vfs_name (path2)); - free (path1); - free (path2); - if (result == -1){ - errno = (*vfs1->ferrno)(); - return -1; - } - return result; -} - off_t mc_lseek (int fd, off_t offset, int whence) { vfs *vfs; + int result; if (fd == -1) return -1; vfs = vfs_op (fd); - return (*vfs->lseek)(vfs_info (fd), offset, whence); + result = vfs->lseek ? (*vfs->lseek)(vfs_info (fd), offset, whence) : -1; + if (result == -1) + errno = vfs->lseek ? ferrno (vfs) : EOPNOTSUPP; + return result; } /* @@ -612,7 +592,7 @@ vfs_kill_dots (char *path, char *local) while (1){ if (ISSLASH (*s)){ if (*last_slash != '/') - vfs_die ("/ not there\n"); + vfs_die ("/ not there.\n"); if (ISSLASH (last_slash [1])) t--; @@ -839,7 +819,7 @@ int mc_chdir (char *path) result = (*current_vfs->chdir)(vfs_name (b)); free (b); if (result == -1){ - errno = (*current_vfs->ferrno)(); + errno = ferrno (current_vfs); free (current_dir); current_vfs = vfs_type (a); current_dir = a; @@ -911,7 +891,7 @@ void vfs_setup_wd (void) mc_return_cwd(); /* mc_return_cwd will fixup current_dir for us */ if (strlen(current_dir)>MC_MAXPATHLEN-2) - vfs_die ("Current dir too long\n"); + vfs_die ("Current dir too long.\n"); return; } @@ -939,9 +919,9 @@ mc_mmap (caddr_t addr, size_t len, int prot, int flags, int fd, off_t offset) return (caddr_t) -1; vfs = vfs_op (fd); - result = (*vfs->mmap)(addr, len, prot, flags, vfs_info (fd), offset); + result = vfs->mmap ? (*vfs->mmap)(addr, len, prot, flags, vfs_info (fd), offset) : (caddr_t)-1; if (result == (caddr_t)-1){ - errno = (*vfs->ferrno)(); + errno = ferrno (vfs); return (caddr_t)-1; } mcm = (struct mc_mmapping *) xmalloc (sizeof (struct mc_mmapping), "vfs: mmap handling"); @@ -963,7 +943,8 @@ int mc_munmap (caddr_t addr, size_t len) mc_mmaparray = mcm->next; else mcm2->next = mcm->next; - (*mcm->vfs->munmap)(addr, len, mcm->vfs_info); + if (*mcm->vfs->munmap) + (*mcm->vfs->munmap)(addr, len, mcm->vfs_info); free (mcm); return 0; } @@ -1013,9 +994,8 @@ char *mc_getlocalcopy (char *path) result = vfs->getlocalcopy ? (*vfs->getlocalcopy)(vfs_name (path)) : mc_def_getlocalcopy (vfs_name (path)); free (path); - if (result == NULL){ + if (!result) errno = ferrno (vfs); - } return result; } @@ -1172,6 +1152,7 @@ void vfs_fill_names (void (*func)(char *)) #endif tarfs_fill_names (func); extfs_fill_names (func); + sfs_fill_names (func); } /* Following stuff (parse_ls_lga) is used by ftpfs and extfs */ @@ -1228,19 +1209,27 @@ static int is_time (char *str, struct tm *tim) static int is_year(char *str, struct tm *tim) { + /* Old code recognized 02904baa as year identification :-( */ long year; - if (!strchr(str, ':')) { - year = atol (str); - if (year < 1900 || year > 3000) - return (0); - tim->tm_year = (int) (year - 1900); - return (1); - } - else - return (0); + if (strchr(str,':')) + return 0; + if (strlen(str)!=4) + return 0; + if (sscanf(str, "%d", &year) != 1) + return 0; + if (year < 1900 || year > 3000) + return 0; + tim->tm_year = (int) (year - 1900); + return 1; } +/* + * FIXME: this is broken. Consider following entry: +-rwx------ 1 root root 1 Aug 31 10:04 2904 1234 +where "2904 1234" is filename. Well, this code decodes it as year :-(. + */ + #define free_and_return(x) { free (p_copy); return (x); } int parse_ls_lga (char *p, struct stat *s, char **filename, char **linkname) {