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