1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 /* Copyright (c) 1988 AT&T */ 27 /* All Rights Reserved */ 28 29 #include "lint.h" 30 #include <mtlib.h> 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <errno.h> 34 #include <sys/types.h> 35 #include <sys/stat.h> 36 #include <sys/vfstab.h> 37 #include <string.h> 38 #include <thread.h> 39 #include <synch.h> 40 #include <strings.h> 41 #include <libc.h> 42 #include "tsd.h" 43 44 45 #define GETTOK_R(xx, ll, tmp)\ 46 if ((vp->xx = (char *)strtok_r(ll, sepstr, tmp)) == NULL)\ 47 return (VFS_TOOFEW);\ 48 if (strcmp(vp->xx, dash) == 0)\ 49 vp->xx = NULL 50 #define GETTOK(xx, ll)\ 51 if ((vp->xx = strtok(ll, sepstr)) == NULL)\ 52 return (VFS_TOOFEW);\ 53 if (strcmp(vp->xx, dash) == 0)\ 54 vp->xx = NULL 55 #define DIFF(xx)\ 56 (vrefp->xx != NULL && (vgetp->xx == NULL ||\ 57 strcmp(vrefp->xx, vgetp->xx) != 0)) 58 #define SDIFF(xx, typem, typer)\ 59 (vgetp->xx == NULL || stat64(vgetp->xx, &statb) == -1 ||\ 60 (statb.st_mode & S_IFMT) != typem ||\ 61 statb.st_rdev != typer) 62 63 static const char sepstr[] = " \t\n"; 64 static const char dash[] = "-"; 65 66 static int getaline(char *, FILE *); 67 68 int 69 getvfsspec(FILE *fd, struct vfstab *vgetp, char *special) 70 { 71 int ret, bstat; 72 mode_t bmode; 73 dev_t brdev; 74 struct stat64 statb; 75 76 77 if (special && stat64(special, &statb) == 0 && 78 ((bmode = (statb.st_mode & S_IFMT)) == S_IFBLK || 79 bmode == S_IFCHR)) { 80 bstat = 1; 81 brdev = statb.st_rdev; 82 } else 83 bstat = 0; 84 85 while ((ret = getvfsent(fd, vgetp)) == 0 && 86 ((bstat == 0 && 87 (special != NULL && (vgetp->vfs_special == NULL || 88 strcmp(special, vgetp->vfs_special) != 0))) || 89 (bstat == 1 && 90 (vgetp->vfs_special == NULL || 91 stat64(vgetp->vfs_special, &statb) == -1 || 92 (statb.st_mode & S_IFMT) != bmode || 93 statb.st_rdev != brdev)))) 94 ; 95 return (ret); 96 } 97 98 int 99 getvfsfile(FILE *fd, struct vfstab *vp, char *mountp) 100 { 101 struct vfstab vv; 102 103 bzero(&vv, (size_t)sizeof (vv)); 104 vv.vfs_mountp = mountp; 105 return (getvfsany(fd, vp, &vv)); 106 } 107 108 int 109 getvfsany(FILE *fd, struct vfstab *vgetp, struct vfstab *vrefp) 110 { 111 int ret, bstat, cstat; 112 mode_t bmode, cmode; 113 dev_t brdev, crdev; 114 struct stat64 statb; 115 off64_t start = ftello64(fd); 116 117 /* Match by straight strcmp */ 118 while ((ret = getvfsent(fd, vgetp)) == 0 && 119 (DIFF(vfs_special) || DIFF(vfs_fsckdev) || 120 DIFF(vfs_mountp) || 121 DIFF(vfs_fstype) || 122 DIFF(vfs_fsckpass) || 123 DIFF(vfs_automnt) || 124 DIFF(vfs_mntopts))) 125 ; 126 127 /* If something other than EOF, return it */ 128 if (ret != -1) 129 return (ret); 130 131 /* 132 * Go back to the original location in the file and try to 133 * match the devices by doing stat's (retains compatibility 134 * with original getvfsany). 135 */ 136 (void) fseeko64(fd, start, SEEK_SET); 137 138 if (vrefp->vfs_special && stat64(vrefp->vfs_special, &statb) == 0 && 139 ((bmode = (statb.st_mode & S_IFMT)) == S_IFBLK || 140 bmode == S_IFCHR)) { 141 bstat = 1; 142 brdev = statb.st_rdev; 143 } else 144 bstat = 0; 145 146 if (vrefp->vfs_fsckdev && stat64(vrefp->vfs_fsckdev, &statb) == 0 && 147 ((cmode = (statb.st_mode & S_IFMT)) == S_IFBLK || 148 cmode == S_IFCHR)) { 149 cstat = 1; 150 crdev = statb.st_rdev; 151 } else 152 cstat = 0; 153 154 while ((ret = getvfsent(fd, vgetp)) == 0 && 155 ((bstat == 0 && DIFF(vfs_special)) || 156 (bstat == 1 && SDIFF(vfs_special, bmode, brdev)) || 157 (cstat == 0 && DIFF(vfs_fsckdev)) || 158 (cstat == 1 && SDIFF(vfs_fsckdev, cmode, crdev)) || 159 DIFF(vfs_mountp) || 160 DIFF(vfs_fstype) || 161 DIFF(vfs_fsckpass) || 162 DIFF(vfs_automnt) || 163 DIFF(vfs_mntopts))) 164 ; 165 return (ret); 166 } 167 168 int 169 getvfsent(FILE *fd, struct vfstab *vp) 170 { 171 int ret; 172 char *tmp, *line; 173 174 line = tsdalloc(_T_GETVFSENT, VFS_LINE_MAX, NULL); 175 if (line == NULL) 176 return (0); 177 178 /* skip leading spaces and comments */ 179 if ((ret = getaline(line, fd)) != 0) 180 return (ret); 181 182 /* split up each field */ 183 GETTOK_R(vfs_special, line, &tmp); 184 GETTOK_R(vfs_fsckdev, NULL, &tmp); 185 GETTOK_R(vfs_mountp, NULL, &tmp); 186 GETTOK_R(vfs_fstype, NULL, &tmp); 187 GETTOK_R(vfs_fsckpass, NULL, &tmp); 188 GETTOK_R(vfs_automnt, NULL, &tmp); 189 GETTOK_R(vfs_mntopts, NULL, &tmp); 190 191 /* check for too many fields */ 192 if (strtok_r(NULL, sepstr, &tmp) != NULL) 193 return (VFS_TOOMANY); 194 195 return (0); 196 } 197 198 static int 199 getaline(char *lp, FILE *fd) 200 { 201 char *cp; 202 203 while ((lp = fgets(lp, VFS_LINE_MAX, fd)) != NULL) { 204 if (strlen(lp) == VFS_LINE_MAX-1 && lp[VFS_LINE_MAX-2] != '\n') 205 return (VFS_TOOLONG); 206 207 for (cp = lp; *cp == ' ' || *cp == '\t'; cp++) 208 ; 209 210 if (*cp != '#' && *cp != '\n') 211 return (0); 212 } 213 return (-1); 214 } 215