[PATCH] fstab, mfstab

Sza'sz Gergely szaszg at hu.inter.net
Fri May 16 22:52:53 UTC 2003


On Fri, May 16, 2003 at 11:56:40AM -0400, Pavel Roskin wrote:
> This is all cool and nice, but I don't think this can be included into the
Thanks!
> sources in its present form.  We shouldn't encourage users to do system
> administration from mc.  I don't want to answer e-mails from the users who
> lost their data because they didn't see and didn't know what they were
> doing.
I see. But I don't think, it is 'system administration' at all:
  - my script is just a frontend for '(u)mount' and 'df'
  - (u)mounting a partition is less 'dangerouse' than delete it [F8] :-)
  - you don't lose any data even if you (u)mount 'root/system' partitions
  - my script can't do any extra thing, which you can't do with (u)mount
  - you can only (u)mount normally a floppy, a CD-ROM (DVD), or e.g. a
    CF card. Those which exist in '/etc/fstab' with 'user' option
  - you can't do any 'unexpected' (u)mount, because, only root (uid=0)
    can (u)mount
  - All in all, to (u)mount user (u)mountable partitions (imho) *not
    system administration*
    
And to top it all:
  - I think that, most of the people (I'm sure, You too), do system
    administration 'from' mc, when editing /etc/xxx files :-) :-)

**But, You are the boss**

> 
> System administration tools must provide a very high level of reliability
> that the development process of GNU Midnight Commander doesn't provide
> and doesn't aim to provide.  Also, the level of testing received by
> undocumented external VFSs is inadequate for system administration tools.
> There were major bugs sitting for years in some of the scripts, and nobody
> complained.
I see. But my script cannot change any of system files (fstab), or system
settings. And if you can't (u)mount a partition from 'fstab VFS', or get
wrong info from an 'fstab' entry/mount... I think that, it is not critical :-)

> I'm ready to put your script to the "contribution" section on the website
> if you write a README and settle on one script.
Thanks. I think this will be the 'mfstab' script, because it can work with
the present state of 'mc' VFS... (fstab need a patch on 'extfs.c', which I
send before...)

Gergely

P.s.: And what about the extfs.c patch? Don't we need any similar function
      in VFS? (Rescan (get a new list/kill from cache) from an external FS
      data when it is neccesary?)
