10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*3957Sth199096 * Common Development and Distribution License (the "License").
6*3957Sth199096 * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
20*3957Sth199096 */
21*3957Sth199096
22*3957Sth199096 /*
23*3957Sth199096 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate /*
280Sstevel@tonic-gate * where.c - get full pathname including host:
290Sstevel@tonic-gate */
300Sstevel@tonic-gate
310Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
320Sstevel@tonic-gate
330Sstevel@tonic-gate #include <netdb.h>
340Sstevel@tonic-gate #include <stdio.h>
350Sstevel@tonic-gate #include <stdlib.h>
360Sstevel@tonic-gate #include <string.h>
370Sstevel@tonic-gate #include <unistd.h>
380Sstevel@tonic-gate #include <fcntl.h>
390Sstevel@tonic-gate #include <errno.h>
400Sstevel@tonic-gate #include <string.h>
410Sstevel@tonic-gate
420Sstevel@tonic-gate #include <sys/mntent.h>
430Sstevel@tonic-gate
440Sstevel@tonic-gate #include <sys/mnttab.h>
450Sstevel@tonic-gate #include <sys/param.h>
460Sstevel@tonic-gate #include <sys/stat.h>
470Sstevel@tonic-gate
48*3957Sth199096 #include <sharefs/share.h>
490Sstevel@tonic-gate #include "sharetab.h"
500Sstevel@tonic-gate
510Sstevel@tonic-gate extern FILE *setmntent();
520Sstevel@tonic-gate
530Sstevel@tonic-gate FILE *setsharetab();
540Sstevel@tonic-gate void endsharetab();
550Sstevel@tonic-gate
560Sstevel@tonic-gate
570Sstevel@tonic-gate
580Sstevel@tonic-gate extern int Debug;
590Sstevel@tonic-gate
600Sstevel@tonic-gate /*
610Sstevel@tonic-gate * where(pn, host, fsname, within)
620Sstevel@tonic-gate *
630Sstevel@tonic-gate * pn is the pathname we are looking for,
640Sstevel@tonic-gate * host gets the name of the host owning the file system,
650Sstevel@tonic-gate * fsname gets the file system name on the host,
660Sstevel@tonic-gate * within gets whatever is left from the pathname
670Sstevel@tonic-gate *
680Sstevel@tonic-gate * Returns: 0 if ERROR, 1 if OK
690Sstevel@tonic-gate */
700Sstevel@tonic-gate int
where(pn,host,fsname,within)710Sstevel@tonic-gate where(pn, host, fsname, within)
720Sstevel@tonic-gate char *pn;
730Sstevel@tonic-gate char *host;
740Sstevel@tonic-gate char *fsname;
750Sstevel@tonic-gate char *within;
760Sstevel@tonic-gate {
770Sstevel@tonic-gate struct stat sb;
780Sstevel@tonic-gate char curdir[MAXPATHLEN];
790Sstevel@tonic-gate char qualpn[MAXPATHLEN];
800Sstevel@tonic-gate char *p;
810Sstevel@tonic-gate
820Sstevel@tonic-gate if (Debug)
830Sstevel@tonic-gate printf("where: pn %s\n", pn);
840Sstevel@tonic-gate
850Sstevel@tonic-gate if (stat(pn, &sb) < 0) {
860Sstevel@tonic-gate char *errstr;
870Sstevel@tonic-gate
880Sstevel@tonic-gate if ((errstr = strerror(errno)) == NULL)
890Sstevel@tonic-gate errstr = "unknown error";
900Sstevel@tonic-gate
910Sstevel@tonic-gate if (Debug)
920Sstevel@tonic-gate printf("where: stat failed");
930Sstevel@tonic-gate strcpy(within, errstr);
940Sstevel@tonic-gate return (0);
950Sstevel@tonic-gate }
960Sstevel@tonic-gate /*
970Sstevel@tonic-gate * first get the working directory,
980Sstevel@tonic-gate */
990Sstevel@tonic-gate if (getcwd(curdir, MAXPATHLEN) == NULL) {
1000Sstevel@tonic-gate sprintf(within, "Unable to get working directory (%s)",
1010Sstevel@tonic-gate curdir);
1020Sstevel@tonic-gate return (0);
1030Sstevel@tonic-gate }
1040Sstevel@tonic-gate if (chdir(pn) == 0) {
1050Sstevel@tonic-gate getcwd(qualpn, MAXPATHLEN);
1060Sstevel@tonic-gate chdir(curdir);
1070Sstevel@tonic-gate } else {
1080Sstevel@tonic-gate if (p = strrchr(pn, '/')) {
1090Sstevel@tonic-gate *p = 0;
1100Sstevel@tonic-gate chdir(pn);
1110Sstevel@tonic-gate (void) getcwd(qualpn, MAXPATHLEN);
1120Sstevel@tonic-gate chdir(curdir);
1130Sstevel@tonic-gate strcat(qualpn, "/");
1140Sstevel@tonic-gate strcat(qualpn, p+1);
1150Sstevel@tonic-gate } else {
1160Sstevel@tonic-gate strcpy(qualpn, curdir);
1170Sstevel@tonic-gate strcat(qualpn, "/");
1180Sstevel@tonic-gate strcat(qualpn, pn);
1190Sstevel@tonic-gate }
1200Sstevel@tonic-gate }
1210Sstevel@tonic-gate return (findmount(qualpn, host, fsname, within));
1220Sstevel@tonic-gate }
1230Sstevel@tonic-gate
1240Sstevel@tonic-gate /*
1250Sstevel@tonic-gate * findmount(qualpn, host, fsname, within)
1260Sstevel@tonic-gate *
1270Sstevel@tonic-gate * Searches the mount table to find the appropriate file system
1280Sstevel@tonic-gate * for a given absolute path name.
1290Sstevel@tonic-gate * host gets the name of the host owning the file system,
1300Sstevel@tonic-gate * fsname gets the file system name on the host,
1310Sstevel@tonic-gate * within gets whatever is left from the pathname
1320Sstevel@tonic-gate *
1330Sstevel@tonic-gate * Returns: 0 on failure, 1 on success.
1340Sstevel@tonic-gate */
1350Sstevel@tonic-gate int
findmount(qualpn,host,fsname,within)1360Sstevel@tonic-gate findmount(qualpn, host, fsname, within)
1370Sstevel@tonic-gate char *qualpn;
1380Sstevel@tonic-gate char *host;
1390Sstevel@tonic-gate char *fsname;
1400Sstevel@tonic-gate char *within;
1410Sstevel@tonic-gate {
1420Sstevel@tonic-gate FILE *mfp;
1430Sstevel@tonic-gate char bestname[MAXPATHLEN];
1440Sstevel@tonic-gate int bestlen = 0,
1450Sstevel@tonic-gate bestnfs = 0;
1460Sstevel@tonic-gate struct share *exp;
1470Sstevel@tonic-gate struct mnttab mp,
1480Sstevel@tonic-gate *mnt;
1490Sstevel@tonic-gate char *endhost; /* points past the colon in name */
1500Sstevel@tonic-gate int i,
1510Sstevel@tonic-gate len;
1520Sstevel@tonic-gate
1530Sstevel@tonic-gate if (Debug)
1540Sstevel@tonic-gate printf("findmount: qualpn %s\n", qualpn);
1550Sstevel@tonic-gate
1560Sstevel@tonic-gate for (i = 0; i < 10; i++) {
1570Sstevel@tonic-gate mfp = setmntent("/etc/mnttab", "r");
1580Sstevel@tonic-gate if (mfp != NULL)
1590Sstevel@tonic-gate break;
1600Sstevel@tonic-gate sleep(1);
1610Sstevel@tonic-gate }
1620Sstevel@tonic-gate
1630Sstevel@tonic-gate if (mfp == NULL) {
1640Sstevel@tonic-gate sprintf(within, "mount table problem");
1650Sstevel@tonic-gate return (0);
1660Sstevel@tonic-gate }
1670Sstevel@tonic-gate
1680Sstevel@tonic-gate bestname[0] = '\0';
1690Sstevel@tonic-gate while ((getmntent(mfp, &mp)) == 0) {
1700Sstevel@tonic-gate if (strcmp(mp.mnt_fstype, "nfs") != 0)
1710Sstevel@tonic-gate /*
1720Sstevel@tonic-gate * If it is not nfs filesystem type, skip the
1730Sstevel@tonic-gate * entry
1740Sstevel@tonic-gate */
1750Sstevel@tonic-gate continue;
1760Sstevel@tonic-gate
1770Sstevel@tonic-gate len = preflen(qualpn, mp.mnt_mountp);
1780Sstevel@tonic-gate
1790Sstevel@tonic-gate if (Debug)
1800Sstevel@tonic-gate printf("preflen: %d %s %s", len, qualpn, mp.mnt_mountp);
1810Sstevel@tonic-gate
1820Sstevel@tonic-gate if (qualpn[len] != '/' && qualpn[len] != '\0' && len > 1)
1830Sstevel@tonic-gate /*
1840Sstevel@tonic-gate * If the last matching character is neither / nor
1850Sstevel@tonic-gate * the end of the pathname, not a real match
1860Sstevel@tonic-gate * (except for matching root, len==1)
1870Sstevel@tonic-gate */
1880Sstevel@tonic-gate continue;
1890Sstevel@tonic-gate
1900Sstevel@tonic-gate if (len > bestlen) {
1910Sstevel@tonic-gate bestlen = len;
1920Sstevel@tonic-gate strncpy(bestname, mp.mnt_special, sizeof (bestname));
1930Sstevel@tonic-gate }
1940Sstevel@tonic-gate if (Debug)
1950Sstevel@tonic-gate printf(" %s\n", bestname);
1960Sstevel@tonic-gate }
1970Sstevel@tonic-gate
1980Sstevel@tonic-gate endmntent(mfp);
1990Sstevel@tonic-gate
2000Sstevel@tonic-gate endhost = strchr(bestname, ':');
2010Sstevel@tonic-gate
2020Sstevel@tonic-gate /*
2030Sstevel@tonic-gate * If the file system was of type NFS, then there should already
2040Sstevel@tonic-gate * be a host name, otherwise, use ours.
2050Sstevel@tonic-gate */
2060Sstevel@tonic-gate if (endhost) {
2070Sstevel@tonic-gate *endhost++ = 0;
2080Sstevel@tonic-gate strncpy(host, bestname, MAXHOSTNAMELEN);
2090Sstevel@tonic-gate strncpy(fsname, endhost, MAXPATHLEN);
2100Sstevel@tonic-gate
2110Sstevel@tonic-gate /*
2120Sstevel@tonic-gate * special case to keep the "/" when we match root
2130Sstevel@tonic-gate */
2140Sstevel@tonic-gate if (bestlen == 1)
2150Sstevel@tonic-gate bestlen = 0;
2160Sstevel@tonic-gate } else {
2170Sstevel@tonic-gate gethostname(host, MAXHOSTNAMELEN);
2180Sstevel@tonic-gate
2190Sstevel@tonic-gate /*
2200Sstevel@tonic-gate * If this is our file system, try for an even longer
2210Sstevel@tonic-gate * match from /etc/xtab.
2220Sstevel@tonic-gate */
2230Sstevel@tonic-gate if (mfp = setsharetab()) {
2240Sstevel@tonic-gate while (getshare(mfp, &exp) > 0)
2250Sstevel@tonic-gate if (len = preflen(qualpn, exp->sh_path))
2260Sstevel@tonic-gate if (len > bestlen) {
2270Sstevel@tonic-gate bestlen = len;
2280Sstevel@tonic-gate strncpy(bestname, exp->sh_path,
2290Sstevel@tonic-gate sizeof (bestname));
2300Sstevel@tonic-gate }
2310Sstevel@tonic-gate endsharetab(mfp);
2320Sstevel@tonic-gate }
2330Sstevel@tonic-gate strncpy(fsname, qualpn, bestlen);
2340Sstevel@tonic-gate fsname[bestlen] = 0;
2350Sstevel@tonic-gate }
2360Sstevel@tonic-gate strncpy(within, qualpn + bestlen, MAXPATHLEN);
2370Sstevel@tonic-gate
2380Sstevel@tonic-gate if (Debug)
2390Sstevel@tonic-gate printf("findmount: qualpn %s\nhost %s\nfsname %s\nwithin %s\n",
2400Sstevel@tonic-gate qualpn, host, fsname, within);
2410Sstevel@tonic-gate return (1);
2420Sstevel@tonic-gate }
2430Sstevel@tonic-gate
2440Sstevel@tonic-gate /*
2450Sstevel@tonic-gate * Returns: length of second argument if it is a prefix of the
2460Sstevel@tonic-gate * first argument, otherwise zero.
2470Sstevel@tonic-gate */
2480Sstevel@tonic-gate int
preflen(str,pref)2490Sstevel@tonic-gate preflen(str, pref)
2500Sstevel@tonic-gate char *str, *pref;
2510Sstevel@tonic-gate {
2520Sstevel@tonic-gate int len;
2530Sstevel@tonic-gate
2540Sstevel@tonic-gate len = strlen(pref);
2550Sstevel@tonic-gate if (strncmp(str, pref, len) == 0)
2560Sstevel@tonic-gate return (len);
2570Sstevel@tonic-gate return (0);
2580Sstevel@tonic-gate }
2590Sstevel@tonic-gate
2600Sstevel@tonic-gate FILE
setsharetab()2610Sstevel@tonic-gate *setsharetab()
2620Sstevel@tonic-gate {
2630Sstevel@tonic-gate FILE *f;
2640Sstevel@tonic-gate
265*3957Sth199096 f = fopen(SHARETAB, "r");
2660Sstevel@tonic-gate if (f == NULL) {
2670Sstevel@tonic-gate return (NULL);
2680Sstevel@tonic-gate }
269*3957Sth199096
2700Sstevel@tonic-gate return (f);
2710Sstevel@tonic-gate }
2720Sstevel@tonic-gate
2730Sstevel@tonic-gate
2740Sstevel@tonic-gate void
endsharetab(f)2750Sstevel@tonic-gate endsharetab(f)
2760Sstevel@tonic-gate FILE *f;
2770Sstevel@tonic-gate {
2780Sstevel@tonic-gate (void) fclose(f);
2790Sstevel@tonic-gate }
280