1330449Seadler/*- 2330449Seadler * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3330449Seadler * 453494Sdillon * Copyright (c) 1999 Martin Blapp 553494Sdillon * All rights reserved. 653494Sdillon * 753494Sdillon * Redistribution and use in source and binary forms, with or without 853494Sdillon * modification, are permitted provided that the following conditions 953494Sdillon * are met: 1053494Sdillon * 1. Redistributions of source code must retain the above copyright 1153494Sdillon * notice, this list of conditions and the following disclaimer. 1253494Sdillon * 2. Redistributions in binary form must reproduce the above copyright 1353494Sdillon * notice, this list of conditions and the following disclaimer in the 1453494Sdillon * documentation and/or other materials provided with the distribution. 1553494Sdillon * 1653494Sdillon * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1753494Sdillon * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1853494Sdillon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1953494Sdillon * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2053494Sdillon * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2153494Sdillon * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2253494Sdillon * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2353494Sdillon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2453494Sdillon * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2553494Sdillon * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2653494Sdillon * SUCH DAMAGE. 2753494Sdillon * 2853494Sdillon */ 2953494Sdillon 30114601Sobrien#include <sys/cdefs.h> 31114601Sobrien__FBSDID("$FreeBSD: stable/11/usr.sbin/rpc.umntall/mounttab.c 330449 2018-03-05 07:26:05Z eadler $"); 3253494Sdillon 3353494Sdillon#include <sys/syslog.h> 3453494Sdillon 3553494Sdillon#include <rpc/rpc.h> 36194880Sdfr#include <rpcsvc/mount.h> 3753494Sdillon 3853494Sdillon#include <err.h> 3953494Sdillon#include <errno.h> 4080146Siedowse#include <limits.h> 4153494Sdillon#include <stdio.h> 4253494Sdillon#include <stdlib.h> 4353494Sdillon#include <string.h> 4453494Sdillon#include <unistd.h> 4553494Sdillon 4653494Sdillon#include "mounttab.h" 4753494Sdillon 4853494Sdillonstruct mtablist *mtabhead; 4953494Sdillon 50201135Sdelphijstatic void badline(const char *field, const char *bad); 5180146Siedowse 5253494Sdillon/* 5353494Sdillon * Add an entry to PATH_MOUNTTAB for each mounted NFS filesystem, 5453494Sdillon * so the client can notify the NFS server even after reboot. 5553494Sdillon */ 5653494Sdillonint 57201252Sedadd_mtab(char *hostp, char *dirp) 58201252Sed{ 5953494Sdillon FILE *mtabfile; 6053494Sdillon 6153494Sdillon if ((mtabfile = fopen(PATH_MOUNTTAB, "a")) == NULL) 6253494Sdillon return (0); 6353494Sdillon else { 6466814Sbde fprintf(mtabfile, "%ld\t%s\t%s\n", 6580146Siedowse (long)time(NULL), hostp, dirp); 6653494Sdillon fclose(mtabfile); 6753494Sdillon return (1); 6853494Sdillon } 6953494Sdillon} 7053494Sdillon 7153494Sdillon/* 7253494Sdillon * Read mounttab line for line and return struct mtablist. 7353494Sdillon */ 7453494Sdillonint 75201252Sedread_mtab(void) 76201252Sed{ 7780146Siedowse struct mtablist **mtabpp, *mtabp; 7853494Sdillon char *hostp, *dirp, *cp; 7953494Sdillon char str[STRSIZ]; 8080146Siedowse char *timep, *endp; 81201135Sdelphij time_t actiontime; 8280146Siedowse u_long ultmp; 8353494Sdillon FILE *mtabfile; 8453494Sdillon 8553494Sdillon if ((mtabfile = fopen(PATH_MOUNTTAB, "r")) == NULL) { 8653494Sdillon if (errno == ENOENT) 8753494Sdillon return (0); 8853494Sdillon else { 8953494Sdillon syslog(LOG_ERR, "can't open %s", PATH_MOUNTTAB); 9053494Sdillon return (0); 9153494Sdillon } 9253494Sdillon } 93201135Sdelphij actiontime = 0; 9453494Sdillon mtabpp = &mtabhead; 9553494Sdillon while (fgets(str, STRSIZ, mtabfile) != NULL) { 9653494Sdillon cp = str; 9753494Sdillon errno = 0; 9853494Sdillon if (*cp == '#' || *cp == ' ' || *cp == '\n') 9953494Sdillon continue; 10053494Sdillon timep = strsep(&cp, " \t\n"); 10180146Siedowse if (timep == NULL || *timep == '\0') { 10280146Siedowse badline("time", timep); 10353494Sdillon continue; 10453494Sdillon } 10553494Sdillon hostp = strsep(&cp, " \t\n"); 10680146Siedowse if (hostp == NULL || *hostp == '\0') { 10780146Siedowse badline("host", hostp); 10853494Sdillon continue; 10953494Sdillon } 11053494Sdillon dirp = strsep(&cp, " \t\n"); 11180146Siedowse if (dirp == NULL || *dirp == '\0') { 11280146Siedowse badline("dir", dirp); 11353494Sdillon continue; 11453494Sdillon } 11580146Siedowse ultmp = strtoul(timep, &endp, 10); 11680146Siedowse if (ultmp == ULONG_MAX || *endp != '\0') { 11780146Siedowse badline("time", timep); 11853494Sdillon continue; 11953494Sdillon } 120201135Sdelphij actiontime = ultmp; 12153494Sdillon if ((mtabp = malloc(sizeof (struct mtablist))) == NULL) { 12253494Sdillon syslog(LOG_ERR, "malloc"); 12353494Sdillon fclose(mtabfile); 12453494Sdillon return (0); 12553494Sdillon } 126201135Sdelphij mtabp->mtab_time = actiontime; 127194880Sdfr memmove(mtabp->mtab_host, hostp, MNTNAMLEN); 128194880Sdfr mtabp->mtab_host[MNTNAMLEN - 1] = '\0'; 129194880Sdfr memmove(mtabp->mtab_dirp, dirp, MNTPATHLEN); 130194880Sdfr mtabp->mtab_dirp[MNTPATHLEN - 1] = '\0'; 13153494Sdillon mtabp->mtab_next = (struct mtablist *)NULL; 13253494Sdillon *mtabpp = mtabp; 13353494Sdillon mtabpp = &mtabp->mtab_next; 13453494Sdillon } 13553494Sdillon fclose(mtabfile); 13653494Sdillon return (1); 13753494Sdillon} 13853494Sdillon 13953494Sdillon/* 14053494Sdillon * Rewrite PATH_MOUNTTAB from scratch and skip bad entries. 14153494Sdillon * Unlink PATH_MOUNTAB if no entry is left. 14253494Sdillon */ 14353494Sdillonint 144201252Sedwrite_mtab(int verbose) 145201252Sed{ 14680146Siedowse struct mtablist *mtabp, *mp; 14753494Sdillon FILE *mtabfile; 14853494Sdillon int line; 14953494Sdillon 15053494Sdillon if ((mtabfile = fopen(PATH_MOUNTTAB, "w")) == NULL) { 15153494Sdillon syslog(LOG_ERR, "can't write to %s", PATH_MOUNTTAB); 15253494Sdillon return (0); 15353494Sdillon } 15453494Sdillon line = 0; 15553494Sdillon for (mtabp = mtabhead; mtabp != NULL; mtabp = mtabp->mtab_next) { 15680146Siedowse if (mtabp->mtab_host[0] == '\0') 15780146Siedowse continue; 15880146Siedowse /* Skip if a later (hence more recent) entry is identical. */ 15980146Siedowse for (mp = mtabp->mtab_next; mp != NULL; mp = mp->mtab_next) 16080146Siedowse if (strcmp(mtabp->mtab_host, mp->mtab_host) == 0 && 16180146Siedowse strcmp(mtabp->mtab_dirp, mp->mtab_dirp) == 0) 16280146Siedowse break; 16380146Siedowse if (mp != NULL) 16480146Siedowse continue; 16580146Siedowse 16680146Siedowse fprintf(mtabfile, "%ld\t%s\t%s\n", 16780146Siedowse (long)mtabp->mtab_time, mtabp->mtab_host, 16880146Siedowse mtabp->mtab_dirp); 16980146Siedowse if (verbose) 17080146Siedowse warnx("write mounttab entry %s:%s", 17180146Siedowse mtabp->mtab_host, mtabp->mtab_dirp); 17280146Siedowse line++; 17353494Sdillon } 17453494Sdillon fclose(mtabfile); 17553494Sdillon if (line == 0) { 17653494Sdillon if (unlink(PATH_MOUNTTAB) == -1) { 17753494Sdillon syslog(LOG_ERR, "can't remove %s", PATH_MOUNTTAB); 17853494Sdillon return (0); 17953494Sdillon } 18053494Sdillon } 18153494Sdillon return (1); 18253494Sdillon} 18353494Sdillon 18453494Sdillon/* 18553494Sdillon * Mark the entries as clean where RPC calls have been done successfully. 18653494Sdillon */ 18753494Sdillonvoid 188201252Sedclean_mtab(char *hostp, char *dirp, int verbose) 189201252Sed{ 19053494Sdillon struct mtablist *mtabp; 19153494Sdillon char *host; 19253494Sdillon 19380146Siedowse /* Copy hostp in case it points to an entry that we are zeroing out. */ 19453494Sdillon host = strdup(hostp); 19553494Sdillon for (mtabp = mtabhead; mtabp != NULL; mtabp = mtabp->mtab_next) { 19681070Siedowse if (strcmp(mtabp->mtab_host, host) != 0) 19780146Siedowse continue; 19880146Siedowse if (dirp != NULL && strcmp(mtabp->mtab_dirp, dirp) != 0) 19980146Siedowse continue; 20080146Siedowse 20180146Siedowse if (verbose) 20280146Siedowse warnx("delete mounttab entry%s %s:%s", 20380146Siedowse (dirp == NULL) ? " by host" : "", 20480146Siedowse mtabp->mtab_host, mtabp->mtab_dirp); 205194880Sdfr bzero(mtabp->mtab_host, MNTNAMLEN); 20653494Sdillon } 20753494Sdillon free(host); 20853494Sdillon} 20953494Sdillon 21053494Sdillon/* 21153494Sdillon * Free struct mtablist mtab. 21253494Sdillon */ 21353494Sdillonvoid 214201252Sedfree_mtab(void) 215201252Sed{ 21653494Sdillon struct mtablist *mtabp; 21753494Sdillon 21880146Siedowse while ((mtabp = mtabhead) != NULL) { 21980146Siedowse mtabhead = mtabhead->mtab_next; 22053494Sdillon free(mtabp); 22153494Sdillon } 22253494Sdillon} 22353494Sdillon 22453494Sdillon/* 22553494Sdillon * Print bad lines to syslog. 22653494Sdillon */ 22780146Siedowsestatic void 228201252Sedbadline(const char *field, const char *bad) 229201252Sed{ 23080146Siedowse syslog(LOG_ERR, "bad mounttab %s field '%s'", field, 23180146Siedowse (bad == NULL) ? "<null>" : bad); 23253494Sdillon} 233