/****************************************************************************** * * NSSDC/CDF Directory utilities. * * Version 1.5b, 29-Oct-97, Hughes STX. * * Modification history: * * V1.0 20-Apr-92, J Love Original version. * V1.1 21-Aug-92, J Love CDF V2.3 (shareable/NeXT). * V1.2 26-Jan-94, J Love CDF V2.4. * V1.3 24-Oct-94, J Love CDF V2.5. * V1.3a 23-Jan-95, J Love IRIX 6.0 (64-bit). * V1.3b 24-Feb-95, J Love Solaris 2.3 IDL i/f. * V1.4 21-Mar-95, J Love POSIX. * V1.4a 18-Apr-95, J Love More POSIX. * V1.5 26-Jul-96, J Love CDF V2.6. * V1.5a 3-Mar-97, J Love Windows NT for MS Visual C/C++ on an IBM PC. * V1.5b 29-Oct-97, J Love More Windows NT. * V1.6 11-Jul-05, M Liu Added MingW port for PC. * *****************************************************************************/ #include "cdflib.h" #include "cdflib64.h" /***************************************************************************** * Macro constants. *****************************************************************************/ #if (defined(unix) && !defined(__MINGW32__)) || defined(posixSHELL) #define DU_MAX_USERNAME_LEN 100 #define DU_MAX_ENVVAR_LEN 80 #endif /****************************************************************************** * Local function prototypes. ******************************************************************************/ #if (defined(unix) && !defined(__MINGW32__)) || defined(posixSHELL) static void DerefEnvVar PROTOARGs((char *shortP, char longP[DU_MAX_PATH_LEN+1])); static char *NextNonENVchar PROTOARGs((char *ptr)); #endif /****************************************************************************** * ExpandPath. ******************************************************************************/ VISIBLE_PREFIX void ExpandPath (shortP, longP) char *shortP; char longP[DU_MAX_PATH_LEN+1]; { #if (defined(unix) && !defined(__MINGW32__)) || defined(posixSHELL) int len; char *tail; struct passwd *pw; char username[DU_MAX_USERNAME_LEN+1], tempP[DU_MAX_PATH_LEN+1]; #endif #if (defined(unix) && !defined(__MINGW32__)) || defined(posixSHELL) DerefEnvVar (shortP, tempP); if (tempP[0] != '~') strcpyX (longP, tempP, DU_MAX_PATH_LEN); else { tail = strchr (tempP, '/'); if (tail != NULL) { len = tail - (tempP + 1); if (len > 0) { strcpyX (username, tempP + 1, MINIMUM(len,DU_MAX_USERNAME_LEN)); pw = getpwnam (username); } else pw = getpwuid (getuid()); if (pw != NULL) strcpyX (longP, pw->pw_dir, DU_MAX_PATH_LEN); else strcpyX (longP, "?", DU_MAX_PATH_LEN); strcatX (longP, tail, DU_MAX_PATH_LEN); } else { if (tempP[1] != NUL) pw = getpwnam (tempP + 1); else pw = getpwuid (getuid()); if (pw != NULL) strcpyX (longP, pw->pw_dir, DU_MAX_PATH_LEN); else strcpyX (longP, "?", DU_MAX_PATH_LEN); } } #endif #if defined(dos) || defined(vms) || defined(mac) || defined(win32) || \ defined(__CYGWIN__) || defined(__MINGW32__) /* If a Macintosh...check for alias? */ strcpyX (longP, shortP, DU_MAX_PATH_LEN); #endif return; } /****************************************************************************** * IsReg. * `stat' on VMS and DOS(/Windows?) systems will indicate a regular file if ANY * file can be found matching a wildcard specification. On UNIX systems, that * doesn't happen. ******************************************************************************/ VISIBLE_PREFIX Logical IsReg (path) char *path; { char pathX[DU_MAX_PATH_LEN+1]; #if defined(mac) struct FInfo fndrInfo; #else struct STAT st; #endif ExpandPath (path, pathX); #if defined(mac) if (GetFInfo(CtoPstr(pathX),0,&fndrInfo) == noErr) return TRUE; else return FALSE; #else #if defined(vms) if (strchr(pathX,'*') != NULL) return FALSE; if (strchr(pathX,'%') != NULL) return FALSE; #endif #if defined(dos) || defined(win32) || defined(__CYGWIN__) || \ defined(__MINGW32__) if (strchr(pathX,'*') != NULL) return FALSE; if (strchr(pathX,'?') != NULL) return FALSE; #endif if (stat(pathX, &st) == 0) { #if defined(SALFORDC) /* Salford's `stat' is broken. */ return (st.st_size > 0); #else #if defined(S_ISREG) return S_ISREG(st.st_mode); #else return (st.st_mode & S_IFREG); #endif #endif } else { #if defined(vms) /************************************************************************** * If this is a VMS system and the file is on DECnet (`::' is in the * pathname following the DECnet nodename), `stat' may produce an error. * In that case, try to open the file before giving up. **************************************************************************/ if (strstr(pathX,"::") != NULL) { FILE *fp = fopen (pathX, READ_ONLY_a_mode); if (fp != NULL) { fclose (fp); return TRUE; } } #endif return FALSE; } #endif } /****************************************************************************** * DerefEnvVar. * (Only used on UNIX/POSIXshell systems). ******************************************************************************/ #if (defined(unix) && !defined(__MINGW32__)) || defined(posixSHELL) static void DerefEnvVar (shortP, longP) char *shortP; /* Short path (with environment variables). */ char longP[DU_MAX_PATH_LEN+1]; /* Long path (with environment variables dereferenced). */ { char *Sptr = shortP; /* Current position in "short" path. */ char *Lptr = longP; /* End position in "long" path. */ char *DOLLARptr; /* Pointer to '$' in "short" path. */ char *ENVptr; /* Pointer to environment variable in "short" path.*/ char *DEREFptr; /* Pointer to dereferenced environment variable "value". */ size_t len; char *ptr; char ENVvar[DU_MAX_ENVVAR_LEN + 1]; /* Environment variable. */ for (*Lptr = NUL;;) { DOLLARptr = strchr (Sptr, '$'); if (DOLLARptr != NULL) { len = DOLLARptr - Sptr; if (len > 0) { strcpyX (Lptr, Sptr, MINIMUM(len,DU_MAX_PATH_LEN)); Lptr += len; } if (*(DOLLARptr + 1) == '{') { ENVptr = DOLLARptr + 2; ptr = strchr (ENVptr, '}'); if (ptr != NULL) { len = ptr - ENVptr; Sptr = ptr + 1; } else { len = strlen (ENVptr); Sptr = ENVptr + len; } } else { ENVptr = DOLLARptr + 1; ptr = NextNonENVchar (ENVptr + 1); if (ptr != NULL) { len = ptr - ENVptr; Sptr = ptr; } else { len = strlen (ENVptr); Sptr = ENVptr + len; } } strcpyX (ENVvar, ENVptr, MINIMUM(len,DU_MAX_ENVVAR_LEN)); DEREFptr = getenv (ENVvar); if (DEREFptr != NULL) { len = strlen (DEREFptr); strcpyX (Lptr, DEREFptr, MINIMUM(len,DU_MAX_PATH_LEN)); Lptr += len; } } else { strcatX (Lptr, Sptr, DU_MAX_PATH_LEN); return; } } } #endif /****************************************************************************** * NextNonENVchar. * (Only used on UNIX/POSIXshell systems). ******************************************************************************/ #if (defined(unix) && !defined(__MINGW32__)) || defined(posixSHELL) static char *NextNonENVchar (ptr) char *ptr; { uChar *p; for (p = (uChar *) ptr; *p != NUL; p++) { if (*p <= '/') return ((char *) p); if (':' <= *p && *p <= '@') return ((char *) p); if ('[' <= *p && *p <= '^') return ((char *) p); if (*p == '`') return ((char *) p); if ('{' <= *p) return ((char *) p); } return NULL; } #endif /****************************************************************************** * MacDirSpecified. (Only used on Macintosh systems). * WARNING - Using `PBHGetVol' caused some really weird things to happen. Use * `HGetVol' instead. ******************************************************************************/ #if defined(mac) STATICforIDL Logical MacDirSpecified (path, vRefNum, dirID) char *path; /* In: Pathname to be checked. */ short *vRefNum; /* Out: Volume reference number. */ long *dirID; /* Out: Directory identifier. */ { char pathX[DU_MAX_PATH_LEN+1]; OSErr rCode; short tVRefNum; long tDirID; ExpandPath (path, pathX); /**************************************************************************** * Check for no directory specified (which implies the current working * directory) or just `:' (which also implies the current working directory). ****************************************************************************/ if (NULstring(pathX) || !strcmp(pathX,":")) { rCode = HGetVol (NULL, &tVRefNum, &tDirID); if (rCode != noErr) return FALSE; } else { /************************************************************************** * Some sort of pathname has been specified (full or partial). **************************************************************************/ HParamBlockRec hParms; CInfoPBRec cParms; long topDirID; /* Top directory ID of partial pathname. */ Str255 tempS; if (pathX[0] == ':') { /***************************************************************** * Partial pathname. *****************************************************************/ rCode = HGetVol (NULL, &tVRefNum, &topDirID); if (rCode != noErr) return FALSE; } else { /***************************************************************** * Full pathname. *****************************************************************/ hParms.volumeParam.ioNamePtr = tempS; strcpyX ((char *) hParms.volumeParam.ioNamePtr, pathX, 255); CtoPstr ((char *) hParms.volumeParam.ioNamePtr); hParms.volumeParam.ioVRefNum = 0; hParms.volumeParam.ioVolIndex = -1; rCode = PBHGetVInfo (&hParms, FALSE); if (rCode == noErr) tVRefNum = hParms.volumeParam.ioVRefNum; else return FALSE; topDirID = 0; } cParms.hFileInfo.ioNamePtr = tempS; strcpyX ((char *) cParms.hFileInfo.ioNamePtr, pathX, 255); CtoPstr ((char *) cParms.hFileInfo.ioNamePtr); cParms.hFileInfo.ioVRefNum = tVRefNum; cParms.hFileInfo.ioFDirIndex = 0; cParms.hFileInfo.ioDirID = topDirID; rCode = PBGetCatInfo (&cParms, FALSE); if (rCode == noErr) tDirID = cParms.hFileInfo.ioDirID; else return FALSE; if (BITCLR(cParms.hFileInfo.ioFlAttrib,4)) return FALSE; /* `Dir' bit */ } /**************************************************************************** * Pass back volume reference number and directory identifier. ****************************************************************************/ ASSIGNnotNULL (vRefNum, tVRefNum) ASSIGNnotNULL (dirID, tDirID) return TRUE; } #endif /****************************************************************************** * AppendToDir. * If necessary, appends a '/' (UNIX), a '\' (MS-DOS), or a `:' (Mac) to make * a directory specification to which the file name can then be appended. ******************************************************************************/ VISIBLE_PREFIX void AppendToDir (dir, name) char *dir; char *name; { #if defined(vms) strcatX (dir, name, 0); #endif #if (defined(unix) && !defined(__CYGWIN__) && !defined(__MINGW32__)) || \ defined(posixSHELL) if (!NULstring(dir)) { int lastChar = strlen(dir) - 1; if (dir[lastChar] != '/') strcatX (dir, "/", 0); } strcatX (dir, name, 0); #endif #if defined(dos) || defined(win32) || defined(__CYGWIN__) || \ defined(__MINGW32__) if (!NULstring(dir)) { int lastChar = strlen(dir) - 1; if (dir[lastChar] != '\\' && dir[lastChar] != ':') strcatX (dir, "\\", 0); } strcatX (dir, name, 0); #endif #if defined(mac) if (!NULstring(dir)) { int lastChar = strlen(dir) - 1; if (dir[lastChar] != ':') strcatX (dir, ":", 0); } strcatX (dir, name, 0); #endif return; }