2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: Access.c /main/11 1996/11/01 10:09:29 drk $ */
24 /************************************<+>*************************************
25 ****************************************************************************
29 ** Project: Run Time Project File Access
31 ** Description: This body of code handles the access routines for the
35 ** (c) Copyright 1987-1994, 1996 Hewlett-Packard Company
36 ** (c) Copyright 1993, 1994, 1996 International Business Machines Corp.
37 ** (c) Copyright 1993, 1994, 1996 Sun Microsystems, Inc.
38 ** (c) Copyright 1993, 1994, 1996 Novell, Inc.
39 ** (c) Copyright 1996 Digital Equipment Corporation.
40 ** (c) Copyright 1996 FUJITSU LIMITED.
41 ** (c) Copyright 1996 Hitachi.
44 ****************************************************************************
45 ************************************<+>*************************************/
57 #include <sys/param.h>
61 #include <X11/Xresource.h>
68 * Canvas Engine includes
71 #include "CanvasSegP.h"
76 #include "CanvasError.h"
79 #include "FontAttrI.h"
82 #include "AccessSDLP.h"
83 #include "AccessSDLI.h"
84 #include "AccessCCDFI.h"
85 #include "FormatUtilI.h"
88 #include "FormatSDLI.h"
90 #include "CCDFUtilI.h"
91 #include "StringFuncsI.h"
93 #include "Lock.h" /* Process and App Lock macros */
98 /******** Private Defines ********/
99 #define LIST_INCREMENT 10
100 #define BUFF_SIZE 256
101 /******** End Private Defines ********/
103 /******** Private Function Declarations ********/
104 static int GetVolumeKeywords (
106 char ***retKeywords);
107 static int VolumeLoad (
109 _DtHelpVolume *retVol);
110 static int VolumeUnload (
112 /******** End Private Function Declarations ********/
114 /******** Private Macro Declarations ********/
115 /******** End Private Macro Declarations ********/
117 /******************************************************************************
119 * Private variables used within this file.
121 *******************************************************************************/
122 static _DtHelpVolume volChain = NULL; /* Pointer to the head of the chain */
123 /* of all the open volumes. */
124 static const char *Slash = "/";
125 static const char *Period = ".";
127 /******************************************************************************
129 ******************************************************************************/
130 /******************************************************************************
131 * Function: CheckVolList (_DtHelpVolume vol, _DtHelpVolume *ret_prev)
133 * Parameters: vol Specifies the volume to search for.
134 * ret_prev Returns the volume whose nextVol element
135 * points to 'vol' if non NULL.
137 * Returns: 0 if successful, -1 if failure.
141 * Purpose: To check for the existance of a volume.
143 ******************************************************************************/
147 _DtHelpVolume *ret_prev )
150 _DtHelpVolume prevVol = NULL;
152 _DtHelpProcessLock();
155 while (myVol != NULL && myVol != vol)
158 myVol = myVol->nextVol;
166 _DtHelpProcessUnlock();
170 _DtHelpProcessUnlock();
174 /******************************************************************************
175 * Function: int VolumeLoad (char *volFile, _DtHelpVolume *retVol);
177 * Parameters: volFile Specifies the name of the Help Volume file
180 * retVol Returns the handle to the loaded volume.
182 * Return Value: Returns 0 if successful,
183 * -1 if an error occurred.
185 * errno Values: CEErrorMalloc
186 * CEErrorIllegalDatabaseFile
188 * Purpose: This function must be called to load a Help Volume file
189 * before any of the information in the volume can be
192 ******************************************************************************/
196 _DtHelpVolume *retVol)
198 /* Allocate the volume structure and initialize it. */
199 *retVol = (_DtHelpVolume) malloc (sizeof (struct _DtHelpVolumeRec));
202 (*retVol)->sdl_flag = False;
203 (*retVol)->volFile = volFile;
204 (*retVol)->keywords = NULL;
205 (*retVol)->keywordTopics = NULL;
206 (*retVol)->openCount = 1;
207 (*retVol)->nextVol = NULL;
208 (*retVol)->vols.ccdf_vol = NULL;
210 if (_DtHelpCeOpenSdlVolume ((*retVol)) == 0)
212 else if (_DtHelpCeOpenCcdfVolume(*retVol) == 0)
216 * Set the global error
218 errno = CEErrorIllegalDatabaseFile;
221 * error on loading the database.
223 free ((char *) ((*retVol)->volFile));
224 free ((char *) (*retVol));
228 errno = CEErrorMalloc;
232 } /* End VolumeLoad */
234 /*******************************************************************************
235 * Function: int VolumeUnload (_DtHelpVolume vol);
237 * Parameters: vol Specifies the loaded volume.
239 * Return Value: 0 if successful, -1 if a failure occurs
243 * Purpose: When the volume is no longer needed, it should be unloaded
244 * with this call. Unloading it frees the memory (which means
245 * any handles on the volume become invalid.)
247 ******************************************************************************/
257 if (vol->sdl_flag == True)
258 _DtHelpCeCloseSdlVolume((_DtHelpVolumeHdl) vol);
260 _DtHelpCeCloseCcdfVolume(vol);
262 if (vol->volFile != NULL)
265 if (vol->keywords != NULL)
266 _DtHelpCeFreeStringArray (vol->keywords);
268 if (vol->keywordTopics != NULL)
270 for (topicList = vol->keywordTopics;
271 *topicList != NULL; topicList++)
272 _DtHelpCeFreeStringArray (*topicList);
274 free (vol->keywordTopics);
283 /*******************************************************************************
284 * Function: int RereadVolume (_DtHelpVolume vol);
286 * Parameters: vol Specifies the loaded volume.
288 * Return Value: 0 if successful, -1 if a failure occurs
292 * Purpose: When the volume is no longer needed, it should be unloaded
293 * with this call. Unloading it frees the memory (which means
294 * any handles on the volume become invalid.)
296 ******************************************************************************/
304 if (vol->keywords != NULL)
306 _DtHelpCeFreeStringArray (vol->keywords);
307 vol->keywords = NULL;
310 if (vol->keywordTopics != NULL)
312 for (topicList = vol->keywordTopics; *topicList != NULL; topicList++)
313 _DtHelpCeFreeStringArray (*topicList);
315 free (vol->keywordTopics);
316 vol->keywordTopics = NULL;
319 if (vol->sdl_flag == False)
320 result = _DtHelpCeRereadCcdfVolume(vol);
322 result = _DtHelpCeRereadSdlVolume(vol);
327 /******************************************************************************
328 * Function: static int GetKeywordTopics (_DtHelpVolume vol, char *keyword,
331 * Parameters: vol Specifies the loaded volume
332 * keyword Specifies the keyword whose location is desired.
333 * topics Returns a NULL-terminated string array of the
334 * list of topics which contain the keyword.
335 * This array is NOT owned by the caller and
336 * should only be read or copied.
338 * Return Value: 0 if successful, -1 if a failure occurs
340 * errno Values: CEErrorNoKeywordList
341 * Specifies that the volume does not
342 * have a keyword list.
343 * CEErrorIllegalKeyword
344 * Specifies that 'keyword' was not
347 * CEErrorIllegalDatabaseFile
348 * Specifies that the keyword file is
349 * invalid or corrupt.
350 * CEErrorMissingKeywordsRes
351 * Specifies that the keyword file does
352 * not contain the 'Keywords/keywords'
353 * resource or the resource is NULL
356 * Purpose: Find which topic contains a specified locationId.
358 ******************************************************************************/
369 _DtHelpProcessLock();
372 /* Get the list of keywords. */
373 if (GetVolumeKeywords (vol, &keywords) != 0)
375 _DtHelpProcessUnlock();
379 if (keywords == NULL || vol->keywordTopics == NULL)
381 errno = CEErrorNoKeywordList;
382 _DtHelpProcessUnlock();
386 /* Search the list of keywords for the current one. */
388 while (*nextKey != NULL && strcmp (*nextKey, keyword))
391 if (*nextKey == NULL)
393 errno = CEErrorIllegalKeyword;
394 _DtHelpProcessUnlock();
398 index = nextKey - keywords;
399 *retTopics = *(vol->keywordTopics + index);
401 _DtHelpProcessUnlock();
405 /******************************************************************************
406 * Function: static int GetVolumeKeywords(_DtHelpVolume vol,char ***keywords);
408 * Parameters: vol Specifies the volume.
409 * keywords Returns a NULL-terminated string array
410 * containing the sorted list of keywords in the
411 * volume. This array is NOT owned by the caller
412 * and should only be read or copied.
414 * Return Value: 0 if successful, -1 if a failure occurs
416 * errno Values: CEErrorMalloc
417 * CEErrorIllegalDatabaseFile
418 * Specifies that the keyword file is
419 * invalid or corrupt.
420 * CEErrorMissingKeywordsRes
421 * Specifies that the keyword file does
422 * not contain the 'Keywords/keywords'
423 * resource or the resource is NULL
425 * Purpose: Get the list of keywords defined in a volume.
427 ******************************************************************************/
434 _DtHelpCeLockInfo lockInfo;
436 _DtHelpProcessLock();
438 /* Keywords aren't loaded until they are needed, so see if they have
440 if (vol->keywords == NULL)
443 * What type of volume is it?
445 if (_DtHelpCeLockVolume(vol, &lockInfo) != 0)
447 _DtHelpProcessUnlock();
451 if (vol->sdl_flag == False)
452 result = _DtHelpCeGetCcdfKeywordList(vol);
454 result = _DtHelpCeGetSdlKeywordList(vol);
456 _DtHelpCeUnlockVolume(lockInfo);
460 _DtHelpProcessUnlock();
465 /* All of the keyword processing is done when they are loaded. */
466 *retKeywords = vol->keywords;
468 if (*retKeywords == NULL)
470 _DtHelpProcessUnlock();
474 _DtHelpProcessUnlock();
478 /*****************************************************************************
479 * Function: GetTopicTitleAndAbbrev (
483 * Memory own by caller:
487 * Returns: 0 if successful, -2 if didn't find the id,
488 * -3 if couldn't format the topic,
491 * Purpose: Find the title and abbreviated title of a topic.
493 *****************************************************************************/
495 GetTopicTitleAndAbbrev (
496 _DtHelpVolume volume,
503 char buffer[BUFF_SIZE];
505 char *filename = NULL;
507 _DtHelpCeLockInfo lockInfo;
509 if (_DtHelpCeLockVolume(volume, &lockInfo) != 0)
512 if (_DtHelpCeFindId(volume, id, lockInfo.fd, &filename, &offset) != True)
516 * What type of volume is it?
520 if (0 == _DtHelpCeGetVolumeFlag(volume))
522 result = _DtHelpCeFileOpenAndSeek(filename,offset,-1,&file,NULL);
526 if (_DtHelpCeReadBuf (file, buffer, BUFF_SIZE) != -1)
530 if (_DtHelpCeGetCcdfTopicAbbrev (NULL, file,
531 buffer, &bufPtr, BUFF_SIZE, MB_CUR_MAX,
532 ret_name, NULL, ret_abbrev) != 0)
535 _DtHelpCeBufFileClose(file, True);
540 _DtHelpProcessLock();
541 if (_DtHelpCeFrmtSDLTitleToAscii(volume, offset,
542 ret_name, ret_abbrev) != 0)
544 _DtHelpProcessUnlock();
548 if (filename != NULL)
551 _DtHelpCeUnlockVolume(lockInfo);
556 /*****************************************************************************
557 * Function: static int FileOpenRtnFd (char *name, int *ret_fd)
559 * Parameters: name Specifies the file to open.
560 * ret_fd Returns the fd of the opened file.
562 * Returns: 0 if required uncompress.
563 * file descriptor to remove the file from the system.
564 * 1 if no uncompression required.
565 * -1 if a failure occurs
567 * errno Values: EINVAL Specifies an invalid parameter was
570 * Specifies the seek offset was invalid.
572 * Purpose: Find out if a file is compressed and uncompress it if it is.
574 *****************************************************************************/
581 char tmpName[MAXPATHLEN + 1];
585 * check to see if the file exists in uncompressed form
587 *ret_fd = open(name, O_RDONLY);
591 * get a temporary name
593 (void) tmpnam (tmpName);
596 * malloc memory for the dot Z file name.
598 inFile = (char *) malloc (strlen (name) + 3);
602 * make the dot Z file
604 strcpy (inFile, name);
605 strcat (inFile, ".Z");
610 result = _DtHelpCeUncompressFile (inFile, tmpName);
620 * now open the uncompressed file
622 *ret_fd = open(tmpName, O_RDONLY);
630 errno = CEErrorMalloc;
637 } /* End FileOpenRtnFd */
639 /******************************************************************************
640 * Semi-Public Functions
641 ******************************************************************************/
642 /*****************************************************************************
643 * Function: char *_DtHelpCeExpandPathname (char *spec, char *filename, char *type,
644 * char *suffix, char *lang, _DtSubstitutionRec *subs, int num)
647 * spec Specifies a string with substitution
649 * containing the character set if found.
650 * filename Specifies the string to substitute for %N.
651 * type Specifies the string to substitute for %T.
652 * suffix Specifies the string to substitute for %S.
653 * lang Specifies the string to substitute for %L.
654 * subs Specifies the application own specific
656 * num Specifies the number of substitution pairs
659 * Memory own by caller:
662 * Returns: The expanded filename if successful. NULL if errors.
664 * Purpose: Expand a string with %<char> substitution values.
665 * Default substitutions are:
666 * %N replaced with 'filename'.
667 * %T replaced with 'type'
668 * %S replaced with 'suffix'
669 * %L replaced with 'lang'
671 * %l replaced with the language sub part of 'lang'.
672 * %t replaced with the territory sub part of 'lang'.
673 * %c replaced with the code set sub part of 'lang'.
674 * Other substitutions can be done via the 'subs' parameter.
676 *****************************************************************************/
678 _DtHelpCeExpandPathname (
684 _DtSubstitutionRec *subs,
694 char pathName [MAXPATHLEN + 5];
695 Boolean previousSlash = False;
697 _DtSubstitutionRec mySubs [MY_NUM];
699 if (spec == NULL || *spec == NULL)
706 * fill in the language sub parts
708 if (_DtHelpCeGetLangSubParts (lang, &partLang, &partTer, &partCodeSet))
711 mySubs[0].match = 'N';
712 mySubs[0].substitution = filename;
713 mySubs[1].match = 'T';
714 mySubs[1].substitution = type;
715 mySubs[2].match = 'S';
716 mySubs[2].substitution = suffix;
717 mySubs[3].match = 'L';
718 mySubs[3].substitution = lang;
720 mySubs[4].match = 'l';
721 mySubs[4].substitution = partLang;
722 mySubs[5].match = 't';
723 mySubs[5].substitution = partTer;
724 mySubs[6].match = 's';
725 mySubs[6].substitution = partCodeSet;
732 len = mblen (spec, MB_CUR_MAX);
734 if (len == 1 && *spec == '/')
740 previousSlash = True;
744 else if (len == 1 && *spec == '%')
756 previousSlash = True;
764 while (i < MY_NUM && mySubs && mySubs[i].match != *spec)
769 if (mySubs[i].substitution != NULL)
771 subString = mySubs[i].substitution;
772 if (((int)(ptr - pathName + strlen(subString)))
775 errno = CEErrorExceedMaxSize;
778 while (subString && *subString)
779 *ptr++ = *subString++;
785 while (i < num && subs && subs[i].match != *spec)
788 * If the substitution character is not found
789 * include the character onto the final string.
793 else if (subs[i].substitution != NULL)
795 subString = subs[i].substitution;
796 if (((int)(ptr - pathName + strlen(subString)))
799 errno = CEErrorExceedMaxSize;
802 while (subString && *subString)
803 *ptr++ = *subString++;
807 previousSlash = False;
813 previousSlash = False;
821 if (ptr - pathName > MAXPATHLEN)
823 errno = CEErrorExceedMaxSize;
836 ptr = strdup (pathName);
838 errno = CEErrorMalloc;
843 /*****************************************************************************
844 * Function: char *_DtHelpCeGetLangSubParts (char *lang, char **subLang,
845 * char **subTer, char **subCodeSet)
848 * lang Specifies the language string.
849 * subLang Returns the language sub part of 'lang'
851 * subTer Returns the territory sub part of 'lang'
853 * subCodeSet Returns the code set sub part of 'lang'
856 * Memory own by caller:
865 * Returns: 0 if successful, -1 if errors.
867 * Purpose: Break a %l_%t.%c language specification into its sub parts.
869 *****************************************************************************/
871 _DtHelpCeGetLangSubParts (
883 if (subLang == NULL || subTer == NULL || subCodeSet == NULL)
889 if (lang != NULL && *lang != '\0')
894 _DtHelpCeStrchr (lang, "_", MB_CUR_MAX, &ptr);
898 * do we want this string?
903 sLang = (char *) malloc (len + 1);
906 strncpy (sLang, lang, len);
911 errno = CEErrorMalloc;
916 * just mark that the lang part was found
925 * look for lang.codeset
927 _DtHelpCeStrchr (lang, Period, MB_CUR_MAX, &ptr);
933 * if it was in the form lang_ter.codeset, sLang will non-null
938 * do we want to save the territory?
942 sTer = (char *) malloc (len + 1);
945 strncpy (sTer, lang, len);
950 errno = CEErrorMalloc;
955 * don't wan to save, but make sure we mark the territory
956 * as being found (non-null).
962 * the lang was in the form lang.codeset.
963 * now check to see if want to save the lang portion.
965 else if (subLang != NULL)
967 sLang = (char *) malloc (len + 1);
970 strncpy (sLang, lang, len);
975 errno = CEErrorMalloc;
980 * didn't want to save the lang portion, but mark as found.
987 * currently pointing at the dot?
989 if (ptr && *ptr == '.')
992 * yes save the code set
995 if (subCodeSet != NULL)
997 sCode = strdup (ptr);
1000 errno = CEErrorMalloc;
1005 * don't save the code set, but make sure we mark as found
1011 * didn't find a code set, so save the current info.
1012 * If we haven't already processed a lang portion, save as the
1015 else if (sLang == NULL)
1017 if (subLang != NULL)
1019 sLang = strdup (lang);
1022 errno = CEErrorMalloc;
1030 * otherwise this is the territory of the language. Save if desired
1032 else if (subTer != NULL)
1034 sTer = strdup (lang);
1037 errno = CEErrorMalloc;
1048 *subCodeSet = sCode;
1053 /*****************************************************************************
1054 * Function: int _DtHelpCeGetUncompressedFileName (char *name, char **ret_name)
1056 * Parameters: name Specifies the file to open.
1057 * ret_name Returns the name of the uncompressed file.
1058 * This memory must be freed by the caller.
1060 * Returns: 0 if required uncompress. ret_name will contain the
1061 * name of the uncompressed file. The caller is required
1062 * to free the memory.
1063 * 1 if no uncompression required. ret_name points to name.
1064 * -1 if a failure occurs
1066 * errno Values: EINVAL Specifies an invalid parameter was
1069 * Specifies the seek offset was invalid.
1071 * Purpose: Find out if a file is compressed and uncompress it if it is.
1073 *****************************************************************************/
1075 _DtHelpCeGetUncompressedFileName (
1079 char *inFile = NULL;
1080 char tmpName[MAXPATHLEN + 1];
1084 * check to see if the file exists in uncompressed form
1087 if (access (name, F_OK) == -1)
1090 * get a temporary name
1092 (void) tmpnam (tmpName);
1095 * malloc memory for the dot Z file name.
1097 inFile = (char *) malloc (strlen (name) + 3);
1101 * make the dot Z file
1103 strcpy (inFile, name);
1104 strcat (inFile, ".Z");
1109 result = _DtHelpCeUncompressFile (inFile, tmpName);
1118 *ret_name = strdup (tmpName);
1119 if (*ret_name == NULL)
1121 errno = CEErrorMalloc;
1127 errno = CEErrorMalloc;
1135 /******************************************************************************
1136 * Function: int _DtHelpCeCompressPathname (char *basePath)
1138 * Parameters: basePath Specifies the path for the file possibily
1139 * containing /./, //, and /../.
1141 * Return Value: 0 for success, -1 for failure.
1142 * The number of bytes in basePath will be less than or
1143 * equal to the number of bytes in basePath when passed
1146 * errno Values: EINVAL
1148 * Purpose: This function compresses directory changes found
1149 * in a file name path.
1151 ******************************************************************************/
1153 _DtHelpCeCompressPathname ( char *basePath )
1160 char *ptr = basePath;
1161 char *prevPtr = NULL;
1163 if (basePath == NULL || *basePath != '/')
1172 * for multi-byte environments, check how far single bytes extend.
1177 if (MB_CUR_MAX == 1 || mblen (&ptr[1], MB_CUR_MAX) == 1)
1180 if (MB_CUR_MAX == 1 || mblen (&ptr[2], MB_CUR_MAX) == 1)
1183 if (MB_CUR_MAX == 1 || mblen (&ptr[3], MB_CUR_MAX) == 1)
1191 if (char1 == True && ptr[1] == '/')
1192 strcpy (ptr, (ptr + 1));
1197 else if (char2 == True && ptr[1] == '.' && ptr[2] == '/')
1198 strcpy (ptr, (ptr + 2));
1203 else if (char3 == True && strncmp (&ptr[1], "../", 3) == 0)
1206 * if at the top of the path, just ignore the extra
1209 if (prevPtr == NULL)
1210 strcpy (ptr, (ptr + 3));
1216 strcpy (prevPtr, (ptr + 3));
1219 * reset the current pointer
1224 * find the previous slash
1227 result = _DtHelpCeStrrchr(basePath,Slash,MB_CUR_MAX,&prevPtr);
1232 * if there is no previous slash, set the pointer to
1233 * indicate that we're at the top of the path (NULL).
1239 * restore the slash (or null byte)
1247 * remember this slash for /../ directory changes
1252 * skip this slash, and find the next one.
1255 result = _DtHelpCeStrcspn (ptr, "/", MB_CUR_MAX, &len);
1258 * if we run into invalid data, error
1266 } while (*ptr != '\0');
1271 /******************************************************************************
1272 * Function: char *_DtHelpCeTracePathName (char *path)
1275 * path Specifies the a path to trace and compress
1277 * Return Value: The new string if successful, NULL otherwise.
1278 * The new string is owned by the caller and contains
1279 * an absolute pathname.
1281 * errno Values: EINVAL Illegal parameter specified.
1282 * getcwd(2) errno set via a getcwd call.
1283 * readlink(2) errno set via a readlink call.
1285 * DtErrorExceedMaxSize The new path will exceed
1287 * DtErrorIllegalPath The compression will required
1288 * the path to change to a parent
1289 * directory beyond the beginning
1292 * Purpose: This function is called to trace the path of a file.
1293 * It can contain symbolic links, //, /./, and /../.
1295 ******************************************************************************/
1297 _DtHelpCeTracePathName (char *path)
1304 char newPath [2 * MAXPATHLEN + 2];
1305 char linkPath [MAXPATHLEN + 2];
1306 char tempPath [MAXPATHLEN + 2];
1308 if (path == NULL || *path == '\0')
1315 * initialize the new path
1320 * if the path passed in does not start with a slash,
1321 * get the current working directory and append the path to it.
1323 if ((MB_CUR_MAX == 1 || mblen(path, MB_CUR_MAX) == 1) && *path != '/')
1325 if (getcwd (newPath, MAXPATHLEN) == NULL)
1328 strcat (newPath, "/");
1332 * put the path in the working path buffer (or append it to
1333 * the current working directory).
1335 strcat (newPath, path);
1338 * Compress out the slashes and directory changes.
1340 if (_DtHelpCeCompressPathname (newPath) != 0)
1347 * point to the first character of the next directory
1352 * get the next slash after that
1354 result = _DtHelpCeStrcspn (prev, "/", MB_CUR_MAX, &len);
1359 * Found either a slash or a null byte.
1360 * place the string terminator at this point
1367 * find out if this path is a symbolic link
1369 result = readlink (newPath, linkPath, MAXPATHLEN);
1372 * replace the slash (or null byte).
1377 * check for the result of the readlink call
1382 * if this was NOT a symbolic link, errno should be EINVAL
1384 if (errno != EINVAL)
1390 * put the null byte on the end of the symbolic link string.
1392 linkPath [result] = '\0';
1395 * Save the rest of the string that we haven't processed
1396 * for tacking on after the new link path has been
1397 * dropped into the path.
1399 strcpy (tempPath, ptr);
1402 * is it an absolute path? Simply replace the path
1403 * being search with the new link path.
1405 if (*linkPath == '/')
1406 strcpy (newPath, linkPath);
1410 * this is a relative link.
1411 * prev is looking at the first character of this directory.
1412 * replace with the link.
1414 strcpy (prev, linkPath);
1418 * now tack on the rest of the name
1420 strcat (newPath, tempPath);
1423 * compress out the directory changes.
1425 if (_DtHelpCeCompressPathname (newPath) != 0)
1429 * start again from the top, until we have a clean path
1434 } while (*ptr != '\0');
1436 return (strdup (newPath));
1439 /******************************************************************************
1440 * Function: char *_DtHelpCeTraceFilenamePath (char *file_path)
1443 * file_path Specifies the a path to trace and compress
1445 * Return Value: The new string if successful, NULL otherwise.
1446 * The new string is owned by the caller and
1447 * contains an absolute filename path.
1449 * errno Values: EINVAL Illegal parameter specified.
1450 * getcwd(2) errno set via a getcwd call.
1451 * readlink(2) errno set via a readlink call.
1453 * DtErrorExceedMaxSize The new path will exceed
1455 * DtErrorIllegalPath The compression will required
1456 * the path to change to a parent
1457 * directory beyond the beginning
1460 * Purpose: This function is called to trace a filename path.
1461 * It can contain symbolic links, //, /./, and /../.
1463 ******************************************************************************/
1465 _DtHelpCeTraceFilenamePath (char *file_path)
1472 char workName [MAXPATHLEN + 2];
1473 char newName [MAXPATHLEN + 2];
1474 char linkName [MAXPATHLEN + 2];
1476 if (file_path == NULL || *file_path == '\0')
1483 if ((MB_CUR_MAX == 1 || mblen(file_path, MB_CUR_MAX) == 1)
1484 && *file_path != '/')
1486 if (getcwd(workName, MAXPATHLEN) == NULL)
1489 strcat(workName, "/");
1492 strcat (workName, file_path);
1497 * find and save the old filename
1499 result = _DtHelpCeStrrchr(workName, Slash, MB_CUR_MAX, &oldName);
1504 * terminate the path
1509 * trace the path, resolving the symbolic links
1510 * and directory changes. If /filename given,
1511 * skip the path tracing.
1514 if (workName[0] != '\0')
1516 newPath = _DtHelpCeTracePathName(workName);
1517 if (newPath == NULL)
1521 * copy the new path and free the allocated copy
1523 strcpy (newName, newPath);
1533 * now append the slash and filename (pointed to by oldName)
1534 * onto the end of the new path.
1536 namePlace = newName + strlen (newName);
1537 strcpy (namePlace, oldName);
1540 * See if the absolute path/filename is a symbolic link.
1542 result = readlink (newName, linkName, MAXPATHLEN);
1545 if (errno != EINVAL)
1553 * put the null byte on the end of the symbolic
1556 linkName [result] = '\0';
1557 if (*linkName == '/')
1558 strcpy (newName, linkName);
1562 * overwrite the filename with the link
1563 * but don't overwrite the slash.
1565 strcpy ((namePlace + 1), linkName);
1569 * make a copy of the new name to work on
1571 strcpy (workName, newName);
1575 return (strdup (newName));
1579 /******************************************************************************
1580 * Core Engine Semi-Public Functions
1581 ******************************************************************************/
1582 /*****************************************************************************
1583 * Function: char *_DtHelpCeGetVolumeName (_DtHelpVolumeHdl volume)
1587 * Returns: ptr to the name of the volume, NULL otherwise.
1589 * Purpose: Get the fully qualified volume name.
1591 *****************************************************************************/
1593 _DtHelpCeGetVolumeName (
1594 _DtHelpVolumeHdl volume_handle)
1598 _DtHelpProcessLock();
1599 volFile = ((_DtHelpVolume)volume_handle)->volFile;
1600 _DtHelpProcessUnlock();
1603 } /* End __DtHelpCeGetVolumeName */
1605 /*****************************************************************************
1606 * Function: int _DtHelpCeFileOpenAndSeek (char *name, int offset, int fildes,
1607 * BufFilePtr *ret_file)
1609 * Parameters: name Specifies the file to open.
1610 * offset Specifies location within the file to seek to.
1612 * Returns: 0 if successful, -1 if a failure occurs
1614 * errno Values: EINVAL Specifies an invalid parameter was
1617 * Specifies the seek offset was invalid.
1619 * Purpose: Open a file and seek to a specific place.
1621 *****************************************************************************/
1623 _DtHelpCeFileOpenAndSeek (
1627 BufFilePtr *ret_file,
1630 unsigned char fileMagic[4];
1637 * Get the file descriptor of the uncompressed file
1642 result = FileOpenRtnFd (name, &tmpFd);
1647 if (ret_time != NULL)
1649 (void) fstat(tmpFd, &buf);
1650 *ret_time = buf.st_mtime;
1654 * make sure we don't go past the end of the file
1656 result = lseek (tmpFd, 0, SEEK_END);
1659 if (result > offset)
1660 result = lseek (tmpFd, offset, SEEK_SET);
1664 errno = CEErrorFileSeek;
1675 bytesRead = read(tmpFd, fileMagic, 4);
1677 { /* something's wrong in reading the file */
1684 { /* started with compressed file magic number */
1686 CECompressInfoPtr myInfo;
1687 BufFilePtr inputRaw;
1690 * allocate the private information
1692 myInfo = (CECompressInfoPtr) malloc(sizeof(CECompressInfo));
1697 errno = CEErrorMalloc;
1702 * set the information
1703 * set the size to the maximum number of bytes we
1708 (((fileMagic[1] * 256) + fileMagic[2]) * 256) + fileMagic[3];
1711 * start with raw functionality
1713 inputRaw = _DtHelpCeBufFileRdRawZ(myInfo);
1714 if (inputRaw == NULL)
1721 *ret_file = _DtHelpCeBufFilePushZ(inputRaw);
1722 if (*ret_file == NULL)
1724 _DtHelpCeBufFileClose(inputRaw, (fd == -1 ? True : False));
1731 * not a compressed file, back up the four bytes we read
1733 result = lseek (tmpFd, offset, SEEK_SET);
1742 * read with raw functionality
1744 *ret_file = _DtHelpCeBufFileRdWithFd(tmpFd);
1745 if (*ret_file == NULL)
1755 } /* End of _DtHelpCeFileOpenAndSeek */
1756 /******************************************************************************
1757 * Core Engine Public Functions
1758 ******************************************************************************/
1759 /******************************************************************************
1760 * Function: int _DtHelpOpenVolume (char *volFile, _DtHelpVolume *retVol);
1762 * Parameters: volFile Specifies the name of the Help Volume file
1765 * retVol Returns the handle to the loaded volume.
1766 * If a volume is opened several times, the
1767 * same handle will be returned each time.
1769 * Return Value: 0 if successful, -1 if a failure occurred.
1771 * errno Values: EINVAL Illegal parameter specified.
1772 * getcwd(2) errno set via a getcwd call.
1773 * readlink(2) errno set via a readlink call.
1775 * CEErrorExceedMaxSize The new path will exceed
1777 * CEErrorIllegalPath The compression will required
1778 * the path to change to a parent
1779 * directory beyond the beginning
1781 * CEErrorIllegalDatabaseFile
1782 * Specifies that 'volFile' is
1783 * an illegal database file.
1786 * Purpose: This function must be called to open a Help Volume file
1787 * before any of the information in the volume can be
1790 ******************************************************************************/
1794 _DtHelpVolumeHdl *retVol)
1797 _DtHelpVolume vol, prevVol;
1799 _DtHelpProcessLock();
1801 if (volFile == NULL || retVol == NULL)
1804 _DtHelpProcessUnlock();
1809 * follow all the symbolic links and get the absolute path and filename.
1811 volFile = _DtHelpCeTraceFilenamePath(volFile);
1812 if (volFile == NULL)
1814 _DtHelpProcessUnlock();
1818 /* Search the volume chain to see if it is already open. */
1821 while (vol != NULL && strcmp (vol->volFile, volFile))
1832 else /* if (vol == NULL) */
1834 /* If it isn't open, open it and insert it in the chain. */
1835 result = VolumeLoad (volFile, &vol);
1838 if (prevVol == NULL)
1841 prevVol->nextVol = vol;
1845 /* Return the volume handle and a status indicating success/failure. */
1846 *retVol = (_DtHelpVolumeHdl) vol;
1847 _DtHelpProcessUnlock();
1851 /******************************************************************************
1852 * Function: int _DtHelpCeUpVolumeOpenCnt (_DtHelpVolumeHdl vol);
1854 * Parameters: vol Specifies the loaded volume.
1856 * Return Value: 0 if successful, -1 if a failure occurs
1858 * errno Values: EINVAL 'vol' was NULL, no volumes open or
1859 * 'vol' does not exist.
1861 * Purpose: When the volume is no longer needed, it should be
1862 * closed with this call. If the volume has been opened
1863 * several times, closing it will just decrement the
1864 * reference count. When it has been closed as many times
1865 * as it was opened, the memory it is using will be freed
1866 * and any handles to the volume will be invalid.
1868 ******************************************************************************/
1870 _DtHelpCeUpVolumeOpenCnt (
1871 _DtHelpVolumeHdl volume)
1873 _DtHelpVolume prevVol;
1874 _DtHelpVolume vol = (_DtHelpVolume)volume;
1876 _DtHelpProcessLock();
1878 if (vol == NULL || volChain == NULL)
1881 _DtHelpProcessUnlock();
1886 * check to see if this volume is in our chain
1888 if (vol != volChain)
1890 if (CheckVolList (vol, &prevVol) == -1)
1893 _DtHelpProcessUnlock();
1899 * increment it's usage count.
1902 _DtHelpProcessUnlock();
1906 /******************************************************************************
1907 * Function: int _DtHelpCloseVolume (_DtHelpVolumeHdl vol);
1909 * Parameters: vol Specifies the loaded volume.
1911 * Return Value: 0 if successful, -1 if a failure occurs
1913 * errno Values: EINVAL 'vol' was NULL, no volumes open or
1914 * 'vol' does not exist.
1916 * Purpose: When the volume is no longer needed, it should be
1917 * closed with this call. If the volume has been opened
1918 * several times, closing it will just decrement the
1919 * reference count. When it has been closed as many times
1920 * as it was opened, the memory it is using will be freed
1921 * and any handles to the volume will be invalid.
1923 ******************************************************************************/
1925 _DtHelpCloseVolume (
1926 _DtHelpVolumeHdl volume)
1928 _DtHelpVolume prevVol;
1929 _DtHelpVolume vol = (_DtHelpVolume)volume;
1931 _DtHelpProcessLock();
1933 if (vol == NULL || volChain == NULL)
1936 _DtHelpProcessUnlock();
1941 * check to see if this volume is in our chain
1943 if (vol != volChain)
1945 if (CheckVolList (vol, &prevVol) == -1)
1948 _DtHelpProcessUnlock();
1954 * decrement it's usage count.
1957 if (vol->openCount == 0)
1959 /* The volume is no longer needed. Unlink it from the chain
1962 if (vol == volChain)
1963 volChain = volChain->nextVol;
1966 prevVol->nextVol = vol->nextVol;
1971 _DtHelpProcessUnlock();
1975 /*****************************************************************************
1976 * Function: int _DtHelpCeGetTopTopicId (_DtHelpVolume vol,
1977 * char **ret_idString)
1979 * Parameters: vol Specifies the loaded volume
1980 * ret_idString Returns the location ID of the
1981 * the top level topic.
1983 * Memory own by caller:
1986 * Returns: True for success, False if a failure occurs.
1988 * errno Values: EINVAL Specifies an invalid parameter was
1990 * CEErrorMissingTopTopicRes
1991 * Specifies that the 'TopTopic/topTopic'
1992 * resource is missing from the database.
1995 * Purpose: Get the information to access the top level topic.
1997 *****************************************************************************/
1999 _DtHelpCeGetTopTopicId (
2000 _DtHelpVolumeHdl volume,
2001 char **ret_idString )
2004 _DtHelpVolume vol = (_DtHelpVolume)volume;
2006 _DtHelpProcessLock();
2008 if (vol == NULL || ret_idString == NULL || CheckVolList(vol, NULL) == -1)
2013 * What type of volume is it?
2015 if (vol->sdl_flag == False)
2016 (void) _DtHelpCeGetCcdfTopTopic(vol, ret_idString);
2018 *ret_idString = _DtHelpCeGetSdlHomeTopicId((_DtHelpVolumeHdl) vol);
2020 if (*ret_idString != NULL)
2021 *ret_idString = strdup(*ret_idString);
2023 if (*ret_idString != NULL)
2027 _DtHelpProcessUnlock();
2030 } /* End _DtHelpCeGetTopTopicId */
2032 /*****************************************************************************
2033 * Function: int _DtHelpCeFindId (_DtHelpVolume vol, char *target_id,
2035 * char *ret_name, int *ret_offset)
2037 * Parameters: vol Specifies the loaded volume
2038 * target_id Specifies target location ID
2039 * fd Specifies the locked file descriptor.
2040 * ret_name Returns a null terminated string
2041 * containing a fully qualified path to
2042 * the file that contains 'target_id'.
2043 * ret_offset Returns the offset into 'ret_name'
2044 * to the topic that contains 'target_id'.
2046 * Memory own by caller:
2049 * Returns: True if successful, False if a failure occurs
2051 * errno Values: EINVAL Specifies an invalid parameter was
2054 * CEErrorMissingFilenameRes
2055 * Specifies that the 'Filename/filename'
2056 * resource for 'topic' does not exist.
2057 * CEErrorMissingFileposRes
2058 * If the resource is not in the
2059 * database or if the resource NULL.
2060 * CEErrorLocIdNotFound
2061 * Specifies that 'locId' was not
2064 * Purpose: Find which topic contains a specified locationID.
2066 *****************************************************************************/
2069 _DtHelpVolumeHdl volume,
2075 _DtHelpVolume vol = (_DtHelpVolume)volume;
2078 _DtHelpProcessLock();
2081 * check the parameters
2083 if (vol == NULL || target_id == NULL || ret_name == NULL ||
2084 ret_offset == NULL || CheckVolList (vol, NULL) == -1)
2087 _DtHelpProcessUnlock();
2092 * What type of volume is it?
2094 if (vol->sdl_flag == False)
2096 result = _DtHelpCeFindCcdfId(vol, target_id, ret_name, ret_offset);
2100 result = _DtHelpCeFindSdlId(vol, target_id, fd, ret_name, ret_offset);
2103 _DtHelpProcessUnlock();
2106 } /* End _DtHelpCeFindId */
2108 /*****************************************************************************
2109 * Function: int _DtHelpCeGetKeywordList (_DtHelpVolume vol, char ***ret_keywords)
2111 * Parameters: vol Specifies the loaded volume
2112 * ret_keywords Returns a NULL-terminated string array
2113 * containing the sorted list of keywords in the
2114 * volume. This array is NOT owned by the caller
2115 * and should only be read or copied.
2117 * Returns: The count of keywords associated with the volume if successful.
2118 * -1 if a failure occurs;
2120 * errno Values: EINVAL Specifies an invalid parameter was
2123 * CEErrorIllegalDatabaseFile
2124 * Specifies that the keyword file is
2125 * invalid or corrupt.
2126 * CEErrorMissingKeywordsRes
2127 * Specifies that the keyword file does
2128 * not contain the 'Keywords/keywords'
2129 * resource or the resource is NULL
2131 * Purpose: Get the list of keywords contained in a volume.
2133 *****************************************************************************/
2135 _DtHelpCeGetKeywordList (
2136 _DtHelpVolumeHdl volume,
2137 char ***ret_keywords )
2140 _DtHelpVolume vol = (_DtHelpVolume)volume;
2142 if (vol == NULL || ret_keywords == NULL || CheckVolList (vol, NULL) == -1)
2144 else if (GetVolumeKeywords (vol, ret_keywords) == 0)
2147 while (*ret_keywords && (*ret_keywords)[nameCount])
2153 } /* End _DtHelpCeGetKeywordList */
2155 /*****************************************************************************
2156 * Function: int _DtHelpCeFindKeyword (_DtHelpVolume vol, char *target, char ***ret_ids)
2158 * Parameters: vol Specifies the loaded volume
2159 * target The target keyword.
2160 * ret_ids Returns a null terminated list of location
2161 * ids associated with the target keyword.
2163 * Returns: The count of ids associated with the keyword if successful.
2164 * -1 if a failure occurs;
2166 * errno Values: EINVAL Specifies an invalid parameter was
2168 * CEErrorNoKeywordList
2169 * Specifies that the volume does not
2170 * have a keyword list.
2171 * CEErrorIllegalKeyword
2172 * Specifies that 'target' was not
2175 * CEErrorIllegalDatabaseFile
2176 * Specifies that the keyword file is
2177 * invalid or corrupt.
2178 * CEErrorMissingKeywordsRes
2179 * Specifies that the keyword file does
2180 * not contain the 'Keywords/keywords'
2181 * resource or the resource is NULL
2183 * Purpose: Get the list of location ids associated with a keyword
2185 *****************************************************************************/
2187 _DtHelpCeFindKeyword (
2188 _DtHelpVolumeHdl volume,
2193 _DtHelpVolume vol = (_DtHelpVolume)volume;
2195 if (vol == NULL || target == NULL || ret_ids == NULL ||
2196 CheckVolList (vol, NULL) == -1)
2198 else if (GetKeywordTopics (vol, target, ret_ids) == 0)
2201 while (*ret_ids && (*ret_ids)[nameCount])
2207 } /* End _DtHelpCeFindKeyword */
2209 /*****************************************************************************
2210 * Function: int _DtHelpGetTopicTitle (
2211 * _DtHelpVolumeHdl volume,
2212 * char *id, char **ret_title)
2214 * Parameters: volume Specifies the volume containing the id.
2215 * id Specifies the id for the topic desired.
2216 * ret_title Returns a null terminated string containing
2219 * Memory own by caller:
2222 * Returns: 0 if successful, -2 if didn't find the id,
2225 * errno Values: EINVAL Specifies an invalid parameter was
2228 * Purpose: Get the title of a topic.
2230 *****************************************************************************/
2232 _DtHelpGetTopicTitle (
2233 _DtHelpVolumeHdl volume,
2239 _DtHelpVolume vol = (_DtHelpVolume)volume;
2241 if (volume == NULL || id == NULL ||
2242 CheckVolList (vol, NULL) == -1 || ret_title == NULL)
2249 * Try to get the title via the <TOPIC> and <ABBREV> tags.
2251 result = GetTopicTitleAndAbbrev(vol, id, ret_title, &abbrevTitle);
2255 * If we have a abbreviated title, return it instead.
2260 free ((char *) *ret_title);
2261 *ret_title = abbrevTitle;
2267 } /* End _DtHelpGetTopicTitle */
2269 /*****************************************************************************
2270 * Function: int _DtHelpCeMapTargetToId (_DtHelpVolume vol,
2274 * Parameters: vol Specifies the loaded volume
2275 * target_id Specifies target location ID
2276 * ret_id Returns the id containing the target_id.
2277 * This memory *IS NOT* owned by the caller.
2279 * Returns: 0 if successful, -1 if a failure occurs
2281 * Purpose: Find which topic contains a specified locationID.
2283 *****************************************************************************/
2285 _DtHelpCeMapTargetToId (
2286 _DtHelpVolumeHdl volume,
2290 _DtHelpVolume vol = (_DtHelpVolume)volume;
2293 _DtHelpProcessLock();
2296 * check the parameters
2298 if (vol == NULL || target_id == NULL || ret_id == NULL ||
2299 CheckVolList (vol, NULL) == -1)
2302 _DtHelpProcessUnlock();
2307 * What type of volume is it?
2309 if (vol->sdl_flag == False)
2311 result = _DtHelpCeMapCcdfTargetToId(vol, target_id, ret_id);
2315 result = _DtHelpCeMapIdToSdlTopicId(vol, target_id, ret_id);
2318 _DtHelpProcessUnlock();
2321 } /* End _DtHelpCeMapTargetToId */
2323 /*****************************************************************************
2324 * Function: char * _DtHelpGetVolumeLocale (_DtHelpVolume vol)
2326 * Parameters: vol Specifies the loaded volume
2328 * Returns: The pointer to the locale string if successful. Otherwise
2331 * Purpose: Get the locale of the specified volume.
2332 * Returns the locale in a unix specific format
2333 * - locale[_ter][.charset] - This memory is owned by
2336 *****************************************************************************/
2338 _DtHelpGetVolumeLocale (
2339 _DtHelpVolumeHdl volume)
2341 _DtHelpVolume vol = (_DtHelpVolume)volume;
2344 _DtHelpProcessLock();
2347 * check the parameters
2349 if (vol == NULL || CheckVolList (vol, NULL) == -1)
2352 _DtHelpProcessUnlock();
2357 * What type of volume is it?
2359 if (vol->sdl_flag == False)
2361 result = _DtHelpCeGetCcdfVolLocale(vol);
2365 result = _DtHelpCeGetSdlVolumeLocale(vol);
2368 _DtHelpProcessUnlock();
2371 } /* End _DtHelpGetVolumeLocale */
2373 /*****************************************************************************
2374 * Function: int _DtHelpCeGetDocStamp (_DtHelpVolumeHdl volume, char **ret_doc,
2377 * Parameters: volume Specifies the loaded volume
2378 * ret_doc Returns the doc id.
2379 * ret_time Returns the time stamp.
2381 * Memory: Caller owns the string in ret_doc and ret_time.
2383 * Returns: 0 if successful, -2 if the volume does not contain
2384 * one or the other, -1 if any other failure.
2386 * Purpose: Get doc id and time stamp of a volume.
2388 *****************************************************************************/
2390 _DtHelpCeGetDocStamp (
2391 _DtHelpVolumeHdl volume,
2395 _DtHelpVolume vol = (_DtHelpVolume)volume;
2398 _DtHelpProcessLock();
2401 * check the parameters
2403 if (vol == NULL || CheckVolList (vol, NULL) == -1)
2406 _DtHelpProcessUnlock();
2411 * What type of volume is it?
2413 if (vol->sdl_flag == False)
2415 result = _DtHelpCeGetCcdfDocStamp (vol, ret_doc, ret_time);
2419 result = _DtHelpCeGetSdlDocStamp(vol, ret_doc, ret_time);
2422 _DtHelpProcessUnlock();
2425 } /* End _DtHelpCeGetDocStamp */
2427 /*****************************************************************************
2428 * Function: char * _DtHelpCeGetTopicChilren (_DtHelpVolumeHdl vol)
2430 * Parameters: vol Specifies the loaded volume
2431 * topic_id Speicifes the topic id of which the
2432 * children are to be found.
2433 * retTopics Returns the null terminated array of
2434 * ids. This memory is owned by the caller
2435 * and must be freed.
2437 * Returns: > 0 if successful, -1 if failures.
2439 * Purpose: Get the children of a topic.
2441 *****************************************************************************/
2443 _DtHelpCeGetTopicChildren (
2444 _DtHelpVolumeHdl volume,
2448 _DtHelpVolume vol = (_DtHelpVolume)volume;
2451 _DtHelpProcessLock();
2454 * check the parameters
2456 if (vol == NULL || CheckVolList (vol, NULL) == -1)
2459 _DtHelpProcessUnlock();
2464 * What type of volume is it?
2466 if (vol->sdl_flag == False)
2468 result = _DtHelpCeGetCcdfTopicChildren(volume, topic_id, retTopics);
2472 result = _DtHelpCeGetSdlTopicChildren(volume, topic_id, retTopics);
2475 _DtHelpProcessUnlock();
2478 } /* End _DtHelpCeGetTopicChildren */
2480 /*****************************************************************************
2481 * Function: int _DtHelpCeGetVolumeFlag (_DtHelpVolumeHdl vol)
2483 * Parameters: vol Specifies the loaded volume
2485 * Returns: 0 if CCDF volume, 1 if SDL, -1 if failures.
2487 * Purpose: Determine the type of volume.
2489 *****************************************************************************/
2491 _DtHelpCeGetVolumeFlag (
2492 _DtHelpVolumeHdl volume)
2494 _DtHelpVolume vol = (_DtHelpVolume)volume;
2497 * check the parameters
2499 if (vol == NULL || CheckVolList (vol, NULL) == -1)
2506 * What type of volume is it?
2508 return((int) vol->sdl_flag);
2510 } /* End _DtHelpCeGetVolumeFlag */
2512 /*****************************************************************************
2513 * Function: int _DtHelpCeLockVolume (_DtHelpVolumeHdl vol)
2515 * Parameters: vol Specifies the loaded volume
2517 * Returns: > 0 if successful, -1 if failures.
2519 * Purpose: Lock the volume so that it can't get change out from
2522 *****************************************************************************/
2524 _DtHelpCeLockVolume (
2525 _DtHelpVolumeHdl volume,
2526 _DtHelpCeLockInfo *lock_info)
2529 _DtHelpVolume vol = (_DtHelpVolume)volume;
2531 _DtHelpProcessLock();
2534 * check the parameters
2536 if (vol == NULL || CheckVolList (vol, NULL) == -1)
2538 _DtHelpProcessUnlock();
2543 * lock it by opening it.
2545 lock_info->fd = open(vol->volFile, O_RDONLY);
2546 if (lock_info->fd == -1)
2548 _DtHelpProcessUnlock();
2552 (void) fstat(lock_info->fd, &buf);
2553 if (buf.st_mtime != vol->check_time)
2555 if (RereadVolume(vol) != 0)
2557 close(lock_info->fd);
2558 _DtHelpProcessUnlock();
2562 vol->check_time = buf.st_mtime;
2569 lock_info->volume = volume;
2570 _DtHelpProcessUnlock();
2573 } /* End _DtHelpCeLockVolume */
2575 /*****************************************************************************
2576 * Function: int _DtHelpCeUnlockVolume (_DtHelpVolumeHdl vol)
2578 * Parameters: vol Specifies the loaded volume
2580 * Returns: > 0 if successful, -1 if failures.
2582 * Purpose: Unlock the volume.
2584 *****************************************************************************/
2586 _DtHelpCeUnlockVolume (
2587 _DtHelpCeLockInfo lock_info)
2589 _DtHelpVolume vol = (_DtHelpVolume)(lock_info.volume);
2591 _DtHelpProcessLock();
2594 * check the parameters
2596 if (vol == NULL || CheckVolList (vol, NULL) == -1)
2598 _DtHelpProcessUnlock();
2603 * check to see if it needs to be unlocked.
2605 if (lock_info.fd != -1)
2606 close(lock_info.fd);
2612 _DtHelpProcessUnlock();
2615 } /* End _DtHelpCeUnlockVolume */
2617 /*****************************************************************************
2618 * Function: int _DtHelpCeIsTopTopic (_DtHelpVolumeHdl volume, const char *id)
2620 * Parameters: vol Specifies the loaded volume
2621 * id Specifies a location id.
2623 * Returns: = 0 if successful, != 0 if failures.
2625 * Purpose: Tests to see if the location id is in the top topic of
2628 *****************************************************************************/
2630 _DtHelpCeIsTopTopic (
2631 _DtHelpVolumeHdl volume,
2635 char *topicId = NULL;
2637 _DtHelpVolume vol = (_DtHelpVolume) volume;
2639 _DtHelpProcessLock();
2641 * check the parameters
2643 if (vol == NULL || CheckVolList (vol, NULL) == -1)
2645 _DtHelpProcessUnlock();
2650 * What type of volume is it?
2652 if (vol->sdl_flag == False)
2654 if (_DtHelpCeMapCcdfTargetToId(vol, id, &topicId) == 0 &&
2655 _DtHelpCeGetCcdfTopTopic(vol, &topId) == 0)
2656 result = _DtHelpCeStrCaseCmpLatin1(topId, topicId);
2658 else if (_DtHelpCeMapIdToSdlTopicId(vol, id, &topicId) == 0)
2660 topId = _DtHelpCeGetSdlHomeTopicId(volume);
2662 result = _DtHelpCeStrCaseCmpLatin1(topId, topicId);
2665 _DtHelpProcessUnlock();
2668 } /* End _DtHelpCeIsTopTopic */