-- -- fstab.lua -- -- $Id$ -- -- Lua 5.2 module providing a mingw-get setup hook for the MSYS fstab. -- -- Written by Keith Marshall -- Copyright (C) 2014, 2015, MinGW.org Project -- -- -- Permission is hereby granted, free of charge, to any person obtaining a -- copy of this software and associated documentation files (the "Software"), -- to deal in the Software without restriction, including without limitation -- the rights to use, copy, modify, merge, publish, distribute, sublicense, -- and/or sell copies of the Software, and to permit persons to whom the -- Software is furnished to do so, subject to the following conditions: -- -- The above copyright notice and this permission notice shall be included -- in all copies or substantial portions of the Software. -- -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -- THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -- DEALINGS IN THE SOFTWARE. -- -- -- We begin by initializing a container, for construction of a Lua module -- to encapsulate the content of this source file. -- local M = {} -- -- mingw-get passes the MSYS installation root directory path, -- in the $MSYS_SYSROOT environment variable; from this, we deduce -- the path name for the working copy of the fstab file... -- local function syspath( varname ) -- -- ...using this local helper function to ensure that the path name -- string, returned from the environment, is free from insignificant -- trailing directory name separators, and that all internal sequences -- of directory name separators are normalized to a single '/'. -- local pathname = string.gsub( os.getenv( varname ), "[/\\]+", "/" ) return string.match( pathname, "(.*[^/])/*$" ) end local sysroot = syspath( "MSYS_SYSROOT" ) local mingw32_sysroot = syspath( "MINGW32_SYSROOT" ) local fstab_file_name = sysroot .. "/etc/fstab" -- -- The following may be adjusted, to control the layout of the mount -- point mapping records, within the fstab file. -- local path_name_field_width, tab_width = 40, 8 -- -- Define a template, from which a sample fstab file for the current -- MSYS installation may be generated, on invocation of this module's -- "dump_sample" method... -- local fstab_sample = { '# /etc/fstab.sample -- sample mount table configuration for MSYS.', '', '# Lines with a "#" in column one are interpreted as comment lines;', '# with the exception of comments described as "magic", neither these', '# lines, nor any blank lines, are interpreted as configuration.', '', '# Comment lines which are described as "magic" should neither be', '# deleted, nor edited manually; ignoring this advice may cause your', '# MSYS installation to malfunction.', '', '# When running MSYS from a portable device, such as a USB thumb drive,', '# the following "magic" comment is used to track changes in host drive', '# letter assignment, so allowing MSYS-Portable start-up hooks to remap', '# mount table entries which refer to the relocated device:', '#', '# MSYSROOT=D:/PortableApps/MSYS/1.0', '', '# The mount table configuration follows below. The line format is', '# simple: you specify the Win32 path, followed by one or more space or', '# tab delimiters, followed by the mount point name. In a typical UNIX', '# installation, each mount point must exist as a named directory on a', '# physically accessible device, before it can actually be used as a', '# mount point. For this implementation the "must exist" requirement', '# is not enforced; however, it will assist programs such as find, and', "# readline's tab completion if each does physically exist.", '', '# Win32_Path Mount_Point', '#------------------------------------- -----------', 'c:/mingw /mingw' } -- -- ...and a further template for a working configuration. -- local fstab_basic = { '# /etc/fstab -- mount table configuration for MSYS.', '# Please refer to /etc/fstab.sample for explanatory annotation.', '', '# MSYS-Portable needs this "magic" comment:', '# MSYSROOT=D:/PortableApps/MSYS/1.0', '', '# Win32_Path Mount_Point', '#------------------------------------- -----------', 'c:/mingw /mingw' } -- -- Define Lua regular expressions which may be used to identify -- comment lines within the fstab file; (the first will match any -- comment, while the second is specific to the "magic" comment, -- as used by MSYS-Portable, to track changes in the allocation -- of the drive identifier for the host device). -- local fstab_comment_line = "^#" local fstab_device_magic = "^(#%s*MSYSROOT=)(%S*)" -- local function map_root_device( assignment ) -- -- A function to update the "magic" comment, which records the -- allocation of the MSYS-Portable host device. -- return string.gsub( assignment, fstab_device_magic, "%1" .. sysroot ) end -- -- Define a Lua regular expression which may be used to verify -- that any fstab file record represents a well formed mount point -- specification; it also incorporates capture fields, which may -- be used to extract each of the path name and mount point -- identification fields from the specification. -- local fstab_mount_specification = "^%s*(%S+)%s+(%S+)%s*$" -- local function is_mount_specification( line ) -- -- A function to verify any fstab file record against the -- preceding regular expression, to confirm whether it does -- represent a well formed mount point specification. -- return string.match( line, fstab_mount_specification ) end -- local function get_mapped_path( specification ) -- -- A function to extract the associated path name field from -- any well formed mount point specification record. -- return string.gsub( specification, fstab_mount_specification, "%1" ) end -- local function get_mount_point( specification ) -- -- A function to extract the mount point identification field -- from any well formed mount point specification record. -- return string.gsub( specification, fstab_mount_specification, "%2" ) end -- -- In the event that a mount table configuration has already been -- specified for this installation, capture this into an internal -- "as built" configuration table... -- local fstab_as_built = {} local fstab = io.open( fstab_file_name ) if fstab then -- -- ...reading the existing configuration file, line by line... -- for line in fstab:lines() do -- -- ...identifying comment lines... -- if string.match( line, fstab_comment_line ) then -- -- ...and ignoring all such, except any "device magic" line... -- if string.match( line, fstab_device_magic ) then -- -- ...from which we retrieve, and subsequently update, the -- configuration-specific "sysroot" identification. -- sysroot = string.gsub( line, fstab_device_magic, "%2" ) end -- -- Also identify mount point specification lines... -- elseif is_mount_specification( line ) then if string.match( get_mount_point( line ), "^/mingw$" ) then -- -- ...and preserve the user's pre-configured path assignment -- for the "/mingw" mount point, if any. -- mingw32_sysroot = get_mapped_path( line ) -- else -- -- ...while, for all EXCEPT the "/mingw" mount point, -- simply record the configuration. -- table.insert( fstab_as_built, line ) end end end end -- -- local function fstab_write_configuration( fstab, template, current ) -- -- A function to write an fstab configuration to a designated output -- stream, based on a specified template, reproducing and encapsulating -- any existing configuration which may also have been specified... -- local function fstab_writeln( line ) -- -- ...using this helper function to write line by line. -- fstab:write( line .. "\n" ) end -- local function assign_mount_point( mapped_path, mount_point ) -- -- This helper function formats each mount point specification -- into a neatly tabulated layout... -- local filled = string.len( mapped_path ) repeat mapped_path, filled = mapped_path .. "\t", filled + tab_width until filled >= path_name_field_width -- -- ...to be written out, with one line per mount point. -- fstab_writeln( mapped_path .. mount_point ) end -- -- Process the template, line by line... -- for ref, line in next, template do -- ...and for each comment, or blank line encountered... -- if string.match( line, "^#" ) or string.match( line, "^%s*$" ) then -- ...simply reproduce it in the output stream, while taking -- care to update any "device magic" which it may incorporate, -- so that it fits the configuration of this installation. -- fstab_writeln( map_root_device( line ) ) -- -- When we encounter a mount point specification line -- for -- which each of the embedded templates should include exactly -- one example... -- elseif is_mount_specification( line ) then -- ...write out the specification for the "/mingw" mount -- point, as appropriate for this installation. -- assign_mount_point( mingw32_sysroot, "/mingw" ) end end -- -- And finally... -- if current then -- ...when inclusion of the current mount configuration has been -- specified, we process each configuration record in turn... -- for ref, line in next, current do -- ...and write out its corresponding mount point specification, -- (noting that we have already excluded the "/mingw" mount point -- from the recorded configuration, but we have already written a -- specification record for it). -- assign_mount_point( get_mapped_path( line ), get_mount_point( line ) ) end end end -- -- function M.pathname( suffix ) -- -- An exported utility function, to facilitate identification of -- the full MS-Windows path name for the "/etc/fstab" configuration -- file, as appropriate to the current installation... -- if suffix then -- ...appending any suffix which may have been specified, (e.g. -- to specify a reference to the "/etc/fstab.sample" file)... -- return fstab_file_name .. suffix end -- -- ...otherwise, specifying a reference to "/etc/fstab" itself. -- return fstab_file_name end -- -- function M.dump_sample( stream_file ) -- -- An exported utility function, providing a method for displaying, -- or otherwise emitting suitable content for the "/etc/fstab.sample" -- file, as directed by the embedded "fstab_sample" template... -- if not stream_file then -- ...writing to "stdout", in the event that no other destination -- has been specified. -- stream_file = io.stdout end -- -- Regardless of output destination, we delegate output to this local -- function, processing the integral sample file template, but we omit -- the current mount table configuration. -- fstab_write_configuration( stream_file, fstab_sample ) end -- -- function M.initialize( stream_file ) -- -- The primary initialization function, exported for use by mingw-get, -- to write a working mount table configuration to the specified file -- stream, which, unless otherwise specified... -- local default_stream_file = nil if not stream_file then -- ...is to be directed to the default "/etc/fstab" file. -- default_stream_file = io.open( fstab_file_name, "w" ) stream_file = default_stream_file end -- -- Once again, regardless of how the output file has been identified, -- provided the stream has been successfully assigned... -- if stream_file then -- ...we delegate the actual output function to the local helper, -- this time, processing the integral working file template, and we -- include the record of the current mount table configuration. -- fstab_write_configuration( stream_file, fstab_basic, fstab_as_built ) end -- -- Finally, when updating the default "/etc/fstab" configuration, -- via a locally opened output file stream... -- if default_stream_file then -- ...we must now ensure that this output stream is closed. -- io.close( default_stream_file ) end end -- -- Since this source file is intended to be loaded as a Lua module, we -- must ultimately return a reference handle for it. -- return M -- -- $RCSfile$: end of file */