123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692 |
- /*
- * CDE - Common Desktop Environment
- *
- * Copyright (c) 1993-2012, The Open Group. All rights reserved.
- *
- * These libraries and programs are free software; you can
- * redistribute them and/or modify them under the terms of the GNU
- * Lesser General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * These libraries and programs are distributed in the hope that
- * they will be useful, but WITHOUT ANY WARRANTY; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with these libraries and programs; if not, write
- * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
- * Floor, Boston, MA 02110-1301 USA
- */
- /* $TOG: FileListUtils.c /main/11 1999/10/14 13:17:49 mgreess $ */
- /************************************<+>*************************************
- ****************************************************************************
- **
- ** File: FileListUtils.c
- **
- ** Project: DtHelp library
- **
- ** Description: Locates and lists all files (volumes) accessible via the
- ** known paths
- **
- ** (c) Copyright 1993, 1994 Hewlett-Packard Company
- ** (c) Copyright 1993, 1994 International Business Machines Corp.
- ** (c) Copyright 1993, 1994 Sun Microsystems, Inc.
- ** (c) Copyright 1993, 1994 Novell, Inc.
- **
- **
- ****************************************************************************
- ************************************<+>*************************************/
- /*
- * system includes
- */
- #include <errno.h>
- #include <fcntl.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/stat.h>
- #include <sys/param.h> /* MAXPATHLEN */
- #include <limits.h>
- #define X_INCLUDE_DIRENT_H
- #define XOS_USE_XT_LOCKING
- #include <X11/Xos_r.h>
- #include <Dt/Help.h>
- /*
- * private includes
- */
- #include "bufioI.h" /* for AccessI.h */
- #include "Access.h"
- #include "AccessI.h"
- #include "StringFuncsI.h"
- #include "FileUtilsI.h"
- #include "FileListUtilsI.h"
- #include "HelposI.h"
- /******** constants *********/
- #define LANG_C_STR "C"
- #define EOS '\0'
- /******** types *********/
- /******** public global variables *********/
- /******** variables *********/
- static const char * PeriodStr = ".";
- static const char * DirSlashStr = "/";
- static const char * PathSeparator = ":";
- /******** functions *********/
- /*****************************************************************************
- * Function: GetExtension()
- *
- * locate the '.' of the filename extension, if present
- *
- *****************************************************************************/
- static char * GetExtension(
- char * filename)
- {
- char * ext;
- if (_DtHelpCeStrrchr(filename,PeriodStr,MB_CUR_MAX,&ext) == 0 ) return ext;
- else return ""; /* do NOT return a NULL*/
- }
- /*****************************************************************************
- * Function: SpecialStrcmp()
- *
- * Tests the args for NULL pointers. If both are NULL or if
- * both aren't NULL and are the same string, then returns 0.
- * If one arg is NULL and other isn't, or if strings are
- * different, returns -1 or +1.
- *
- *****************************************************************************/
- static int SpecialStrcmp(
- const char * str1,
- const char * str2)
- {
- if(NULL == str1)
- {
- if(NULL == str2) return 0; /* str1 == str2 */
- return -1; /* str1 < str2 */
- }
- if(NULL == str2) return 1; /* str1 > str2 */
- return(strcmp(str1,str2)); /* str1 ? str2 */
- }
- /*****************************************************************************
- * Function: FileInfoMatchesP()
- *
- * Compares the info of an existing file entry with test file info
- * and determines whether they match.
- * Returns: True or False
- *
- *****************************************************************************/
- static Boolean FileInfoMatchesP(
- _DtHelpFileEntry file1,
- _DtHelpFileEntry file2,
- int compareFlags)
- {
- /* no duplicate files allowed: compare doc stamps */
- /* note: currently am not comparing nameKey nor returning
- a placement (-1,+1) val from the compare. */
- if ( ( (compareFlags & _DtHELP_FILE_NAME) == 0
- || SpecialStrcmp(file1->fileName,file2->fileName) == 0)
- && ( (compareFlags & _DtHELP_FILE_TITLE) == 0
- || SpecialStrcmp(file1->fileTitle,file2->fileTitle) == 0)
- && ( (compareFlags & _DtHELP_FILE_IDSTR) == 0
- || SpecialStrcmp(file1->docId,file2->docId) == 0)
- && ( (compareFlags & _DtHELP_FILE_TIME) == 0
- || SpecialStrcmp(file1->timeStamp,file2->timeStamp) == 0) )
- return True;
- return False;
- }
- /*****************************************************************************
- * Function: _DtHelpFileIsSameP()
- *
- * Compares the info of two files and determines whether they match.
- * Returns: True or False
- *
- *****************************************************************************/
- Boolean _DtHelpFileIsSameP(
- char * fileName1,
- char * fileName2,
- _DtHelpFileInfoProc infoProc,
- int compareFlags,
- XtPointer pDisplayArea)
- {
- _DtHelpFileRec file1, file2;
- char * fileName;
- Boolean ret;
- /* get filenames without path */
- if (_DtHelpCeStrrchr(fileName1, DirSlashStr, MB_CUR_MAX, &fileName) == 0)
- fileName1 = fileName + 1;
- if (_DtHelpCeStrrchr(fileName2, DirSlashStr, MB_CUR_MAX, &fileName) == 0)
- fileName2 = fileName + 1;
- /* init the structs */
- memset(&file1,0,sizeof(file1));
- memset(&file2,0,sizeof(file2));
- file1.fileName = fileName1;
- file2.fileName = fileName2;
- /* get info on the files */
- (*infoProc)(pDisplayArea,fileName1,NULL,NULL,
- &file1.docId,&file1.timeStamp,&file1.nameKey,
- NULL,NULL);
- (*infoProc)(pDisplayArea,fileName2,NULL,NULL,
- &file2.docId,&file2.timeStamp,&file2.nameKey,
- NULL,NULL);
- ret = FileInfoMatchesP(&file1,&file2,compareFlags);
- XtFree(file1.docId);
- XtFree(file1.timeStamp);
- XtFree(file2.docId);
- XtFree(file2.timeStamp);
- return ret;
- }
- /*****************************************************************************
- * Function: ScanDirForFiles
- *
- * scan a directory looking for files with a matching suffix
- * returns number of files found in this directory
- *
- *****************************************************************************/
- static int ScanDirForFiles(
- char * dirpath,
- const char * suffixList[],
- _DtHelpFileList * in_out_list,
- XmFontList * io_fontList,
- Boolean * ret_mod,
- int foundFilesCnt,
- _DtHelpFileInfoProc infoProc,
- XtPointer pDisplayArea,
- int compareFlags,
- int sortFlags,
- _DtHelpFileScanProcCB scanProc,
- XtPointer clientData)
- {
- int count = 0;
- char fullName [MAXPATHLEN + 2];
- char *ptr;
- DIR *pDir;
- struct dirent *result;
- _Xreaddirparams dirEntryBuf;
- /* open the directory */
- pDir = opendir (dirpath);
- if (pDir == NULL) return 0; /* RETURN */
- /* build the pathname */
- snprintf(fullName, sizeof(fullName), "%s%s", dirpath, DirSlashStr);
- ptr = fullName + strlen (fullName);
- /*
- * Scan through the files looking for matching suffixes
- */
- while ((result = _XReaddir(pDir, dirEntryBuf)) != NULL) {
- const char * matchedSuffix;
- char * ext;
- /* Skip over any "." and ".." entries. */
- if ((strcmp(result->d_name, ".") == 0) ||
- (strcmp(result->d_name, "..") == 0))
- continue;
- /* get working values */
- ext = GetExtension (result->d_name);
- matchedSuffix = ""; /* default (==>no suffix to match) */
- /* try to match with a suffix, if specified */
- if (NULL != suffixList)
- {
- const char * * pSuffix;
- matchedSuffix = NULL;
- for (pSuffix = suffixList;
- NULL != *pSuffix && NULL == matchedSuffix;
- pSuffix++ )
- {
- if (strcmp(ext,*pSuffix) == 0)
- matchedSuffix = *pSuffix;
- }
- }
- /* and a match is found */
- if ( NULL != matchedSuffix )
- {
- Boolean mod;
- /* then generate the full path and add to the list */
- strcpy (ptr, result->d_name);
- if (_DtHelpFileListAddFile(in_out_list,io_fontList,&mod,
- fullName,ptr,infoProc,compareFlags,sortFlags,pDisplayArea))
- {
- count++;
- if (scanProc) (*scanProc)(count + foundFilesCnt,clientData);
- }
- *ret_mod |= mod; /* accumulate mods */
- }
- } /* while more entries */
- /* close the directory stream */
- closedir(pDir);
- return count;
- }
- /******************************************************************************
- * Function: _DtHelpFileListGetMatch ()
- *
- * Parameters:
- * fileListHead head of the list
- * fullFilePath fullFilePath to file to find
- * infoProc will deliver info on the file
- * pDisplayArea used to interpret vol info
- *
- * Returns: pointer to matching _DtHelpFileList entry
- * or NULL if none is found
- *
- * Purpose: Looks for a file list entry for the file
- * identified by fullFilePath.
- * The infoProc routine gets info about the file
- * to be matched, and uses that when comparing
- * with the file list. This allows more
- * than one file with the same name to be in
- * the list and be discriminated on the basis
- * of the info.
- *
- *****************************************************************************/
- _DtHelpFileList _DtHelpFileListGetMatch (
- _DtHelpFileList fileListHead,
- char * fullFilePath,
- _DtHelpFileInfoProc infoProc,
- int compareFlags,
- XtPointer pDisplayArea)
- {
- _DtHelpFileList next;
- _DtHelpFileRec file;
- /* zero the record */
- memset (&file,0,sizeof(file));
- if (NULL == fileListHead || NULL == fullFilePath) return NULL; /* RETURN */
- /* get filename without path */
- file.fileName = fullFilePath;
- if (_DtHelpCeStrrchr(fullFilePath,DirSlashStr,MB_CUR_MAX,&file.fileName) == 0)
- file.fileName++;
- /* if an info proc, use it, otherwise make due */
- if (infoProc)
- (*infoProc)(pDisplayArea,fullFilePath,
- NULL,NULL,&file.docId,&file.timeStamp,&file.nameKey,
- NULL,NULL);
- else
- file.nameKey = _DtHelpCeStrHashToKey(file.fileName);
- next = NULL;
- while ( (next = _DtHelpFileListGetNext(fileListHead, next)) != NULL )
- {
- if ( FileInfoMatchesP(next,&file,compareFlags) )
- break; /* next is the matching entry */
- }
- /* fileName is part of fullFilePath */
- XtFree(file.docId);
- XtFree(file.timeStamp);
- return next;
- }
- /******************************************************************************
- * Function: int _DtHelpFileListGetNext ()
- *
- * Parameters:
- * fileListHead head of the list
- * curFile current entry in the list
- *
- * Returns: pointer to next _DtHelpFileList entry
- * or NULL if end of list has been reached
- *
- * Purpose: Gets the next file in the list
- *
- *****************************************************************************/
- _DtHelpFileList _DtHelpFileListGetNext (
- _DtHelpFileList fileListHead,
- _DtHelpFileList curFile)
- {
- /* could do a sanity test on curFile here */
- if ( curFile ) return curFile->next;
- else return fileListHead;
- }
- /******************************************************************************
- * Function: int _DtHelpFileFreeEntry ()
- *
- * Parameters:
- *
- * Purpose: free the contents of an entry
- *
- *****************************************************************************/
- void _DtHelpFileFreeEntry (
- _DtHelpFileEntry entry)
- {
- if(NULL == entry) return;
- XmStringFree(entry->fileTitleXmStr);
- XtFree(entry->docId);
- XtFree(entry->timeStamp);
- XtFree(entry->fileTitle);
- XtFree((char *) entry->fileName);
- XtFree((char *) entry->fullFilePath);
- XtFree((char *) entry->clientData);
- XtFree((char *) entry);
- }
- /******************************************************************************
- * Function: int _DtHelpFileListAddFile ()
- *
- * Parameters:
- *
- * Returns: True if added a new entry
- * False if entry not added because already present
- * or an error occurred
- *
- *
- * errno Values:
- * 0 no error
- * ENOMEM memory allocation error
- *
- * Purpose: adds a file to the file list if its not already present
- *
- *****************************************************************************/
- Boolean _DtHelpFileListAddFile (
- _DtHelpFileList * in_out_list,
- XmFontList * io_fontList,
- Boolean * ret_mod,
- char * fullFilePath,
- char * fileName,
- _DtHelpFileInfoProc infoProc,
- int compareFlags,
- int sortFlags,
- XtPointer pDisplayArea)
- {
- _DtHelpFileList next;
- _DtHelpFileList prev;
- _DtHelpFileList newList;
- _DtHelpFileRec addFile;
- char * actualPath;
- char empty = 0;
- int nameKey = 0;
- typedef int (*_CEStrcollProc)(const char *,const char *);
- extern _CEStrcollProc _DtHelpCeGetStrcollProc();
- _CEStrcollProc strcollfn = _DtHelpCeGetStrcollProc();
- /* init the variable */
- memset(&addFile, 0, sizeof(addFile));
- /* if no full file path, go look for it */
- if (NULL == fullFilePath || fullFilePath[0] == EOS)
- return False; /* RETURN : incomplete file spec */
- /* trace any links; _DtHelpFileTraceLinks may chg actualPath ptr */
- actualPath = XtNewString(fullFilePath);
- if ( _DtHelpFileTraceLinks(&actualPath) == False )
- {
- XtFree(actualPath);
- return False; /* RETURN: invalid file */
- }
- fullFilePath = actualPath;
- /* if no filespec, get it */
- if (NULL == fileName)
- {
- fileName = fullFilePath;
- if(_DtHelpCeStrrchr(fullFilePath, DirSlashStr, MB_CUR_MAX,&fileName)==0)
- fileName++;
- }
- addFile.fileName = fileName;
- /* if an info proc, use it, otherwise make due */
- if (infoProc)
- {
- (*infoProc)(pDisplayArea,fullFilePath,
- &addFile.fileTitle,&addFile.fileTitleXmStr,
- &addFile.docId,&addFile.timeStamp,&addFile.nameKey,
- io_fontList,ret_mod);
- }
- else
- {
- nameKey = _DtHelpCeStrHashToKey(fileName);
- }
- /* look for prior existence and position */
- next = prev = NULL;
- while ( (next = _DtHelpFileListGetNext(*in_out_list, next)) != NULL )
- {
- if ( FileInfoMatchesP(next,&addFile,compareFlags) )
- {
- XtFree(addFile.docId);
- XtFree(addFile.timeStamp);
- XtFree(addFile.fileTitle);
- XmStringFree(addFile.fileTitleXmStr);
- XtFree(fullFilePath);
- return False; /* RETURN : repeat entry */
- }
- /* insert lexically according to title */
- /* use case insensitive NLS collating for ordering */
- if ( (sortFlags & _DtHELP_FILE_TITLE)
- && (*strcollfn) (addFile.fileTitle, next->fileTitle) <= 0 )
- break; /* BREAK: insert after prev, before next */
- /* FIX: add support for other sorting here */
- /* if ( (sortFlags & _DtHELP_FILE_DIR) */
- /* if ( (sortFlags & _DtHELP_FILE_TIME) */
- /* if ( (sortFlags & _DtHELP_FILE_IDSTR) */
- /* if ( (sortFlags & _DtHELP_FILE_LOCALE) */
- prev = next; /* save ref to prior entry */
- }
- /* if dup not found, fall thru, with prev valid */
- /* no matching path, so create, initialize, and append to list */
- newList = (_DtHelpFileList) XtCalloc(1, sizeof(_DtHelpFileRec));
- if (NULL == newList)
- {
- XtFree(addFile.docId);
- XtFree(addFile.timeStamp);
- XtFree(addFile.fileTitle);
- XmStringFree(addFile.fileTitleXmStr);
- XtFree(fullFilePath);
- return False; /* RETURN : error */
- }
- /* init the contents */
- newList->fullFilePath = fullFilePath; /* copy made earlier */
- newList->fileName = XtNewString(addFile.fileName);
- newList->nameKey = addFile.nameKey;
- newList->docId = (addFile.docId == &empty ? NULL : addFile.docId);
- newList->timeStamp = (addFile.timeStamp == &empty ? NULL : addFile.timeStamp);
- newList->fileTitle = addFile.fileTitle;
- newList->fileTitleXmStr = addFile.fileTitleXmStr;
- if (next) newList->next = next;
- if (prev) prev->next = newList;
- else *in_out_list = newList;
- return True; /* created new entry */
- }
- /******************************************************************************
- * Function: int _DtHelpFileListScanPaths ()
- *
- * Parameters:
- * type: subdirectories to search (%T)
- * suffix: extension of the files to find (%S)
- * searchHomeDir: boolean flag
- * in_out_list: manages list of files generated
- *
- * Returns: count of files added to the list or -1
- *
- * errno Values:
- * EINVAL
- *
- * Purpose: Scans all paths of given type looking for files with the suffixes
- *
- *****************************************************************************/
- int _DtHelpFileListScanPaths (
- _DtHelpFileList * in_out_list,
- XmFontList * io_fontList,
- Boolean * ret_mod,
- char * type,
- const char * suffixList[],
- Boolean searchHomeDir,
- _DtHelpFileInfoProc infoProc,
- XtPointer pDisplayArea,
- int sysPathCompareFlags,
- int otherPathCompareFlags,
- int sortFlags,
- _DtHelpFileScanProcCB scanProc,
- XtPointer clientData)
- {
- char *loc;
- char *ptr;
- char *pathName;
- struct stat status;
- char *curPath;
- int curPathIndex;
- int foundFilesCnt;
- int compareFlags;
- char * paths[_DtHELP_FILE_NUM_PATHS];
- char ** scannedPaths = NULL;
- int scannedPathsCnt = 0;
- /* get the search paths */
- _DtHelpFileGetSearchPaths( paths, searchHomeDir );
- /* get the locale */
- loc = _DtHelpGetLocale();
- if (NULL == loc || EOS == loc[0]) loc = strdup(LANG_C_STR);
- /* zero found */
- if (scanProc) (*scanProc)(0,clientData);
- /* outer loop is once for each path */
- foundFilesCnt = 0;
- for ( curPathIndex = 0;
- curPathIndex < _DtHELP_FILE_NUM_PATHS;
- curPathIndex++ )
- {
- curPath = paths[curPathIndex];
- if (NULL == curPath) continue;
- /* set the comparison flags */
- /* This enables implementation of different policies for
- listing files that are found, e.g. only list the first file
- of a given name found in the SYS search path, while listing
- same named files that have different times & ids in the
- USER PATH. */
- compareFlags = sysPathCompareFlags;
- if (_DtHELP_FILE_SYS_PATH != curPathIndex)
- compareFlags = otherPathCompareFlags;
-
- /* find the files in that path */
- do
- {
- char * slashptr;
- /* look for next subpath separator and insert and EOS if found */
- if (_DtHelpCeStrchr(curPath,PathSeparator,MB_CUR_MAX,&ptr)==0)
- *ptr = EOS;
- /* generate the (directory) path using all the variables
- and fix it up to remove the unwanted stuff involving the filename*/
- pathName = _DtHelpCeExpandPathname(curPath,
- NULL, type, NULL, loc, NULL, 0);
- if( pathName
- && _DtHelpCeStrrchr(pathName,DirSlashStr,MB_CUR_MAX,&slashptr) == 0)
- slashptr[0] = EOS;
- /* restore the subpath separator and advance past it */
- if (ptr) *ptr++ = *PathSeparator;
- /* if its a directory; scan for matching files in it */
- if ( pathName != NULL
- && *pathName != EOS
- && access (pathName, R_OK | X_OK) == 0
- && stat (pathName, &status) == 0
- && S_ISDIR(status.st_mode)) /* a dir */
- {
- int i;
- /* check that we haven't already scanned it */
- for ( i=0; i<scannedPathsCnt; i++ )
- if (strcmp(scannedPaths[i],pathName) == 0) break;
- /* scan it if haven't already */
- if ( i == scannedPathsCnt )
- {
- foundFilesCnt += ScanDirForFiles(
- pathName,suffixList,
- in_out_list,io_fontList,ret_mod,
- foundFilesCnt,infoProc,pDisplayArea,
- compareFlags,sortFlags,scanProc,clientData);
- /* add to list of scanned */
- scannedPaths = (char **) XtRealloc((char *)scannedPaths,
- (scannedPathsCnt+1) * sizeof(char *) );
- scannedPaths[scannedPathsCnt++] = strdup(pathName);
- } /* if haven' scanned already */
- } /* if a directory */
- #if 0
- else
- {
- printf("Unknown dir: %s\n", pathName);
- printf("Access: %d, stat: %d, IS_DIR: %d, mode: %x\n",
- access (pathName, R_OK | X_OK),
- stat (pathName, &status),
- S_ISDIR(status.st_mode),
- status.st_mode);
- }
- #endif
- if (pathName) free (pathName);
- curPath = ptr;
- } while (curPath && *curPath); /* while more subpaths */
- } /* for all paths */
- /* free all scanned paths */
- while ( scannedPathsCnt-- > 0 ) XtFree(scannedPaths[scannedPathsCnt]);
- XtFree((char *)scannedPaths);
- XtFree(loc);
- return foundFilesCnt;
- }
|