1 /******************************************************************************
2 *
3 * NSSDC/CDF Directory utilities.
4 *
5 * Version 1.5b, 29-Oct-97, Hughes STX.
6 *
7 * Modification history:
8 *
9 * V1.0 20-Apr-92, J Love Original version.
10 * V1.1 21-Aug-92, J Love CDF V2.3 (shareable/NeXT).
11 * V1.2 26-Jan-94, J Love CDF V2.4.
12 * V1.3 24-Oct-94, J Love CDF V2.5.
13 * V1.3a 23-Jan-95, J Love IRIX 6.0 (64-bit).
14 * V1.3b 24-Feb-95, J Love Solaris 2.3 IDL i/f.
15 * V1.4 21-Mar-95, J Love POSIX.
16 * V1.4a 18-Apr-95, J Love More POSIX.
17 * V1.5 26-Jul-96, J Love CDF V2.6.
18 * V1.5a 3-Mar-97, J Love Windows NT for MS Visual C/C++ on an IBM PC.
19 * V1.5b 29-Oct-97, J Love More Windows NT.
20 * V1.6 11-Jul-05, M Liu Added MingW port for PC.
21 *
22 *****************************************************************************/
23
24 #include "cdflib.h"
25 #include "cdflib64.h"
26
27 /*****************************************************************************
28 * Macro constants.
29 *****************************************************************************/
30
31 #if (defined(unix) && !defined(__MINGW32__)) || defined(posixSHELL)
32 #define DU_MAX_USERNAME_LEN 100
33 #define DU_MAX_ENVVAR_LEN 80
34 #endif
35
36 /******************************************************************************
37 * Local function prototypes.
38 ******************************************************************************/
39
40 #if (defined(unix) && !defined(__MINGW32__)) || defined(posixSHELL)
41 static void DerefEnvVar PROTOARGs((char *shortP,
42 char longP[DU_MAX_PATH_LEN+1]));
43 static char *NextNonENVchar PROTOARGs((char *ptr));
44 #endif
45
46 /******************************************************************************
47 * ExpandPath.
48 ******************************************************************************/
49
ExpandPath(shortP,longP)50 VISIBLE_PREFIX void ExpandPath (shortP, longP)
51 char *shortP;
52 char longP[DU_MAX_PATH_LEN+1];
53 {
54 #if (defined(unix) && !defined(__MINGW32__)) || defined(posixSHELL)
55 int len; char *tail; struct passwd *pw;
56 char username[DU_MAX_USERNAME_LEN+1], tempP[DU_MAX_PATH_LEN+1];
57 #endif
58
59 #if (defined(unix) && !defined(__MINGW32__)) || defined(posixSHELL)
60 DerefEnvVar (shortP, tempP);
61 if (tempP[0] != '~')
62 strcpyX (longP, tempP, DU_MAX_PATH_LEN);
63 else {
64 tail = strchr (tempP, '/');
65 if (tail != NULL) {
66 len = tail - (tempP + 1);
67 if (len > 0) {
68 strcpyX (username, tempP + 1, MINIMUM(len,DU_MAX_USERNAME_LEN));
69 pw = getpwnam (username);
70 }
71 else
72 pw = getpwuid (getuid());
73 if (pw != NULL)
74 strcpyX (longP, pw->pw_dir, DU_MAX_PATH_LEN);
75 else
76 strcpyX (longP, "?", DU_MAX_PATH_LEN);
77 strcatX (longP, tail, DU_MAX_PATH_LEN);
78 }
79 else {
80 if (tempP[1] != NUL)
81 pw = getpwnam (tempP + 1);
82 else
83 pw = getpwuid (getuid());
84 if (pw != NULL)
85 strcpyX (longP, pw->pw_dir, DU_MAX_PATH_LEN);
86 else
87 strcpyX (longP, "?", DU_MAX_PATH_LEN);
88 }
89 }
90 #endif
91
92 #if defined(dos) || defined(vms) || defined(mac) || defined(win32) || \
93 defined(__CYGWIN__) || defined(__MINGW32__)
94 /* If a Macintosh...check for alias? */
95 strcpyX (longP, shortP, DU_MAX_PATH_LEN);
96 #endif
97
98 return;
99 }
100
101 /******************************************************************************
102 * IsReg.
103 * `stat' on VMS and DOS(/Windows?) systems will indicate a regular file if ANY
104 * file can be found matching a wildcard specification. On UNIX systems, that
105 * doesn't happen.
106 ******************************************************************************/
107
IsReg(path)108 VISIBLE_PREFIX Logical IsReg (path)
109 char *path;
110 {
111 char pathX[DU_MAX_PATH_LEN+1];
112 #if defined(mac)
113 struct FInfo fndrInfo;
114 #else
115 struct STAT st;
116 #endif
117 ExpandPath (path, pathX);
118 #if defined(mac)
119 if (GetFInfo(CtoPstr(pathX),0,&fndrInfo) == noErr)
120 return TRUE;
121 else
122 return FALSE;
123 #else
124 #if defined(vms)
125 if (strchr(pathX,'*') != NULL) return FALSE;
126 if (strchr(pathX,'%') != NULL) return FALSE;
127 #endif
128 #if defined(dos) || defined(win32) || defined(__CYGWIN__) || \
129 defined(__MINGW32__)
130 if (strchr(pathX,'*') != NULL) return FALSE;
131 if (strchr(pathX,'?') != NULL) return FALSE;
132 #endif
133 if (stat(pathX, &st) == 0) {
134 #if defined(SALFORDC) /* Salford's `stat' is broken. */
135 return (st.st_size > 0);
136 #else
137 #if defined(S_ISREG)
138 return S_ISREG(st.st_mode);
139 #else
140 return (st.st_mode & S_IFREG);
141 #endif
142 #endif
143 }
144 else {
145 #if defined(vms)
146 /**************************************************************************
147 * If this is a VMS system and the file is on DECnet (`::' is in the
148 * pathname following the DECnet nodename), `stat' may produce an error.
149 * In that case, try to open the file before giving up.
150 **************************************************************************/
151 if (strstr(pathX,"::") != NULL) {
152 FILE *fp = fopen (pathX, READ_ONLY_a_mode);
153 if (fp != NULL) {
154 fclose (fp);
155 return TRUE;
156 }
157 }
158 #endif
159 return FALSE;
160 }
161 #endif
162 }
163
164 /******************************************************************************
165 * DerefEnvVar.
166 * (Only used on UNIX/POSIXshell systems).
167 ******************************************************************************/
168
169 #if (defined(unix) && !defined(__MINGW32__)) || defined(posixSHELL)
DerefEnvVar(shortP,longP)170 static void DerefEnvVar (shortP, longP)
171 char *shortP; /* Short path (with environment variables). */
172 char longP[DU_MAX_PATH_LEN+1]; /* Long path (with environment variables
173 dereferenced). */
174 {
175 char *Sptr = shortP; /* Current position in "short" path. */
176 char *Lptr = longP; /* End position in "long" path. */
177 char *DOLLARptr; /* Pointer to '$' in "short" path. */
178 char *ENVptr; /* Pointer to environment variable in "short" path.*/
179 char *DEREFptr; /* Pointer to dereferenced environment variable
180 "value". */
181 size_t len;
182 char *ptr;
183 char ENVvar[DU_MAX_ENVVAR_LEN + 1]; /* Environment variable. */
184 for (*Lptr = NUL;;) {
185 DOLLARptr = strchr (Sptr, '$');
186 if (DOLLARptr != NULL) {
187 len = DOLLARptr - Sptr;
188 if (len > 0) {
189 strcpyX (Lptr, Sptr, MINIMUM(len,DU_MAX_PATH_LEN));
190 Lptr += len;
191 }
192 if (*(DOLLARptr + 1) == '{') {
193 ENVptr = DOLLARptr + 2;
194 ptr = strchr (ENVptr, '}');
195 if (ptr != NULL) {
196 len = ptr - ENVptr;
197 Sptr = ptr + 1;
198 }
199 else {
200 len = strlen (ENVptr);
201 Sptr = ENVptr + len;
202 }
203 }
204 else {
205 ENVptr = DOLLARptr + 1;
206 ptr = NextNonENVchar (ENVptr + 1);
207 if (ptr != NULL) {
208 len = ptr - ENVptr;
209 Sptr = ptr;
210 }
211 else {
212 len = strlen (ENVptr);
213 Sptr = ENVptr + len;
214 }
215 }
216 strcpyX (ENVvar, ENVptr, MINIMUM(len,DU_MAX_ENVVAR_LEN));
217 DEREFptr = getenv (ENVvar);
218 if (DEREFptr != NULL) {
219 len = strlen (DEREFptr);
220 strcpyX (Lptr, DEREFptr, MINIMUM(len,DU_MAX_PATH_LEN));
221 Lptr += len;
222 }
223 }
224 else {
225 strcatX (Lptr, Sptr, DU_MAX_PATH_LEN);
226 return;
227 }
228 }
229 }
230 #endif
231
232 /******************************************************************************
233 * NextNonENVchar.
234 * (Only used on UNIX/POSIXshell systems).
235 ******************************************************************************/
236
237 #if (defined(unix) && !defined(__MINGW32__)) || defined(posixSHELL)
NextNonENVchar(ptr)238 static char *NextNonENVchar (ptr)
239 char *ptr;
240 {
241 uChar *p;
242 for (p = (uChar *) ptr; *p != NUL; p++) {
243 if (*p <= '/') return ((char *) p);
244 if (':' <= *p && *p <= '@') return ((char *) p);
245 if ('[' <= *p && *p <= '^') return ((char *) p);
246 if (*p == '`') return ((char *) p);
247 if ('{' <= *p) return ((char *) p);
248 }
249 return NULL;
250 }
251 #endif
252
253 /******************************************************************************
254 * MacDirSpecified. (Only used on Macintosh systems).
255 * WARNING - Using `PBHGetVol' caused some really weird things to happen. Use
256 * `HGetVol' instead.
257 ******************************************************************************/
258
259 #if defined(mac)
MacDirSpecified(path,vRefNum,dirID)260 STATICforIDL Logical MacDirSpecified (path, vRefNum, dirID)
261 char *path; /* In: Pathname to be checked. */
262 short *vRefNum; /* Out: Volume reference number. */
263 long *dirID; /* Out: Directory identifier. */
264 {
265 char pathX[DU_MAX_PATH_LEN+1];
266 OSErr rCode;
267 short tVRefNum;
268 long tDirID;
269 ExpandPath (path, pathX);
270 /****************************************************************************
271 * Check for no directory specified (which implies the current working
272 * directory) or just `:' (which also implies the current working directory).
273 ****************************************************************************/
274 if (NULstring(pathX) || !strcmp(pathX,":")) {
275 rCode = HGetVol (NULL, &tVRefNum, &tDirID);
276 if (rCode != noErr) return FALSE;
277 }
278 else {
279 /**************************************************************************
280 * Some sort of pathname has been specified (full or partial).
281 **************************************************************************/
282 HParamBlockRec hParms;
283 CInfoPBRec cParms;
284 long topDirID; /* Top directory ID of partial pathname. */
285 Str255 tempS;
286 if (pathX[0] == ':') {
287 /*****************************************************************
288 * Partial pathname.
289 *****************************************************************/
290 rCode = HGetVol (NULL, &tVRefNum, &topDirID);
291 if (rCode != noErr) return FALSE;
292 }
293 else {
294 /*****************************************************************
295 * Full pathname.
296 *****************************************************************/
297 hParms.volumeParam.ioNamePtr = tempS;
298 strcpyX ((char *) hParms.volumeParam.ioNamePtr, pathX, 255);
299 CtoPstr ((char *) hParms.volumeParam.ioNamePtr);
300 hParms.volumeParam.ioVRefNum = 0;
301 hParms.volumeParam.ioVolIndex = -1;
302 rCode = PBHGetVInfo (&hParms, FALSE);
303 if (rCode == noErr)
304 tVRefNum = hParms.volumeParam.ioVRefNum;
305 else
306 return FALSE;
307 topDirID = 0;
308 }
309 cParms.hFileInfo.ioNamePtr = tempS;
310 strcpyX ((char *) cParms.hFileInfo.ioNamePtr, pathX, 255);
311 CtoPstr ((char *) cParms.hFileInfo.ioNamePtr);
312 cParms.hFileInfo.ioVRefNum = tVRefNum;
313 cParms.hFileInfo.ioFDirIndex = 0;
314 cParms.hFileInfo.ioDirID = topDirID;
315 rCode = PBGetCatInfo (&cParms, FALSE);
316 if (rCode == noErr)
317 tDirID = cParms.hFileInfo.ioDirID;
318 else
319 return FALSE;
320 if (BITCLR(cParms.hFileInfo.ioFlAttrib,4)) return FALSE; /* `Dir' bit */
321 }
322 /****************************************************************************
323 * Pass back volume reference number and directory identifier.
324 ****************************************************************************/
325 ASSIGNnotNULL (vRefNum, tVRefNum)
326 ASSIGNnotNULL (dirID, tDirID)
327 return TRUE;
328 }
329 #endif
330
331 /******************************************************************************
332 * AppendToDir.
333 * If necessary, appends a '/' (UNIX), a '\' (MS-DOS), or a `:' (Mac) to make
334 * a directory specification to which the file name can then be appended.
335 ******************************************************************************/
336
AppendToDir(dir,name)337 VISIBLE_PREFIX void AppendToDir (dir, name)
338 char *dir;
339 char *name;
340 {
341 #if defined(vms)
342 strcatX (dir, name, 0);
343 #endif
344 #if (defined(unix) && !defined(__CYGWIN__) && !defined(__MINGW32__)) || \
345 defined(posixSHELL)
346 if (!NULstring(dir)) {
347 int lastChar = strlen(dir) - 1;
348 if (dir[lastChar] != '/') strcatX (dir, "/", 0);
349 }
350 strcatX (dir, name, 0);
351 #endif
352 #if defined(dos) || defined(win32) || defined(__CYGWIN__) || \
353 defined(__MINGW32__)
354 if (!NULstring(dir)) {
355 int lastChar = strlen(dir) - 1;
356 if (dir[lastChar] != '\\' && dir[lastChar] != ':') strcatX (dir, "\\", 0);
357 }
358 strcatX (dir, name, 0);
359 #endif
360 #if defined(mac)
361 if (!NULstring(dir)) {
362 int lastChar = strlen(dir) - 1;
363 if (dir[lastChar] != ':') strcatX (dir, ":", 0);
364 }
365 strcatX (dir, name, 0);
366 #endif
367 return;
368 }
369