1 |
|
|
/* $OpenBSD: parsenfsfh.c,v 1.14 2016/01/15 18:02:18 mmcc Exp $ */ |
2 |
|
|
|
3 |
|
|
/* |
4 |
|
|
* Copyright (c) 1993, 1994 Jeffrey C. Mogul, Digital Equipment Corporation, |
5 |
|
|
* Western Research Laboratory. All rights reserved. |
6 |
|
|
* Copyright (c) 2001 Compaq Computer Corporation. All rights reserved. |
7 |
|
|
* |
8 |
|
|
* Permission to use, copy, and modify this software and its |
9 |
|
|
* documentation is hereby granted only under the following terms and |
10 |
|
|
* conditions. Both the above copyright notice and this permission |
11 |
|
|
* notice must appear in all copies of the software, derivative works |
12 |
|
|
* or modified versions, and any portions thereof, and both notices |
13 |
|
|
* must appear in supporting documentation. |
14 |
|
|
* |
15 |
|
|
* Redistribution and use in source and binary forms, with or without |
16 |
|
|
* modification, are permitted provided that the following conditions |
17 |
|
|
* are met: |
18 |
|
|
* 1. Redistributions of source code must retain the above copyright |
19 |
|
|
* notice, this list of conditions and the following disclaimer. |
20 |
|
|
* 2. Redistributions in binary form must reproduce the above copyright |
21 |
|
|
* notice, this list of conditions and the following disclaimer in |
22 |
|
|
* the documentation and/or other materials provided with the |
23 |
|
|
* distribution. |
24 |
|
|
* |
25 |
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND COMPAQ COMPUTER CORPORATION |
26 |
|
|
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING |
27 |
|
|
* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO |
28 |
|
|
* EVENT SHALL COMPAQ COMPUTER CORPORATION BE LIABLE FOR ANY |
29 |
|
|
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
30 |
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN |
31 |
|
|
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING |
32 |
|
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS |
33 |
|
|
* SOFTWARE. |
34 |
|
|
*/ |
35 |
|
|
|
36 |
|
|
/* |
37 |
|
|
* parsenfsfh.c - portable parser for NFS file handles |
38 |
|
|
* uses all sorts of heuristics |
39 |
|
|
* |
40 |
|
|
* Jeffrey C. Mogul |
41 |
|
|
* Digital Equipment Corporation |
42 |
|
|
* Western Research Laboratory |
43 |
|
|
*/ |
44 |
|
|
|
45 |
|
|
#include <sys/types.h> |
46 |
|
|
#include <sys/time.h> |
47 |
|
|
|
48 |
|
|
#include <ctype.h> |
49 |
|
|
#include <stdio.h> |
50 |
|
|
#include <string.h> |
51 |
|
|
|
52 |
|
|
#include "interface.h" |
53 |
|
|
#include "nfsfh.h" |
54 |
|
|
|
55 |
|
|
/* |
56 |
|
|
* This routine attempts to parse a file handle (in network byte order), |
57 |
|
|
* using heuristics to guess what kind of format it is in. See the |
58 |
|
|
* file "fhandle_layouts" for a detailed description of the various |
59 |
|
|
* patterns we know about. |
60 |
|
|
* |
61 |
|
|
* The file handle is parsed into our internal representation of a |
62 |
|
|
* file-system id, and an internal representation of an inode-number. |
63 |
|
|
*/ |
64 |
|
|
|
65 |
|
|
#define FHT_UNKNOWN 0 |
66 |
|
|
#define FHT_AUSPEX 1 |
67 |
|
|
#define FHT_DECOSF 2 |
68 |
|
|
#define FHT_IRIX4 3 |
69 |
|
|
#define FHT_IRIX5 4 |
70 |
|
|
#define FHT_SUNOS3 5 |
71 |
|
|
#define FHT_SUNOS4 6 |
72 |
|
|
#define FHT_ULTRIX 7 |
73 |
|
|
#define FHT_VMSUCX 8 |
74 |
|
|
#define FHT_SUNOS5 9 |
75 |
|
|
#define FHT_AIX32 10 |
76 |
|
|
#define FHT_HPUX9 11 |
77 |
|
|
|
78 |
|
|
#define make_uint32(msb,b,c,lsb)\ |
79 |
|
|
((lsb) + ((c)<<8) + ((b)<<16) + ((msb)<<24)) |
80 |
|
|
|
81 |
|
|
#define make_uint24(msb,b, lsb)\ |
82 |
|
|
((lsb) + ((b)<<8) + ((msb)<<16)) |
83 |
|
|
|
84 |
|
|
#define make_uint16(msb,lsb)\ |
85 |
|
|
((lsb) + ((msb)<<8)) |
86 |
|
|
|
87 |
|
|
#ifdef __alpha |
88 |
|
|
/* or other 64-bit systems */ |
89 |
|
|
#define make_uint48(msb,b,c,d,e,lsb)\ |
90 |
|
|
((lsb) + ((e)<<8) + ((d)<<16) + ((c)<<24) + ((b)<<32) + ((msb)<<40)) |
91 |
|
|
#else |
92 |
|
|
/* on 32-bit systems ignore high-order bits */ |
93 |
|
|
#define make_uint48(msb,b,c,d,e,lsb)\ |
94 |
|
|
((lsb) + ((e)<<8) + ((d)<<16) + ((c)<<24)) |
95 |
|
|
#endif |
96 |
|
|
|
97 |
|
|
static int is_UCX(unsigned char *); |
98 |
|
|
|
99 |
|
|
void |
100 |
|
|
Parse_fh(fh, fsidp, inop, osnamep, fsnamep) |
101 |
|
|
caddr_t *fh; |
102 |
|
|
my_fsid *fsidp; |
103 |
|
|
ino_t *inop; |
104 |
|
|
char **osnamep; /* if non-NULL, return OS name here */ |
105 |
|
|
char **fsnamep; /* if non-NULL, return server fs name here (for VMS) */ |
106 |
|
|
{ |
107 |
|
|
unsigned char *fhp = (unsigned char *)fh; |
108 |
|
|
u_int32_t temp; |
109 |
|
|
int fhtype = FHT_UNKNOWN; |
110 |
|
|
|
111 |
|
|
/* |
112 |
|
|
* This is basically a big decision tree |
113 |
|
|
*/ |
114 |
|
|
if ((fhp[0] == 0) && (fhp[1] == 0)) { |
115 |
|
|
/* bytes[0,1] == (0,0); rules out Ultrix, IRIX5, SUNOS5 */ |
116 |
|
|
/* probably rules out HP-UX, AIX unless they allow major=0 */ |
117 |
|
|
if ((fhp[2] == 0) && (fhp[3] == 0)) { |
118 |
|
|
/* bytes[2,3] == (0,0); must be Auspex */ |
119 |
|
|
/* XXX or could be Ultrix+MASSBUS "hp" disk? */ |
120 |
|
|
fhtype = FHT_AUSPEX; |
121 |
|
|
} |
122 |
|
|
else { |
123 |
|
|
/* |
124 |
|
|
* bytes[2,3] != (0,0); rules out Auspex, could be |
125 |
|
|
* DECOSF, SUNOS4, or IRIX4 |
126 |
|
|
*/ |
127 |
|
|
if ((fhp[4] != 0) && (fhp[5] == 0) && |
128 |
|
|
(fhp[8] == 12) && (fhp[9] == 0)) { |
129 |
|
|
/* seems to be DECOSF, with minor == 0 */ |
130 |
|
|
fhtype = FHT_DECOSF; |
131 |
|
|
} |
132 |
|
|
else { |
133 |
|
|
/* could be SUNOS4 or IRIX4 */ |
134 |
|
|
/* XXX the test of fhp[5] == 8 could be wrong */ |
135 |
|
|
if ((fhp[4] == 0) && (fhp[5] == 8) && (fhp[6] == 0) && |
136 |
|
|
(fhp[7] == 0)) { |
137 |
|
|
/* looks like a length, not a file system typecode */ |
138 |
|
|
fhtype = FHT_IRIX4; |
139 |
|
|
} |
140 |
|
|
else { |
141 |
|
|
/* by elimination */ |
142 |
|
|
fhtype = FHT_SUNOS4; |
143 |
|
|
} |
144 |
|
|
} |
145 |
|
|
} |
146 |
|
|
} |
147 |
|
|
else { |
148 |
|
|
/* |
149 |
|
|
* bytes[0,1] != (0,0); rules out Auspex, IRIX4, SUNOS4 |
150 |
|
|
* could be IRIX5, DECOSF, UCX, Ultrix, SUNOS5 |
151 |
|
|
* could be AIX, HP-UX |
152 |
|
|
*/ |
153 |
|
|
if ((fhp[2] == 0) && (fhp[3] == 0)) { |
154 |
|
|
/* |
155 |
|
|
* bytes[2,3] == (0,0); rules out OSF, probably not UCX |
156 |
|
|
* (unless the exported device name is just one letter!), |
157 |
|
|
* could be Ultrix, IRIX5, AIX, or SUNOS5 |
158 |
|
|
* might be HP-UX (depends on their values for minor devs) |
159 |
|
|
*/ |
160 |
|
|
/*XXX we probably only need to test of these two bytes */ |
161 |
|
|
if ((fhp[21] == 0) && (fhp[23] == 0)) { |
162 |
|
|
fhtype = FHT_ULTRIX; |
163 |
|
|
} |
164 |
|
|
else { |
165 |
|
|
/* Could be SUNOS5/IRIX5, maybe AIX */ |
166 |
|
|
/* XXX no obvious difference between SUNOS5 and IRIX5 */ |
167 |
|
|
if (fhp[9] == 10) |
168 |
|
|
fhtype = FHT_SUNOS5; |
169 |
|
|
/* XXX what about AIX? */ |
170 |
|
|
} |
171 |
|
|
} |
172 |
|
|
else { |
173 |
|
|
/* |
174 |
|
|
* bytes[2,3] != (0,0); rules out Ultrix, could be |
175 |
|
|
* DECOSF, SUNOS5, IRIX5, AIX, HP-UX, or UCX |
176 |
|
|
*/ |
177 |
|
|
if ((fhp[8] == 12) && (fhp[9] == 0)) { |
178 |
|
|
fhtype = FHT_DECOSF; |
179 |
|
|
} |
180 |
|
|
else if ((fhp[8] == 0) && (fhp[9] == 10)) { |
181 |
|
|
/* could be SUNOS5/IRIX5, AIX, HP-UX */ |
182 |
|
|
if ((fhp[7] == 0) && (fhp[6] == 0) && |
183 |
|
|
(fhp[5] == 0) && (fhp[4] == 0)) { |
184 |
|
|
/* XXX is this always true of HP-UX? */ |
185 |
|
|
fhtype = FHT_HPUX9; |
186 |
|
|
} |
187 |
|
|
else if (fhp[7] == 2) { |
188 |
|
|
/* This would be MNT_NFS on AIX, which is impossible */ |
189 |
|
|
fhtype = FHT_SUNOS5; /* or maybe IRIX5 */ |
190 |
|
|
} |
191 |
|
|
else { |
192 |
|
|
/* |
193 |
|
|
* XXX Could be SUNOS5/IRIX5 or AIX. I don't |
194 |
|
|
* XXX see any way to disambiguate these, so |
195 |
|
|
* XXX I'm going with the more likely guess. |
196 |
|
|
* XXX Sorry, Big Blue. |
197 |
|
|
*/ |
198 |
|
|
fhtype = FHT_SUNOS5; /* or maybe IRIX5 */ |
199 |
|
|
} |
200 |
|
|
} |
201 |
|
|
else { |
202 |
|
|
if (is_UCX(fhp)) { |
203 |
|
|
fhtype = FHT_VMSUCX; |
204 |
|
|
} |
205 |
|
|
else { |
206 |
|
|
fhtype = FHT_UNKNOWN; |
207 |
|
|
} |
208 |
|
|
} |
209 |
|
|
} |
210 |
|
|
} |
211 |
|
|
|
212 |
|
|
/* XXX still needs to handle SUNOS3 */ |
213 |
|
|
|
214 |
|
|
switch (fhtype) { |
215 |
|
|
case FHT_AUSPEX: |
216 |
|
|
fsidp->Fsid_dev.Minor = fhp[7]; |
217 |
|
|
fsidp->Fsid_dev.Major = fhp[6]; |
218 |
|
|
fsidp->fsid_code = 0; |
219 |
|
|
|
220 |
|
|
temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]); |
221 |
|
|
*inop = temp; |
222 |
|
|
|
223 |
|
|
if (osnamep) |
224 |
|
|
*osnamep = "Auspex"; |
225 |
|
|
break; |
226 |
|
|
|
227 |
|
|
case FHT_DECOSF: |
228 |
|
|
fsidp->fsid_code = make_uint32(fhp[7], fhp[6], fhp[5], fhp[4]); |
229 |
|
|
/* XXX could ignore 3 high-order bytes */ |
230 |
|
|
|
231 |
|
|
temp = make_uint32(fhp[3], fhp[2], fhp[1], fhp[0]); |
232 |
|
|
fsidp->Fsid_dev.Minor = temp & 0xFFFFF; |
233 |
|
|
fsidp->Fsid_dev.Major = (temp>>20) & 0xFFF; |
234 |
|
|
|
235 |
|
|
temp = make_uint32(fhp[15], fhp[14], fhp[13], fhp[12]); |
236 |
|
|
*inop = temp; |
237 |
|
|
if (osnamep) |
238 |
|
|
*osnamep = "OSF"; |
239 |
|
|
break; |
240 |
|
|
|
241 |
|
|
case FHT_IRIX4: |
242 |
|
|
fsidp->Fsid_dev.Minor = fhp[3]; |
243 |
|
|
fsidp->Fsid_dev.Major = fhp[2]; |
244 |
|
|
fsidp->fsid_code = 0; |
245 |
|
|
|
246 |
|
|
temp = make_uint32(fhp[8], fhp[9], fhp[10], fhp[11]); |
247 |
|
|
*inop = temp; |
248 |
|
|
|
249 |
|
|
if (osnamep) |
250 |
|
|
*osnamep = "IRIX4"; |
251 |
|
|
break; |
252 |
|
|
|
253 |
|
|
case FHT_IRIX5: |
254 |
|
|
fsidp->Fsid_dev.Minor = make_uint16(fhp[2], fhp[3]); |
255 |
|
|
fsidp->Fsid_dev.Major = make_uint16(fhp[0], fhp[1]); |
256 |
|
|
fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]); |
257 |
|
|
|
258 |
|
|
temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]); |
259 |
|
|
*inop = temp; |
260 |
|
|
|
261 |
|
|
if (osnamep) |
262 |
|
|
*osnamep = "IRIX5"; |
263 |
|
|
break; |
264 |
|
|
|
265 |
|
|
case FHT_SUNOS3: |
266 |
|
|
if (osnamep) |
267 |
|
|
*osnamep = "SUNOS3"; |
268 |
|
|
break; |
269 |
|
|
|
270 |
|
|
case FHT_SUNOS4: |
271 |
|
|
fsidp->Fsid_dev.Minor = fhp[3]; |
272 |
|
|
fsidp->Fsid_dev.Major = fhp[2]; |
273 |
|
|
fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]); |
274 |
|
|
|
275 |
|
|
temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]); |
276 |
|
|
*inop = temp; |
277 |
|
|
|
278 |
|
|
if (osnamep) |
279 |
|
|
*osnamep = "SUNOS4"; |
280 |
|
|
break; |
281 |
|
|
|
282 |
|
|
case FHT_SUNOS5: |
283 |
|
|
temp = make_uint16(fhp[0], fhp[1]); |
284 |
|
|
fsidp->Fsid_dev.Major = (temp>>2) & 0x3FFF; |
285 |
|
|
temp = make_uint24(fhp[1], fhp[2], fhp[3]); |
286 |
|
|
fsidp->Fsid_dev.Minor = temp & 0x3FFFF; |
287 |
|
|
fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]); |
288 |
|
|
|
289 |
|
|
temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]); |
290 |
|
|
*inop = temp; |
291 |
|
|
|
292 |
|
|
if (osnamep) |
293 |
|
|
*osnamep = "SUNOS5"; |
294 |
|
|
break; |
295 |
|
|
|
296 |
|
|
case FHT_ULTRIX: |
297 |
|
|
fsidp->fsid_code = 0; |
298 |
|
|
fsidp->Fsid_dev.Minor = fhp[0]; |
299 |
|
|
fsidp->Fsid_dev.Major = fhp[1]; |
300 |
|
|
|
301 |
|
|
temp = make_uint32(fhp[7], fhp[6], fhp[5], fhp[4]); |
302 |
|
|
*inop = temp; |
303 |
|
|
if (osnamep) |
304 |
|
|
*osnamep = "Ultrix"; |
305 |
|
|
break; |
306 |
|
|
|
307 |
|
|
case FHT_VMSUCX: |
308 |
|
|
/* No numeric file system ID, so hash on the device-name */ |
309 |
|
|
if (sizeof(*fsidp) >= 14) { |
310 |
|
|
if (sizeof(*fsidp) > 14) |
311 |
|
|
memset((char *)fsidp, 0, sizeof(*fsidp)); |
312 |
|
|
/* just use the whole thing */ |
313 |
|
|
memcpy((char *)fsidp, (char *)fh, 14); |
314 |
|
|
} |
315 |
|
|
else { |
316 |
|
|
u_int32_t tempa[4]; /* at least 16 bytes, maybe more */ |
317 |
|
|
|
318 |
|
|
memset((char *)tempa, 0, sizeof(tempa)); |
319 |
|
|
memcpy((char *)tempa, (char *)fh, 14); /* ensure alignment */ |
320 |
|
|
fsidp->Fsid_dev.Minor = tempa[0] + (tempa[1]<<1); |
321 |
|
|
fsidp->Fsid_dev.Major = tempa[2] + (tempa[3]<<1); |
322 |
|
|
fsidp->fsid_code = 0; |
323 |
|
|
} |
324 |
|
|
|
325 |
|
|
/* VMS file ID is: (RVN, FidHi, FidLo) */ |
326 |
|
|
*inop = make_uint32(fhp[26], fhp[27], fhp[23], fhp[22]); |
327 |
|
|
|
328 |
|
|
/* Caller must save (and null-terminate?) this value */ |
329 |
|
|
if (fsnamep) |
330 |
|
|
*fsnamep = (char *)&(fhp[1]); |
331 |
|
|
|
332 |
|
|
if (osnamep) |
333 |
|
|
*osnamep = "VMS"; |
334 |
|
|
break; |
335 |
|
|
|
336 |
|
|
case FHT_AIX32: |
337 |
|
|
fsidp->Fsid_dev.Minor = make_uint16(fhp[2], fhp[3]); |
338 |
|
|
fsidp->Fsid_dev.Major = make_uint16(fhp[0], fhp[1]); |
339 |
|
|
fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]); |
340 |
|
|
|
341 |
|
|
temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]); |
342 |
|
|
*inop = temp; |
343 |
|
|
|
344 |
|
|
if (osnamep) |
345 |
|
|
*osnamep = "AIX32"; |
346 |
|
|
break; |
347 |
|
|
|
348 |
|
|
case FHT_HPUX9: |
349 |
|
|
fsidp->Fsid_dev.Major = fhp[0]; |
350 |
|
|
temp = make_uint24(fhp[1], fhp[2], fhp[3]); |
351 |
|
|
fsidp->Fsid_dev.Minor = temp; |
352 |
|
|
fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]); |
353 |
|
|
|
354 |
|
|
temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]); |
355 |
|
|
*inop = temp; |
356 |
|
|
|
357 |
|
|
if (osnamep) |
358 |
|
|
*osnamep = "HPUX9"; |
359 |
|
|
break; |
360 |
|
|
|
361 |
|
|
case FHT_UNKNOWN: |
362 |
|
|
#ifdef DEBUG |
363 |
|
|
{ |
364 |
|
|
int i; |
365 |
|
|
for (i = 0; i < 32; i++) |
366 |
|
|
(void)fprintf(stderr, "%x.", fhp[i]); |
367 |
|
|
(void)fprintf(stderr, "\n"); |
368 |
|
|
} |
369 |
|
|
#endif |
370 |
|
|
/* XXX for now, give "bogus" values to aid debugging */ |
371 |
|
|
fsidp->fsid_code = 0; |
372 |
|
|
fsidp->Fsid_dev.Minor = 257; |
373 |
|
|
fsidp->Fsid_dev.Major = 257; |
374 |
|
|
*inop = 1; |
375 |
|
|
|
376 |
|
|
/* display will show this string instead of (257,257) */ |
377 |
|
|
if (fsnamep) |
378 |
|
|
*fsnamep = "Unknown"; |
379 |
|
|
|
380 |
|
|
if (osnamep) |
381 |
|
|
*osnamep = "Unknown"; |
382 |
|
|
break; |
383 |
|
|
|
384 |
|
|
} |
385 |
|
|
} |
386 |
|
|
|
387 |
|
|
/* |
388 |
|
|
* Is this a VMS UCX file handle? |
389 |
|
|
* Check for: |
390 |
|
|
* (1) leading code byte [XXX not yet] |
391 |
|
|
* (2) followed by string of printing chars & spaces |
392 |
|
|
* (3) followed by string of nulls |
393 |
|
|
*/ |
394 |
|
|
static int |
395 |
|
|
is_UCX(fhp) |
396 |
|
|
unsigned char *fhp; |
397 |
|
|
{ |
398 |
|
|
int i; |
399 |
|
|
int seen_null = 0; |
400 |
|
|
|
401 |
|
|
for (i = 1; i < 14; i++) { |
402 |
|
|
if (isprint(fhp[i])) { |
403 |
|
|
if (seen_null) |
404 |
|
|
return(0); |
405 |
|
|
else |
406 |
|
|
continue; |
407 |
|
|
} |
408 |
|
|
else if (fhp[i] == 0) { |
409 |
|
|
seen_null = 1; |
410 |
|
|
continue; |
411 |
|
|
} |
412 |
|
|
else |
413 |
|
|
return(0); |
414 |
|
|
} |
415 |
|
|
|
416 |
|
|
return(1); |
417 |
|
|
} |