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