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 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1988 AT&T */ 28 /* All Rights Reserved */ 29 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 #include "lint.h" 33 #include <mtlib.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <errno.h> 37 #include <sys/types.h> 38 #include <sys/stat.h> 39 #include <sys/vfstab.h> 40 #include <string.h> 41 #include <thread.h> 42 #include <synch.h> 43 #include <strings.h> 44 #include <libc.h> 45 #include "tsd.h" 46 47 48 #define GETTOK_R(xx, ll, tmp)\ 49 if ((vp->xx = (char *)strtok_r(ll, sepstr, tmp)) == NULL)\ 50 return (VFS_TOOFEW);\ 51 if (strcmp(vp->xx, dash) == 0)\ 52 vp->xx = NULL 53 #define GETTOK(xx, ll)\ 54 if ((vp->xx = strtok(ll, sepstr)) == NULL)\ 55 return (VFS_TOOFEW);\ 56 if (strcmp(vp->xx, dash) == 0)\ 57 vp->xx = NULL 58 #define DIFF(xx)\ 59 (vrefp->xx != NULL && (vgetp->xx == NULL ||\ 60 strcmp(vrefp->xx, vgetp->xx) != 0)) 61 #define SDIFF(xx, typem, typer)\ 62 (vgetp->xx == NULL || stat64(vgetp->xx, &statb) == -1 ||\ 63 (statb.st_mode & S_IFMT) != typem ||\ 64 statb.st_rdev != typer) 65 66 static const char sepstr[] = " \t\n"; 67 static const char dash[] = "-"; 68 69 static int getline(char *, FILE *); 70 71 int 72 getvfsspec(FILE *fd, struct vfstab *vgetp, char *special) 73 { 74 int ret, bstat; 75 mode_t bmode; 76 dev_t brdev; 77 struct stat64 statb; 78 79 80 if (special && stat64(special, &statb) == 0 && 81 ((bmode = (statb.st_mode & S_IFMT)) == S_IFBLK || 82 bmode == S_IFCHR)) { 83 bstat = 1; 84 brdev = statb.st_rdev; 85 } else 86 bstat = 0; 87 88 while ((ret = getvfsent(fd, vgetp)) == 0 && 89 ((bstat == 0 && 90 (special != NULL && (vgetp->vfs_special == NULL || 91 strcmp(special, vgetp->vfs_special) != 0))) || 92 (bstat == 1 && 93 (vgetp->vfs_special == NULL || 94 stat64(vgetp->vfs_special, &statb) == -1 || 95 (statb.st_mode & S_IFMT) != bmode || 96 statb.st_rdev != brdev)))) 97 ; 98 return (ret); 99 } 100 101 int 102 getvfsfile(FILE *fd, struct vfstab *vp, char *mountp) 103 { 104 struct vfstab vv; 105 106 bzero(&vv, (size_t)sizeof (vv)); 107 vv.vfs_mountp = mountp; 108 return (getvfsany(fd, vp, &vv)); 109 } 110 111 int 112 getvfsany(FILE *fd, struct vfstab *vgetp, struct vfstab *vrefp) 113 { 114 int ret, bstat, cstat; 115 mode_t bmode, cmode; 116 dev_t brdev, crdev; 117 struct stat64 statb; 118 off64_t start = ftello64(fd); 119 120 /* Match by straight strcmp */ 121 while ((ret = getvfsent(fd, vgetp)) == 0 && 122 (DIFF(vfs_special) || DIFF(vfs_fsckdev) || 123 DIFF(vfs_mountp) || 124 DIFF(vfs_fstype) || 125 DIFF(vfs_fsckpass) || 126 DIFF(vfs_automnt) || 127 DIFF(vfs_mntopts))) 128 ; 129 130 /* If something other than EOF, return it */ 131 if (ret != -1) 132 return (ret); 133 134 /* 135 * Go back to the original location in the file and try to 136 * match the devices by doing stat's (retains compatibility 137 * with original getvfsany). 138 */ 139 (void) fseeko64(fd, start, SEEK_SET); 140 141 if (vrefp->vfs_special && stat64(vrefp->vfs_special, &statb) == 0 && 142 ((bmode = (statb.st_mode & S_IFMT)) == S_IFBLK || 143 bmode == S_IFCHR)) { 144 bstat = 1; 145 brdev = statb.st_rdev; 146 } else 147 bstat = 0; 148 149 if (vrefp->vfs_fsckdev && stat64(vrefp->vfs_fsckdev, &statb) == 0 && 150 ((cmode = (statb.st_mode & S_IFMT)) == S_IFBLK || 151 cmode == S_IFCHR)) { 152 cstat = 1; 153 crdev = statb.st_rdev; 154 } else 155 cstat = 0; 156 157 while ((ret = getvfsent(fd, vgetp)) == 0 && 158 ((bstat == 0 && DIFF(vfs_special)) || 159 (bstat == 1 && SDIFF(vfs_special, bmode, brdev)) || 160 (cstat == 0 && DIFF(vfs_fsckdev)) || 161 (cstat == 1 && SDIFF(vfs_fsckdev, cmode, crdev)) || 162 DIFF(vfs_mountp) || 163 DIFF(vfs_fstype) || 164 DIFF(vfs_fsckpass) || 165 DIFF(vfs_automnt) || 166 DIFF(vfs_mntopts))) 167 ; 168 return (ret); 169 } 170 171 int 172 getvfsent(FILE *fd, struct vfstab *vp) 173 { 174 int ret; 175 char *tmp, *line; 176 177 line = tsdalloc(_T_GETVFSENT, VFS_LINE_MAX, NULL); 178 if (line == NULL) 179 return (0); 180 181 /* skip leading spaces and comments */ 182 if ((ret = getline(line, fd)) != 0) 183 return (ret); 184 185 /* split up each field */ 186 GETTOK_R(vfs_special, line, &tmp); 187 GETTOK_R(vfs_fsckdev, NULL, &tmp); 188 GETTOK_R(vfs_mountp, NULL, &tmp); 189 GETTOK_R(vfs_fstype, NULL, &tmp); 190 GETTOK_R(vfs_fsckpass, NULL, &tmp); 191 GETTOK_R(vfs_automnt, NULL, &tmp); 192 GETTOK_R(vfs_mntopts, NULL, &tmp); 193 194 /* check for too many fields */ 195 if (strtok_r(NULL, sepstr, &tmp) != NULL) 196 return (VFS_TOOMANY); 197 198 return (0); 199 } 200 201 static int 202 getline(char *lp, FILE *fd) 203 { 204 char *cp; 205 206 while ((lp = fgets(lp, VFS_LINE_MAX, fd)) != NULL) { 207 if (strlen(lp) == VFS_LINE_MAX-1 && lp[VFS_LINE_MAX-2] != '\n') 208 return (VFS_TOOLONG); 209 210 for (cp = lp; *cp == ' ' || *cp == '\t'; cp++) 211 ; 212 213 if (*cp != '#' && *cp != '\n') 214 return (0); 215 } 216 return (-1); 217 } 218