#!/bin/sh # # exportfs # A shell-script to mimic exportfs on Mac OS X (and probably Darwin) # # (C) 2002, Christian Czezatke # # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY # NAME=exportfs VERSION="v0.12, (C) 2002, Christian Czezatke " NIUTIL=niutil TMPNAME=foosball # Takes the export line without the export point as an argument. # Sets $opts and $clients so that they can be stuffed into the corresponding # netinfo properties. function parse_args() { opts="" clients="" while [ "$1" != "" ] do arg=$1 if [ "-${arg##-}" = "${arg}" ] ; then # arg starts with a "-", so it's an option... opts="${opts} ${arg##-}" else # arg does not start with a "-": # It could be following a "mask" or "network" decl # in that case it goes to the "opts" string, otherwise # it is a host name. # This is a kludge added to work around a common mistake # (thanks to the bugs in the exports(5) man page...) if [ "${prev}" = "-mask" -o "${prev}" = "-network" ] ; then opts="${opts}=${arg}" else clients="${clients} ${arg}" fi fi prev=${arg} shift done } # create the export entry. - This function relies on the following variables # to be pre-set: # (The contents of these variables correspond to the netinfo properties for # the new export entry). # $name - Directory to be exported # $opts - Export options # $clients - Clients allowed to mount the export # $opts and $clients are set by a "parse_args", so make sure this gets called # each time before "export_entry" is being called. function export_entry() { # see if the entry already exists. -- If so, remove it before # re-creating it. id=`$NIUTIL -list / /exports | grep ${name}\$ | cut -f1` if [ "$id" != "" ] ; then # Entry already exists; remove it $NIUTIL -destroy / $id if [ $? -ne 0 ] ; then echo Existing entry for export $name could not be removed >&2 exit 3 fi fi # Create temporary entry $NIUTIL -create / /exports/$TMPNAME id=`$NIUTIL -list / /exports | grep $TMPNAME\$ | cut -f1` if [ "$id" = "" ] ; then echo Could not create temporary export entry >&2 exit 2 fi # fix the name of the export entry and set the export # properties $NIUTIL -insertval / $id name "$name" 0 && \ $NIUTIL -destroyval / $id name "$TMPNAME" && \ $NIUTIL -createprop / $id "opts" $opts && \ $NIUTIL -createprop / $id "clients" $clients rv=$? if [ $rv -ne 0 ] ; then # remove the incomplete entry $NIUTIL -destroy / $id echo Could not set export properties for $name >&2 exit 3 fi } # implements "-a" command function export_from_file() { local fname="$1" # eliminate all the comments from the file if [ "$fname" == "--" ] ; then fname="" fi cat $fname | sed s/\#\.\*// | grep -v \^\$ | ( while read name ARGS ; do parse_args $ARGS export_entry done ) KICK_MOUNTD=yes } # implements "-c" command function export_from_arg() { # process the export entry passed into this function echo $* | ( while read name ARGS ; do parse_args $ARGS export_entry done ) KICK_MOUNTD=yes } #implements "-r" command function remove_export() { name="$1" # See if the given export exists id=`$NIUTIL -list / /exports | grep ${name}\$` if [ "$id" = "" ] ; then echo "Could not find entry $name in export list (try exportfs -l)" >&2 exit 4 fi $NIUTIL -destroy / $id if [ $? -ne 0 ] ; then echo "Could not remove entry $name from export list" >&2 exit 5 fi KICK_MOUNTD=yes } # implements "-l" command function list_exports() { $NIUTIL -list / /exports | cut -f2 } #implements "-s" command function show_export() { name="$1" id=`$NIUTIL -list / /exports | grep ${name}\$` if [ "$id" = "" ] ; then echo "Could not find entry $name in export list (try exportfs -l)" >&2 exit 4 fi $NIUTIL -read / $id if [ $? -ne 0 ] ; then echo "Could not read properties for export ${name}" >&2 exit 4 fi } #implements "-p" function -- Just removes your "exports" entry from the Netinfo DB function purge_exports() { $NIUTIL -destroy / /exports if [ $? != 0 ] ; then echo "Could not remove /exports entry in Netinfo DB" >&2 fi KICK_MOUNTD=yes } function print_usage() { echo $NAME $VERSION cat <] [-c ] [-r ] [-l] [-s ] [-p] [-h] Either one of the options listed above can be specified. -a : exports everything from the listed exports file (-- : read from stdin) See exports(5) for more info -c : processes an export entry specified at the command line. (See exports(5) for valid export entries -r : removes a given export entry (example: exportfs -r /Users) -l : lists all currently exported filesystems (check with showmount -e whether NFS is happy) -s : show all the properties for a given export -p : Removes all export entries -h : Shows this usage message EOF } # # Execution starts here # # at first, make sure an /exports entry exists in the netinfo database EXPORTS_NUM=`$NIUTIL -list / / | grep exports\$ | cut -f1` if [ "$EXPORTS_NUM" = "" ] ; then # create exports directory echo "Creating exports entry in netinfo DB. - Remove with exportfs -p" $NIUTIL -create / /exports EXPORTS_NUM=`$NIUTIL -list / / | grep exports\$ | cut -f1` if [ "$EXPORTS_NUM" = "" ] ; then echo "Could not creates /exports entry in netinfo database" >&2 exit 1 fi fi case "$1" in -a) shift export_from_file $1 shift ;; -c) shift export_from_arg $* shift ;; -r) shift remove_export "$1" shift ;; -l) list_exports shift ;; -s) shift show_export "$1" ;; -p) purge_exports shift ;; -h|*) print_usage shift ;; esac if [ "$KICK_MOUNTD" = "yes" ] ; then # Send mountd a HUP mountd_line=`ps ax | grep "[0-9] mountd"` if [ "$mountd_line" = "" ] ; then ( echo Warning: It appears that your mountd is not running... echo Chances are you have no NFS services running. echo For NFS, you need to start \"portmap\", then \"nfsd\" echo and \"mountd\". ) >&2 else echo $mountd_line | ( read mount_pid JUNK kill -HUP $mount_pid ) fi fi exit 0