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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 * 22 * Copyright 2001 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * where.c - get full pathname including host: 28 */ 29 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 33 #include <netdb.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <string.h> 37 #include <unistd.h> 38 #include <fcntl.h> 39 #include <errno.h> 40 #include <string.h> 41 42 #include <sys/mntent.h> 43 44 #include <sys/mnttab.h> 45 #include <sys/param.h> 46 #include <sys/stat.h> 47 48 #include "sharetab.h" 49 50 extern FILE *setmntent(); 51 52 FILE *setsharetab(); 53 void endsharetab(); 54 55 56 57 extern int Debug; 58 59 /* 60 * where(pn, host, fsname, within) 61 * 62 * pn is the pathname we are looking for, 63 * host gets the name of the host owning the file system, 64 * fsname gets the file system name on the host, 65 * within gets whatever is left from the pathname 66 * 67 * Returns: 0 if ERROR, 1 if OK 68 */ 69 int 70 where(pn, host, fsname, within) 71 char *pn; 72 char *host; 73 char *fsname; 74 char *within; 75 { 76 struct stat sb; 77 char curdir[MAXPATHLEN]; 78 char qualpn[MAXPATHLEN]; 79 char *p; 80 81 if (Debug) 82 printf("where: pn %s\n", pn); 83 84 if (stat(pn, &sb) < 0) { 85 char *errstr; 86 87 if ((errstr = strerror(errno)) == NULL) 88 errstr = "unknown error"; 89 90 if (Debug) 91 printf("where: stat failed"); 92 strcpy(within, errstr); 93 return (0); 94 } 95 /* 96 * first get the working directory, 97 */ 98 if (getcwd(curdir, MAXPATHLEN) == NULL) { 99 sprintf(within, "Unable to get working directory (%s)", 100 curdir); 101 return (0); 102 } 103 if (chdir(pn) == 0) { 104 getcwd(qualpn, MAXPATHLEN); 105 chdir(curdir); 106 } else { 107 if (p = strrchr(pn, '/')) { 108 *p = 0; 109 chdir(pn); 110 (void) getcwd(qualpn, MAXPATHLEN); 111 chdir(curdir); 112 strcat(qualpn, "/"); 113 strcat(qualpn, p+1); 114 } else { 115 strcpy(qualpn, curdir); 116 strcat(qualpn, "/"); 117 strcat(qualpn, pn); 118 } 119 } 120 return (findmount(qualpn, host, fsname, within)); 121 } 122 123 /* 124 * findmount(qualpn, host, fsname, within) 125 * 126 * Searches the mount table to find the appropriate file system 127 * for a given absolute path name. 128 * host gets the name of the host owning the file system, 129 * fsname gets the file system name on the host, 130 * within gets whatever is left from the pathname 131 * 132 * Returns: 0 on failure, 1 on success. 133 */ 134 int 135 findmount(qualpn, host, fsname, within) 136 char *qualpn; 137 char *host; 138 char *fsname; 139 char *within; 140 { 141 FILE *mfp; 142 char bestname[MAXPATHLEN]; 143 int bestlen = 0, 144 bestnfs = 0; 145 struct share *exp; 146 struct mnttab mp, 147 *mnt; 148 char *endhost; /* points past the colon in name */ 149 int i, 150 len; 151 152 if (Debug) 153 printf("findmount: qualpn %s\n", qualpn); 154 155 for (i = 0; i < 10; i++) { 156 mfp = setmntent("/etc/mnttab", "r"); 157 if (mfp != NULL) 158 break; 159 sleep(1); 160 } 161 162 if (mfp == NULL) { 163 sprintf(within, "mount table problem"); 164 return (0); 165 } 166 167 bestname[0] = '\0'; 168 while ((getmntent(mfp, &mp)) == 0) { 169 if (strcmp(mp.mnt_fstype, "nfs") != 0) 170 /* 171 * If it is not nfs filesystem type, skip the 172 * entry 173 */ 174 continue; 175 176 len = preflen(qualpn, mp.mnt_mountp); 177 178 if (Debug) 179 printf("preflen: %d %s %s", len, qualpn, mp.mnt_mountp); 180 181 if (qualpn[len] != '/' && qualpn[len] != '\0' && len > 1) 182 /* 183 * If the last matching character is neither / nor 184 * the end of the pathname, not a real match 185 * (except for matching root, len==1) 186 */ 187 continue; 188 189 if (len > bestlen) { 190 bestlen = len; 191 strncpy(bestname, mp.mnt_special, sizeof (bestname)); 192 } 193 if (Debug) 194 printf(" %s\n", bestname); 195 } 196 197 endmntent(mfp); 198 199 endhost = strchr(bestname, ':'); 200 201 /* 202 * If the file system was of type NFS, then there should already 203 * be a host name, otherwise, use ours. 204 */ 205 if (endhost) { 206 *endhost++ = 0; 207 strncpy(host, bestname, MAXHOSTNAMELEN); 208 strncpy(fsname, endhost, MAXPATHLEN); 209 210 /* 211 * special case to keep the "/" when we match root 212 */ 213 if (bestlen == 1) 214 bestlen = 0; 215 } else { 216 gethostname(host, MAXHOSTNAMELEN); 217 218 /* 219 * If this is our file system, try for an even longer 220 * match from /etc/xtab. 221 */ 222 if (mfp = setsharetab()) { 223 while (getshare(mfp, &exp) > 0) 224 if (len = preflen(qualpn, exp->sh_path)) 225 if (len > bestlen) { 226 bestlen = len; 227 strncpy(bestname, exp->sh_path, 228 sizeof (bestname)); 229 } 230 endsharetab(mfp); 231 } 232 strncpy(fsname, qualpn, bestlen); 233 fsname[bestlen] = 0; 234 } 235 strncpy(within, qualpn + bestlen, MAXPATHLEN); 236 237 if (Debug) 238 printf("findmount: qualpn %s\nhost %s\nfsname %s\nwithin %s\n", 239 qualpn, host, fsname, within); 240 return (1); 241 } 242 243 /* 244 * Returns: length of second argument if it is a prefix of the 245 * first argument, otherwise zero. 246 */ 247 int 248 preflen(str, pref) 249 char *str, *pref; 250 { 251 int len; 252 253 len = strlen(pref); 254 if (strncmp(str, pref, len) == 0) 255 return (len); 256 return (0); 257 } 258 259 FILE 260 *setsharetab() 261 { 262 FILE *f; 263 int fd; 264 265 /* 266 * Create the tab file if it does not exist already 267 */ 268 if (access(SHARETAB, F_OK) < 0) { 269 fd = open(SHARETAB, O_CREAT, 0644); 270 close(fd); 271 } 272 if (access(SHARETAB, W_OK) == 0) { 273 f = fopen(SHARETAB, "r+"); 274 } else { 275 f = fopen(SHARETAB, "r"); 276 } 277 if (f == NULL) { 278 return (NULL); 279 } 280 if (lockf(fileno(f), F_LOCK, 0L) < 0) { 281 (void) fclose(f); 282 return (NULL); 283 } 284 return (f); 285 } 286 287 288 void 289 endsharetab(f) 290 FILE *f; 291 { 292 (void) fclose(f); 293 } 294