@ -1,11 +1,75 @@
{ pkgs , config , . . . }:
let
###### interface
options = {
fileSystems = pkgs . lib . mkOption {
default = null ;
example = [
{ mountPoint = " / " ;
device = " / d e v / h d a 1 " ;
}
{ mountPoint = " / d a t a " ;
device = " / d e v / h d a 2 " ;
fsType = " e x t 3 " ;
options = " d a t a = j o u r n a l " ;
}
{ mountPoint = " / b i g d i s k " ;
label = " b i g d i s k " ;
}
] ;
description = "
The file systems to be mounted . It must include an entry for
the root directory ( <literal> mountPoint = \ " / \" < / l i t e r a l > ) . E a c h
entry in the list is an attribute set with the following fields :
<literal> mountPoint < /literal > , <literal> device < /literal > ,
<literal> fsType < /literal > ( a file system type recognised by
<command> mount < /command > ; defaults to
<literal> \ " a u t o \" < / l i t e r a l > ) , a n d < l i t e r a l > o p t i o n s < / l i t e r a l >
( the mount options passed to <command> mount < /command > using the
<option> - o < /option > flag ; defaults to <literal> \ " d e f a u l t s \" < / l i t e r a l > ) .
Instead of specifying <literal> device < /literal > , you can also
specify a volume label ( <literal> label < /literal > ) for file
systems that support it , such as ext2/ext3 ( see <command> mke2fs
- L < /command > ) .
<literal> autocreate < /literal > forces <literal> mountPoint < /literal > to be created with
<command> mkdir - p < /command > .
" ;
} ;
system . sbin . mount = pkgs . lib . mkOption {
internal = true ;
default = pkgs . utillinuxng . override {
buildMountOnly = true ;
mountHelpers = pkgs . buildEnv {
name = " m o u n t - h e l p e r s " ;
paths = [
pkgs . ntfs3g
pkgs . mount_cifs
pkgs . nfsUtils
] ;
pathsToLink = " / s b i n " ;
} + " / s b i n " ;
} ;
description = "
A patched ` mount' command that looks in a directory in the Nix
store instead of in /sbin for mount helpers ( like mount . ntfs-3g or
mount . cifs ) .
" ;
} ;
} ;
###### implementation
let
inherit ( pkgs ) e2fsprogs ;
mountPoints = map ( fs : fs . mountPoint ) fileSystems ;
fileSystems = config . fileSystems ;
mountPoints = map ( fs : fs . mountPoint ) fileSystems ;
devices = map ( fs : if fs ? device then fs . device else " L A B E L = " + fs . label ) fileSystems ;
fsTypes = map ( fs : if fs ? fsType then fs . fsType else " a u t o " ) fileSystems ;
optionss = map ( fs : if fs ? options then fs . options else " d e f a u l t s " ) fileSystems ;
@ -13,110 +77,111 @@ let
mount = config . system . sbin . mount ;
job = ''
start on startup
start on new-devices
start on ip-up
script
PATH = $ { e2fsprogs } /sbin : $ PATH
mountPoints = ( $ { toString mountPoints } )
devices = ( $ { toString devices } )
fsTypes = ( $ { toString fsTypes } )
optionss = ( $ { toString optionss } )
autocreates = ( $ { toString autocreates } )
newDevices = 1
# If we mount any file system, we repeat this loop, because new
# mount opportunities may have become available (such as images
# for loopback mounts).
while test - n " $ n e w D e v i c e s " ; do
newDevices =
for ( ( n = 0 ; n < '' ${ #mountPoints[*]}; n++)); do
mountPoint = '' ${ mountPoints [ $ n ] }
device = '' ${ devices [ $ n ] }
fsType = '' ${ fsTypes [ $ n ] }
options = '' ${ optionss [ $ n ] }
autocreate = '' ${ autocreates [ $ n ] }
isLabel =
if echo " $ d e v i c e " | grep - q ' ^ LABEL = ' ; then isLabel = 1 ; fi
isPseudo =
if test " $ f s T y p e " = " n f s " || test " $ f s T y p e " = " t m p f s " ||
test " $ f s T y p e " = " e x t 3 c o w " ; then isPseudo = 1 ; fi
if ! test - n " $ i s L a b e l " - o - n " $ i s P s e u d o " - o - e " $ d e v i c e " ; then
echo " s k i p p i n g $ d e v i c e , d o e s n ' t e x i s t ( y e t ) "
continue
fi
# !!! quick hack: if mount point already exists, try a
# remount to change the options but nothing else.
if cat /proc/mounts | grep - F - q " $ m o u n t P o i n t " ; then
echo " r e m o u n t i n g $ d e v i c e o n $ m o u n t P o i n t "
$ { mount } /bin/mount - t " $ f s T y p e " \
- o remount , " $ o p t i o n s " \
" $ d e v i c e " " $ m o u n t P o i n t " || true
continue
fi
# If $device is already mounted somewhere else, unmount it first.
# !!! Note: we use /etc/mtab, not /proc/mounts, because mtab
# contains more accurate info when using loop devices.
# !!! not very smart about labels yet; should resolve the label somehow.
if test - z " $ i s L a b e l " - a - z " $ i s P s e u d o " ; then
device = $ ( readlink - f " $ d e v i c e " )
prevMountPoint = $ (
cat /etc/mtab \
| grep " ^ $ d e v i c e " \
| sed ' s | ^ [ ^ ] \ + \ + \ ( [ ^ ] \ + \ ) . * | \ 1 | ' \
)
if test " $ p r e v M o u n t P o i n t " = " $ m o u n t P o i n t " ; then
start on startup
start on new-devices
start on ip-up
script
PATH = $ { e2fsprogs } /sbin : $ PATH
mountPoints = ( $ { toString mountPoints } )
devices = ( $ { toString devices } )
fsTypes = ( $ { toString fsTypes } )
optionss = ( $ { toString optionss } )
autocreates = ( $ { toString autocreates } )
newDevices = 1
# If we mount any file system, we repeat this loop, because new
# mount opportunities may have become available (such as images
# for loopback mounts).
while test - n " $ n e w D e v i c e s " ; do
newDevices =
for ( ( n = 0 ; n < '' ${ #mountPoints[*]}; n++)); do
mountPoint = '' ${ mountPoints [ $ n ] }
device = '' ${ devices [ $ n ] }
fsType = '' ${ fsTypes [ $ n ] }
options = '' ${ optionss [ $ n ] }
autocreate = '' ${ autocreates [ $ n ] }
isLabel =
if echo " $ d e v i c e " | grep - q ' ^ LABEL = ' ; then isLabel = 1 ; fi
isPseudo =
if test " $ f s T y p e " = " n f s " || test " $ f s T y p e " = " t m p f s " ||
test " $ f s T y p e " = " e x t 3 c o w " ; then isPseudo = 1 ; fi
if ! test - n " $ i s L a b e l " - o - n " $ i s P s e u d o " - o - e " $ d e v i c e " ; then
echo " s k i p p i n g $ d e v i c e , d o e s n ' t e x i s t ( y e t ) "
continue
fi
# !!! quick hack: if mount point already exists, try a
# remount to change the options but nothing else.
if cat /proc/mounts | grep - F - q " $ m o u n t P o i n t " ; then
echo " r e m o u n t i n g $ d e v i c e o n $ m o u n t P o i n t "
$ { mount } /bin/mount - t " $ f s T y p e " \
- o remount , " $ o p t i o n s " \
" $ d e v i c e " " $ m o u n t P o i n t " || true
continue
fi
if test - n " $ p r e v M o u n t P o i n t " ; then
echo " u n m o u n t $ d e v i c e f r o m $ p r e v M o u n t P o i n t "
$ { mount } /bin/umount " $ p r e v M o u n t P o i n t " || true
# If $device is already mounted somewhere else, unmount it first.
# !!! Note: we use /etc/mtab, not /proc/mounts, because mtab
# contains more accurate info when using loop devices.
# !!! not very smart about labels yet; should resolve the label somehow.
if test - z " $ i s L a b e l " - a - z " $ i s P s e u d o " ; then
device = $ ( readlink - f " $ d e v i c e " )
prevMountPoint = $ (
cat /etc/mtab \
| grep " ^ $ d e v i c e " \
| sed ' s | ^ [ ^ ] \ + \ + \ ( [ ^ ] \ + \ ) . * | \ 1 | ' \
)
if test " $ p r e v M o u n t P o i n t " = " $ m o u n t P o i n t " ; then
echo " r e m o u n t i n g $ d e v i c e o n $ m o u n t P o i n t "
$ { mount } /bin/mount - t " $ f s T y p e " \
- o remount , " $ o p t i o n s " \
" $ d e v i c e " " $ m o u n t P o i n t " || true
continue
fi
if test - n " $ p r e v M o u n t P o i n t " ; then
echo " u n m o u n t $ d e v i c e f r o m $ p r e v M o u n t P o i n t "
$ { mount } /bin/umount " $ p r e v M o u n t P o i n t " || true
fi
fi
fi
echo " m o u n t i n g $ d e v i c e o n $ m o u n t P o i n t "
# !!! should do something with the result; also prevent repeated fscks.
if test - z " $ i s P s e u d o " ; then
fsck - a " $ d e v i c e " || true
fi
if test " $ a u t o c r e a t e " = 1 ; then mkdir - p " $ m o u n t P o i n t " ; fi
if $ { mount } /bin/mount - t " $ f s T y p e " - o " $ o p t i o n s " " $ d e v i c e " " $ m o u n t P o i n t " ; then
newDevices = 1
fi
echo " m o u n t i n g $ d e v i c e o n $ m o u n t P o i n t "
# !!! should do something with the result; also prevent repeated fscks.
if test - z " $ i s P s e u d o " ; then
fsck - a " $ d e v i c e " || true
fi
if test " $ a u t o c r e a t e " = 1 ; then mkdir - p " $ m o u n t P o i n t " ; fi
if $ { moun t} /bin/mount - t " $ f s T y p e " - o " $ o p t i o n s " " $ d e v i c e " " $ m o u n t P o i n t " ; then
newDevices = 1
fi
done
done
done
end script
end script
'' ;
in
{
require = [ options ] ;
services = {
extraJobs = [ {
name = " f i l e s y s t e m s " ;