[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