mounttab.c revision 80146
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
2853494Sdillon#ifndef lint
2953494Sdillonstatic const char rcsid[] =
3053494Sdillon  "$FreeBSD: head/usr.sbin/rpc.umntall/mounttab.c 80146 2001-07-22 12:17:51Z iedowse $";
3153494Sdillon#endif /* not lint */
3253494Sdillon
3353494Sdillon#include <sys/syslog.h>
3453494Sdillon
3553494Sdillon#include <rpc/rpc.h>
3653494Sdillon#include <nfs/rpcv2.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
5080146Siedowsestatic void badline(char *field, 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
5753494Sdillonadd_mtab(char *hostp, char *dirp) {
5853494Sdillon	FILE *mtabfile;
5953494Sdillon
6053494Sdillon	if ((mtabfile = fopen(PATH_MOUNTTAB, "a")) == NULL)
6153494Sdillon		return (0);
6253494Sdillon	else {
6366814Sbde		fprintf(mtabfile, "%ld\t%s\t%s\n",
6480146Siedowse		    (long)time(NULL), hostp, dirp);
6553494Sdillon		fclose(mtabfile);
6653494Sdillon		return (1);
6753494Sdillon	}
6853494Sdillon}
6953494Sdillon
7053494Sdillon/*
7153494Sdillon * Read mounttab line for line and return struct mtablist.
7253494Sdillon */
7353494Sdillonint
7480146Siedowseread_mtab() {
7580146Siedowse	struct mtablist **mtabpp, *mtabp;
7653494Sdillon	char *hostp, *dirp, *cp;
7753494Sdillon	char str[STRSIZ];
7880146Siedowse	char *timep, *endp;
7953494Sdillon	time_t time;
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	}
9153494Sdillon	time = 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		}
11880146Siedowse		time = ultmp;
11953494Sdillon		if ((mtabp = malloc(sizeof (struct mtablist))) == NULL) {
12053494Sdillon			syslog(LOG_ERR, "malloc");
12153494Sdillon			fclose(mtabfile);
12253494Sdillon			return (0);
12353494Sdillon		}
12453494Sdillon		mtabp->mtab_time = time;
12553494Sdillon		memmove(mtabp->mtab_host, hostp, RPCMNT_NAMELEN);
12653494Sdillon		mtabp->mtab_host[RPCMNT_NAMELEN - 1] = '\0';
12753494Sdillon		memmove(mtabp->mtab_dirp, dirp, RPCMNT_PATHLEN);
12853494Sdillon		mtabp->mtab_dirp[RPCMNT_PATHLEN - 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
14280146Siedowsewrite_mtab(int verbose) {
14380146Siedowse	struct mtablist *mtabp, *mp;
14453494Sdillon	FILE *mtabfile;
14553494Sdillon	int line;
14653494Sdillon
14753494Sdillon	if ((mtabfile = fopen(PATH_MOUNTTAB, "w")) == NULL) {
14853494Sdillon		syslog(LOG_ERR, "can't write to %s", PATH_MOUNTTAB);
14953494Sdillon			return (0);
15053494Sdillon	}
15153494Sdillon	line = 0;
15253494Sdillon	for (mtabp = mtabhead; mtabp != NULL; mtabp = mtabp->mtab_next) {
15380146Siedowse		if (mtabp->mtab_host[0] == '\0')
15480146Siedowse			continue;
15580146Siedowse		/* Skip if a later (hence more recent) entry is identical. */
15680146Siedowse		for (mp = mtabp->mtab_next; mp != NULL; mp = mp->mtab_next)
15780146Siedowse			if (strcmp(mtabp->mtab_host, mp->mtab_host) == 0 &&
15880146Siedowse			    strcmp(mtabp->mtab_dirp, mp->mtab_dirp) == 0)
15980146Siedowse				break;
16080146Siedowse		if (mp != NULL)
16180146Siedowse			continue;
16280146Siedowse
16380146Siedowse		fprintf(mtabfile, "%ld\t%s\t%s\n",
16480146Siedowse		    (long)mtabp->mtab_time, mtabp->mtab_host,
16580146Siedowse		    mtabp->mtab_dirp);
16680146Siedowse		if (verbose)
16780146Siedowse			warnx("write mounttab entry %s:%s",
16880146Siedowse			    mtabp->mtab_host, mtabp->mtab_dirp);
16980146Siedowse		line++;
17053494Sdillon	}
17153494Sdillon	fclose(mtabfile);
17253494Sdillon	if (line == 0) {
17353494Sdillon		if (unlink(PATH_MOUNTTAB) == -1) {
17453494Sdillon			syslog(LOG_ERR, "can't remove %s", PATH_MOUNTTAB);
17553494Sdillon			return (0);
17653494Sdillon		}
17753494Sdillon	}
17853494Sdillon	return (1);
17953494Sdillon}
18053494Sdillon
18153494Sdillon/*
18253494Sdillon * Mark the entries as clean where RPC calls have been done successfully.
18353494Sdillon */
18453494Sdillonvoid
18580146Siedowseclean_mtab(char *hostp, char *dirp, int verbose) {
18653494Sdillon	struct mtablist *mtabp;
18753494Sdillon	char *host;
18853494Sdillon
18980146Siedowse	/* Copy hostp in case it points to an entry that we are zeroing out. */
19053494Sdillon	host = strdup(hostp);
19153494Sdillon	for (mtabp = mtabhead; mtabp != NULL; mtabp = mtabp->mtab_next) {
19280146Siedowse		if (strcmp(mtabp->mtab_host, hostp) != 0)
19380146Siedowse			continue;
19480146Siedowse		if (dirp != NULL && strcmp(mtabp->mtab_dirp, dirp) != 0)
19580146Siedowse			continue;
19680146Siedowse
19780146Siedowse		if (verbose)
19880146Siedowse			warnx("delete mounttab entry%s %s:%s",
19980146Siedowse			    (dirp == NULL) ? " by host" : "",
20080146Siedowse			    mtabp->mtab_host, mtabp->mtab_dirp);
20180146Siedowse		bzero(mtabp->mtab_host, RPCMNT_NAMELEN);
20253494Sdillon	}
20353494Sdillon	free(host);
20453494Sdillon}
20553494Sdillon
20653494Sdillon/*
20753494Sdillon * Free struct mtablist mtab.
20853494Sdillon */
20953494Sdillonvoid
21053494Sdillonfree_mtab() {
21153494Sdillon	struct mtablist *mtabp;
21253494Sdillon
21380146Siedowse	while ((mtabp = mtabhead) != NULL) {
21480146Siedowse		mtabhead = mtabhead->mtab_next;
21553494Sdillon		free(mtabp);
21653494Sdillon	}
21753494Sdillon}
21853494Sdillon
21953494Sdillon/*
22053494Sdillon * Print bad lines to syslog.
22153494Sdillon */
22280146Siedowsestatic void
22380146Siedowsebadline(char *field, char *bad) {
22480146Siedowse	syslog(LOG_ERR, "bad mounttab %s field '%s'", field,
22580146Siedowse	    (bad == NULL) ? "<null>" : bad);
22653494Sdillon}
227