[PATCH] fstabfs
Sza'sz Gergely
szaszg at hu.inter.net
Thu May 15 00:27:21 UTC 2003
Hi!
I make an 'fstab' vfs for mc. If you cd to it (an archiveless vfs), you
get a directory tree (with some symlink shorthand) represents the
'/etc/fstab' mounts. You can get information from mounts (wieving the 'info'
files at the leafs), and you can mount/umount these predefined mounts (by
executing the mount/umount files).
So, it is nice, but... because the vfs cacheing,I have to hack the extfs.c,
to make rescan after executing the mount/umount 'virtual' file...
So, these patch add an enchacement to the extfs.ini file. If we write
a /xxx after the vfs definition (e.g. fstab:/r ), than we can controll
the needed rescannings. 'r' mean -> need rescan after a 'run',
'u' -> after 'unlink', 'd' -> after rmdir. So, the later ones (u,d) are
useless for fstab (and may any other vfs)... These options can mixed,
e.g. whatsfs/dru mean need rescan after unlink and rmdir and run...
Gergely
-------------- next part --------------
#! /usr/bin/perl
#
# 2003 (c) Gergely Sz?sz <szaszg at hu.inter.net>
# This software is under GNU license
#
sub mcfstabfs_list
{
#
#
print "-r--r--r-- 1 root root 0 $date README\n";
print "-r--r--r-- 1 root root 0 $date TODO\n";
print "-r--r--r-- 1 root root 0 $date BUGS\n";
print "-r--r--r-- 1 root root 0 $date read_fstab\n";
print "-r--r--r-- 1 root root 0 $date pipe_mount\n";
print "-r--r--r-- 1 root root 0 $date read_mtab\n";
$i = 0;
foreach (@f)
{
@_ = @{$_};
print "-r--r--r-- 1 root root 0 $date $_[0] on $_[1]/info\n";
if ($_[6] eq 'Yes')
{
if ($_[7] eq undef)
{
$_[7] = 2;
}
else
{
$_[7] = 1;
}
printf "lr-xr-xr-x 1 root root $_[7] $date _mount_%03d -> $_[0] on $_[1]\n", $i;
print "---x--x--x 1 root root 0 $date $_[0] on $_[1]/umount\n";
}
else
{
printf "lr-xr-xr-x 1 root root 0 $date _mount_%03d -> $_[0] on $_[1]\n", $i;
print "---x--x--x 1 root root 0 $date $_[0] on $_[1]/mount\n";
}
$i++;
}
}
sub mcfstabfs_dumpfile # $destfile $string
{
if (open (FILEOUT,">$_[0]"))
{
print FILEOUT $_[1];
close FILEOUT;
# system ("chmod a+x $_[0]"); #we need it?
}
}
sub mcfstab_uline
{
@_ = split //, $_[0];
return '_' . join ('_', @_);
}
sub mcfstab_bold
{
my $r;
@_ = split //, $_[0];
foreach (@_)
{
$r .= $_ . '' . $_;
}
return $r;
}
sub mcfstabfs_copyout
{
local($archive,$filename,$destfile)=@_;
if ($filename eq 'README')
{
mcfstabfs_dumpfile ($destfile, $readme_str);
exit 0;
}
if ($filename eq 'BUGS')
{
mcfstabfs_dumpfile ($destfile, $bugs_str);
exit 0;
}
if ($filename eq 'TODO')
{
mcfstabfs_dumpfile ($destfile, $todo_str);
exit 0;
}
if ($filename eq 'read_fstab')
{
open (FSTAB, "</etc/fstab");
$fstab .= $_ while (<FSTAB>);
close FSTAB;
mcfstabfs_dumpfile ($destfile, $fstab);
exit 0;
}
if ($filename eq 'pipe_mount')
{
open (FSTAB, "/bin/mount |");
$fstab .= $_ while (<FSTAB>);
close FSTAB;
mcfstabfs_dumpfile ($destfile, $fstab);
exit 0;
}
if ($filename eq 'read_mtab')
{
open (FSTAB, "</etc/mtab");
$fstab .= $_ while (<FSTAB>);
close FSTAB;
mcfstabfs_dumpfile ($destfile, $fstab);
exit 0;
}
if ($filename =~ s/\/umount$//)
{
($_, $filename) = split / on /, $filename;
mcfstabfs_dumpfile ($destfile, sprintf ($umount_str,
mcfstab_uline ($_),
mcfstab_uline ($filename)));
exit 0;
}
if ($filename =~ s/\/mount$//)
{
($_, $filename) = split / on /, $filename;
mcfstabfs_dumpfile ($destfile, sprintf ($mount_str,
mcfstab_uline ($_),
mcfstab_uline ($filename)));
exit 0;
}
if ($filename eq 'mount-OPEN-ERROR')
{
mcfstabfs_dumpfile ($destfile, "*** ERROR***\n\nCannot execute /bin/mount system utility!\n");
exit 0;
}
if ($filename eq 'fstab-OPEN-ERROR')
{
mcfstabfs_dumpfile ($destfile, "*** ERROR***\n\nCannot read the /etc/fstab file!\n");
exit 0;
}
if ($filename =~ s/\/info$//)
{
$fs =~ /$filename ([^\n]+)/m;
@_ = @{@f[$1]};
$_ = "Device:\t\t" . mcfstab_bold ($_[0]) .
"\nMount point:\t" . mcfstab_bold ($_[1]) .
"\nType:\t\t" . mcfstab_uline ($_[2]) .
"\nOptions:\t" . mcfstab_uline ($_[3]) .
"\nDump:\t\t" . $_[4] .
"\nPass:\t\t" . $_[5] .
"\nMounted:\t" . mcfstab_bold ($_[6]);
if ($_[7] ne undef)
{
$_ .= "\nSize:\t\t" . mcfstab_bold ($_[7]) .
"k\nUsed:\t\t" . mcfstab_bold ($_[8]) .
"k\nFree:\t\t" . mcfstab_bold ($_[9]) .
"k\nUsage:\t\t" . mcfstab_bold ($_[10]);
}
mcfstabfs_dumpfile ($destfile, $_);
}
}
sub mcfstabfs_run
{
local($archive,$filename)=@_;
unless ($filename =~ /_mount_([0-9]+)/)
{
$fs =~ /$filename ([^\n]+)/m;
}
@_ = @{@f[$1]};
if($filename =~ /\/umount$/)
{
print "Umounting: $_[0] from $_[1]...\n";
system("umount $_[1]");
}
else
{
print "Mounting: $_[0] to $_[1]...\n";
system("mount $_[1]");
# system("mount -t $_[2] -o $_[4] $_[0] $_[1]");
}
}
$readme_str=<<EOS;
****FFSSTTAABBFFSS****
This virtual filesystem (fstab) give you an easy to use (u)mount
tool for 'mounting' and 'umounting' filesystems defined in '/etc/fstab'.
You see one symlink for each definition in fstab, named '_mount_NNN'.
Where NNN a number. The size of the symlinks is 0 if not mounted, 1 if mounted
and 2 if mounted, but no size information (e.g. usbfs, procfs ...).
Every symlink points to a directory, which represents the fstab entry.
The path of the directory is like 'DEVICE on MOUNTPOINT', where DEVICE is the
device and the MOUNTPOINT is the mount point of it (e.g. '/dev/hda1 on /usr'.
There is a 'dev' directory, coantaning the 'hda1 on' directory, containing the
'usr' directory.).
There are two file in every 'end' directory:
- a readable 'info' and
- an executable 'mount' or 'umount'
Read the 'info' ([F3]) for get some information, and execute ([ENTER]) the
(u)mount file, to (u)mount the specified device.
Please enjoy...
Created by Gergely Sz?sz <mailto:szaszg at hu.inter.net>
EOS
$bugs_str=<<EOS;
****KKNNOOWWNN BBUUGGSS****
* Can not handle current mounts, different from /etc/fstab...
Please report bugs to <mailto:szaszg at hu.inter.net>...
EOS
$mount_str=<<EOS;
****MMOOUUNNTTIINNGG AANN FFSS****
If you tap _[_E_N_T_E_R_] over this file, you mount filesystem on
%s device to the %s directory.
EOS
$umount_str=<<EOS;
****UUMMOOUUNNTTIINNGG AANN FFSS****
If you tap _[_E_N_T_E_R_] over this file, you umount filesystem on
%s device from the %s directory.
EOS
$todo_str=<<EOS;
****TTOODDOO****
* Include current mounts (not in fstab). (info only)..
Please write your ideas for me <mailto:szaszg at hu.inter.net>...
EOS
umask 077;
chop($date=`LC_ALL=C date "+%b %d %Y %H:%M"`);
unless (-x '/bin/mount')
{
print "-r--r--r-- 1 root root 0 $date mount-EXEC-ERROR\n";
exit 0;
}
unless (-r '/etc/fstab')
{
print "-r--r--r-- 1 root root 0 $date fstab-OPEN-ERROR\n";
exit 0;
}
unless (-r '/etc/mtab')
{
print "-r--r--r-- 1 root root 0 $date mtab-OPEN-ERROR\n";
exit 0;
}
undef $/;
open (IN, "</etc/fstab") and $fs = <IN>;
open (IN, "mount |") and $mn = <IN>;
open (IN, "df |") and $df = <IN>;
close IN;
$/ = "\n";
$fs =~ s/^#.*\n|^[ \t]*\n//mg;
$fs =~ s/[ \t]+/ /mg;
$mn =~ s/ on | type / /mg;
$mn =~ s/\((.*?)\)\n/$1\n/mg;
$df =~ s/File.*?\n//g;
$df =~ s/[ \t]+/ /mg;
@fs = split /\n/, $fs;
@mn = split /\n/, $mn;
@df = split /\n/, $df;
$i = 0;
foreach (@fs) #process predefined ones
{
split; #get pieces $_[0] = filesys, 1 = mountp, 2 = type,
# 3 = options, 4 = dump, 5 = pass
if ($mn =~ /^$_[0] $_[1] ([^ ]+) ([^\n]+)/m) #ok! mounted
# get actual options...
{
$_[6] = 'Yes'; #mounted
$_[2] = $1; $_[3] = $2; #type and options
if ($df =~ /^$_[0] ([^ ]+) ([^ ]+) ([^ ]+) ([^\n]+) $_[1]$/m) #
# ok, have size info!!!
{
$_[7] = $1; $_[8] = $2; $_[9] = $3; $_[10] = $4;
#size, used, free, use%
}
}
else
{
$_[6] = 'No'; #umounted
}
push (@f, [@_]); #an array
$_[0] =~ s/^\///; #we throw it away... :-)
$fs .= join (' ', $_[0], 'on', $_[1], $i) . "\n";
#a matchable var with linenum
$i++;
}
if($ARGV[0] eq "list") { shift; &mcfstabfs_list(@ARGV); exit 0; }
elsif($ARGV[0] eq "copyout") { shift; &mcfstabfs_copyout(@ARGV); exit 0; }
elsif($ARGV[0] eq "run") { shift; &mcfstabfs_run(@ARGV); exit 0; }
exit 1;
-------------- next part --------------
--- extfs.c.bak Tue Mar 11 01:01:56 2003
+++ extfs.c Wed May 14 22:51:16 2003
@@ -44,6 +44,11 @@
#undef ERRNOR
#define ERRNOR(x,y) do { my_errno = x; return y; } while(0)
+#define EXTFS_REFRESH_RUN 1
+#define EXTFS_REFRESH_UNLINK 2
+#define EXTFS_REFRESH_RMDIR 4
+#define EXTFS_REFRESH_WRITE 8
+
struct inode {
nlink_t nlink;
struct entry *first_in_subdir; /* only used if this is a directory */
@@ -90,6 +95,7 @@
#define MAXEXTFS 32
static char *extfs_prefixes [MAXEXTFS];
static char extfs_need_archive [MAXEXTFS];
+static char extfs_refresh_flag [MAXEXTFS];
static int extfs_no = 0;
static void extfs_fill_names (vfs *me, void (*func)(char *))
@@ -411,6 +417,19 @@
return 0;
}
+static void reread_archive (struct archive *archive)
+{
+ int fstype = archive->fstype;
+ char *name = g_strdup (archive->name);
+
+ free_archive (archive);
+ read_archive (fstype, name, &archive);
+ g_free (name);
+ update_panels (UP_OPTIMIZE, UP_KEEPSEL);
+ repaint_screen ();
+}
+
+
static char *get_path (char *inname, struct archive **archive, int is_dir,
int do_not_open);
@@ -633,6 +652,9 @@
g_free (q);
shell_execute (cmd, 0);
g_free (cmd);
+
+ if (extfs_refresh_flag[archive->fstype] & EXTFS_REFRESH_RUN)
+ reread_archive (archive);
}
static void *
@@ -1054,6 +1076,9 @@
}
remove_entry (entry);
+ if (extfs_refresh_flag[archive->fstype] & EXTFS_REFRESH_UNLINK)
+ reread_archive (archive);
+
return 0;
}
@@ -1104,6 +1129,9 @@
}
remove_entry (entry);
+ if (extfs_refresh_flag[archive->fstype] & EXTFS_REFRESH_RMDIR)
+ reread_archive (archive);
+
return 0;
}
@@ -1291,6 +1319,7 @@
{
FILE *cfg;
char *mc_extfsini;
+ char refresh_flag = 0;
mc_extfsini = concat_dir_and_file (mc_home, "extfs" PATH_SEP_STR "extfs.ini");
cfg = fopen (mc_extfsini, "r");
@@ -1314,6 +1343,10 @@
/* Handle those with a trailing ':', those flag that the
* file system does not require an archive to work
+ * filesys:/rduw r - reread after run
+ * d - reread after rmdir
+ * u - reread after unlink
+ * w - reread after write not implemented
*/
if (*key == '[') {
@@ -1326,6 +1359,31 @@
if (*key == '#')
continue;
+ c = key;
+ while ((*c != '/') && (*c != '\n') && (*c != '\0'))
+ c++;
+ if (*c == '/') {
+ *c = '\n';
+ c++;
+ while ((*c != '\n') && (*c != '\0')) {
+ switch (*c) {
+ case 'r':
+ refresh_flag |= EXTFS_REFRESH_RUN;
+ break;
+ case 'd':
+ refresh_flag |= EXTFS_REFRESH_RMDIR;
+ break;
+ case 'u':
+ refresh_flag |= EXTFS_REFRESH_UNLINK;
+ break;
+/* case 'w':
+ refresh_flag |= EXTFS_REFRESH_WRITE;
+ break; */
+ }
+ c++;
+ }
+ }
+
if ((c = strchr (key, '\n'))){
*c = 0;
c = &key [strlen (key) - 1];
@@ -1333,6 +1391,7 @@
c = key;
}
extfs_need_archive [extfs_no] = !(*c == ':');
+ extfs_refresh_flag [extfs_no] = refresh_flag;
if (*c == ':')
*c = 0;
if (!(*key))
More information about the mc-devel
mailing list