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