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