mounttab.c revision 201135
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: head/usr.sbin/rpc.umntall/mounttab.c 201135 2009-12-28 17:57:37Z delphij $");
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
5553494Sdillonadd_mtab(char *hostp, char *dirp) {
5653494Sdillon	FILE *mtabfile;
5753494Sdillon
5853494Sdillon	if ((mtabfile = fopen(PATH_MOUNTTAB, "a")) == NULL)
5953494Sdillon		return (0);
6053494Sdillon	else {
6166814Sbde		fprintf(mtabfile, "%ld\t%s\t%s\n",
6280146Siedowse		    (long)time(NULL), hostp, dirp);
6353494Sdillon		fclose(mtabfile);
6453494Sdillon		return (1);
6553494Sdillon	}
6653494Sdillon}
6753494Sdillon
6853494Sdillon/*
6953494Sdillon * Read mounttab line for line and return struct mtablist.
7053494Sdillon */
7153494Sdillonint
72201135Sdelphijread_mtab(void) {
7380146Siedowse	struct mtablist **mtabpp, *mtabp;
7453494Sdillon	char *hostp, *dirp, *cp;
7553494Sdillon	char str[STRSIZ];
7680146Siedowse	char *timep, *endp;
77201135Sdelphij	time_t actiontime;
7880146Siedowse	u_long ultmp;
7953494Sdillon	FILE *mtabfile;
8053494Sdillon
8153494Sdillon	if ((mtabfile = fopen(PATH_MOUNTTAB, "r")) == NULL) {
8253494Sdillon		if (errno == ENOENT)
8353494Sdillon			return (0);
8453494Sdillon		else {
8553494Sdillon			syslog(LOG_ERR, "can't open %s", PATH_MOUNTTAB);
8653494Sdillon			return (0);
8753494Sdillon		}
8853494Sdillon	}
89201135Sdelphij	actiontime = 0;
9053494Sdillon	mtabpp = &mtabhead;
9153494Sdillon	while (fgets(str, STRSIZ, mtabfile) != NULL) {
9253494Sdillon		cp = str;
9353494Sdillon		errno = 0;
9453494Sdillon		if (*cp == '#' || *cp == ' ' || *cp == '\n')
9553494Sdillon			continue;
9653494Sdillon		timep = strsep(&cp, " \t\n");
9780146Siedowse		if (timep == NULL || *timep == '\0') {
9880146Siedowse			badline("time", timep);
9953494Sdillon			continue;
10053494Sdillon		}
10153494Sdillon		hostp = strsep(&cp, " \t\n");
10280146Siedowse		if (hostp == NULL || *hostp == '\0') {
10380146Siedowse			badline("host", hostp);
10453494Sdillon			continue;
10553494Sdillon		}
10653494Sdillon		dirp = strsep(&cp, " \t\n");
10780146Siedowse		if (dirp == NULL || *dirp == '\0') {
10880146Siedowse			badline("dir", dirp);
10953494Sdillon			continue;
11053494Sdillon		}
11180146Siedowse		ultmp = strtoul(timep, &endp, 10);
11280146Siedowse		if (ultmp == ULONG_MAX || *endp != '\0') {
11380146Siedowse			badline("time", timep);
11453494Sdillon			continue;
11553494Sdillon		}
116201135Sdelphij		actiontime = ultmp;
11753494Sdillon		if ((mtabp = malloc(sizeof (struct mtablist))) == NULL) {
11853494Sdillon			syslog(LOG_ERR, "malloc");
11953494Sdillon			fclose(mtabfile);
12053494Sdillon			return (0);
12153494Sdillon		}
122201135Sdelphij		mtabp->mtab_time = actiontime;
123194880Sdfr		memmove(mtabp->mtab_host, hostp, MNTNAMLEN);
124194880Sdfr		mtabp->mtab_host[MNTNAMLEN - 1] = '\0';
125194880Sdfr		memmove(mtabp->mtab_dirp, dirp, MNTPATHLEN);
126194880Sdfr		mtabp->mtab_dirp[MNTPATHLEN - 1] = '\0';
12753494Sdillon		mtabp->mtab_next = (struct mtablist *)NULL;
12853494Sdillon		*mtabpp = mtabp;
12953494Sdillon		mtabpp = &mtabp->mtab_next;
13053494Sdillon	}
13153494Sdillon	fclose(mtabfile);
13253494Sdillon	return (1);
13353494Sdillon}
13453494Sdillon
13553494Sdillon/*
13653494Sdillon * Rewrite PATH_MOUNTTAB from scratch and skip bad entries.
13753494Sdillon * Unlink PATH_MOUNTAB if no entry is left.
13853494Sdillon */
13953494Sdillonint
14080146Siedowsewrite_mtab(int verbose) {
14180146Siedowse	struct mtablist *mtabp, *mp;
14253494Sdillon	FILE *mtabfile;
14353494Sdillon	int line;
14453494Sdillon
14553494Sdillon	if ((mtabfile = fopen(PATH_MOUNTTAB, "w")) == NULL) {
14653494Sdillon		syslog(LOG_ERR, "can't write to %s", PATH_MOUNTTAB);
14753494Sdillon			return (0);
14853494Sdillon	}
14953494Sdillon	line = 0;
15053494Sdillon	for (mtabp = mtabhead; mtabp != NULL; mtabp = mtabp->mtab_next) {
15180146Siedowse		if (mtabp->mtab_host[0] == '\0')
15280146Siedowse			continue;
15380146Siedowse		/* Skip if a later (hence more recent) entry is identical. */
15480146Siedowse		for (mp = mtabp->mtab_next; mp != NULL; mp = mp->mtab_next)
15580146Siedowse			if (strcmp(mtabp->mtab_host, mp->mtab_host) == 0 &&
15680146Siedowse			    strcmp(mtabp->mtab_dirp, mp->mtab_dirp) == 0)
15780146Siedowse				break;
15880146Siedowse		if (mp != NULL)
15980146Siedowse			continue;
16080146Siedowse
16180146Siedowse		fprintf(mtabfile, "%ld\t%s\t%s\n",
16280146Siedowse		    (long)mtabp->mtab_time, mtabp->mtab_host,
16380146Siedowse		    mtabp->mtab_dirp);
16480146Siedowse		if (verbose)
16580146Siedowse			warnx("write mounttab entry %s:%s",
16680146Siedowse			    mtabp->mtab_host, mtabp->mtab_dirp);
16780146Siedowse		line++;
16853494Sdillon	}
16953494Sdillon	fclose(mtabfile);
17053494Sdillon	if (line == 0) {
17153494Sdillon		if (unlink(PATH_MOUNTTAB) == -1) {
17253494Sdillon			syslog(LOG_ERR, "can't remove %s", PATH_MOUNTTAB);
17353494Sdillon			return (0);
17453494Sdillon		}
17553494Sdillon	}
17653494Sdillon	return (1);
17753494Sdillon}
17853494Sdillon
17953494Sdillon/*
18053494Sdillon * Mark the entries as clean where RPC calls have been done successfully.
18153494Sdillon */
18253494Sdillonvoid
18380146Siedowseclean_mtab(char *hostp, char *dirp, int verbose) {
18453494Sdillon	struct mtablist *mtabp;
18553494Sdillon	char *host;
18653494Sdillon
18780146Siedowse	/* Copy hostp in case it points to an entry that we are zeroing out. */
18853494Sdillon	host = strdup(hostp);
18953494Sdillon	for (mtabp = mtabhead; mtabp != NULL; mtabp = mtabp->mtab_next) {
19081070Siedowse		if (strcmp(mtabp->mtab_host, host) != 0)
19180146Siedowse			continue;
19280146Siedowse		if (dirp != NULL && strcmp(mtabp->mtab_dirp, dirp) != 0)
19380146Siedowse			continue;
19480146Siedowse
19580146Siedowse		if (verbose)
19680146Siedowse			warnx("delete mounttab entry%s %s:%s",
19780146Siedowse			    (dirp == NULL) ? " by host" : "",
19880146Siedowse			    mtabp->mtab_host, mtabp->mtab_dirp);
199194880Sdfr		bzero(mtabp->mtab_host, MNTNAMLEN);
20053494Sdillon	}
20153494Sdillon	free(host);
20253494Sdillon}
20353494Sdillon
20453494Sdillon/*
20553494Sdillon * Free struct mtablist mtab.
20653494Sdillon */
20753494Sdillonvoid
20853494Sdillonfree_mtab() {
20953494Sdillon	struct mtablist *mtabp;
21053494Sdillon
21180146Siedowse	while ((mtabp = mtabhead) != NULL) {
21280146Siedowse		mtabhead = mtabhead->mtab_next;
21353494Sdillon		free(mtabp);
21453494Sdillon	}
21553494Sdillon}
21653494Sdillon
21753494Sdillon/*
21853494Sdillon * Print bad lines to syslog.
21953494Sdillon */
22080146Siedowsestatic void
221201135Sdelphijbadline(const char *field, const char *bad) {
22280146Siedowse	syslog(LOG_ERR, "bad mounttab %s field '%s'", field,
22380146Siedowse	    (bad == NULL) ? "<null>" : bad);
22453494Sdillon}
225