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 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * where.c - get full pathname including host:
29 */
30
31 #pragma ident "%Z%%M% %I% %E% SMI"
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 <sharefs/share.h>
49 #include "sharetab.h"
50
51 extern FILE *setmntent();
52
53 FILE *setsharetab();
54 void endsharetab();
55
56
57
58 extern int Debug;
59
60 /*
61 * where(pn, host, fsname, within)
62 *
63 * pn is the pathname we are looking for,
64 * host gets the name of the host owning the file system,
65 * fsname gets the file system name on the host,
66 * within gets whatever is left from the pathname
67 *
68 * Returns: 0 if ERROR, 1 if OK
69 */
70 int
where(pn,host,fsname,within)71 where(pn, host, fsname, within)
72 char *pn;
73 char *host;
74 char *fsname;
75 char *within;
76 {
77 struct stat sb;
78 char curdir[MAXPATHLEN];
79 char qualpn[MAXPATHLEN];
80 char *p;
81
82 if (Debug)
83 printf("where: pn %s\n", pn);
84
85 if (stat(pn, &sb) < 0) {
86 char *errstr;
87
88 if ((errstr = strerror(errno)) == NULL)
89 errstr = "unknown error";
90
91 if (Debug)
92 printf("where: stat failed");
93 strcpy(within, errstr);
94 return (0);
95 }
96 /*
97 * first get the working directory,
98 */
99 if (getcwd(curdir, MAXPATHLEN) == NULL) {
100 sprintf(within, "Unable to get working directory (%s)",
101 curdir);
102 return (0);
103 }
104 if (chdir(pn) == 0) {
105 getcwd(qualpn, MAXPATHLEN);
106 chdir(curdir);
107 } else {
108 if (p = strrchr(pn, '/')) {
109 *p = 0;
110 chdir(pn);
111 (void) getcwd(qualpn, MAXPATHLEN);
112 chdir(curdir);
113 strcat(qualpn, "/");
114 strcat(qualpn, p+1);
115 } else {
116 strcpy(qualpn, curdir);
117 strcat(qualpn, "/");
118 strcat(qualpn, pn);
119 }
120 }
121 return (findmount(qualpn, host, fsname, within));
122 }
123
124 /*
125 * findmount(qualpn, host, fsname, within)
126 *
127 * Searches the mount table to find the appropriate file system
128 * for a given absolute path name.
129 * host gets the name of the host owning the file system,
130 * fsname gets the file system name on the host,
131 * within gets whatever is left from the pathname
132 *
133 * Returns: 0 on failure, 1 on success.
134 */
135 int
findmount(qualpn,host,fsname,within)136 findmount(qualpn, host, fsname, within)
137 char *qualpn;
138 char *host;
139 char *fsname;
140 char *within;
141 {
142 FILE *mfp;
143 char bestname[MAXPATHLEN];
144 int bestlen = 0,
145 bestnfs = 0;
146 struct share *exp;
147 struct mnttab mp,
148 *mnt;
149 char *endhost; /* points past the colon in name */
150 int i,
151 len;
152
153 if (Debug)
154 printf("findmount: qualpn %s\n", qualpn);
155
156 for (i = 0; i < 10; i++) {
157 mfp = setmntent("/etc/mnttab", "r");
158 if (mfp != NULL)
159 break;
160 sleep(1);
161 }
162
163 if (mfp == NULL) {
164 sprintf(within, "mount table problem");
165 return (0);
166 }
167
168 bestname[0] = '\0';
169 while ((getmntent(mfp, &mp)) == 0) {
170 if (strcmp(mp.mnt_fstype, "nfs") != 0)
171 /*
172 * If it is not nfs filesystem type, skip the
173 * entry
174 */
175 continue;
176
177 len = preflen(qualpn, mp.mnt_mountp);
178
179 if (Debug)
180 printf("preflen: %d %s %s", len, qualpn, mp.mnt_mountp);
181
182 if (qualpn[len] != '/' && qualpn[len] != '\0' && len > 1)
183 /*
184 * If the last matching character is neither / nor
185 * the end of the pathname, not a real match
186 * (except for matching root, len==1)
187 */
188 continue;
189
190 if (len > bestlen) {
191 bestlen = len;
192 strncpy(bestname, mp.mnt_special, sizeof (bestname));
193 }
194 if (Debug)
195 printf(" %s\n", bestname);
196 }
197
198 endmntent(mfp);
199
200 endhost = strchr(bestname, ':');
201
202 /*
203 * If the file system was of type NFS, then there should already
204 * be a host name, otherwise, use ours.
205 */
206 if (endhost) {
207 *endhost++ = 0;
208 strncpy(host, bestname, MAXHOSTNAMELEN);
209 strncpy(fsname, endhost, MAXPATHLEN);
210
211 /*
212 * special case to keep the "/" when we match root
213 */
214 if (bestlen == 1)
215 bestlen = 0;
216 } else {
217 gethostname(host, MAXHOSTNAMELEN);
218
219 /*
220 * If this is our file system, try for an even longer
221 * match from /etc/xtab.
222 */
223 if (mfp = setsharetab()) {
224 while (getshare(mfp, &exp) > 0)
225 if (len = preflen(qualpn, exp->sh_path))
226 if (len > bestlen) {
227 bestlen = len;
228 strncpy(bestname, exp->sh_path,
229 sizeof (bestname));
230 }
231 endsharetab(mfp);
232 }
233 strncpy(fsname, qualpn, bestlen);
234 fsname[bestlen] = 0;
235 }
236 strncpy(within, qualpn + bestlen, MAXPATHLEN);
237
238 if (Debug)
239 printf("findmount: qualpn %s\nhost %s\nfsname %s\nwithin %s\n",
240 qualpn, host, fsname, within);
241 return (1);
242 }
243
244 /*
245 * Returns: length of second argument if it is a prefix of the
246 * first argument, otherwise zero.
247 */
248 int
preflen(str,pref)249 preflen(str, pref)
250 char *str, *pref;
251 {
252 int len;
253
254 len = strlen(pref);
255 if (strncmp(str, pref, len) == 0)
256 return (len);
257 return (0);
258 }
259
260 FILE
setsharetab()261 *setsharetab()
262 {
263 FILE *f;
264
265 f = fopen(SHARETAB, "r");
266 if (f == NULL) {
267 return (NULL);
268 }
269
270 return (f);
271 }
272
273
274 void
endsharetab(f)275 endsharetab(f)
276 FILE *f;
277 {
278 (void) fclose(f);
279 }
280