parsenfsfh.c revision 18976
169800Stomsoft#ifndef lint 269800Stomsoftstatic char *RCSid = "$Header: parsenfsfh.c,v 1.9 95/10/19 20:27:44 leres Exp $"; 369800Stomsoft#endif 469800Stomsoft 5114067Sschweikh/* 669800Stomsoft * parsenfsfh.c - portable parser for NFS file handles 769800Stomsoft * uses all sorts of heuristics 8114067Sschweikh * 969800Stomsoft * Jeffrey C. Mogul 1069800Stomsoft * Digital Equipment Corporation 1169800Stomsoft * Western Research Laboratory 1269800Stomsoft */ 1369800Stomsoft 1469800Stomsoft#include <sys/types.h> 1569800Stomsoft#include <sys/time.h> 1669800Stomsoft 1769800Stomsoft#include <ctype.h> 1869800Stomsoft#include <memory.h> 1969800Stomsoft#include <stdio.h> 2069800Stomsoft#include <string.h> 2169800Stomsoft 2269800Stomsoft#include "interface.h" 2369800Stomsoft#include "nfsfh.h" 2469800Stomsoft 25114067Sschweikh/* 2669800Stomsoft * This routine attempts to parse a file handle (in network byte order), 2769800Stomsoft * using heuristics to guess what kind of format it is in. See the 2869800Stomsoft * file "fhandle_layouts" for a detailed description of the various 2969800Stomsoft * patterns we know about. 3069800Stomsoft * 3169800Stomsoft * The file handle is parsed into our internal representation of a 3269800Stomsoft * file-system id, and an internal representation of an inode-number. 3369800Stomsoft */ 3469800Stomsoft 3569800Stomsoft#define FHT_UNKNOWN 0 3669800Stomsoft#define FHT_AUSPEX 1 3769800Stomsoft#define FHT_DECOSF 2 3869926Stomsoft#define FHT_IRIX4 3 3969800Stomsoft#define FHT_IRIX5 4 4069800Stomsoft#define FHT_SUNOS3 5 4169800Stomsoft#define FHT_SUNOS4 6 4269800Stomsoft#define FHT_ULTRIX 7 4369800Stomsoft#define FHT_VMSUCX 8 4469800Stomsoft#define FHT_SUNOS5 9 4569800Stomsoft#define FHT_AIX32 10 4669800Stomsoft#define FHT_HPUX9 11 4769800Stomsoft 4869800Stomsoft#ifdef ultrix 49140351Scharnier/* Nasty hack to keep the Ultrix C compiler from emitting bogus warnings */ 50140351Scharnier#define XFF(x) ((u_int32_t)(x)) 5169800Stomsoft#else 5269800Stomsoft#define XFF(x) (x) 5369800Stomsoft#endif 5469800Stomsoft 5569800Stomsoft#define make_uint32(msb,b,c,lsb)\ 5669800Stomsoft (XFF(lsb) + (XFF(c)<<8) + (XFF(b)<<16) + (XFF(msb)<<24)) 57114936Sgrog 5869800Stomsoft#define make_uint24(msb,b, lsb)\ 5969800Stomsoft (XFF(lsb) + (XFF(b)<<8) + (XFF(msb)<<16)) 6069800Stomsoft 6169800Stomsoft#define make_uint16(msb,lsb)\ 6269800Stomsoft (XFF(lsb) + (XFF(msb)<<8)) 6369800Stomsoft 64103949Smike#ifdef __alpha 6569800Stomsoft /* or other 64-bit systems */ 66127798Sle#define make_uint48(msb,b,c,d,e,lsb)\ 6769800Stomsoft ((lsb) + ((e)<<8) + ((d)<<16) + ((c)<<24) + ((b)<<32) + ((msb)<<40)) 68127821Sbde#else 6969800Stomsoft /* on 32-bit systems ignore high-order bits */ 7069800Stomsoft#define make_uint48(msb,b,c,d,e,lsb)\ 7169800Stomsoft ((lsb) + ((e)<<8) + ((d)<<16) + ((c)<<24)) 7269800Stomsoft#endif 7369800Stomsoft 7469800Stomsoftstatic int is_UCX(unsigned char *); 7569800Stomsoft 7669800Stomsoftvoid 7769800StomsoftParse_fh(fh, len, fsidp, inop, osnamep, fsnamep, ourself) 7869800Stomsoftregister caddr_t *fh; 7969800Stomsoftint len; 8069800Stomsoftmy_fsid *fsidp; 8169800Stomsoftino_t *inop; 8298542Smckusickchar **osnamep; /* if non-NULL, return OS name here */ 8369800Stomsoftchar **fsnamep; /* if non-NULL, return server fs name here (for VMS) */ 8469800Stomsoftint ourself; /* true if file handle was generated on this host */ 8569800Stomsoft{ 8669800Stomsoft register unsigned char *fhp = (unsigned char *)fh; 8798542Smckusick u_int32_t temp; 8898542Smckusick int fhtype = FHT_UNKNOWN; 8998542Smckusick 9098542Smckusick if (ourself) { 9198542Smckusick /* File handle generated on this host, no need for guessing */ 9298542Smckusick#if defined(IRIX40) 9369800Stomsoft fhtype = FHT_IRIX4; 9469800Stomsoft#endif 9569800Stomsoft#if defined(IRIX50) 9669800Stomsoft fhtype = FHT_IRIX5; 9769800Stomsoft#endif 9869800Stomsoft#if defined(IRIX51) 9969800Stomsoft fhtype = FHT_IRIX5; 10098542Smckusick#endif 10169800Stomsoft#if defined(SUNOS4) 10298542Smckusick fhtype = FHT_SUNOS4; 10369800Stomsoft#endif 10498542Smckusick#if defined(SUNOS5) 10598542Smckusick fhtype = FHT_SUNOS5; 10698542Smckusick#endif 10769800Stomsoft#if defined(ultrix) 10898542Smckusick fhtype = FHT_ULTRIX; 10998542Smckusick#endif 110127798Sle#if defined(__osf__) 111132832Sle fhtype = FHT_DECOSF; 112132832Sle#endif 113132832Sle } 114132832Sle /* 115132832Sle * This is basically a big decision tree 116132832Sle */ 11798542Smckusick else if ((fhp[0] == 0) && (fhp[1] == 0)) { 11898542Smckusick /* bytes[0,1] == (0,0); rules out Ultrix, IRIX5, SUNOS5 */ 119127798Sle /* probably rules out HP-UX, AIX unless they allow major=0 */ 120114936Sgrog if ((fhp[2] == 0) && (fhp[3] == 0)) { 12169800Stomsoft /* bytes[2,3] == (0,0); must be Auspex */ 12269800Stomsoft /* XXX or could be Ultrix+MASSBUS "hp" disk? */ 123114067Sschweikh fhtype = FHT_AUSPEX; 12469800Stomsoft } 12569800Stomsoft else { 12669800Stomsoft /* 12769800Stomsoft * bytes[2,3] != (0,0); rules out Auspex, could be 12898542Smckusick * DECOSF, SUNOS4, or IRIX4 12998542Smckusick */ 13069800Stomsoft if ((fhp[4] != 0) && (fhp[5] == 0) && 13169800Stomsoft (fhp[8] == 12) && (fhp[9] == 0)) { 13277885Stomsoft /* seems to be DECOSF, with minor == 0 */ 13369800Stomsoft fhtype = FHT_DECOSF; 13469800Stomsoft } 13569800Stomsoft else { 13669800Stomsoft /* could be SUNOS4 or IRIX4 */ 13777885Stomsoft /* XXX the test of fhp[5] == 8 could be wrong */ 13898542Smckusick if ((fhp[4] == 0) && (fhp[5] == 8) && (fhp[6] == 0) && 13998542Smckusick (fhp[7] == 0)) { 14098542Smckusick /* looks like a length, not a file system typecode */ 14169800Stomsoft fhtype = FHT_IRIX4; 14269926Stomsoft } 14369800Stomsoft else { 14469800Stomsoft /* by elimination */ 14569800Stomsoft fhtype = FHT_SUNOS4; 14677885Stomsoft } 14777885Stomsoft } 14877885Stomsoft } 14969800Stomsoft } 15077885Stomsoft else { 15198542Smckusick /* 15298542Smckusick * bytes[0,1] != (0,0); rules out Auspex, IRIX4, SUNOS4 15398542Smckusick * could be IRIX5, DECOSF, UCX, Ultrix, SUNOS5 15498542Smckusick * could be AIX, HP-UX 15569800Stomsoft */ 15677885Stomsoft if ((fhp[2] == 0) && (fhp[3] == 0)) { 15798542Smckusick /* 15898542Smckusick * bytes[2,3] == (0,0); rules out OSF, probably not UCX 159114936Sgrog * (unless the exported device name is just one letter!), 16069800Stomsoft * could be Ultrix, IRIX5, AIX, or SUNOS5 16169800Stomsoft * might be HP-UX (depends on their values for minor devs) 16269800Stomsoft */ 163114067Sschweikh /*XXX we probably only need to test of these two bytes */ 164114067Sschweikh if ((fhp[21] == 0) && (fhp[23] == 0)) { 165114067Sschweikh fhtype = FHT_ULTRIX; 16669800Stomsoft } 167114067Sschweikh else { 168114067Sschweikh /* Could be SUNOS5/IRIX5, maybe AIX */ 169114067Sschweikh /* XXX no obvious difference between SUNOS5 and IRIX5 */ 17069800Stomsoft if (fhp[9] == 10) 17169800Stomsoft fhtype = FHT_SUNOS5; 17269800Stomsoft /* XXX what about AIX? */ 17369800Stomsoft } 17477885Stomsoft } 17569800Stomsoft else { 17669800Stomsoft /* 17769800Stomsoft * bytes[2,3] != (0,0); rules out Ultrix, could be 178203770Smckusick * DECOSF, SUNOS5, IRIX5, AIX, HP-UX, or UCX 179203770Smckusick */ 18069800Stomsoft if ((fhp[8] == 12) && (fhp[9] == 0)) { 18169800Stomsoft fhtype = FHT_DECOSF; 18269800Stomsoft } 18369800Stomsoft else if ((fhp[8] == 0) && (fhp[9] == 10)) { 18469800Stomsoft /* could be SUNOS5/IRIX5, AIX, HP-UX */ 18569800Stomsoft if ((fhp[7] == 0) && (fhp[6] == 0) && 18669800Stomsoft (fhp[5] == 0) && (fhp[4] == 0)) { 18769800Stomsoft /* XXX is this always true of HP-UX? */ 18869800Stomsoft fhtype = FHT_HPUX9; 18969800Stomsoft } 19069800Stomsoft else if (fhp[7] == 2) { 19169800Stomsoft /* This would be MNT_NFS on AIX, which is impossible */ 19269800Stomsoft fhtype = FHT_SUNOS5; /* or maybe IRIX5 */ 19369800Stomsoft } 19469800Stomsoft else { 19569800Stomsoft /* 19669800Stomsoft * XXX Could be SUNOS5/IRIX5 or AIX. I don't 19769800Stomsoft * XXX see any way to disambiguate these, so 19869800Stomsoft * XXX I'm going with the more likely guess. 19969800Stomsoft * XXX Sorry, Big Blue. 20077885Stomsoft */ 20169926Stomsoft fhtype = FHT_SUNOS5; /* or maybe IRIX5 */ 20269926Stomsoft } 20369926Stomsoft } 20469800Stomsoft else { 20569800Stomsoft if (is_UCX(fhp)) { 20677885Stomsoft fhtype = FHT_VMSUCX; 20777885Stomsoft } 20869800Stomsoft else { 20969800Stomsoft fhtype = FHT_UNKNOWN; 21069800Stomsoft } 21169800Stomsoft } 21269800Stomsoft } 21369800Stomsoft } 21469800Stomsoft 21569800Stomsoft /* XXX still needs to handle SUNOS3 */ 21669800Stomsoft 21769800Stomsoft switch (fhtype) { 21877885Stomsoft case FHT_AUSPEX: 21977885Stomsoft fsidp->fsid_dev.Minor = fhp[7]; 22069926Stomsoft fsidp->fsid_dev.Major = fhp[6]; 22169926Stomsoft fsidp->fsid_code = 0; 22269926Stomsoft 22369800Stomsoft temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]); 22469800Stomsoft *inop = temp; 22569800Stomsoft 22669800Stomsoft if (osnamep) 22769800Stomsoft *osnamep = "Auspex"; 22869800Stomsoft break; 22969800Stomsoft 23069800Stomsoft case FHT_DECOSF: 23169800Stomsoft fsidp->fsid_code = make_uint32(fhp[7], fhp[6], fhp[5], fhp[4]); 23269800Stomsoft /* XXX could ignore 3 high-order bytes */ 23369800Stomsoft 234102231Strhodes temp = make_uint32(fhp[3], fhp[2], fhp[1], fhp[0]); 23569800Stomsoft fsidp->fsid_dev.Minor = temp & 0xFFFFF; 23698542Smckusick fsidp->fsid_dev.Major = (temp>>20) & 0xFFF; 237127816Smux 23869800Stomsoft temp = make_uint32(fhp[15], fhp[14], fhp[13], fhp[12]); 239127816Smux *inop = temp; 240127816Smux if (osnamep) 24198542Smckusick *osnamep = "OSF"; 24298542Smckusick break; 24398542Smckusick 24498542Smckusick case FHT_IRIX4: 24598542Smckusick fsidp->fsid_dev.Minor = fhp[3]; 24698542Smckusick fsidp->fsid_dev.Major = fhp[2]; 24769800Stomsoft fsidp->fsid_code = 0; 24869800Stomsoft 24969800Stomsoft temp = make_uint32(fhp[8], fhp[9], fhp[10], fhp[11]); 25069800Stomsoft *inop = temp; 25169800Stomsoft 25269800Stomsoft if (osnamep) 25369800Stomsoft *osnamep = "IRIX4"; 25469800Stomsoft break; 25569800Stomsoft 25669800Stomsoft case FHT_IRIX5: 25769800Stomsoft fsidp->fsid_dev.Minor = make_uint16(fhp[2], fhp[3]); 25869800Stomsoft fsidp->fsid_dev.Major = make_uint16(fhp[0], fhp[1]); 25969800Stomsoft fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]); 26069800Stomsoft 261174706Sdas temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]); 262174706Sdas *inop = temp; 26369800Stomsoft 26469800Stomsoft if (osnamep) 26569800Stomsoft *osnamep = "IRIX5"; 26669800Stomsoft break; 26769800Stomsoft 26869800Stomsoft case FHT_SUNOS3: 26969800Stomsoft if (osnamep) 27069800Stomsoft *osnamep = "SUNOS3"; 27169800Stomsoft break; 27269800Stomsoft 27369800Stomsoft case FHT_SUNOS4: 27469800Stomsoft fsidp->fsid_dev.Minor = fhp[3]; 27569800Stomsoft fsidp->fsid_dev.Major = fhp[2]; 27669800Stomsoft fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]); 27769800Stomsoft 27869800Stomsoft temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]); 27969800Stomsoft *inop = temp; 28069800Stomsoft 28169800Stomsoft if (osnamep) 28269800Stomsoft *osnamep = "SUNOS4"; 28369800Stomsoft break; 28469800Stomsoft 28577885Stomsoft case FHT_SUNOS5: 28677885Stomsoft temp = make_uint16(fhp[0], fhp[1]); 28769800Stomsoft fsidp->fsid_dev.Major = (temp>>2) & 0x3FFF; 28869800Stomsoft temp = make_uint24(fhp[1], fhp[2], fhp[3]); 28969800Stomsoft fsidp->fsid_dev.Minor = temp & 0x3FFFF; 29069800Stomsoft fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]); 29169800Stomsoft 29269800Stomsoft temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]); 29369800Stomsoft *inop = temp; 29469800Stomsoft 29569800Stomsoft if (osnamep) 29669800Stomsoft *osnamep = "SUNOS5"; 29769800Stomsoft break; 29877885Stomsoft 29977885Stomsoft case FHT_ULTRIX: 30069926Stomsoft fsidp->fsid_code = 0; 30169926Stomsoft fsidp->fsid_dev.Minor = fhp[0]; 30269926Stomsoft fsidp->fsid_dev.Major = fhp[1]; 30369800Stomsoft 30469800Stomsoft temp = make_uint32(fhp[7], fhp[6], fhp[5], fhp[4]); 30569800Stomsoft *inop = temp; 30669800Stomsoft if (osnamep) 30769800Stomsoft *osnamep = "Ultrix"; 30869800Stomsoft break; 30969800Stomsoft 31069800Stomsoft case FHT_VMSUCX: 31198542Smckusick /* No numeric file system ID, so hash on the device-name */ 31269800Stomsoft if (sizeof(*fsidp) >= 14) { 31369926Stomsoft if (sizeof(*fsidp) > 14) 31469926Stomsoft memset((char *)fsidp, 0, sizeof(*fsidp)); 31569800Stomsoft memcpy((char *)fsidp, fh, 14); /* just use the whole thing */ 31669800Stomsoft } 31769800Stomsoft else { 31869800Stomsoft u_int32_t tempa[4]; /* at least 16 bytes, maybe more */ 31969800Stomsoft 32069800Stomsoft memset((char *)tempa, 0, sizeof(tempa)); 32169800Stomsoft memcpy((char *)tempa, fh, 14); /* ensure alignment */ 32269800Stomsoft fsidp->fsid_dev.Minor = tempa[0] + (tempa[1]<<1); 32369800Stomsoft fsidp->fsid_dev.Major = tempa[2] + (tempa[3]<<1); 32469800Stomsoft fsidp->fsid_code = 0; 32569800Stomsoft } 32669800Stomsoft 32769800Stomsoft /* VMS file ID is: (RVN, FidHi, FidLo) */ 32869800Stomsoft *inop = make_uint32(fhp[26], fhp[27], fhp[23], fhp[22]); 329114067Sschweikh 33069800Stomsoft /* Caller must save (and null-terminate?) this value */ 33169800Stomsoft if (fsnamep) 33269800Stomsoft *fsnamep = (char *)&(fhp[1]); 33369800Stomsoft 33469800Stomsoft if (osnamep) 33569800Stomsoft *osnamep = "VMS"; 33669800Stomsoft break; 33769800Stomsoft 33869800Stomsoft case FHT_AIX32: 33969800Stomsoft fsidp->fsid_dev.Minor = make_uint16(fhp[2], fhp[3]); 34069800Stomsoft fsidp->fsid_dev.Major = make_uint16(fhp[0], fhp[1]); 341114067Sschweikh fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]); 34269800Stomsoft 34369800Stomsoft temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]); 344114067Sschweikh *inop = temp; 34569800Stomsoft 34669800Stomsoft if (osnamep) 34769800Stomsoft *osnamep = "AIX32"; 34869800Stomsoft break; 34969800Stomsoft 35069800Stomsoft case FHT_HPUX9: 35169800Stomsoft fsidp->fsid_dev.Major = fhp[0]; 35269800Stomsoft temp = make_uint24(fhp[1], fhp[2], fhp[3]); 35398542Smckusick fsidp->fsid_dev.Minor = temp; 35469800Stomsoft fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]); 35569800Stomsoft 35669926Stomsoft temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]); 35769926Stomsoft *inop = temp; 35869800Stomsoft 35969800Stomsoft if (osnamep) 36069800Stomsoft *osnamep = "HPUX9"; 36169800Stomsoft break; 36269800Stomsoft 36369800Stomsoft case FHT_UNKNOWN: 36469800Stomsoft#ifdef DEBUG 365114067Sschweikh { 366114067Sschweikh /* XXX debugging */ 367114067Sschweikh int i; 36869800Stomsoft for (i = 0; i < 32; i++) 36969800Stomsoft (void)fprintf(stderr, "%x.", fhp[i]); 37069800Stomsoft (void)fprintf(stderr, "\n"); 37177885Stomsoft } 37269800Stomsoft#endif 37369800Stomsoft /* XXX for now, give "bogus" values to aid debugging */ 374127816Smux fsidp->fsid_code = 0; 375203770Smckusick fsidp->fsid_dev.Minor = 257; 376127798Sle fsidp->fsid_dev.Major = 257; 37798542Smckusick *inop = 1; 37892806Sobrien 379203770Smckusick /* display will show this string instead of (257,257) */ 38069800Stomsoft if (fsnamep) 38198542Smckusick *fsnamep = "Unknown"; 38298542Smckusick 38398542Smckusick if (osnamep) 38469800Stomsoft *osnamep = "Unknown"; 38569800Stomsoft break; 38698542Smckusick 38798542Smckusick } 38869800Stomsoft} 38969800Stomsoft 39069800Stomsoft/* 39198542Smckusick * Is this a VMS UCX file handle? 39269800Stomsoft * Check for: 39369800Stomsoft * (1) leading code byte [XXX not yet] 39469800Stomsoft * (2) followed by string of printing chars & spaces 39598542Smckusick * (3) followed by string of nulls 39669800Stomsoft */ 39798542Smckusickstatic int 39898542Smckusickis_UCX(fhp) 399197763Smjacobunsigned char *fhp; 400197763Smjacob{ 401197763Smjacob register int i; 402197763Smjacob int seen_null = 0; 403197763Smjacob 404197763Smjacob for (i = 1; i < 14; i++) { 405197763Smjacob if (isprint(fhp[i])) { 40669800Stomsoft if (seen_null) 40769800Stomsoft return(0); 40869800Stomsoft else 40969800Stomsoft continue; 41069800Stomsoft } 41198542Smckusick else if (fhp[i] == 0) { 41269800Stomsoft seen_null = 1; 41398542Smckusick continue; 41498542Smckusick } 41598542Smckusick else 41698542Smckusick return(0); 41798542Smckusick } 41898542Smckusick 41998542Smckusick return(1); 42098542Smckusick} 42198542Smckusick