mounttab.c revision 80146
1233294Sstas/*
255682Smarkm * Copyright (c) 1999 Martin Blapp
3233294Sstas * All rights reserved.
4233294Sstas *
5233294Sstas * Redistribution and use in source and binary forms, with or without
655682Smarkm * modification, are permitted provided that the following conditions
7233294Sstas * are met:
8233294Sstas * 1. Redistributions of source code must retain the above copyright
9233294Sstas *    notice, this list of conditions and the following disclaimer.
1055682Smarkm * 2. Redistributions in binary form must reproduce the above copyright
11233294Sstas *    notice, this list of conditions and the following disclaimer in the
12233294Sstas *    documentation and/or other materials provided with the distribution.
1355682Smarkm *
14233294Sstas * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1755682Smarkm * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2155682Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24233294Sstas * SUCH DAMAGE.
25233294Sstas *
26233294Sstas */
27233294Sstas
28233294Sstas#ifndef lint
29233294Sstasstatic const char rcsid[] =
30233294Sstas  "$FreeBSD: head/usr.sbin/rpc.umntall/mounttab.c 80146 2001-07-22 12:17:51Z iedowse $";
31233294Sstas#endif /* not lint */
32233294Sstas
3355682Smarkm#include <sys/syslog.h>
3455682Smarkm
35233294Sstas#include <rpc/rpc.h>
3655682Smarkm#include <nfs/rpcv2.h>
3755682Smarkm
3855682Smarkm#include <err.h>
3955682Smarkm#include <errno.h>
4055682Smarkm#include <limits.h>
4155682Smarkm#include <stdio.h>
4255682Smarkm#include <stdlib.h>
4355682Smarkm#include <string.h>
4455682Smarkm#include <unistd.h>
4555682Smarkm
4655682Smarkm#include "mounttab.h"
4755682Smarkm
4872445Sassarstruct mtablist *mtabhead;
4972445Sassar
5072445Sassarstatic void badline(char *field, char *bad);
5155682Smarkm
5255682Smarkm/*
5355682Smarkm * Add an entry to PATH_MOUNTTAB for each mounted NFS filesystem,
5455682Smarkm * so the client can notify the NFS server even after reboot.
5555682Smarkm */
5655682Smarkmint
5755682Smarkmadd_mtab(char *hostp, char *dirp) {
5855682Smarkm	FILE *mtabfile;
5955682Smarkm
60233294Sstas	if ((mtabfile = fopen(PATH_MOUNTTAB, "a")) == NULL)
61233294Sstas		return (0);
62233294Sstas	else {
63233294Sstas		fprintf(mtabfile, "%ld\t%s\t%s\n",
64233294Sstas		    (long)time(NULL), hostp, dirp);
6555682Smarkm		fclose(mtabfile);
6655682Smarkm		return (1);
6755682Smarkm	}
6855682Smarkm}
6955682Smarkm
7055682Smarkm/*
7155682Smarkm * Read mounttab line for line and return struct mtablist.
7255682Smarkm */
7372445Sassarint
7472445Sassarread_mtab() {
7555682Smarkm	struct mtablist **mtabpp, *mtabp;
7655682Smarkm	char *hostp, *dirp, *cp;
7755682Smarkm	char str[STRSIZ];
7855682Smarkm	char *timep, *endp;
7955682Smarkm	time_t time;
8055682Smarkm	u_long ultmp;
8172445Sassar	FILE *mtabfile;
8272445Sassar
8372445Sassar	if ((mtabfile = fopen(PATH_MOUNTTAB, "r")) == NULL) {
8455682Smarkm		if (errno == ENOENT)
8555682Smarkm			return (0);
8672445Sassar		else {
8755682Smarkm			syslog(LOG_ERR, "can't open %s", PATH_MOUNTTAB);
8855682Smarkm			return (0);
8972445Sassar		}
9072445Sassar	}
9172445Sassar	time = 0;
9272445Sassar	mtabpp = &mtabhead;
9372445Sassar	while (fgets(str, STRSIZ, mtabfile) != NULL) {
9472445Sassar		cp = str;
9572445Sassar		errno = 0;
9655682Smarkm		if (*cp == '#' || *cp == ' ' || *cp == '\n')
9755682Smarkm			continue;
9855682Smarkm		timep = strsep(&cp, " \t\n");
9955682Smarkm		if (timep == NULL || *timep == '\0') {
100233294Sstas			badline("time", timep);
101233294Sstas			continue;
10255682Smarkm		}
10355682Smarkm		hostp = strsep(&cp, " \t\n");
10455682Smarkm		if (hostp == NULL || *hostp == '\0') {
10555682Smarkm			badline("host", hostp);
106233294Sstas			continue;
10755682Smarkm		}
10855682Smarkm		dirp = strsep(&cp, " \t\n");
10955682Smarkm		if (dirp == NULL || *dirp == '\0') {
11055682Smarkm			badline("dir", dirp);
11155682Smarkm			continue;
11255682Smarkm		}
11355682Smarkm		ultmp = strtoul(timep, &endp, 10);
11455682Smarkm		if (ultmp == ULONG_MAX || *endp != '\0') {
11555682Smarkm			badline("time", timep);
11655682Smarkm			continue;
11755682Smarkm		}
118233294Sstas		time = ultmp;
11955682Smarkm		if ((mtabp = malloc(sizeof (struct mtablist))) == NULL) {
12055682Smarkm			syslog(LOG_ERR, "malloc");
12155682Smarkm			fclose(mtabfile);
12255682Smarkm			return (0);
123233294Sstas		}
12455682Smarkm		mtabp->mtab_time = time;
12555682Smarkm		memmove(mtabp->mtab_host, hostp, RPCMNT_NAMELEN);
12655682Smarkm		mtabp->mtab_host[RPCMNT_NAMELEN - 1] = '\0';
12755682Smarkm		memmove(mtabp->mtab_dirp, dirp, RPCMNT_PATHLEN);
128233294Sstas		mtabp->mtab_dirp[RPCMNT_PATHLEN - 1] = '\0';
12955682Smarkm		mtabp->mtab_next = (struct mtablist *)NULL;
13055682Smarkm		*mtabpp = mtabp;
13155682Smarkm		mtabpp = &mtabp->mtab_next;
13255682Smarkm	}
13355682Smarkm	fclose(mtabfile);
134127808Snectar	return (1);
135127808Snectar}
136127808Snectar
137127808Snectar/*
138233294Sstas * Rewrite PATH_MOUNTTAB from scratch and skip bad entries.
139127808Snectar * Unlink PATH_MOUNTAB if no entry is left.
140233294Sstas */
141233294Sstasint
142178825Sdfrwrite_mtab(int verbose) {
143178825Sdfr	struct mtablist *mtabp, *mp;
144178825Sdfr	FILE *mtabfile;
145178825Sdfr	int line;
146178825Sdfr
147178825Sdfr	if ((mtabfile = fopen(PATH_MOUNTTAB, "w")) == NULL) {
148178825Sdfr		syslog(LOG_ERR, "can't write to %s", PATH_MOUNTTAB);
149127808Snectar			return (0);
150127808Snectar	}
151127808Snectar	line = 0;
152127808Snectar	for (mtabp = mtabhead; mtabp != NULL; mtabp = mtabp->mtab_next) {
153127808Snectar		if (mtabp->mtab_host[0] == '\0')
154127808Snectar			continue;
155233294Sstas		/* Skip if a later (hence more recent) entry is identical. */
156233294Sstas		for (mp = mtabp->mtab_next; mp != NULL; mp = mp->mtab_next)
157127808Snectar			if (strcmp(mtabp->mtab_host, mp->mtab_host) == 0 &&
158127808Snectar			    strcmp(mtabp->mtab_dirp, mp->mtab_dirp) == 0)
159127808Snectar				break;
160127808Snectar		if (mp != NULL)
161233294Sstas			continue;
162233294Sstas
163127808Snectar		fprintf(mtabfile, "%ld\t%s\t%s\n",
164233294Sstas		    (long)mtabp->mtab_time, mtabp->mtab_host,
165233294Sstas		    mtabp->mtab_dirp);
166127808Snectar		if (verbose)
167127808Snectar			warnx("write mounttab entry %s:%s",
168127808Snectar			    mtabp->mtab_host, mtabp->mtab_dirp);
169127808Snectar		line++;
170178825Sdfr	}
171178825Sdfr	fclose(mtabfile);
172178825Sdfr	if (line == 0) {
173178825Sdfr		if (unlink(PATH_MOUNTTAB) == -1) {
174178825Sdfr			syslog(LOG_ERR, "can't remove %s", PATH_MOUNTTAB);
175178825Sdfr			return (0);
176178825Sdfr		}
177178825Sdfr	}
178178825Sdfr	return (1);
179178825Sdfr}
180233294Sstas
181178825Sdfr/*
182178825Sdfr * Mark the entries as clean where RPC calls have been done successfully.
183178825Sdfr */
184178825Sdfrvoid
185178825Sdfrclean_mtab(char *hostp, char *dirp, int verbose) {
186178825Sdfr	struct mtablist *mtabp;
187178825Sdfr	char *host;
188178825Sdfr
189178825Sdfr	/* Copy hostp in case it points to an entry that we are zeroing out. */
190178825Sdfr	host = strdup(hostp);
191178825Sdfr	for (mtabp = mtabhead; mtabp != NULL; mtabp = mtabp->mtab_next) {
192178825Sdfr		if (strcmp(mtabp->mtab_host, hostp) != 0)
193178825Sdfr			continue;
194178825Sdfr		if (dirp != NULL && strcmp(mtabp->mtab_dirp, dirp) != 0)
195178825Sdfr			continue;
196178825Sdfr
197178825Sdfr		if (verbose)
198178825Sdfr			warnx("delete mounttab entry%s %s:%s",
199178825Sdfr			    (dirp == NULL) ? " by host" : "",
200178825Sdfr			    mtabp->mtab_host, mtabp->mtab_dirp);
201178825Sdfr		bzero(mtabp->mtab_host, RPCMNT_NAMELEN);
202178825Sdfr	}
203178825Sdfr	free(host);
204178825Sdfr}
205178825Sdfr
206178825Sdfr/*
207178825Sdfr * Free struct mtablist mtab.
208178825Sdfr */
209178825Sdfrvoid
210178825Sdfrfree_mtab() {
211178825Sdfr	struct mtablist *mtabp;
212178825Sdfr
213178825Sdfr	while ((mtabp = mtabhead) != NULL) {
214178825Sdfr		mtabhead = mtabhead->mtab_next;
215178825Sdfr		free(mtabp);
216233294Sstas	}
217178825Sdfr}
218178825Sdfr
219178825Sdfr/*
220178825Sdfr * Print bad lines to syslog.
221178825Sdfr */
222178825Sdfrstatic void
223233294Sstasbadline(char *field, char *bad) {
22455682Smarkm	syslog(LOG_ERR, "bad mounttab %s field '%s'", field,
22555682Smarkm	    (bad == NULL) ? "<null>" : bad);
22655682Smarkm}
22755682Smarkm