FileListUtils.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  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: FileListUtils.c /main/11 1999/10/14 13:17:49 mgreess $ */
  24. /************************************<+>*************************************
  25. ****************************************************************************
  26. **
  27. ** File: FileListUtils.c
  28. **
  29. ** Project: DtHelp library
  30. **
  31. ** Description: Locates and lists all files (volumes) accessible via the
  32. ** known paths
  33. **
  34. ** (c) Copyright 1993, 1994 Hewlett-Packard Company
  35. ** (c) Copyright 1993, 1994 International Business Machines Corp.
  36. ** (c) Copyright 1993, 1994 Sun Microsystems, Inc.
  37. ** (c) Copyright 1993, 1994 Novell, Inc.
  38. **
  39. **
  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 <sys/stat.h>
  52. #include <sys/param.h> /* MAXPATHLEN */
  53. #include <limits.h>
  54. #define X_INCLUDE_DIRENT_H
  55. #define XOS_USE_XT_LOCKING
  56. #include <X11/Xos_r.h>
  57. #include <Dt/Help.h>
  58. /*
  59. * private includes
  60. */
  61. #include "bufioI.h" /* for AccessI.h */
  62. #include "Access.h"
  63. #include "AccessI.h"
  64. #include "StringFuncsI.h"
  65. #include "FileUtilsI.h"
  66. #include "FileListUtilsI.h"
  67. #include "HelposI.h"
  68. /******** constants *********/
  69. #define LANG_C_STR "C"
  70. #define EOS '\0'
  71. /******** types *********/
  72. /******** public global variables *********/
  73. /******** variables *********/
  74. static const char * PeriodStr = ".";
  75. static const char * DirSlashStr = "/";
  76. static const char * PathSeparator = ":";
  77. /******** functions *********/
  78. /*****************************************************************************
  79. * Function: GetExtension()
  80. *
  81. * locate the '.' of the filename extension, if present
  82. *
  83. *****************************************************************************/
  84. static char * GetExtension(
  85. char * filename)
  86. {
  87. char * ext;
  88. if (_DtHelpCeStrrchr(filename,PeriodStr,MB_CUR_MAX,&ext) == 0 ) return ext;
  89. else return ""; /* do NOT return a NULL*/
  90. }
  91. /*****************************************************************************
  92. * Function: SpecialStrcmp()
  93. *
  94. * Tests the args for NULL pointers. If both are NULL or if
  95. * both aren't NULL and are the same string, then returns 0.
  96. * If one arg is NULL and other isn't, or if strings are
  97. * different, returns -1 or +1.
  98. *
  99. *****************************************************************************/
  100. static int SpecialStrcmp(
  101. const char * str1,
  102. const char * str2)
  103. {
  104. if(NULL == str1)
  105. {
  106. if(NULL == str2) return 0; /* str1 == str2 */
  107. return -1; /* str1 < str2 */
  108. }
  109. if(NULL == str2) return 1; /* str1 > str2 */
  110. return(strcmp(str1,str2)); /* str1 ? str2 */
  111. }
  112. /*****************************************************************************
  113. * Function: FileInfoMatchesP()
  114. *
  115. * Compares the info of an existing file entry with test file info
  116. * and determines whether they match.
  117. * Returns: True or False
  118. *
  119. *****************************************************************************/
  120. static Boolean FileInfoMatchesP(
  121. _DtHelpFileEntry file1,
  122. _DtHelpFileEntry file2,
  123. int compareFlags)
  124. {
  125. /* no duplicate files allowed: compare doc stamps */
  126. /* note: currently am not comparing nameKey nor returning
  127. a placement (-1,+1) val from the compare. */
  128. if ( ( (compareFlags & _DtHELP_FILE_NAME) == 0
  129. || SpecialStrcmp(file1->fileName,file2->fileName) == 0)
  130. && ( (compareFlags & _DtHELP_FILE_TITLE) == 0
  131. || SpecialStrcmp(file1->fileTitle,file2->fileTitle) == 0)
  132. && ( (compareFlags & _DtHELP_FILE_IDSTR) == 0
  133. || SpecialStrcmp(file1->docId,file2->docId) == 0)
  134. && ( (compareFlags & _DtHELP_FILE_TIME) == 0
  135. || SpecialStrcmp(file1->timeStamp,file2->timeStamp) == 0) )
  136. return True;
  137. return False;
  138. }
  139. /*****************************************************************************
  140. * Function: _DtHelpFileIsSameP()
  141. *
  142. * Compares the info of two files and determines whether they match.
  143. * Returns: True or False
  144. *
  145. *****************************************************************************/
  146. Boolean _DtHelpFileIsSameP(
  147. char * fileName1,
  148. char * fileName2,
  149. _DtHelpFileInfoProc infoProc,
  150. int compareFlags,
  151. XtPointer pDisplayArea)
  152. {
  153. _DtHelpFileRec file1, file2;
  154. char * fileName;
  155. Boolean ret;
  156. /* get filenames without path */
  157. if (_DtHelpCeStrrchr(fileName1, DirSlashStr, MB_CUR_MAX, &fileName) == 0)
  158. fileName1 = fileName + 1;
  159. if (_DtHelpCeStrrchr(fileName2, DirSlashStr, MB_CUR_MAX, &fileName) == 0)
  160. fileName2 = fileName + 1;
  161. /* init the structs */
  162. memset(&file1,0,sizeof(file1));
  163. memset(&file2,0,sizeof(file2));
  164. file1.fileName = fileName1;
  165. file2.fileName = fileName2;
  166. /* get info on the files */
  167. (*infoProc)(pDisplayArea,fileName1,NULL,NULL,
  168. &file1.docId,&file1.timeStamp,&file1.nameKey,
  169. NULL,NULL);
  170. (*infoProc)(pDisplayArea,fileName2,NULL,NULL,
  171. &file2.docId,&file2.timeStamp,&file2.nameKey,
  172. NULL,NULL);
  173. ret = FileInfoMatchesP(&file1,&file2,compareFlags);
  174. XtFree(file1.docId);
  175. XtFree(file1.timeStamp);
  176. XtFree(file2.docId);
  177. XtFree(file2.timeStamp);
  178. return ret;
  179. }
  180. /*****************************************************************************
  181. * Function: ScanDirForFiles
  182. *
  183. * scan a directory looking for files with a matching suffix
  184. * returns number of files found in this directory
  185. *
  186. *****************************************************************************/
  187. static int ScanDirForFiles(
  188. char * dirpath,
  189. const char * suffixList[],
  190. _DtHelpFileList * in_out_list,
  191. XmFontList * io_fontList,
  192. Boolean * ret_mod,
  193. int foundFilesCnt,
  194. _DtHelpFileInfoProc infoProc,
  195. XtPointer pDisplayArea,
  196. int compareFlags,
  197. int sortFlags,
  198. _DtHelpFileScanProcCB scanProc,
  199. XtPointer clientData)
  200. {
  201. int count = 0;
  202. char fullName [MAXPATHLEN + 2];
  203. char *ptr;
  204. DIR *pDir;
  205. struct dirent *result;
  206. _Xreaddirparams dirEntryBuf;
  207. /* open the directory */
  208. pDir = opendir (dirpath);
  209. if (pDir == NULL) return 0; /* RETURN */
  210. /* build the pathname */
  211. snprintf(fullName, sizeof(fullName), "%s%s", dirpath, DirSlashStr);
  212. ptr = fullName + strlen (fullName);
  213. /*
  214. * Scan through the files looking for matching suffixes
  215. */
  216. while ((result = _XReaddir(pDir, dirEntryBuf)) != NULL) {
  217. const char * matchedSuffix;
  218. char * ext;
  219. /* Skip over any "." and ".." entries. */
  220. if ((strcmp(result->d_name, ".") == 0) ||
  221. (strcmp(result->d_name, "..") == 0))
  222. continue;
  223. /* get working values */
  224. ext = GetExtension (result->d_name);
  225. matchedSuffix = ""; /* default (==>no suffix to match) */
  226. /* try to match with a suffix, if specified */
  227. if (NULL != suffixList)
  228. {
  229. const char * * pSuffix;
  230. matchedSuffix = NULL;
  231. for (pSuffix = suffixList;
  232. NULL != *pSuffix && NULL == matchedSuffix;
  233. pSuffix++ )
  234. {
  235. if (strcmp(ext,*pSuffix) == 0)
  236. matchedSuffix = *pSuffix;
  237. }
  238. }
  239. /* and a match is found */
  240. if ( NULL != matchedSuffix )
  241. {
  242. Boolean mod;
  243. /* then generate the full path and add to the list */
  244. strcpy (ptr, result->d_name);
  245. if (_DtHelpFileListAddFile(in_out_list,io_fontList,&mod,
  246. fullName,ptr,infoProc,compareFlags,sortFlags,pDisplayArea))
  247. {
  248. count++;
  249. if (scanProc) (*scanProc)(count + foundFilesCnt,clientData);
  250. }
  251. *ret_mod |= mod; /* accumulate mods */
  252. }
  253. } /* while more entries */
  254. /* close the directory stream */
  255. closedir(pDir);
  256. return count;
  257. }
  258. /******************************************************************************
  259. * Function: _DtHelpFileListGetMatch ()
  260. *
  261. * Parameters:
  262. * fileListHead head of the list
  263. * fullFilePath fullFilePath to file to find
  264. * infoProc will deliver info on the file
  265. * pDisplayArea used to interpret vol info
  266. *
  267. * Returns: pointer to matching _DtHelpFileList entry
  268. * or NULL if none is found
  269. *
  270. * Purpose: Looks for a file list entry for the file
  271. * identified by fullFilePath.
  272. * The infoProc routine gets info about the file
  273. * to be matched, and uses that when comparing
  274. * with the file list. This allows more
  275. * than one file with the same name to be in
  276. * the list and be discriminated on the basis
  277. * of the info.
  278. *
  279. *****************************************************************************/
  280. _DtHelpFileList _DtHelpFileListGetMatch (
  281. _DtHelpFileList fileListHead,
  282. char * fullFilePath,
  283. _DtHelpFileInfoProc infoProc,
  284. int compareFlags,
  285. XtPointer pDisplayArea)
  286. {
  287. _DtHelpFileList next;
  288. _DtHelpFileRec file;
  289. /* zero the record */
  290. memset (&file,0,sizeof(file));
  291. if (NULL == fileListHead || NULL == fullFilePath) return NULL; /* RETURN */
  292. /* get filename without path */
  293. file.fileName = fullFilePath;
  294. if (_DtHelpCeStrrchr(fullFilePath,DirSlashStr,MB_CUR_MAX,&file.fileName) == 0)
  295. file.fileName++;
  296. /* if an info proc, use it, otherwise make due */
  297. if (infoProc)
  298. (*infoProc)(pDisplayArea,fullFilePath,
  299. NULL,NULL,&file.docId,&file.timeStamp,&file.nameKey,
  300. NULL,NULL);
  301. else
  302. file.nameKey = _DtHelpCeStrHashToKey(file.fileName);
  303. next = NULL;
  304. while ( (next = _DtHelpFileListGetNext(fileListHead, next)) != NULL )
  305. {
  306. if ( FileInfoMatchesP(next,&file,compareFlags) )
  307. break; /* next is the matching entry */
  308. }
  309. /* fileName is part of fullFilePath */
  310. XtFree(file.docId);
  311. XtFree(file.timeStamp);
  312. return next;
  313. }
  314. /******************************************************************************
  315. * Function: int _DtHelpFileListGetNext ()
  316. *
  317. * Parameters:
  318. * fileListHead head of the list
  319. * curFile current entry in the list
  320. *
  321. * Returns: pointer to next _DtHelpFileList entry
  322. * or NULL if end of list has been reached
  323. *
  324. * Purpose: Gets the next file in the list
  325. *
  326. *****************************************************************************/
  327. _DtHelpFileList _DtHelpFileListGetNext (
  328. _DtHelpFileList fileListHead,
  329. _DtHelpFileList curFile)
  330. {
  331. /* could do a sanity test on curFile here */
  332. if ( curFile ) return curFile->next;
  333. else return fileListHead;
  334. }
  335. /******************************************************************************
  336. * Function: int _DtHelpFileFreeEntry ()
  337. *
  338. * Parameters:
  339. *
  340. * Purpose: free the contents of an entry
  341. *
  342. *****************************************************************************/
  343. void _DtHelpFileFreeEntry (
  344. _DtHelpFileEntry entry)
  345. {
  346. if(NULL == entry) return;
  347. XmStringFree(entry->fileTitleXmStr);
  348. XtFree(entry->docId);
  349. XtFree(entry->timeStamp);
  350. XtFree(entry->fileTitle);
  351. XtFree((char *) entry->fileName);
  352. XtFree((char *) entry->fullFilePath);
  353. XtFree((char *) entry->clientData);
  354. XtFree((char *) entry);
  355. }
  356. /******************************************************************************
  357. * Function: int _DtHelpFileListAddFile ()
  358. *
  359. * Parameters:
  360. *
  361. * Returns: True if added a new entry
  362. * False if entry not added because already present
  363. * or an error occurred
  364. *
  365. *
  366. * errno Values:
  367. * 0 no error
  368. * ENOMEM memory allocation error
  369. *
  370. * Purpose: adds a file to the file list if its not already present
  371. *
  372. *****************************************************************************/
  373. Boolean _DtHelpFileListAddFile (
  374. _DtHelpFileList * in_out_list,
  375. XmFontList * io_fontList,
  376. Boolean * ret_mod,
  377. char * fullFilePath,
  378. char * fileName,
  379. _DtHelpFileInfoProc infoProc,
  380. int compareFlags,
  381. int sortFlags,
  382. XtPointer pDisplayArea)
  383. {
  384. _DtHelpFileList next;
  385. _DtHelpFileList prev;
  386. _DtHelpFileList newList;
  387. _DtHelpFileRec addFile;
  388. char * actualPath;
  389. char empty = 0;
  390. int nameKey = 0;
  391. typedef int (*_CEStrcollProc)(const char *,const char *);
  392. extern _CEStrcollProc _DtHelpCeGetStrcollProc();
  393. _CEStrcollProc strcollfn = _DtHelpCeGetStrcollProc();
  394. /* init the variable */
  395. memset(&addFile, 0, sizeof(addFile));
  396. /* if no full file path, go look for it */
  397. if (NULL == fullFilePath || fullFilePath[0] == EOS)
  398. return False; /* RETURN : incomplete file spec */
  399. /* trace any links; _DtHelpFileTraceLinks may chg actualPath ptr */
  400. actualPath = XtNewString(fullFilePath);
  401. if ( _DtHelpFileTraceLinks(&actualPath) == False )
  402. {
  403. XtFree(actualPath);
  404. return False; /* RETURN: invalid file */
  405. }
  406. fullFilePath = actualPath;
  407. /* if no filespec, get it */
  408. if (NULL == fileName)
  409. {
  410. fileName = fullFilePath;
  411. if(_DtHelpCeStrrchr(fullFilePath, DirSlashStr, MB_CUR_MAX,&fileName)==0)
  412. fileName++;
  413. }
  414. addFile.fileName = fileName;
  415. /* if an info proc, use it, otherwise make due */
  416. if (infoProc)
  417. {
  418. (*infoProc)(pDisplayArea,fullFilePath,
  419. &addFile.fileTitle,&addFile.fileTitleXmStr,
  420. &addFile.docId,&addFile.timeStamp,&addFile.nameKey,
  421. io_fontList,ret_mod);
  422. }
  423. else
  424. {
  425. nameKey = _DtHelpCeStrHashToKey(fileName);
  426. }
  427. /* look for prior existence and position */
  428. next = prev = NULL;
  429. while ( (next = _DtHelpFileListGetNext(*in_out_list, next)) != NULL )
  430. {
  431. if ( FileInfoMatchesP(next,&addFile,compareFlags) )
  432. {
  433. XtFree(addFile.docId);
  434. XtFree(addFile.timeStamp);
  435. XtFree(addFile.fileTitle);
  436. XmStringFree(addFile.fileTitleXmStr);
  437. XtFree(fullFilePath);
  438. return False; /* RETURN : repeat entry */
  439. }
  440. /* insert lexically according to title */
  441. /* use case insensitive NLS collating for ordering */
  442. if ( (sortFlags & _DtHELP_FILE_TITLE)
  443. && (*strcollfn) (addFile.fileTitle, next->fileTitle) <= 0 )
  444. break; /* BREAK: insert after prev, before next */
  445. /* FIX: add support for other sorting here */
  446. /* if ( (sortFlags & _DtHELP_FILE_DIR) */
  447. /* if ( (sortFlags & _DtHELP_FILE_TIME) */
  448. /* if ( (sortFlags & _DtHELP_FILE_IDSTR) */
  449. /* if ( (sortFlags & _DtHELP_FILE_LOCALE) */
  450. prev = next; /* save ref to prior entry */
  451. }
  452. /* if dup not found, fall thru, with prev valid */
  453. /* no matching path, so create, initialize, and append to list */
  454. newList = (_DtHelpFileList) XtCalloc(1, sizeof(_DtHelpFileRec));
  455. if (NULL == newList)
  456. {
  457. XtFree(addFile.docId);
  458. XtFree(addFile.timeStamp);
  459. XtFree(addFile.fileTitle);
  460. XmStringFree(addFile.fileTitleXmStr);
  461. XtFree(fullFilePath);
  462. return False; /* RETURN : error */
  463. }
  464. /* init the contents */
  465. newList->fullFilePath = fullFilePath; /* copy made earlier */
  466. newList->fileName = XtNewString(addFile.fileName);
  467. newList->nameKey = addFile.nameKey;
  468. newList->docId = (addFile.docId == &empty ? NULL : addFile.docId);
  469. newList->timeStamp = (addFile.timeStamp == &empty ? NULL : addFile.timeStamp);
  470. newList->fileTitle = addFile.fileTitle;
  471. newList->fileTitleXmStr = addFile.fileTitleXmStr;
  472. if (next) newList->next = next;
  473. if (prev) prev->next = newList;
  474. else *in_out_list = newList;
  475. return True; /* created new entry */
  476. }
  477. /******************************************************************************
  478. * Function: int _DtHelpFileListScanPaths ()
  479. *
  480. * Parameters:
  481. * type: subdirectories to search (%T)
  482. * suffix: extension of the files to find (%S)
  483. * searchHomeDir: boolean flag
  484. * in_out_list: manages list of files generated
  485. *
  486. * Returns: count of files added to the list or -1
  487. *
  488. * errno Values:
  489. * EINVAL
  490. *
  491. * Purpose: Scans all paths of given type looking for files with the suffixes
  492. *
  493. *****************************************************************************/
  494. int _DtHelpFileListScanPaths (
  495. _DtHelpFileList * in_out_list,
  496. XmFontList * io_fontList,
  497. Boolean * ret_mod,
  498. char * type,
  499. const char * suffixList[],
  500. Boolean searchHomeDir,
  501. _DtHelpFileInfoProc infoProc,
  502. XtPointer pDisplayArea,
  503. int sysPathCompareFlags,
  504. int otherPathCompareFlags,
  505. int sortFlags,
  506. _DtHelpFileScanProcCB scanProc,
  507. XtPointer clientData)
  508. {
  509. char *loc;
  510. char *ptr;
  511. char *pathName;
  512. struct stat status;
  513. char *curPath;
  514. int curPathIndex;
  515. int foundFilesCnt;
  516. int compareFlags;
  517. char * paths[_DtHELP_FILE_NUM_PATHS];
  518. char ** scannedPaths = NULL;
  519. int scannedPathsCnt = 0;
  520. /* get the search paths */
  521. _DtHelpFileGetSearchPaths( paths, searchHomeDir );
  522. /* get the locale */
  523. loc = _DtHelpGetLocale();
  524. if (NULL == loc || EOS == loc[0]) loc = strdup(LANG_C_STR);
  525. /* zero found */
  526. if (scanProc) (*scanProc)(0,clientData);
  527. /* outer loop is once for each path */
  528. foundFilesCnt = 0;
  529. for ( curPathIndex = 0;
  530. curPathIndex < _DtHELP_FILE_NUM_PATHS;
  531. curPathIndex++ )
  532. {
  533. curPath = paths[curPathIndex];
  534. if (NULL == curPath) continue;
  535. /* set the comparison flags */
  536. /* This enables implementation of different policies for
  537. listing files that are found, e.g. only list the first file
  538. of a given name found in the SYS search path, while listing
  539. same named files that have different times & ids in the
  540. USER PATH. */
  541. compareFlags = sysPathCompareFlags;
  542. if (_DtHELP_FILE_SYS_PATH != curPathIndex)
  543. compareFlags = otherPathCompareFlags;
  544. /* find the files in that path */
  545. do
  546. {
  547. char * slashptr;
  548. /* look for next subpath separator and insert and EOS if found */
  549. if (_DtHelpCeStrchr(curPath,PathSeparator,MB_CUR_MAX,&ptr)==0)
  550. *ptr = EOS;
  551. /* generate the (directory) path using all the variables
  552. and fix it up to remove the unwanted stuff involving the filename*/
  553. pathName = _DtHelpCeExpandPathname(curPath,
  554. NULL, type, NULL, loc, NULL, 0);
  555. if( pathName
  556. && _DtHelpCeStrrchr(pathName,DirSlashStr,MB_CUR_MAX,&slashptr) == 0)
  557. slashptr[0] = EOS;
  558. /* restore the subpath separator and advance past it */
  559. if (ptr) *ptr++ = *PathSeparator;
  560. /* if its a directory; scan for matching files in it */
  561. if ( pathName != NULL
  562. && *pathName != EOS
  563. && access (pathName, R_OK | X_OK) == 0
  564. && stat (pathName, &status) == 0
  565. && S_ISDIR(status.st_mode)) /* a dir */
  566. {
  567. int i;
  568. /* check that we haven't already scanned it */
  569. for ( i=0; i<scannedPathsCnt; i++ )
  570. if (strcmp(scannedPaths[i],pathName) == 0) break;
  571. /* scan it if haven't already */
  572. if ( i == scannedPathsCnt )
  573. {
  574. foundFilesCnt += ScanDirForFiles(
  575. pathName,suffixList,
  576. in_out_list,io_fontList,ret_mod,
  577. foundFilesCnt,infoProc,pDisplayArea,
  578. compareFlags,sortFlags,scanProc,clientData);
  579. /* add to list of scanned */
  580. scannedPaths = (char **) XtRealloc((char *)scannedPaths,
  581. (scannedPathsCnt+1) * sizeof(char *) );
  582. scannedPaths[scannedPathsCnt++] = strdup(pathName);
  583. } /* if haven' scanned already */
  584. } /* if a directory */
  585. #if 0
  586. else
  587. {
  588. printf("Unknown dir: %s\n", pathName);
  589. printf("Access: %d, stat: %d, IS_DIR: %d, mode: %x\n",
  590. access (pathName, R_OK | X_OK),
  591. stat (pathName, &status),
  592. S_ISDIR(status.st_mode),
  593. status.st_mode);
  594. }
  595. #endif
  596. if (pathName) free (pathName);
  597. curPath = ptr;
  598. } while (curPath && *curPath); /* while more subpaths */
  599. } /* for all paths */
  600. /* free all scanned paths */
  601. while ( scannedPathsCnt-- > 0 ) XtFree(scannedPaths[scannedPathsCnt]);
  602. XtFree((char *)scannedPaths);
  603. XtFree(loc);
  604. return foundFilesCnt;
  605. }