FileUtils.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /* $TOG: FileUtils.c /main/8 1998/07/28 15:37:38 mgreess $ */
  24. /************************************<+>*************************************
  25. ****************************************************************************
  26. **
  27. ** File: FileUtils.c
  28. **
  29. ** Project: File locating
  30. **
  31. ** Description: Locates files (volumes) accessible via the
  32. ** known paths
  33. **
  34. ** NOTE: this file must remain free of Xt & Xm calls.
  35. **
  36. ** (c) Copyright 1993, 1994 Hewlett-Packard Company
  37. ** (c) Copyright 1993, 1994 International Business Machines Corp.
  38. ** (c) Copyright 1993, 1994 Sun Microsystems, Inc.
  39. ** (c) Copyright 1993, 1994 Novell, Inc.
  40. ****************************************************************************
  41. ************************************<+>*************************************/
  42. /*
  43. * system includes
  44. */
  45. #include <errno.h>
  46. #include <fcntl.h>
  47. #include <stdlib.h>
  48. #include <stdio.h>
  49. #include <string.h>
  50. #include <unistd.h>
  51. #include <dirent.h>
  52. #include <sys/stat.h>
  53. #include <sys/param.h> /* MAXPATHLEN */
  54. #include <Dt/Help.h>
  55. /*
  56. * private includes
  57. */
  58. #include "bufioI.h" /* for AccessI.h */
  59. #include "Access.h" /* CompressPathname */
  60. #include "AccessI.h" /* ExpandPathname */
  61. #include "HelpP.h" /* for DtDEFAULT_xxx */
  62. #include "HelposI.h" /* for search path access */
  63. #include "StringFuncsI.h"
  64. #include "FileUtilsI.h"
  65. #include "Lock.h"
  66. /******** constants *********/
  67. #define LANG_C_STR "C"
  68. #define DIR_SLASH '/'
  69. #define EOS '\0'
  70. /******** types *********/
  71. /******** public global variables *********/
  72. const char * _DtHelpFileSuffixList[3] = {
  73. DtHelpSDL_VOL_SUFFIX,
  74. DtHelpCCDF_VOL_SUFFIX,
  75. NULL };
  76. /******** variables *********/
  77. #ifdef not_used
  78. static const char * PeriodStr = ".";
  79. #endif
  80. static const char * DirSlashStr = "/";
  81. static const char * PathSeparator = ":";
  82. static const _DtHelpCeDirStruct DefCacheDir = { NULL, ENOTDIR, 0, NULL };
  83. static _DtHelpCeDirStruct *CachedDirs = NULL;
  84. /******** functions *********/
  85. #define MyNewString(s) (NULL != s ? strdup((char *)s) : NULL)
  86. #define MyRealloc(p,s) (NULL != (p) ? realloc((char *)p,s) : malloc(s) )
  87. #define MyMalloc(s) malloc(s)
  88. /*****************************************************************************
  89. * Function: MyFree()
  90. *
  91. * locate the '.' of the filename extension, if present
  92. *
  93. *****************************************************************************/
  94. static void MyFree(char * ptr)
  95. {
  96. if(ptr) free(ptr);
  97. }
  98. #ifdef not_used
  99. /*****************************************************************************
  100. * Function: GetExtension()
  101. *
  102. * locate the '.' of the filename extension, if present
  103. *
  104. *****************************************************************************/
  105. static char * GetExtension(
  106. char * filename)
  107. {
  108. char * ext;
  109. if (_DtHelpCeStrrchr(filename,PeriodStr,MB_CUR_MAX,&ext) == 0 ) return ext;
  110. else return ""; /* do NOT return a NULL*/
  111. }
  112. /*****************************************************************************
  113. * Function: SpecialStrcmp()
  114. *
  115. * Tests the args for NULL pointers. If both are NULL or if
  116. * both aren't NULL and are the same string, then returns 0.
  117. * If one arg is NULL and other isn't, or if strings are
  118. * different, returns -1 or +1.
  119. *
  120. *****************************************************************************/
  121. static int SpecialStrcmp(
  122. const char * str1,
  123. const char * str2)
  124. {
  125. if(NULL == str1)
  126. {
  127. if(NULL == str2) return 0; /* str1 == str2 */
  128. return -1; /* str1 < str2 */
  129. }
  130. if(NULL == str2) return 1; /* str1 > str2 */
  131. return(strcmp(str1,str2)); /* str1 ? str2 */
  132. }
  133. #endif
  134. /************************************************************************
  135. * Function: _DtHelpFileTraceLinks (pathName)
  136. *
  137. * Purpose: Traces pathname through all symbolic links
  138. * until a real file is found or the link is
  139. * found to be invalid.
  140. *
  141. * Returns: True if file found at end of link, False if not
  142. *
  143. * Memory: pathName must point to a malloc'd string. The string
  144. * may be freed by the function and pathName assigned a pointer
  145. * to a different string specifying a different path to the same file.
  146. * If a file is found, foundPath is set to the same pointer
  147. * as pathName, otherwise it is set to NULL.
  148. ***********************************************************************/
  149. Boolean
  150. _DtHelpFileTraceLinks (
  151. char * * pPathName)
  152. {
  153. int result = 0;
  154. char curBuf;
  155. char * linkPath;
  156. char * filePath;
  157. char buf [2][MAXPATHLEN+2]; /* 2K+ bytes on stack */
  158. if ( NULL == *pPathName ) return False; /* RETURN */
  159. /* init */
  160. snprintf(buf[0], sizeof(buf[0]), "%s", *pPathName);
  161. linkPath = buf[0]; /* will be assigned to filePath below */
  162. curBuf = 1; /* next valid buf */
  163. /* find out if this path is a symbolic link */
  164. while ( result >= 0 )
  165. {
  166. /* exchange buffer ptrs and toggle index */
  167. filePath = linkPath;
  168. linkPath = buf[curBuf % 2];
  169. curBuf++;
  170. /* get the link info */
  171. result = readlink (filePath, linkPath, MAXPATHLEN);
  172. /* check for the result of the readlink call */
  173. if (result == -1)
  174. {
  175. /* if newPath is not a symbolic link, errno != EINVAL */
  176. if (errno != EINVAL)
  177. return False; /* RETURN */
  178. /* filePath is not a sym link ==> a real file or directory */
  179. /* so return filePath in caller-owned memory */
  180. if ( curBuf != 1 ) /* curBuf == 1 when pPathName is a file */
  181. {
  182. /*
  183. * pPathName had memory allocated before this function was called.
  184. * only increase the memory if needed.
  185. */
  186. if ( strlen (*pPathName) < strlen(filePath) )
  187. *pPathName = (char *)realloc((void *)*pPathName, (sizeof(char)
  188. * (strlen(filePath) +1)));
  189. strcpy(*pPathName, filePath);
  190. }
  191. /* printf("actual is: %s\n", filePath); ** DBG */
  192. return True; /* RETURN */
  193. } /* if an error */
  194. else
  195. { /* no error--handle the link */
  196. /* if the path is absolute, just take it as such */
  197. linkPath [result] = EOS; /* for safety */
  198. /* is path relative to current directory? */
  199. if ( linkPath[0] != DIR_SLASH )
  200. {
  201. char * slash = NULL;
  202. /* get last slash in the current file path */
  203. if(_DtHelpCeStrrchr(filePath,DirSlashStr,MB_CUR_MAX,&slash) == 0)
  204. { /* there is a path component in filePath; use it with linkPath */
  205. strcpy(++slash,linkPath);
  206. strcpy(linkPath,filePath); /* leave result in linkPath */
  207. }
  208. } /* if path is relative */
  209. /* printf("traced to: %s\n", linkPath); ** DBG */
  210. } /* if no error */
  211. } /* while result >= 0 */
  212. return False; /* RETURN */
  213. }
  214. /************************************************************************
  215. * Function: _DtHelpFileTraceToFile (pathName, accessMode, foundPath)
  216. *
  217. * Memory: pPathName must point to a malloc'd string. The string
  218. * may be freed by the function and pathName assigned a pointer
  219. * to a different string specifying a different path to the same file.
  220. * If a file is found, foundPath is set to the same pointer
  221. * as pathName, otherwise it is set to NULL.
  222. * Returns:
  223. * True: file found
  224. * False: file not found or error
  225. ***********************************************************************/
  226. Boolean
  227. _DtHelpFileTraceToFile (
  228. char * * pPathName,
  229. int accessMode,
  230. char * * pFoundPath)
  231. {
  232. struct stat status;
  233. char * pathName = *pPathName; /* avoid indirection */
  234. *pFoundPath = NULL;
  235. if ( pathName == NULL || pathName[0] == EOS )
  236. return False;
  237. /* if it's a file, trace its links */
  238. if ( access (pathName, accessMode) == 0
  239. && stat (pathName, &status) == 0
  240. && S_ISREG(status.st_mode) ) /* a file */
  241. {
  242. /* trace any links */
  243. if ( _DtHelpFileTraceLinks(pPathName) == False )
  244. {
  245. /* don't free pPathName here */
  246. return False; /* RETURN: no file */
  247. }
  248. pathName = *pPathName;
  249. /* find out if its an accessible file */
  250. if ( pathName != NULL
  251. && pathName[0] != EOS
  252. && access (pathName, accessMode) == 0
  253. && stat (pathName, &status) == 0
  254. && S_ISREG(status.st_mode)) /* a file */
  255. {
  256. /* point foundPath at the path */
  257. *pFoundPath = pathName;
  258. return True; /* RETURN: its a file */
  259. } /* if a valid path */
  260. } /* if a path */
  261. #if 0
  262. printf("Unknown file: %s\n", pathName);
  263. printf("Access: %d, stat: %d, IS_REG: %d, mode: %x\n",
  264. access (pathName, accessMode),
  265. stat (pathName, &status),
  266. S_ISREG(status.st_mode),
  267. status.st_mode);
  268. #endif
  269. /* its not a file */
  270. *pFoundPath = NULL;
  271. return False;
  272. }
  273. /******************************************************************************
  274. * Function: int _DtHelpFileGetSearchPaths ()
  275. *
  276. * Parameters:
  277. * paths: caller array size _DtHELP_FILE_NUM_PATHS in which
  278. * to store ptrs to the private path strings
  279. * searchHomeDir: boolean flag
  280. *
  281. * Memory:
  282. * the memory pointed to by the array is NOT owned by the
  283. * caller and should not be freed or modified
  284. *
  285. * Purpose: make the search paths available
  286. *
  287. *****************************************************************************/
  288. void _DtHelpFileGetSearchPaths(
  289. char * paths[],
  290. Boolean searchHomeDir)
  291. {
  292. static char * pathsSet[_DtHELP_FILE_NUM_PATHS];
  293. char tmpPath[MAXPATHLEN + 2];
  294. /* get user's home directory; is used in _DtHELP_FILE_USER_PATH as well */
  295. if (NULL == pathsSet[_DtHELP_FILE_HOME_PATH])
  296. {
  297. _DtHelpOSGetHomeDirName(tmpPath, sizeof(tmpPath));
  298. pathsSet[_DtHELP_FILE_HOME_PATH] = strdup(tmpPath);
  299. }
  300. if (searchHomeDir)
  301. paths[_DtHELP_FILE_HOME_PATH] = pathsSet[_DtHELP_FILE_HOME_PATH];
  302. else
  303. paths[_DtHELP_FILE_HOME_PATH] = NULL;
  304. /* generate the user path */
  305. if (NULL == pathsSet[_DtHELP_FILE_USER_PATH])
  306. pathsSet[_DtHELP_FILE_USER_PATH] = _DtHelpGetUserSearchPath();
  307. paths[_DtHELP_FILE_USER_PATH] = pathsSet[_DtHELP_FILE_USER_PATH];
  308. /* get the system search path */
  309. if (NULL == pathsSet[_DtHELP_FILE_SYS_PATH])
  310. pathsSet[_DtHELP_FILE_SYS_PATH] = _DtHelpGetSystemSearchPath();
  311. paths[_DtHELP_FILE_SYS_PATH] = pathsSet[_DtHELP_FILE_SYS_PATH];
  312. }
  313. /******************************************************************************
  314. * Function: char * _DtHelpFileLocate ()
  315. *
  316. * Parameters:
  317. * type: subdirectories to search (%T)
  318. * base: basename of the file
  319. * suffix: extension of the file to find (%S)
  320. * searchCurDir: boolean flag
  321. * accessMode: constant value from access(2)
  322. *
  323. * Returns: malloc'd path of the located file or NULL if none located
  324. *
  325. * errno Values:
  326. * EINVAL
  327. *
  328. * Purpose: Scans all paths of given type looking for a matching file
  329. * If file contains a valid absolute path, that is also
  330. * acceptable.
  331. *
  332. * FIX: merge _DtHelpFileLocate() and _DtHelpFileListScanPaths()
  333. *****************************************************************************/
  334. char * _DtHelpFileLocate (
  335. char * type,
  336. char * filespec,
  337. const char * suffixList[],
  338. Boolean searchCurDir,
  339. int accessMode)
  340. {
  341. char * loc;
  342. char * ptr;
  343. char * pathName;
  344. char * curPath;
  345. char * base;
  346. int curPathIndex;
  347. char * foundPath;
  348. const char empty = 0;
  349. const char * sufList[2];
  350. #define NUM_BUGS 1
  351. _DtSubstitutionRec bugFixSubs [NUM_BUGS];
  352. char * paths[_DtHELP_FILE_NUM_PATHS];
  353. char tmpPath[MAXPATHLEN + 2];
  354. const char * * pSuffix;
  355. char * eos = NULL;
  356. char * slash = NULL;
  357. /* test args */
  358. if (NULL == filespec) return NULL;
  359. /* init suffix list to empty if not specified */
  360. if (suffixList == NULL)
  361. {
  362. sufList[0] = &empty;
  363. sufList[1] = NULL;
  364. suffixList = sufList; /* override initial argument setting */
  365. }
  366. /*** first look for file as specified ***/
  367. /* if filespec begins with . or .. then stop after the cwd path */
  368. if ( ( MB_CUR_MAX == 1
  369. || mblen(filespec, MB_CUR_MAX) == 1) /* 1st char is 1 byte */
  370. && *filespec == '/') /* and its a / */
  371. {
  372. /* _DtHelpFileTraceToFile() needs a malloc'd string */
  373. /* 10: leaves room for add'l suffixes */
  374. pathName = MyMalloc(sizeof(char) * (strlen(filespec)+10));
  375. pathName = strcpy(pathName,filespec);
  376. _DtHelpCeCompressPathname(pathName); /* compress out relative paths */
  377. if ( _DtHelpFileTraceToFile(&pathName,accessMode,&foundPath) )
  378. return foundPath; /* RETURN */
  379. /* test all suffixes */
  380. eos = pathName + strlen(pathName);
  381. for ( pSuffix = suffixList; NULL != *pSuffix; pSuffix++ )
  382. {
  383. strcpy(eos,(char *) *pSuffix);
  384. /*recall: _DtHelpFileTraceToFile() requires pathName to be malloc'd*/
  385. if ( _DtHelpFileTraceToFile(&pathName,accessMode,&foundPath) )
  386. return foundPath; /* RETURN: found */
  387. } /* for all suffixes */
  388. MyFree(pathName);
  389. }
  390. /*** second, check if its relative to the current directory ***/
  391. /* if filespec begins with . or .. then stop after the cwd path */
  392. if ( searchCurDir
  393. || ( MB_CUR_MAX == 1
  394. || mblen(filespec, MB_CUR_MAX) == 1) /* 1st char is 1 byte */
  395. && *filespec == '.') /* and its a . */
  396. { /* we're looking at a cwd-relative path; ignore others */
  397. /*** this is monstrously inefficient--but it shouldn't get called often ***/
  398. /* get user's current working directory */
  399. /* JET - CERT VU#575804 */
  400. if (getcwd(tmpPath, MAXPATHLEN - 1) == NULL) return NULL; /* RETURN: error */
  401. /* make path end in a slash */
  402. eos = tmpPath + strlen(tmpPath);
  403. _DtHelpCeStrrchr(tmpPath,DirSlashStr,MB_CUR_MAX,&slash);
  404. if ( slash != (eos - 1) ) { *eos++ = DIR_SLASH; *eos = EOS; }
  405. /* make a malloc'd copy of the path with room to grow */
  406. slash = filespec + strlen(filespec);
  407. pathName = malloc(sizeof(char) *
  408. ((eos-tmpPath) + (slash-filespec) + 50) ); /* 50: arbitrary */
  409. if (NULL == pathName) return NULL; /* RETURN: error */
  410. strcpy(pathName,tmpPath);
  411. /* cat on the relative path */
  412. strcat(pathName,filespec);
  413. /* compress out any relative paths */
  414. _DtHelpCeCompressPathname(pathName);
  415. /* see if we find the file now */
  416. /* recall: _DtHelpFileTraceToFile() requires pathName to be malloc'd */
  417. if ( _DtHelpFileTraceToFile(&pathName,accessMode,&foundPath) )
  418. return foundPath; /* RETURN: found */
  419. /* test all suffixes */
  420. eos = pathName + strlen(pathName);
  421. for ( pSuffix = suffixList; NULL != *pSuffix; pSuffix++ )
  422. {
  423. strcpy(eos,(char *) *pSuffix);
  424. /* recall: _DtHelpFileTraceToFile() requires pathName to be malloc'd */
  425. if ( _DtHelpFileTraceToFile(&pathName,accessMode,&foundPath) )
  426. return foundPath; /* RETURN: found */
  427. } /* for all suffixes */
  428. MyFree(pathName);
  429. return NULL; /* RETURN: error */
  430. } /* filespec is a relative path or search cur dir */
  431. /*** third look in search path directories ***/
  432. /* get the search paths */
  433. _DtHelpFileGetSearchPaths( paths, False );
  434. /*** prep variables to pass through the path search loop ***/
  435. /* we're not looking at a cwd-relative path and
  436. we know that 'filespec' isn't a valid path to a volume
  437. (from _DtHelpFileTraceToFile), so just pick off the
  438. basename of the spec */
  439. base = filespec;
  440. if ( _DtHelpCeStrrchr(filespec,DirSlashStr,MB_CUR_MAX,&ptr) == 0 )
  441. base = ++ptr; /* begin past the slash */
  442. /* Have to support %H explicitly */
  443. bugFixSubs[0].match = 'H';
  444. bugFixSubs[0].substitution = base;
  445. /* get the LANG value */
  446. loc = _DtHelpGetLocale();
  447. if (NULL == loc || EOS == loc[0]) loc = strdup(LANG_C_STR);
  448. /* outer loop is once for each path */
  449. foundPath = NULL;
  450. for ( curPathIndex = 0;
  451. curPathIndex < _DtHELP_FILE_NUM_PATHS && NULL == foundPath;
  452. curPathIndex++ )
  453. {
  454. curPath = paths[curPathIndex];
  455. if (NULL == curPath) continue; /* continue */
  456. /* look for the file in that path */
  457. if (NULL != curPath) do
  458. {
  459. /* look for next subpath separator and insert and EOS if found */
  460. if (_DtHelpCeStrchr(curPath,PathSeparator,MB_CUR_MAX,&ptr)==0)
  461. *ptr = EOS;
  462. /* compress that path */
  463. /* JET - CERT VU#575804 */
  464. strncpy(tmpPath, curPath, MAXPATHLEN);
  465. _DtHelpCeCompressPathname(tmpPath);
  466. /* test all suffixes */
  467. for ( pSuffix = suffixList, foundPath = NULL;
  468. NULL == foundPath && NULL != *pSuffix;
  469. pSuffix++ )
  470. {
  471. /* generate the (directory) path using all the variables and fix
  472. it up to remove the unwanted stuff involving the filename */
  473. pathName = _DtHelpCeExpandPathname (curPath, base, type,
  474. (char *) *pSuffix, loc, bugFixSubs, NUM_BUGS);
  475. if ( _DtHelpFileTraceToFile(&pathName,accessMode,&foundPath)==False
  476. && NULL != pathName)
  477. free(pathName);
  478. } /* for all suffixes */
  479. /* restore the subpath separator and advance past it */
  480. if (ptr) *ptr++ = *PathSeparator;
  481. curPath = ptr;
  482. } while (curPath && *curPath && NULL == foundPath);
  483. /* do while more subpaths */
  484. } /* for all paths */
  485. MyFree(loc);
  486. return foundPath;
  487. }
  488. /******************************************************************************
  489. * Function: int _DtHelpCeCheckAndCacheDir (char *dir)
  490. *
  491. * Parameters:
  492. * dir Specifies the directory to test.
  493. *
  494. * Returns: 0 if the directory exists.
  495. * ENOTDIR if the directory is invalid.
  496. *
  497. * Purpose: To check a directory only once and remember the result.
  498. *
  499. *****************************************************************************/
  500. int
  501. _DtHelpCeCheckAndCacheDir (char *dir)
  502. {
  503. int result = ENOTDIR;
  504. _DtHelpCeDirStruct *curDir = CachedDirs;
  505. _DtHelpCeDirStruct *prevDir = NULL;
  506. struct stat buf;
  507. _DtHelpProcessLock();
  508. if (dir == NULL || *dir == '\0')
  509. return ENOTDIR;
  510. /*
  511. * search the cached directories
  512. */
  513. while (curDir != NULL && strcmp(curDir->dir_name, dir))
  514. {
  515. prevDir = curDir;
  516. curDir = curDir->next_dir;
  517. }
  518. /*
  519. * was the directory found in the cache? If so, return the type.
  520. */
  521. if (curDir != NULL)
  522. result = curDir->type;
  523. else
  524. {
  525. /*
  526. * new directory - malloc room for this entry.
  527. */
  528. result = ENOMEM;
  529. curDir = (_DtHelpCeDirStruct *) malloc(sizeof(_DtHelpCeDirStruct));
  530. if (curDir != NULL)
  531. {
  532. /*
  533. * initialize the new entry. I.E. type starts out ENOTDIR.
  534. */
  535. *curDir = DefCacheDir;
  536. curDir->dir_name = strdup(dir);
  537. if (curDir->dir_name != NULL)
  538. {
  539. /*
  540. * put this entry in the list
  541. */
  542. if (prevDir != NULL)
  543. prevDir->next_dir = curDir;
  544. else
  545. CachedDirs = curDir;
  546. /*
  547. * is this a directory?
  548. */
  549. if (access(dir, R_OK) == 0 &&
  550. stat(dir, &buf) == 0 && S_ISDIR(buf.st_mode))
  551. curDir->type = 0;
  552. /*
  553. * return the result of the tests.
  554. */
  555. result = curDir->type;
  556. }
  557. else
  558. free(curDir);
  559. }
  560. }
  561. /*
  562. * This should never happen, but just in case the directory
  563. * can't be cached, go ahead and check it anyway.
  564. */
  565. if (result == ENOMEM && access(dir, R_OK) == 0 &&
  566. stat(dir, &buf) == 0 && S_ISDIR(buf.st_mode))
  567. result = 0;
  568. _DtHelpProcessUnlock();
  569. return result;
  570. }
  571. #ifdef not_done
  572. /******************************************************************************
  573. * Function: _DtHelpCeDirStruct *_DtHelpCeGetCachedDirs (void)
  574. *
  575. * Parameters: none.
  576. *
  577. * Returns: A pointer to the cached directories.
  578. *
  579. * Purpose: To allow access to the cached directories.
  580. *
  581. *****************************************************************************/
  582. _DtHelpCeDirStruct *
  583. _DtHelpCeGetCachedDirs (void)
  584. {
  585. return CachedDirs;
  586. }
  587. #endif /* not_done */