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