1 /* $OpenBSD: fstab.c,v 1.16 2007/09/27 14:07:23 blambert Exp $ */ 2 /* 3 * Copyright (c) 1980, 1988, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of the University nor the names of its contributors 15 * may be used to endorse or promote products derived from this software 16 * without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 #include <sys/types.h> 32 #include <sys/uio.h> 33 #include <sys/stat.h> 34 35 #include <errno.h> 36 #include <limits.h> 37 #include <fstab.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <unistd.h> 42 43 static FILE *_fs_fp; 44 static struct fstab _fs_fstab; 45 46 static void error(int); 47 static int fstabscan(void); 48 49 static int 50 fstabscan(void) 51 { 52 char *cp; 53 #define MAXLINELENGTH 1024 54 static char line[MAXLINELENGTH]; 55 char subline[MAXLINELENGTH]; 56 const char *errstr; 57 char *last; 58 int typexx; 59 60 for (;;) { 61 if (!(cp = fgets(line, sizeof(line), _fs_fp))) 62 return(0); 63 /* OLD_STYLE_FSTAB */ 64 if (!strpbrk(cp, " \t")) { 65 _fs_fstab.fs_spec = strtok_r(cp, ":\n", &last); 66 if (!_fs_fstab.fs_spec || *_fs_fstab.fs_spec == '#') 67 continue; 68 _fs_fstab.fs_file = strtok_r((char *)NULL, ":\n", &last); 69 _fs_fstab.fs_type = strtok_r((char *)NULL, ":\n", &last); 70 if (_fs_fstab.fs_type) { 71 if (!strcmp(_fs_fstab.fs_type, FSTAB_XX)) 72 continue; 73 _fs_fstab.fs_mntops = _fs_fstab.fs_type; 74 _fs_fstab.fs_vfstype = 75 strcmp(_fs_fstab.fs_type, FSTAB_SW) ? 76 "ufs" : "swap"; 77 if ((cp = strtok_r((char *)NULL, ":\n", &last))) { 78 _fs_fstab.fs_freq = strtonum(cp, 0, 79 INT_MAX, &errstr); 80 if (errstr) 81 goto bad; 82 if ((cp = strtok_r((char *)NULL, 83 ":\n", &last))) { 84 _fs_fstab.fs_passno = 85 strtonum(cp, 0, INT_MAX, 86 &errstr); 87 if (errstr) 88 goto bad; 89 return(1); 90 } 91 } 92 } 93 goto bad; 94 } 95 /* OLD_STYLE_FSTAB */ 96 _fs_fstab.fs_spec = strtok_r(cp, " \t\n", &last); 97 if (!_fs_fstab.fs_spec || *_fs_fstab.fs_spec == '#') 98 continue; 99 _fs_fstab.fs_file = strtok_r((char *)NULL, " \t\n", &last); 100 _fs_fstab.fs_vfstype = strtok_r((char *)NULL, " \t\n", &last); 101 _fs_fstab.fs_mntops = strtok_r((char *)NULL, " \t\n", &last); 102 if (_fs_fstab.fs_mntops == NULL) 103 goto bad; 104 _fs_fstab.fs_freq = 0; 105 _fs_fstab.fs_passno = 0; 106 if ((cp = strtok_r((char *)NULL, " \t\n", &last)) != NULL) { 107 _fs_fstab.fs_freq = strtonum(cp, 0, INT_MAX, &errstr); 108 if (errstr) 109 goto bad; 110 if ((cp = strtok_r((char *)NULL, " \t\n", &last)) != NULL) { 111 _fs_fstab.fs_passno = strtonum(cp, 0, INT_MAX, 112 &errstr); 113 if (errstr) 114 goto bad; 115 } 116 } 117 strlcpy(subline, _fs_fstab.fs_mntops, sizeof subline); 118 for (typexx = 0, cp = strtok_r(subline, ",", &last); cp; 119 cp = strtok_r((char *)NULL, ",", &last)) { 120 if (strlen(cp) != 2) 121 continue; 122 if (!strcmp(cp, FSTAB_RW)) { 123 _fs_fstab.fs_type = FSTAB_RW; 124 break; 125 } 126 if (!strcmp(cp, FSTAB_RQ)) { 127 _fs_fstab.fs_type = FSTAB_RQ; 128 break; 129 } 130 if (!strcmp(cp, FSTAB_RO)) { 131 _fs_fstab.fs_type = FSTAB_RO; 132 break; 133 } 134 if (!strcmp(cp, FSTAB_SW)) { 135 _fs_fstab.fs_type = FSTAB_SW; 136 break; 137 } 138 if (!strcmp(cp, FSTAB_XX)) { 139 _fs_fstab.fs_type = FSTAB_XX; 140 typexx++; 141 break; 142 } 143 } 144 if (typexx) 145 continue; 146 if (cp != NULL) 147 return(1); 148 149 bad: /* no way to distinguish between EOF and syntax error */ 150 error(EFTYPE); 151 } 152 /* NOTREACHED */ 153 } 154 155 struct fstab * 156 getfsent(void) 157 { 158 if ((!_fs_fp && !setfsent()) || !fstabscan()) 159 return(NULL); 160 return(&_fs_fstab); 161 } 162 163 struct fstab * 164 getfsspec(const char *name) 165 { 166 if (setfsent()) 167 while (fstabscan()) 168 if (!strcmp(_fs_fstab.fs_spec, name)) 169 return(&_fs_fstab); 170 return((struct fstab *)NULL); 171 } 172 173 struct fstab * 174 getfsfile(const char *name) 175 { 176 if (setfsent()) 177 while (fstabscan()) 178 if (!strcmp(_fs_fstab.fs_file, name)) 179 return(&_fs_fstab); 180 return((struct fstab *)NULL); 181 } 182 183 int 184 setfsent(void) 185 { 186 struct stat sbuf; 187 188 if (_fs_fp) { 189 rewind(_fs_fp); 190 return(1); 191 } 192 193 if (stat(_PATH_FSTAB, &sbuf) != 0) 194 goto fail; 195 if ((sbuf.st_size == 0) || ((sbuf.st_mode & S_IFMT) != S_IFREG)) { 196 errno = EFTYPE; 197 goto fail; 198 } 199 200 if ((_fs_fp = fopen(_PATH_FSTAB, "r"))) 201 return(1); 202 203 fail: 204 error(errno); 205 return(0); 206 } 207 208 void 209 endfsent(void) 210 { 211 if (_fs_fp) { 212 (void)fclose(_fs_fp); 213 _fs_fp = NULL; 214 } 215 } 216 217 static void 218 error(int err) 219 { 220 struct iovec iov[5]; 221 222 iov[0].iov_base = "fstab: "; 223 iov[0].iov_len = 7; 224 iov[1].iov_base = _PATH_FSTAB; 225 iov[1].iov_len = sizeof(_PATH_FSTAB) - 1; 226 iov[2].iov_base = ": "; 227 iov[2].iov_len = 2; 228 iov[3].iov_base = strerror(err); 229 iov[3].iov_len = strlen(iov[3].iov_base); 230 iov[4].iov_base = "\n"; 231 iov[4].iov_len = 1; 232 (void)writev(STDERR_FILENO, iov, 5); 233 } 234