1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 1999 Martin Blapp 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 */ 29 30 #include <sys/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 33 #include <sys/syslog.h> 34 35 #include <rpc/rpc.h> 36 #include <rpcsvc/mount.h> 37 38 #include <err.h> 39 #include <errno.h> 40 #include <limits.h> 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include <unistd.h> 45 46 #include "mounttab.h" 47 48 struct mtablist *mtabhead; 49 50 static void badline(const char *field, const char *bad); 51 52 /* 53 * Add an entry to PATH_MOUNTTAB for each mounted NFS filesystem, 54 * so the client can notify the NFS server even after reboot. 55 */ 56 int 57 add_mtab(char *hostp, char *dirp) 58 { 59 FILE *mtabfile; 60 61 if ((mtabfile = fopen(PATH_MOUNTTAB, "a")) == NULL) 62 return (0); 63 else { 64 fprintf(mtabfile, "%ld\t%s\t%s\n", 65 (long)time(NULL), hostp, dirp); 66 fclose(mtabfile); 67 return (1); 68 } 69 } 70 71 /* 72 * Read mounttab line for line and return struct mtablist. 73 */ 74 int 75 read_mtab(void) 76 { 77 struct mtablist **mtabpp, *mtabp; 78 char *hostp, *dirp, *cp; 79 char str[STRSIZ]; 80 char *timep, *endp; 81 time_t actiontime; 82 u_long ultmp; 83 FILE *mtabfile; 84 85 if ((mtabfile = fopen(PATH_MOUNTTAB, "r")) == NULL) { 86 if (errno == ENOENT) 87 return (0); 88 else { 89 syslog(LOG_ERR, "can't open %s", PATH_MOUNTTAB); 90 return (0); 91 } 92 } 93 actiontime = 0; 94 mtabpp = &mtabhead; 95 while (fgets(str, STRSIZ, mtabfile) != NULL) { 96 cp = str; 97 errno = 0; 98 if (*cp == '#' || *cp == ' ' || *cp == '\n') 99 continue; 100 timep = strsep(&cp, " \t\n"); 101 if (timep == NULL || *timep == '\0') { 102 badline("time", timep); 103 continue; 104 } 105 hostp = strsep(&cp, " \t\n"); 106 if (hostp == NULL || *hostp == '\0') { 107 badline("host", hostp); 108 continue; 109 } 110 dirp = strsep(&cp, " \t\n"); 111 if (dirp == NULL || *dirp == '\0') { 112 badline("dir", dirp); 113 continue; 114 } 115 ultmp = strtoul(timep, &endp, 10); 116 if (ultmp == ULONG_MAX || *endp != '\0') { 117 badline("time", timep); 118 continue; 119 } 120 actiontime = ultmp; 121 if ((mtabp = malloc(sizeof (struct mtablist))) == NULL) { 122 syslog(LOG_ERR, "malloc"); 123 fclose(mtabfile); 124 return (0); 125 } 126 mtabp->mtab_time = actiontime; 127 memmove(mtabp->mtab_host, hostp, MNTNAMLEN); 128 mtabp->mtab_host[MNTNAMLEN - 1] = '\0'; 129 memmove(mtabp->mtab_dirp, dirp, MNTPATHLEN); 130 mtabp->mtab_dirp[MNTPATHLEN - 1] = '\0'; 131 mtabp->mtab_next = (struct mtablist *)NULL; 132 *mtabpp = mtabp; 133 mtabpp = &mtabp->mtab_next; 134 } 135 fclose(mtabfile); 136 return (1); 137 } 138 139 /* 140 * Rewrite PATH_MOUNTTAB from scratch and skip bad entries. 141 * Unlink PATH_MOUNTAB if no entry is left. 142 */ 143 int 144 write_mtab(int verbose) 145 { 146 struct mtablist *mtabp, *mp; 147 FILE *mtabfile; 148 int line; 149 150 if ((mtabfile = fopen(PATH_MOUNTTAB, "w")) == NULL) { 151 syslog(LOG_ERR, "can't write to %s", PATH_MOUNTTAB); 152 return (0); 153 } 154 line = 0; 155 for (mtabp = mtabhead; mtabp != NULL; mtabp = mtabp->mtab_next) { 156 if (mtabp->mtab_host[0] == '\0') 157 continue; 158 /* Skip if a later (hence more recent) entry is identical. */ 159 for (mp = mtabp->mtab_next; mp != NULL; mp = mp->mtab_next) 160 if (strcmp(mtabp->mtab_host, mp->mtab_host) == 0 && 161 strcmp(mtabp->mtab_dirp, mp->mtab_dirp) == 0) 162 break; 163 if (mp != NULL) 164 continue; 165 166 fprintf(mtabfile, "%ld\t%s\t%s\n", 167 (long)mtabp->mtab_time, mtabp->mtab_host, 168 mtabp->mtab_dirp); 169 if (verbose) 170 warnx("write mounttab entry %s:%s", 171 mtabp->mtab_host, mtabp->mtab_dirp); 172 line++; 173 } 174 fclose(mtabfile); 175 if (line == 0) { 176 if (unlink(PATH_MOUNTTAB) == -1) { 177 syslog(LOG_ERR, "can't remove %s", PATH_MOUNTTAB); 178 return (0); 179 } 180 } 181 return (1); 182 } 183 184 /* 185 * Mark the entries as clean where RPC calls have been done successfully. 186 */ 187 void 188 clean_mtab(char *hostp, char *dirp, int verbose) 189 { 190 struct mtablist *mtabp; 191 char *host; 192 193 /* Copy hostp in case it points to an entry that we are zeroing out. */ 194 host = strdup(hostp); 195 for (mtabp = mtabhead; mtabp != NULL; mtabp = mtabp->mtab_next) { 196 if (strcmp(mtabp->mtab_host, host) != 0) 197 continue; 198 if (dirp != NULL && strcmp(mtabp->mtab_dirp, dirp) != 0) 199 continue; 200 201 if (verbose) 202 warnx("delete mounttab entry%s %s:%s", 203 (dirp == NULL) ? " by host" : "", 204 mtabp->mtab_host, mtabp->mtab_dirp); 205 bzero(mtabp->mtab_host, MNTNAMLEN); 206 } 207 free(host); 208 } 209 210 /* 211 * Free struct mtablist mtab. 212 */ 213 void 214 free_mtab(void) 215 { 216 struct mtablist *mtabp; 217 218 while ((mtabp = mtabhead) != NULL) { 219 mtabhead = mtabhead->mtab_next; 220 free(mtabp); 221 } 222 } 223 224 /* 225 * Print bad lines to syslog. 226 */ 227 static void 228 badline(const char *field, const char *bad) 229 { 230 syslog(LOG_ERR, "bad mounttab %s field '%s'", field, 231 (bad == NULL) ? "<null>" : bad); 232 } 233