153494Sdillon/* 253494Sdillon * Copyright (c) 1999 Martin Blapp 353494Sdillon * All rights reserved. 453494Sdillon * 553494Sdillon * Redistribution and use in source and binary forms, with or without 653494Sdillon * modification, are permitted provided that the following conditions 753494Sdillon * are met: 853494Sdillon * 1. Redistributions of source code must retain the above copyright 953494Sdillon * notice, this list of conditions and the following disclaimer. 1053494Sdillon * 2. Redistributions in binary form must reproduce the above copyright 1153494Sdillon * notice, this list of conditions and the following disclaimer in the 1253494Sdillon * documentation and/or other materials provided with the distribution. 1353494Sdillon * 1453494Sdillon * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1553494Sdillon * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1653494Sdillon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1753494Sdillon * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1853494Sdillon * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1953494Sdillon * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2053494Sdillon * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2153494Sdillon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2253494Sdillon * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2353494Sdillon * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2453494Sdillon * SUCH DAMAGE. 2553494Sdillon * 2653494Sdillon */ 2753494Sdillon 28114601Sobrien#include <sys/cdefs.h> 29114601Sobrien__FBSDID("$FreeBSD$"); 3053494Sdillon 3153494Sdillon#include <sys/syslog.h> 3253494Sdillon 3353494Sdillon#include <rpc/rpc.h> 34194880Sdfr#include <rpcsvc/mount.h> 3553494Sdillon 3653494Sdillon#include <err.h> 3753494Sdillon#include <errno.h> 3880146Siedowse#include <limits.h> 3953494Sdillon#include <stdio.h> 4053494Sdillon#include <stdlib.h> 4153494Sdillon#include <string.h> 4253494Sdillon#include <unistd.h> 4353494Sdillon 4453494Sdillon#include "mounttab.h" 4553494Sdillon 4653494Sdillonstruct mtablist *mtabhead; 4753494Sdillon 48201135Sdelphijstatic void badline(const char *field, const char *bad); 4980146Siedowse 5053494Sdillon/* 5153494Sdillon * Add an entry to PATH_MOUNTTAB for each mounted NFS filesystem, 5253494Sdillon * so the client can notify the NFS server even after reboot. 5353494Sdillon */ 5453494Sdillonint 55201252Sedadd_mtab(char *hostp, char *dirp) 56201252Sed{ 5753494Sdillon FILE *mtabfile; 5853494Sdillon 5953494Sdillon if ((mtabfile = fopen(PATH_MOUNTTAB, "a")) == NULL) 6053494Sdillon return (0); 6153494Sdillon else { 6266814Sbde fprintf(mtabfile, "%ld\t%s\t%s\n", 6380146Siedowse (long)time(NULL), hostp, dirp); 6453494Sdillon fclose(mtabfile); 6553494Sdillon return (1); 6653494Sdillon } 6753494Sdillon} 6853494Sdillon 6953494Sdillon/* 7053494Sdillon * Read mounttab line for line and return struct mtablist. 7153494Sdillon */ 7253494Sdillonint 73201252Sedread_mtab(void) 74201252Sed{ 7580146Siedowse struct mtablist **mtabpp, *mtabp; 7653494Sdillon char *hostp, *dirp, *cp; 7753494Sdillon char str[STRSIZ]; 7880146Siedowse char *timep, *endp; 79201135Sdelphij time_t actiontime; 8080146Siedowse u_long ultmp; 8153494Sdillon FILE *mtabfile; 8253494Sdillon 8353494Sdillon if ((mtabfile = fopen(PATH_MOUNTTAB, "r")) == NULL) { 8453494Sdillon if (errno == ENOENT) 8553494Sdillon return (0); 8653494Sdillon else { 8753494Sdillon syslog(LOG_ERR, "can't open %s", PATH_MOUNTTAB); 8853494Sdillon return (0); 8953494Sdillon } 9053494Sdillon } 91201135Sdelphij actiontime = 0; 9253494Sdillon mtabpp = &mtabhead; 9353494Sdillon while (fgets(str, STRSIZ, mtabfile) != NULL) { 9453494Sdillon cp = str; 9553494Sdillon errno = 0; 9653494Sdillon if (*cp == '#' || *cp == ' ' || *cp == '\n') 9753494Sdillon continue; 9853494Sdillon timep = strsep(&cp, " \t\n"); 9980146Siedowse if (timep == NULL || *timep == '\0') { 10080146Siedowse badline("time", timep); 10153494Sdillon continue; 10253494Sdillon } 10353494Sdillon hostp = strsep(&cp, " \t\n"); 10480146Siedowse if (hostp == NULL || *hostp == '\0') { 10580146Siedowse badline("host", hostp); 10653494Sdillon continue; 10753494Sdillon } 10853494Sdillon dirp = strsep(&cp, " \t\n"); 10980146Siedowse if (dirp == NULL || *dirp == '\0') { 11080146Siedowse badline("dir", dirp); 11153494Sdillon continue; 11253494Sdillon } 11380146Siedowse ultmp = strtoul(timep, &endp, 10); 11480146Siedowse if (ultmp == ULONG_MAX || *endp != '\0') { 11580146Siedowse badline("time", timep); 11653494Sdillon continue; 11753494Sdillon } 118201135Sdelphij actiontime = ultmp; 11953494Sdillon if ((mtabp = malloc(sizeof (struct mtablist))) == NULL) { 12053494Sdillon syslog(LOG_ERR, "malloc"); 12153494Sdillon fclose(mtabfile); 12253494Sdillon return (0); 12353494Sdillon } 124201135Sdelphij mtabp->mtab_time = actiontime; 125194880Sdfr memmove(mtabp->mtab_host, hostp, MNTNAMLEN); 126194880Sdfr mtabp->mtab_host[MNTNAMLEN - 1] = '\0'; 127194880Sdfr memmove(mtabp->mtab_dirp, dirp, MNTPATHLEN); 128194880Sdfr mtabp->mtab_dirp[MNTPATHLEN - 1] = '\0'; 12953494Sdillon mtabp->mtab_next = (struct mtablist *)NULL; 13053494Sdillon *mtabpp = mtabp; 13153494Sdillon mtabpp = &mtabp->mtab_next; 13253494Sdillon } 13353494Sdillon fclose(mtabfile); 13453494Sdillon return (1); 13553494Sdillon} 13653494Sdillon 13753494Sdillon/* 13853494Sdillon * Rewrite PATH_MOUNTTAB from scratch and skip bad entries. 13953494Sdillon * Unlink PATH_MOUNTAB if no entry is left. 14053494Sdillon */ 14153494Sdillonint 142201252Sedwrite_mtab(int verbose) 143201252Sed{ 14480146Siedowse struct mtablist *mtabp, *mp; 14553494Sdillon FILE *mtabfile; 14653494Sdillon int line; 14753494Sdillon 14853494Sdillon if ((mtabfile = fopen(PATH_MOUNTTAB, "w")) == NULL) { 14953494Sdillon syslog(LOG_ERR, "can't write to %s", PATH_MOUNTTAB); 15053494Sdillon return (0); 15153494Sdillon } 15253494Sdillon line = 0; 15353494Sdillon for (mtabp = mtabhead; mtabp != NULL; mtabp = mtabp->mtab_next) { 15480146Siedowse if (mtabp->mtab_host[0] == '\0') 15580146Siedowse continue; 15680146Siedowse /* Skip if a later (hence more recent) entry is identical. */ 15780146Siedowse for (mp = mtabp->mtab_next; mp != NULL; mp = mp->mtab_next) 15880146Siedowse if (strcmp(mtabp->mtab_host, mp->mtab_host) == 0 && 15980146Siedowse strcmp(mtabp->mtab_dirp, mp->mtab_dirp) == 0) 16080146Siedowse break; 16180146Siedowse if (mp != NULL) 16280146Siedowse continue; 16380146Siedowse 16480146Siedowse fprintf(mtabfile, "%ld\t%s\t%s\n", 16580146Siedowse (long)mtabp->mtab_time, mtabp->mtab_host, 16680146Siedowse mtabp->mtab_dirp); 16780146Siedowse if (verbose) 16880146Siedowse warnx("write mounttab entry %s:%s", 16980146Siedowse mtabp->mtab_host, mtabp->mtab_dirp); 17080146Siedowse line++; 17153494Sdillon } 17253494Sdillon fclose(mtabfile); 17353494Sdillon if (line == 0) { 17453494Sdillon if (unlink(PATH_MOUNTTAB) == -1) { 17553494Sdillon syslog(LOG_ERR, "can't remove %s", PATH_MOUNTTAB); 17653494Sdillon return (0); 17753494Sdillon } 17853494Sdillon } 17953494Sdillon return (1); 18053494Sdillon} 18153494Sdillon 18253494Sdillon/* 18353494Sdillon * Mark the entries as clean where RPC calls have been done successfully. 18453494Sdillon */ 18553494Sdillonvoid 186201252Sedclean_mtab(char *hostp, char *dirp, int verbose) 187201252Sed{ 18853494Sdillon struct mtablist *mtabp; 18953494Sdillon char *host; 19053494Sdillon 19180146Siedowse /* Copy hostp in case it points to an entry that we are zeroing out. */ 19253494Sdillon host = strdup(hostp); 19353494Sdillon for (mtabp = mtabhead; mtabp != NULL; mtabp = mtabp->mtab_next) { 19481070Siedowse if (strcmp(mtabp->mtab_host, host) != 0) 19580146Siedowse continue; 19680146Siedowse if (dirp != NULL && strcmp(mtabp->mtab_dirp, dirp) != 0) 19780146Siedowse continue; 19880146Siedowse 19980146Siedowse if (verbose) 20080146Siedowse warnx("delete mounttab entry%s %s:%s", 20180146Siedowse (dirp == NULL) ? " by host" : "", 20280146Siedowse mtabp->mtab_host, mtabp->mtab_dirp); 203194880Sdfr bzero(mtabp->mtab_host, MNTNAMLEN); 20453494Sdillon } 20553494Sdillon free(host); 20653494Sdillon} 20753494Sdillon 20853494Sdillon/* 20953494Sdillon * Free struct mtablist mtab. 21053494Sdillon */ 21153494Sdillonvoid 212201252Sedfree_mtab(void) 213201252Sed{ 21453494Sdillon struct mtablist *mtabp; 21553494Sdillon 21680146Siedowse while ((mtabp = mtabhead) != NULL) { 21780146Siedowse mtabhead = mtabhead->mtab_next; 21853494Sdillon free(mtabp); 21953494Sdillon } 22053494Sdillon} 22153494Sdillon 22253494Sdillon/* 22353494Sdillon * Print bad lines to syslog. 22453494Sdillon */ 22580146Siedowsestatic void 226201252Sedbadline(const char *field, const char *bad) 227201252Sed{ 22880146Siedowse syslog(LOG_ERR, "bad mounttab %s field '%s'", field, 22980146Siedowse (bad == NULL) ? "<null>" : bad); 23053494Sdillon} 231