mounttab.c revision 256281
197403Sobrien/*
297403Sobrien * Copyright (c) 1999 Martin Blapp
3169691Skan * All rights reserved.
497403Sobrien *
597403Sobrien * Redistribution and use in source and binary forms, with or without
697403Sobrien * modification, are permitted provided that the following conditions
797403Sobrien * are met:
897403Sobrien * 1. Redistributions of source code must retain the above copyright
997403Sobrien *    notice, this list of conditions and the following disclaimer.
1097403Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1197403Sobrien *    notice, this list of conditions and the following disclaimer in the
1297403Sobrien *    documentation and/or other materials provided with the distribution.
1397403Sobrien *
1497403Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1597403Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1697403Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1797403Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1897403Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19169691Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2097403Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2197403Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2297403Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2397403Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2497403Sobrien * SUCH DAMAGE.
2597403Sobrien *
2697403Sobrien */
2797403Sobrien
2897403Sobrien#include <sys/cdefs.h>
2997403Sobrien__FBSDID("$FreeBSD: stable/10/usr.sbin/rpc.umntall/mounttab.c 201252 2009-12-30 06:36:42Z ed $");
3097403Sobrien
31169691Skan#include <sys/syslog.h>
32169691Skan
33169691Skan#include <rpc/rpc.h>
34169691Skan#include <rpcsvc/mount.h>
3597403Sobrien
36132720Skan#include <err.h>
37132720Skan#include <errno.h>
3897403Sobrien#include <limits.h>
3997403Sobrien#include <stdio.h>
4097403Sobrien#include <stdlib.h>
41132720Skan#include <string.h>
42132720Skan#include <unistd.h>
4397403Sobrien
44169691Skan#include "mounttab.h"
4597403Sobrien
46169691Skanstruct mtablist *mtabhead;
47169691Skan
4897403Sobrienstatic void badline(const char *field, const char *bad);
4997403Sobrien
5097403Sobrien/*
5197403Sobrien * Add an entry to PATH_MOUNTTAB for each mounted NFS filesystem,
5297403Sobrien * so the client can notify the NFS server even after reboot.
53132720Skan */
54132720Skanint
55132720Skanadd_mtab(char *hostp, char *dirp)
56132720Skan{
57132720Skan	FILE *mtabfile;
58132720Skan
59132720Skan	if ((mtabfile = fopen(PATH_MOUNTTAB, "a")) == NULL)
60132720Skan		return (0);
61132720Skan	else {
6297403Sobrien		fprintf(mtabfile, "%ld\t%s\t%s\n",
6397403Sobrien		    (long)time(NULL), hostp, dirp);
6497403Sobrien		fclose(mtabfile);
6597403Sobrien		return (1);
6697403Sobrien	}
6797403Sobrien}
6897403Sobrien
6997403Sobrien/*
7097403Sobrien * Read mounttab line for line and return struct mtablist.
7197403Sobrien */
7297403Sobrienint
7397403Sobrienread_mtab(void)
7497403Sobrien{
7597403Sobrien	struct mtablist **mtabpp, *mtabp;
76132720Skan	char *hostp, *dirp, *cp;
77132720Skan	char str[STRSIZ];
78132720Skan	char *timep, *endp;
79132720Skan	time_t actiontime;
80132720Skan	u_long ultmp;
81132720Skan	FILE *mtabfile;
82132720Skan
83132720Skan	if ((mtabfile = fopen(PATH_MOUNTTAB, "r")) == NULL) {
84132720Skan		if (errno == ENOENT)
85132720Skan			return (0);
86132720Skan		else {
8797403Sobrien			syslog(LOG_ERR, "can't open %s", PATH_MOUNTTAB);
88132720Skan			return (0);
89132720Skan		}
90132720Skan	}
91132720Skan	actiontime = 0;
92132720Skan	mtabpp = &mtabhead;
93132720Skan	while (fgets(str, STRSIZ, mtabfile) != NULL) {
94132720Skan		cp = str;
95132720Skan		errno = 0;
96132720Skan		if (*cp == '#' || *cp == ' ' || *cp == '\n')
97132720Skan			continue;
98132720Skan		timep = strsep(&cp, " \t\n");
99132720Skan		if (timep == NULL || *timep == '\0') {
100132720Skan			badline("time", timep);
101132720Skan			continue;
102132720Skan		}
103132720Skan		hostp = strsep(&cp, " \t\n");
104132720Skan		if (hostp == NULL || *hostp == '\0') {
105132720Skan			badline("host", hostp);
106132720Skan			continue;
107132720Skan		}
108132720Skan		dirp = strsep(&cp, " \t\n");
109132720Skan		if (dirp == NULL || *dirp == '\0') {
110132720Skan			badline("dir", dirp);
11197403Sobrien			continue;
11297403Sobrien		}
113132720Skan		ultmp = strtoul(timep, &endp, 10);
114132720Skan		if (ultmp == ULONG_MAX || *endp != '\0') {
11597403Sobrien			badline("time", timep);
11697403Sobrien			continue;
11797403Sobrien		}
11897403Sobrien		actiontime = ultmp;
11997403Sobrien		if ((mtabp = malloc(sizeof (struct mtablist))) == NULL) {
120132720Skan			syslog(LOG_ERR, "malloc");
121132720Skan			fclose(mtabfile);
12297403Sobrien			return (0);
123132720Skan		}
12497403Sobrien		mtabp->mtab_time = actiontime;
125132720Skan		memmove(mtabp->mtab_host, hostp, MNTNAMLEN);
126132720Skan		mtabp->mtab_host[MNTNAMLEN - 1] = '\0';
127132720Skan		memmove(mtabp->mtab_dirp, dirp, MNTPATHLEN);
128132720Skan		mtabp->mtab_dirp[MNTPATHLEN - 1] = '\0';
129132720Skan		mtabp->mtab_next = (struct mtablist *)NULL;
130132720Skan		*mtabpp = mtabp;
131132720Skan		mtabpp = &mtabp->mtab_next;
132132720Skan	}
133132720Skan	fclose(mtabfile);
134132720Skan	return (1);
135132720Skan}
136132720Skan
137132720Skan/*
138132720Skan * Rewrite PATH_MOUNTTAB from scratch and skip bad entries.
139132720Skan * Unlink PATH_MOUNTAB if no entry is left.
140132720Skan */
141132720Skanint
142132720Skanwrite_mtab(int verbose)
143132720Skan{
144132720Skan	struct mtablist *mtabp, *mp;
145132720Skan	FILE *mtabfile;
146132720Skan	int line;
147132720Skan
148132720Skan	if ((mtabfile = fopen(PATH_MOUNTTAB, "w")) == NULL) {
149132720Skan		syslog(LOG_ERR, "can't write to %s", PATH_MOUNTTAB);
150132720Skan			return (0);
151132720Skan	}
152132720Skan	line = 0;
153132720Skan	for (mtabp = mtabhead; mtabp != NULL; mtabp = mtabp->mtab_next) {
154132720Skan		if (mtabp->mtab_host[0] == '\0')
155132720Skan			continue;
156132720Skan		/* Skip if a later (hence more recent) entry is identical. */
157132720Skan		for (mp = mtabp->mtab_next; mp != NULL; mp = mp->mtab_next)
158132720Skan			if (strcmp(mtabp->mtab_host, mp->mtab_host) == 0 &&
159132720Skan			    strcmp(mtabp->mtab_dirp, mp->mtab_dirp) == 0)
160132720Skan				break;
161132720Skan		if (mp != NULL)
162132720Skan			continue;
163132720Skan
164132720Skan		fprintf(mtabfile, "%ld\t%s\t%s\n",
165132720Skan		    (long)mtabp->mtab_time, mtabp->mtab_host,
166132720Skan		    mtabp->mtab_dirp);
167132720Skan		if (verbose)
168132720Skan			warnx("write mounttab entry %s:%s",
169132720Skan			    mtabp->mtab_host, mtabp->mtab_dirp);
170132720Skan		line++;
171132720Skan	}
172132720Skan	fclose(mtabfile);
173132720Skan	if (line == 0) {
174132720Skan		if (unlink(PATH_MOUNTTAB) == -1) {
175132720Skan			syslog(LOG_ERR, "can't remove %s", PATH_MOUNTTAB);
176132720Skan			return (0);
177132720Skan		}
178132720Skan	}
179132720Skan	return (1);
180132720Skan}
181132720Skan
182132720Skan/*
183132720Skan * Mark the entries as clean where RPC calls have been done successfully.
184132720Skan */
185132720Skanvoid
186132720Skanclean_mtab(char *hostp, char *dirp, int verbose)
187132720Skan{
188132720Skan	struct mtablist *mtabp;
189132720Skan	char *host;
190132720Skan
191132720Skan	/* Copy hostp in case it points to an entry that we are zeroing out. */
192132720Skan	host = strdup(hostp);
193132720Skan	for (mtabp = mtabhead; mtabp != NULL; mtabp = mtabp->mtab_next) {
194132720Skan		if (strcmp(mtabp->mtab_host, host) != 0)
195132720Skan			continue;
196132720Skan		if (dirp != NULL && strcmp(mtabp->mtab_dirp, dirp) != 0)
197169691Skan			continue;
198169691Skan
199132720Skan		if (verbose)
200132720Skan			warnx("delete mounttab entry%s %s:%s",
201132720Skan			    (dirp == NULL) ? " by host" : "",
202132720Skan			    mtabp->mtab_host, mtabp->mtab_dirp);
203132720Skan		bzero(mtabp->mtab_host, MNTNAMLEN);
204132720Skan	}
205132720Skan	free(host);
206132720Skan}
207132720Skan
208132720Skan/*
209132720Skan * Free struct mtablist mtab.
210132720Skan */
211132720Skanvoid
212132720Skanfree_mtab(void)
213132720Skan{
214132720Skan	struct mtablist *mtabp;
215132720Skan
216132720Skan	while ((mtabp = mtabhead) != NULL) {
217132720Skan		mtabhead = mtabhead->mtab_next;
21897403Sobrien		free(mtabp);
21997403Sobrien	}
220132720Skan}
221132720Skan
222132720Skan/*
223117397Skan * Print bad lines to syslog.
224132720Skan */
225132720Skanstatic void
226132720Skanbadline(const char *field, const char *bad)
227132720Skan{
228132720Skan	syslog(LOG_ERR, "bad mounttab %s field '%s'", field,
229132720Skan	    (bad == NULL) ? "<null>" : bad);
230132720Skan}
231132720Skan