mounttab.c revision 194880
1254721Semaste/* 2254721Semaste * Copyright (c) 1999 Martin Blapp 3254721Semaste * All rights reserved. 4254721Semaste * 5254721Semaste * Redistribution and use in source and binary forms, with or without 6254721Semaste * modification, are permitted provided that the following conditions 7254721Semaste * are met: 8254721Semaste * 1. Redistributions of source code must retain the above copyright 9254721Semaste * notice, this list of conditions and the following disclaimer. 10254721Semaste * 2. Redistributions in binary form must reproduce the above copyright 11254721Semaste * notice, this list of conditions and the following disclaimer in the 12254721Semaste * documentation and/or other materials provided with the distribution. 13254721Semaste * 14254721Semaste * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15296417Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16254721Semaste * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17254721Semaste * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18254721Semaste * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19254721Semaste * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20254721Semaste * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21254721Semaste * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22254721Semaste * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23254721Semaste * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24254721Semaste * SUCH DAMAGE. 25254721Semaste * 26254721Semaste */ 27254721Semaste 28254721Semaste#include <sys/cdefs.h> 29254721Semaste__FBSDID("$FreeBSD: head/usr.sbin/rpc.umntall/mounttab.c 194880 2009-06-24 18:42:21Z dfr $"); 30254721Semaste 31254721Semaste#include <sys/syslog.h> 32254721Semaste 33254721Semaste#include <rpc/rpc.h> 34254721Semaste#include <rpcsvc/mount.h> 35254721Semaste 36254721Semaste#include <err.h> 37254721Semaste#include <errno.h> 38254721Semaste#include <limits.h> 39254721Semaste#include <stdio.h> 40254721Semaste#include <stdlib.h> 41254721Semaste#include <string.h> 42254721Semaste#include <unistd.h> 43254721Semaste 44254721Semaste#include "mounttab.h" 45254721Semaste 46254721Semastestruct mtablist *mtabhead; 47254721Semaste 48254721Semastestatic void badline(char *field, char *bad); 49254721Semaste 50254721Semaste/* 51254721Semaste * Add an entry to PATH_MOUNTTAB for each mounted NFS filesystem, 52254721Semaste * so the client can notify the NFS server even after reboot. 53254721Semaste */ 54254721Semasteint 55254721Semasteadd_mtab(char *hostp, char *dirp) { 56254721Semaste FILE *mtabfile; 57254721Semaste 58254721Semaste if ((mtabfile = fopen(PATH_MOUNTTAB, "a")) == NULL) 59254721Semaste return (0); 60254721Semaste else { 61254721Semaste fprintf(mtabfile, "%ld\t%s\t%s\n", 62254721Semaste (long)time(NULL), hostp, dirp); 63254721Semaste fclose(mtabfile); 64254721Semaste return (1); 65254721Semaste } 66254721Semaste} 67254721Semaste 68254721Semaste/* 69254721Semaste * Read mounttab line for line and return struct mtablist. 70254721Semaste */ 71254721Semasteint 72254721Semasteread_mtab() { 73254721Semaste struct mtablist **mtabpp, *mtabp; 74254721Semaste char *hostp, *dirp, *cp; 75254721Semaste char str[STRSIZ]; 76254721Semaste char *timep, *endp; 77254721Semaste time_t time; 78254721Semaste u_long ultmp; 79254721Semaste FILE *mtabfile; 80254721Semaste 81254721Semaste if ((mtabfile = fopen(PATH_MOUNTTAB, "r")) == NULL) { 82254721Semaste if (errno == ENOENT) 83254721Semaste return (0); 84254721Semaste else { 85254721Semaste syslog(LOG_ERR, "can't open %s", PATH_MOUNTTAB); 86254721Semaste return (0); 87254721Semaste } 88296417Sdim } 89296417Sdim time = 0; 90296417Sdim mtabpp = &mtabhead; 91296417Sdim while (fgets(str, STRSIZ, mtabfile) != NULL) { 92296417Sdim cp = str; 93296417Sdim errno = 0; 94254721Semaste if (*cp == '#' || *cp == ' ' || *cp == '\n') 95254721Semaste continue; 96254721Semaste timep = strsep(&cp, " \t\n"); 97254721Semaste if (timep == NULL || *timep == '\0') { 98254721Semaste badline("time", timep); 99254721Semaste continue; 100254721Semaste } 101254721Semaste hostp = strsep(&cp, " \t\n"); 102254721Semaste if (hostp == NULL || *hostp == '\0') { 103254721Semaste badline("host", hostp); 104254721Semaste continue; 105254721Semaste } 106254721Semaste dirp = strsep(&cp, " \t\n"); 107254721Semaste if (dirp == NULL || *dirp == '\0') { 108254721Semaste badline("dir", dirp); 109254721Semaste continue; 110254721Semaste } 111254721Semaste ultmp = strtoul(timep, &endp, 10); 112254721Semaste if (ultmp == ULONG_MAX || *endp != '\0') { 113254721Semaste badline("time", timep); 114254721Semaste continue; 115254721Semaste } 116254721Semaste time = ultmp; 117254721Semaste if ((mtabp = malloc(sizeof (struct mtablist))) == NULL) { 118254721Semaste syslog(LOG_ERR, "malloc"); 119254721Semaste fclose(mtabfile); 120254721Semaste return (0); 121254721Semaste } 122254721Semaste mtabp->mtab_time = time; 123254721Semaste memmove(mtabp->mtab_host, hostp, MNTNAMLEN); 124254721Semaste mtabp->mtab_host[MNTNAMLEN - 1] = '\0'; 125254721Semaste memmove(mtabp->mtab_dirp, dirp, MNTPATHLEN); 126254721Semaste mtabp->mtab_dirp[MNTPATHLEN - 1] = '\0'; 127254721Semaste mtabp->mtab_next = (struct mtablist *)NULL; 128254721Semaste *mtabpp = mtabp; 129254721Semaste mtabpp = &mtabp->mtab_next; 130254721Semaste } 131254721Semaste fclose(mtabfile); 132254721Semaste return (1); 133254721Semaste} 134254721Semaste 135254721Semaste/* 136254721Semaste * Rewrite PATH_MOUNTTAB from scratch and skip bad entries. 137254721Semaste * Unlink PATH_MOUNTAB if no entry is left. 138254721Semaste */ 139254721Semasteint 140254721Semastewrite_mtab(int verbose) { 141254721Semaste struct mtablist *mtabp, *mp; 142254721Semaste FILE *mtabfile; 143254721Semaste int line; 144254721Semaste 145254721Semaste if ((mtabfile = fopen(PATH_MOUNTTAB, "w")) == NULL) { 146254721Semaste syslog(LOG_ERR, "can't write to %s", PATH_MOUNTTAB); 147254721Semaste return (0); 148254721Semaste } 149254721Semaste line = 0; 150254721Semaste for (mtabp = mtabhead; mtabp != NULL; mtabp = mtabp->mtab_next) { 151254721Semaste if (mtabp->mtab_host[0] == '\0') 152296417Sdim continue; 153 /* Skip if a later (hence more recent) entry is identical. */ 154 for (mp = mtabp->mtab_next; mp != NULL; mp = mp->mtab_next) 155 if (strcmp(mtabp->mtab_host, mp->mtab_host) == 0 && 156 strcmp(mtabp->mtab_dirp, mp->mtab_dirp) == 0) 157 break; 158 if (mp != NULL) 159 continue; 160 161 fprintf(mtabfile, "%ld\t%s\t%s\n", 162 (long)mtabp->mtab_time, mtabp->mtab_host, 163 mtabp->mtab_dirp); 164 if (verbose) 165 warnx("write mounttab entry %s:%s", 166 mtabp->mtab_host, mtabp->mtab_dirp); 167 line++; 168 } 169 fclose(mtabfile); 170 if (line == 0) { 171 if (unlink(PATH_MOUNTTAB) == -1) { 172 syslog(LOG_ERR, "can't remove %s", PATH_MOUNTTAB); 173 return (0); 174 } 175 } 176 return (1); 177} 178 179/* 180 * Mark the entries as clean where RPC calls have been done successfully. 181 */ 182void 183clean_mtab(char *hostp, char *dirp, int verbose) { 184 struct mtablist *mtabp; 185 char *host; 186 187 /* Copy hostp in case it points to an entry that we are zeroing out. */ 188 host = strdup(hostp); 189 for (mtabp = mtabhead; mtabp != NULL; mtabp = mtabp->mtab_next) { 190 if (strcmp(mtabp->mtab_host, host) != 0) 191 continue; 192 if (dirp != NULL && strcmp(mtabp->mtab_dirp, dirp) != 0) 193 continue; 194 195 if (verbose) 196 warnx("delete mounttab entry%s %s:%s", 197 (dirp == NULL) ? " by host" : "", 198 mtabp->mtab_host, mtabp->mtab_dirp); 199 bzero(mtabp->mtab_host, MNTNAMLEN); 200 } 201 free(host); 202} 203 204/* 205 * Free struct mtablist mtab. 206 */ 207void 208free_mtab() { 209 struct mtablist *mtabp; 210 211 while ((mtabp = mtabhead) != NULL) { 212 mtabhead = mtabhead->mtab_next; 213 free(mtabp); 214 } 215} 216 217/* 218 * Print bad lines to syslog. 219 */ 220static void 221badline(char *field, char *bad) { 222 syslog(LOG_ERR, "bad mounttab %s field '%s'", field, 223 (bad == NULL) ? "<null>" : bad); 224} 225