-------------- 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-xr-xr-x   1 root     root     0 $date $_[0] on $_[1]/info\n";
		if ($_[6] eq 'Yes (not in fstab)')
		{
			printf "lr-xr-xr-x   1 root     root     0 $date _mount_%03d -> $_[0] on $_[1]\n", $i;
		}
		else
		{
			printf "lr-xr-xr-x   1 root     root     0 $date _fstab_%03d -> $_[0] on $_[1]\n", $i;
			print  "---x--x--x   1 root     root     0 $date $_[0] on $_[1]/mount\n";
			print  "---x--x--x   1 root     root     0 $date $_[0] on $_[1]/umount\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 mcfstab_red
{
	return '' . $_[0] . '';
}

sub mcfstab_yellow
{
	return '' . $_[0] . '';
}

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;
	}

	unless ($filename =~ /_mount_([0-9]+)/)
	{
		$fs =~ /$filename ([^\n]+)/m;
	}
	@_ = @{@f[$1]};

	if ($filename =~ s/\/info$//)
	{
	    mcfstabfs_dumpfile ($destfile, sprintf ($info_str,
						    mcfstab_uline ($_[0]),
						    mcfstab_uline ($_[1])));
	    exit 0;
	}

	if ($filename =~ s/\/umount$//)
	{
	    ($_, $filename) = split / on /, $filename;
	    mcfstabfs_dumpfile ($destfile, sprintf ($umount_str,
						    mcfstab_uline ($_[0]),
						    mcfstab_uline ($_[1])));
	    exit 0;
	}

	if ($filename =~ s/\/mount$//)
	{
	    ($_, $filename) = split / on /, $filename;
	    mcfstabfs_dumpfile ($destfile, sprintf ($mount_str,
						    mcfstab_uline ($_[0]),
						    mcfstab_uline ($_[1])));
	    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;
	}
	
}

sub mcfstabfs_run
{
	local($archive,$filename)=@_;
	unless ($filename =~ /_mount_([0-9]+)/)
	{
		$fs =~ /$filename ([^\n]+)/m;
	}
	@_ = @{@f[$1]};
	if($filename =~ /\/info$/)
	{
		$_ =	"\n\nDevice:\t\t" . mcfstab_yellow ($_[0]) . 
			"\nMount point:\t" . mcfstab_yellow ($_[1]) .
			"\nType:\t\t" . mcfstab_red ($_[2]) .
			"\nOptions:\t" . mcfstab_red ($_[3]) .
			"\nDump:\t\t" . $_[4] .
			"\nPass:\t\t" . $_[5] .
			"\nMounted:\t" . mcfstab_yellow ($_[6]);
		if ($_[7] ne undef)
		{
			$_ .=	"\nSize:\t\t" . mcfstab_yellow ($_[7]) .
				"k\nUsed:\t\t" . mcfstab_yellow ($_[8]) .
				"k\nFree:\t\t" . mcfstab_yellow ($_[9]) .
				"k\nUsage:\t\t" . mcfstab_yellow ($_[10]);
		}
		print $_ . "\n\n";
	}
	elsif($filename =~ /\/umount$/)
	{
		if ($_[6] eq 'Yes')
		{
		    print "Umounting: $_[0] from $_[1]...\n";
		    system("umount $_[1]");
		}
		else
		{
		    print "This filesystem " . mcfstab_red ('do not') .
			  " mounted yet.\n";
		}
	}
	else
	{
		if ($_[6] eq 'No')
		{
			print "Mounting: $_[0] to $_[1]...\n";
			system("mount $_[1]");
#		system("mount -t $_[2] -o $_[4] $_[0] $_[1]");
		}
		else
		{
		    print "This filesystem " . mcfstab_red ('already') .
			  " mounted.\n";
		}
	}
}


$readme_str=<<EOS;

                         ****FFSSTTAABB VVFFSS****

    This is a modified version of the original fstab VFS, to work with an
unmodified 'mc'. We found executable 'info' files in each leaf directory,
and we can get information from a specified mount when executing this info
file, rather than showing ([F3]) it...
    The sizes of symlinks are all zero (no mount/umount info in it), and
the 'mount' and 'umount' executables exist together, and warn if you try
to mount a mounted, or umount a not mounted filesystem...
    So, not so nice interface, but works with unpatched VFS...

The original README:

    This virtual filesystem (fstab) gives you an easy to use (u)mounting
tool for 'mounting' and 'umounting' filesystems defined in '/etc/fstab'.
You see one symlink for each definition in fstab, named '_mount_NNN'.
Where NNN is a number. The size of the symlinks is 0 if not mounted, 1 if
mounted and 2 if mounted, but there is 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, containing a 'hda1 on' directory, which containing
an 'usr' directory.).
There are two files in every 'leaf' directory:
  - a readable 'info' and
  - an executable 'mount' or 'umount' depend on the state of the filesystem
Read the 'info' ([F3]) to 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****
			  
Please report bugs to <mailto:szaszg at hu.inter.net>...

EOS

$info_str=<<EOS;

                         ****GGEETTTTIINNGG IINNFFOO****

    If you tap _[_E_N_T_E_R_] over this file, you get information
about %s on %s mount.

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****
			  
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++;
}

foreach (@mn)	#process actual mounts
{
	split;		#get pieces $_[0] = filesys, 1 = mountp, 2 = type,
			# 		3 = options, 4 = dump, 5 = pass

	next if ($fs =~ /^$_[0] $_[1]/m);	#ok! already have
						    # get actual options...
	$_[4] = '-'; $_[5] = '-';
	$_[6] = 'Yes (not in fstab)';		#mounted
	if ($df =~ /^$_[0] ([^ ]+) ([^ ]+) ([^ ]+) ([^\n]+) $_[1]$/m) #
					# ok, have size info!!!
	{
		$_[7] = $1; $_[8] = $2; $_[9] = $3; $_[10] = $4;
			#size, used, free, use%
	}
	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 --------------

                            **FSTAB VFS**

    This is a modified version of the original fstab VFS, to work with an
unmodified 'mc'. We found executable 'info' files in each leaf directory,
and we can get information from a specified mount when executing this info
file, rather than showing ([F3]) it...
    The sizes of symlinks are all zero (no mount/umount info in it), and
the 'mount' and 'umount' executables exist together, and warn if you try
to mount a mounted, or umount a not mounted filesystem...
    So, not so nice interface, but works with unpatched VFS...

The original README:

    This virtual filesystem (fstab) gives you an easy to use (u)mounting
tool for 'mounting' and 'umounting' filesystems defined in '/etc/fstab'.
You see one symlink for each definition in fstab, named '_mount_NNN'.
Where NNN is a number. The size of the symlinks is 0 if not mounted, 1 if
mounted and 2 if mounted, but there is 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, containing a 'hda1 on' directory, which containing
an 'usr' directory.).
There are two files in every 'leaf' directory:
  - a readable 'info' and
  - an executable 'mount' or 'umount' depend on the state of the filesystem
Read the 'info' ([F3]) to get some information, and execute ([ENTER]) the
(u)mount file, to (u)mount the specified device.

You should add a line (mfstab:) to the 'extfs.ini' file, and copy the 'mfstab'
script to that directory (where is 'extfs.ini').
Then start 'mc' and type: cd #mfstab[ENTER]

Please enjoy...

Created by Gergely Sz?sz <mailto:szaszg at hu.inter.net>


More information about the mc-devel mailing list