PageRenderTime 60ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/cde/lib/DtHelp/Access.c

https://bitbucket.org/tifan/cde
C | 2066 lines | 1047 code | 199 blank | 820 comment | 362 complexity | 2f3d826713d3e10343509872c7536963 MD5 | raw file
Possible License(s): LGPL-2.1, IPL-1.0, 0BSD
  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 librararies 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. /* $XConsortium: Access.c /main/11 1996/11/01 10:09:29 drk $ */
  24. /************************************<+>*************************************
  25. ****************************************************************************
  26. **
  27. ** File: Access.c
  28. **
  29. ** Project: Run Time Project File Access
  30. **
  31. ** Description: This body of code handles the access routines for the
  32. ** Display Area.
  33. **
  34. **
  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.
  42. **
  43. **
  44. ****************************************************************************
  45. ************************************<+>*************************************/
  46. /*
  47. * system includes
  48. */
  49. #include <errno.h>
  50. #include <fcntl.h>
  51. #include <limits.h>
  52. #include <stdlib.h>
  53. #include <stdio.h>
  54. #include <string.h>
  55. #include <unistd.h>
  56. #include <sys/param.h>
  57. #include <sys/stat.h>
  58. #include <X11/Xlib.h>
  59. #include <X11/Xresource.h>
  60. #ifdef X_NOT_STDC_ENV
  61. extern int errno;
  62. #endif
  63. /*
  64. * Canvas Engine includes
  65. */
  66. #include "CanvasP.h"
  67. #include "CanvasSegP.h"
  68. /*
  69. * private includes
  70. */
  71. #include "CanvasError.h"
  72. #include "Access.h"
  73. #include "bufioI.h"
  74. #include "FontAttrI.h"
  75. #include "AccessP.h"
  76. #include "AccessI.h"
  77. #include "AccessSDLP.h"
  78. #include "AccessSDLI.h"
  79. #include "AccessCCDFI.h"
  80. #include "FormatUtilI.h"
  81. #include "SDLI.h"
  82. #include "FormatSDLI.h"
  83. #include "CCDFUtilI.h"
  84. #include "StringFuncsI.h"
  85. #include "Lock.h" /* Process and App Lock macros */
  86. #ifdef NLS16
  87. #endif
  88. /******** Private Defines ********/
  89. #define LIST_INCREMENT 10
  90. #define BUFF_SIZE 256
  91. /******** End Private Defines ********/
  92. /******** Private Function Declarations ********/
  93. static int GetVolumeKeywords (
  94. _DtHelpVolume vol,
  95. char ***retKeywords);
  96. static int VolumeLoad (
  97. char *volFile,
  98. _DtHelpVolume *retVol);
  99. static int VolumeUnload (
  100. _DtHelpVolume vol);
  101. /******** End Private Function Declarations ********/
  102. /******** Private Macro Declarations ********/
  103. /******** End Private Macro Declarations ********/
  104. /******************************************************************************
  105. *
  106. * Private variables used within this file.
  107. *
  108. *******************************************************************************/
  109. static _DtHelpVolume volChain = NULL; /* Pointer to the head of the chain */
  110. /* of all the open volumes. */
  111. static const char *Slash = "/";
  112. static const char *Period = ".";
  113. /******************************************************************************
  114. * Private Functions
  115. ******************************************************************************/
  116. /******************************************************************************
  117. * Function: CheckVolList (_DtHelpVolume vol, _DtHelpVolume *ret_prev)
  118. *
  119. * Parameters: vol Specifies the volume to search for.
  120. * ret_prev Returns the volume whose nextVol element
  121. * points to 'vol' if non NULL.
  122. *
  123. * Returns: 0 if successful, -1 if failure.
  124. *
  125. * errno Values:
  126. *
  127. * Purpose: To check for the existance of a volume.
  128. *
  129. ******************************************************************************/
  130. static int
  131. CheckVolList (
  132. _DtHelpVolume vol,
  133. _DtHelpVolume *ret_prev )
  134. {
  135. _DtHelpVolume myVol;
  136. _DtHelpVolume prevVol = NULL;
  137. _DtHelpProcessLock();
  138. myVol = volChain;
  139. while (myVol != NULL && myVol != vol)
  140. {
  141. prevVol = myVol;
  142. myVol = myVol->nextVol;
  143. }
  144. if (ret_prev)
  145. *ret_prev = prevVol;
  146. if (myVol != vol)
  147. {
  148. _DtHelpProcessUnlock();
  149. return -1;
  150. }
  151. _DtHelpProcessUnlock();
  152. return 0;
  153. }
  154. /******************************************************************************
  155. * Function: int VolumeLoad (char *volFile, _DtHelpVolume *retVol);
  156. *
  157. * Parameters: volFile Specifies the name of the Help Volume file
  158. * to load.
  159. *
  160. * retVol Returns the handle to the loaded volume.
  161. *
  162. * Return Value: Returns 0 if successful,
  163. * -1 if an error occurred.
  164. *
  165. * errno Values: CEErrorMalloc
  166. * CEErrorIllegalDatabaseFile
  167. *
  168. * Purpose: This function must be called to load a Help Volume file
  169. * before any of the information in the volume can be
  170. * accessed.
  171. *
  172. ******************************************************************************/
  173. static int
  174. VolumeLoad (
  175. char *volFile,
  176. _DtHelpVolume *retVol)
  177. {
  178. /* Allocate the volume structure and initialize it. */
  179. *retVol = (_DtHelpVolume) malloc (sizeof (struct _DtHelpVolumeRec));
  180. if (*retVol)
  181. {
  182. (*retVol)->sdl_flag = False;
  183. (*retVol)->volFile = volFile;
  184. (*retVol)->keywords = NULL;
  185. (*retVol)->keywordTopics = NULL;
  186. (*retVol)->openCount = 1;
  187. (*retVol)->nextVol = NULL;
  188. (*retVol)->vols.ccdf_vol = NULL;
  189. if (_DtHelpCeOpenSdlVolume ((*retVol)) == 0)
  190. return 0;
  191. else if (_DtHelpCeOpenCcdfVolume(*retVol) == 0)
  192. return 0;
  193. /*
  194. * Set the global error
  195. */
  196. errno = CEErrorIllegalDatabaseFile;
  197. /*
  198. * error on loading the database.
  199. */
  200. free ((char *) ((*retVol)->volFile));
  201. free ((char *) (*retVol));
  202. *retVol = NULL;
  203. }
  204. else
  205. errno = CEErrorMalloc;
  206. return -1;
  207. } /* End VolumeLoad */
  208. /*******************************************************************************
  209. * Function: int VolumeUnload (_DtHelpVolume vol);
  210. *
  211. * Parameters: vol Specifies the loaded volume.
  212. *
  213. * Return Value: 0 if successful, -1 if a failure occurs
  214. *
  215. * errno Values: None
  216. *
  217. * Purpose: When the volume is no longer needed, it should be unloaded
  218. * with this call. Unloading it frees the memory (which means
  219. * any handles on the volume become invalid.)
  220. *
  221. ******************************************************************************/
  222. static int
  223. VolumeUnload (
  224. _DtHelpVolume vol)
  225. {
  226. char ***topicList;
  227. if (vol != NULL)
  228. {
  229. if (vol->sdl_flag == True)
  230. _DtHelpCeCloseSdlVolume((_DtHelpVolumeHdl) vol);
  231. else
  232. _DtHelpCeCloseCcdfVolume(vol);
  233. if (vol->volFile != NULL)
  234. free (vol->volFile);
  235. if (vol->keywords != NULL)
  236. _DtHelpCeFreeStringArray (vol->keywords);
  237. if (vol->keywordTopics != NULL)
  238. {
  239. for (topicList = vol->keywordTopics;
  240. *topicList != NULL; topicList++)
  241. _DtHelpCeFreeStringArray (*topicList);
  242. free (vol->keywordTopics);
  243. }
  244. free (vol);
  245. }
  246. return (0);
  247. }
  248. /*******************************************************************************
  249. * Function: int RereadVolume (_DtHelpVolume vol);
  250. *
  251. * Parameters: vol Specifies the loaded volume.
  252. *
  253. * Return Value: 0 if successful, -1 if a failure occurs
  254. *
  255. * errno Values: None
  256. *
  257. * Purpose: When the volume is no longer needed, it should be unloaded
  258. * with this call. Unloading it frees the memory (which means
  259. * any handles on the volume become invalid.)
  260. *
  261. ******************************************************************************/
  262. static int
  263. RereadVolume (
  264. _DtHelpVolume vol)
  265. {
  266. int result;
  267. char ***topicList;
  268. if (vol->keywords != NULL)
  269. {
  270. _DtHelpCeFreeStringArray (vol->keywords);
  271. vol->keywords = NULL;
  272. }
  273. if (vol->keywordTopics != NULL)
  274. {
  275. for (topicList = vol->keywordTopics; *topicList != NULL; topicList++)
  276. _DtHelpCeFreeStringArray (*topicList);
  277. free (vol->keywordTopics);
  278. vol->keywordTopics = NULL;
  279. }
  280. if (vol->sdl_flag == False)
  281. result = _DtHelpCeRereadCcdfVolume(vol);
  282. else
  283. result = _DtHelpCeRereadSdlVolume(vol);
  284. return (result);
  285. }
  286. /******************************************************************************
  287. * Function: static int GetKeywordTopics (_DtHelpVolume vol, char *keyword,
  288. * char ***topics);
  289. *
  290. * Parameters: vol Specifies the loaded volume
  291. * keyword Specifies the keyword whose location is desired.
  292. * topics Returns a NULL-terminated string array of the
  293. * list of topics which contain the keyword.
  294. * This array is NOT owned by the caller and
  295. * should only be read or copied.
  296. *
  297. * Return Value: 0 if successful, -1 if a failure occurs
  298. *
  299. * errno Values: CEErrorNoKeywordList
  300. * Specifies that the volume does not
  301. * have a keyword list.
  302. * CEErrorIllegalKeyword
  303. * Specifies that 'keyword' was not
  304. * found.
  305. * CEErrorMalloc
  306. * CEErrorIllegalDatabaseFile
  307. * Specifies that the keyword file is
  308. * invalid or corrupt.
  309. * CEErrorMissingKeywordsRes
  310. * Specifies that the keyword file does
  311. * not contain the 'Keywords/keywords'
  312. * resource or the resource is NULL
  313. *
  314. *
  315. * Purpose: Find which topic contains a specified locationId.
  316. *
  317. ******************************************************************************/
  318. static int
  319. GetKeywordTopics (
  320. _DtHelpVolume vol,
  321. char *keyword,
  322. char ***retTopics)
  323. {
  324. char **keywords;
  325. char **nextKey;
  326. int index;
  327. _DtHelpProcessLock();
  328. *retTopics = NULL;
  329. /* Get the list of keywords. */
  330. if (GetVolumeKeywords (vol, &keywords) != 0)
  331. {
  332. _DtHelpProcessUnlock();
  333. return -1;
  334. }
  335. if (keywords == NULL || vol->keywordTopics == NULL)
  336. {
  337. errno = CEErrorNoKeywordList;
  338. _DtHelpProcessUnlock();
  339. return -1;
  340. }
  341. /* Search the list of keywords for the current one. */
  342. nextKey = keywords;
  343. while (*nextKey != NULL && strcmp (*nextKey, keyword))
  344. nextKey++;
  345. if (*nextKey == NULL)
  346. {
  347. errno = CEErrorIllegalKeyword;
  348. _DtHelpProcessUnlock();
  349. return -1;
  350. }
  351. index = nextKey - keywords;
  352. *retTopics = *(vol->keywordTopics + index);
  353. _DtHelpProcessUnlock();
  354. return (0);
  355. }
  356. /******************************************************************************
  357. * Function: static int GetVolumeKeywords(_DtHelpVolume vol,char ***keywords);
  358. *
  359. * Parameters: vol Specifies the volume.
  360. * keywords Returns a NULL-terminated string array
  361. * containing the sorted list of keywords in the
  362. * volume. This array is NOT owned by the caller
  363. * and should only be read or copied.
  364. *
  365. * Return Value: 0 if successful, -1 if a failure occurs
  366. *
  367. * errno Values: CEErrorMalloc
  368. * CEErrorIllegalDatabaseFile
  369. * Specifies that the keyword file is
  370. * invalid or corrupt.
  371. * CEErrorMissingKeywordsRes
  372. * Specifies that the keyword file does
  373. * not contain the 'Keywords/keywords'
  374. * resource or the resource is NULL
  375. *
  376. * Purpose: Get the list of keywords defined in a volume.
  377. *
  378. ******************************************************************************/
  379. static int
  380. GetVolumeKeywords (
  381. _DtHelpVolume vol,
  382. char ***retKeywords)
  383. {
  384. int result;
  385. _DtHelpCeLockInfo lockInfo;
  386. _DtHelpProcessLock();
  387. /* Keywords aren't loaded until they are needed, so see if they have
  388. been loaded yet. */
  389. if (vol->keywords == NULL)
  390. {
  391. /*
  392. * What type of volume is it?
  393. */
  394. if (_DtHelpCeLockVolume(vol, &lockInfo) != 0)
  395. {
  396. _DtHelpProcessUnlock();
  397. return -1;
  398. }
  399. if (vol->sdl_flag == False)
  400. result = _DtHelpCeGetCcdfKeywordList(vol);
  401. else
  402. result = _DtHelpCeGetSdlKeywordList(vol);
  403. _DtHelpCeUnlockVolume(lockInfo);
  404. if (result != 0)
  405. {
  406. _DtHelpProcessUnlock();
  407. return -1;
  408. }
  409. }
  410. /* All of the keyword processing is done when they are loaded. */
  411. *retKeywords = vol->keywords;
  412. if (*retKeywords == NULL)
  413. {
  414. _DtHelpProcessUnlock();
  415. return (-1);
  416. }
  417. _DtHelpProcessUnlock();
  418. return (0);
  419. }
  420. /*****************************************************************************
  421. * Function: GetTopicTitleAndAbbrev (
  422. *
  423. * Parameters:
  424. *
  425. * Memory own by caller:
  426. * ret_name
  427. * ret_abrrev
  428. *
  429. * Returns: 0 if successful, -2 if didn't find the id,
  430. * -3 if couldn't format the topic,
  431. * otherwise -1.
  432. *
  433. * Purpose: Find the title and abbreviated title of a topic.
  434. *
  435. *****************************************************************************/
  436. static int
  437. GetTopicTitleAndAbbrev (
  438. _DtHelpVolume volume,
  439. char *id,
  440. char **ret_name,
  441. char **ret_abbrev )
  442. {
  443. int result = 0;
  444. int offset;
  445. char buffer[BUFF_SIZE];
  446. char *bufPtr;
  447. char *filename = NULL;
  448. BufFilePtr file;
  449. _DtHelpCeLockInfo lockInfo;
  450. if (_DtHelpCeLockVolume(volume, &lockInfo) != 0)
  451. return -1;
  452. if (_DtHelpCeFindId(volume, id, lockInfo.fd, &filename, &offset) != True)
  453. result = -2;
  454. /*
  455. * What type of volume is it?
  456. */
  457. if (result == 0)
  458. {
  459. if (0 == _DtHelpCeGetVolumeFlag(volume))
  460. {
  461. result = _DtHelpCeFileOpenAndSeek(filename,offset,-1,&file,NULL);
  462. if (result == 0)
  463. {
  464. result = -1;
  465. if (_DtHelpCeReadBuf (file, buffer, BUFF_SIZE) != -1)
  466. {
  467. result = 0;
  468. bufPtr = buffer;
  469. if (_DtHelpCeGetCcdfTopicAbbrev (NULL, file,
  470. buffer, &bufPtr, BUFF_SIZE, MB_CUR_MAX,
  471. ret_name, NULL, ret_abbrev) != 0)
  472. result = -3;
  473. }
  474. _DtHelpCeBufFileClose(file, True);
  475. }
  476. }
  477. else
  478. {
  479. _DtHelpProcessLock();
  480. if (_DtHelpCeFrmtSDLTitleToAscii(volume, offset,
  481. ret_name, ret_abbrev) != 0)
  482. result = -3;
  483. _DtHelpProcessUnlock();
  484. }
  485. }
  486. if (filename != NULL)
  487. free(filename);
  488. _DtHelpCeUnlockVolume(lockInfo);
  489. return result;
  490. }
  491. /*****************************************************************************
  492. * Function: static int FileOpenRtnFd (char *name, int *ret_fd)
  493. *
  494. * Parameters: name Specifies the file to open.
  495. * ret_fd Returns the fd of the opened file.
  496. *
  497. * Returns: 0 if required uncompress.
  498. * file descriptor to remove the file from the system.
  499. * 1 if no uncompression required.
  500. * -1 if a failure occurs
  501. *
  502. * errno Values: EINVAL Specifies an invalid parameter was
  503. * used.
  504. * CEErrorFileSeek
  505. * Specifies the seek offset was invalid.
  506. *
  507. * Purpose: Find out if a file is compressed and uncompress it if it is.
  508. *
  509. *****************************************************************************/
  510. static int
  511. FileOpenRtnFd (
  512. char *name,
  513. int *ret_fd )
  514. {
  515. char *inFile = NULL;
  516. char tmpName[MAXPATHLEN + 1];
  517. int result = 1;
  518. /*
  519. * check to see if the file exists in uncompressed form
  520. */
  521. *ret_fd = open(name, O_RDONLY);
  522. if (*ret_fd == -1)
  523. {
  524. /*
  525. * get a temporary name
  526. */
  527. (void) tmpnam (tmpName);
  528. /*
  529. * malloc memory for the dot Z file name.
  530. */
  531. inFile = (char *) malloc (strlen (name) + 3);
  532. if (inFile != NULL)
  533. {
  534. /*
  535. * make the dot Z file
  536. */
  537. strcpy (inFile, name);
  538. strcat (inFile, ".Z");
  539. /*
  540. * do the uncompress
  541. */
  542. result = _DtHelpCeUncompressFile (inFile, tmpName);
  543. free (inFile);
  544. if (result != 0)
  545. {
  546. errno = ENOENT;
  547. return -1;
  548. }
  549. /*
  550. * now open the uncompressed file
  551. */
  552. *ret_fd = open(tmpName, O_RDONLY);
  553. if (*ret_fd == -1)
  554. result = -1;
  555. else
  556. unlink(tmpName);
  557. }
  558. else
  559. {
  560. errno = CEErrorMalloc;
  561. return -1;
  562. }
  563. }
  564. return result;
  565. } /* End FileOpenRtnFd */
  566. /******************************************************************************
  567. * Semi-Public Functions
  568. ******************************************************************************/
  569. /*****************************************************************************
  570. * Function: char *_DtHelpCeExpandPathname (char *spec, char *filename, char *type,
  571. * char *suffix, char *lang, _DtSubstitutionRec *subs, int num)
  572. *
  573. * Parameters:
  574. * spec Specifies a string with substitution
  575. * characters.
  576. * containing the character set if found.
  577. * filename Specifies the string to substitute for %N.
  578. * type Specifies the string to substitute for %T.
  579. * suffix Specifies the string to substitute for %S.
  580. * lang Specifies the string to substitute for %L.
  581. * subs Specifies the application own specific
  582. * substitutions.
  583. * num Specifies the number of substitution pairs
  584. * in 'subs'.
  585. *
  586. * Memory own by caller:
  587. * returned pointer
  588. *
  589. * Returns: The expanded filename if successful. NULL if errors.
  590. *
  591. * Purpose: Expand a string with %<char> substitution values.
  592. * Default substitutions are:
  593. * %N replaced with 'filename'.
  594. * %T replaced with 'type'
  595. * %S replaced with 'suffix'
  596. * %L replaced with 'lang'
  597. *
  598. * %l replaced with the language sub part of 'lang'.
  599. * %t replaced with the territory sub part of 'lang'.
  600. * %c replaced with the code set sub part of 'lang'.
  601. * Other substitutions can be done via the 'subs' parameter.
  602. *
  603. *****************************************************************************/
  604. char *
  605. _DtHelpCeExpandPathname (
  606. char *spec,
  607. char *filename,
  608. char *type,
  609. char *suffix,
  610. char *lang,
  611. _DtSubstitutionRec *subs,
  612. int num )
  613. {
  614. int i;
  615. int len = 1;
  616. char *ptr;
  617. char *subString;
  618. char *partLang;
  619. char *partTer;
  620. char *partCodeSet;
  621. char pathName [MAXPATHLEN + 5];
  622. Boolean previousSlash = False;
  623. #define MY_NUM 7
  624. _DtSubstitutionRec mySubs [MY_NUM];
  625. if (spec == NULL || *spec == NULL)
  626. {
  627. errno = EINVAL;
  628. return NULL;
  629. }
  630. /*
  631. * fill in the language sub parts
  632. */
  633. if (_DtHelpCeGetLangSubParts (lang, &partLang, &partTer, &partCodeSet))
  634. return NULL;
  635. mySubs[0].match = 'N';
  636. mySubs[0].substitution = filename;
  637. mySubs[1].match = 'T';
  638. mySubs[1].substitution = type;
  639. mySubs[2].match = 'S';
  640. mySubs[2].substitution = suffix;
  641. mySubs[3].match = 'L';
  642. mySubs[3].substitution = lang;
  643. mySubs[4].match = 'l';
  644. mySubs[4].substitution = partLang;
  645. mySubs[5].match = 't';
  646. mySubs[5].substitution = partTer;
  647. mySubs[6].match = 's';
  648. mySubs[6].substitution = partCodeSet;
  649. ptr = pathName;
  650. while (*spec)
  651. {
  652. len = 1;
  653. if (MB_CUR_MAX != 1)
  654. len = mblen (spec, MB_CUR_MAX);
  655. if (len == 1 && *spec == '/')
  656. {
  657. if (previousSlash)
  658. spec++;
  659. else
  660. {
  661. previousSlash = True;
  662. *ptr++ = *spec++;
  663. }
  664. }
  665. else if (len == 1 && *spec == '%')
  666. {
  667. spec++;
  668. switch (*spec)
  669. {
  670. case '\0':
  671. *ptr++ = '%';
  672. break;
  673. case '/':
  674. if (!previousSlash)
  675. {
  676. previousSlash = True;
  677. *ptr++ = *spec;
  678. }
  679. spec++;
  680. break;
  681. default:
  682. i = 0;
  683. while (i < MY_NUM && mySubs && mySubs[i].match != *spec)
  684. i++;
  685. if (i < MY_NUM)
  686. {
  687. if (mySubs[i].substitution != NULL)
  688. {
  689. subString = mySubs[i].substitution;
  690. if (((int)(ptr - pathName + strlen(subString)))
  691. > MAXPATHLEN)
  692. {
  693. errno = CEErrorExceedMaxSize;
  694. return NULL;
  695. }
  696. while (subString && *subString)
  697. *ptr++ = *subString++;
  698. }
  699. }
  700. else
  701. {
  702. i = 0;
  703. while (i < num && subs && subs[i].match != *spec)
  704. i++;
  705. /*
  706. * If the substitution character is not found
  707. * include the character onto the final string.
  708. */
  709. if (i >= num)
  710. *ptr++ = *spec;
  711. else if (subs[i].substitution != NULL)
  712. {
  713. subString = subs[i].substitution;
  714. if (((int)(ptr - pathName + strlen(subString)))
  715. > MAXPATHLEN)
  716. {
  717. errno = CEErrorExceedMaxSize;
  718. return NULL;
  719. }
  720. while (subString && *subString)
  721. *ptr++ = *subString++;
  722. }
  723. }
  724. spec++;
  725. previousSlash = False;
  726. break;
  727. }
  728. }
  729. else
  730. {
  731. previousSlash = False;
  732. do
  733. {
  734. *ptr++ = *spec++;
  735. len--;
  736. } while (len > 0);
  737. }
  738. if (ptr - pathName > MAXPATHLEN)
  739. {
  740. errno = CEErrorExceedMaxSize;
  741. return NULL;
  742. }
  743. }
  744. if (partLang)
  745. free (partLang);
  746. if (partTer)
  747. free (partTer);
  748. if (partCodeSet)
  749. free (partCodeSet);
  750. *ptr = '\0';
  751. ptr = strdup (pathName);
  752. if (ptr == NULL)
  753. errno = CEErrorMalloc;
  754. return ptr;
  755. }
  756. /*****************************************************************************
  757. * Function: char *_DtHelpCeGetLangSubParts (char *lang, char **subLang,
  758. * char **subTer, char **subCodeSet)
  759. *
  760. * Parameters:
  761. * lang Specifies the language string.
  762. * subLang Returns the language sub part of 'lang'
  763. * or NULL.
  764. * subTer Returns the territory sub part of 'lang'
  765. * or NULL.
  766. * subCodeSet Returns the code set sub part of 'lang'
  767. * or NULL.
  768. *
  769. * Memory own by caller:
  770. * subLang
  771. * subTer
  772. * subCodeSet
  773. *
  774. * errno Values:
  775. * EINVAL
  776. * CEErrorMalloc
  777. *
  778. * Returns: 0 if successful, -1 if errors.
  779. *
  780. * Purpose: Break a %l_%t.%c language specification into its sub parts.
  781. *
  782. *****************************************************************************/
  783. int
  784. _DtHelpCeGetLangSubParts (
  785. char *lang,
  786. char **subLang,
  787. char **subTer,
  788. char **subCodeSet )
  789. {
  790. int len;
  791. char *ptr;
  792. char *sLang = NULL;
  793. char *sTer = NULL;
  794. char *sCode = NULL;
  795. if (subLang == NULL || subTer == NULL || subCodeSet == NULL)
  796. {
  797. errno = EINVAL;
  798. return -1;
  799. }
  800. if (lang != NULL && *lang != '\0')
  801. {
  802. /*
  803. * look for lang_ter
  804. */
  805. _DtHelpCeStrchr (lang, "_", MB_CUR_MAX, &ptr);
  806. if (ptr)
  807. {
  808. /*
  809. * do we want this string?
  810. */
  811. if (subLang != NULL)
  812. {
  813. len = ptr - lang;
  814. sLang = (char *) malloc (len + 1);
  815. if (sLang != NULL)
  816. {
  817. strncpy (sLang, lang, len);
  818. sLang[len] = '\0';
  819. }
  820. else
  821. {
  822. errno = CEErrorMalloc;
  823. return -1;
  824. }
  825. }
  826. /*
  827. * just mark that the lang part was found
  828. */
  829. else
  830. sLang = lang;
  831. lang = ptr + 1;
  832. }
  833. /*
  834. * look for lang.codeset
  835. */
  836. _DtHelpCeStrchr (lang, Period, MB_CUR_MAX, &ptr);
  837. if (ptr)
  838. {
  839. len = ptr - lang;
  840. /*
  841. * if it was in the form lang_ter.codeset, sLang will non-null
  842. */
  843. if (sLang != NULL)
  844. {
  845. /*
  846. * do we want to save the territory?
  847. */
  848. if (subTer != NULL)
  849. {
  850. sTer = (char *) malloc (len + 1);
  851. if (sTer != NULL)
  852. {
  853. strncpy (sTer, lang, len);
  854. sTer[len] = '\0';
  855. }
  856. else
  857. {
  858. errno = CEErrorMalloc;
  859. return -1;
  860. }
  861. }
  862. /*
  863. * don't wan to save, but make sure we mark the territory
  864. * as being found (non-null).
  865. */
  866. else
  867. sTer = lang;
  868. }
  869. /*
  870. * the lang was in the form lang.codeset.
  871. * now check to see if want to save the lang portion.
  872. */
  873. else if (subLang != NULL)
  874. {
  875. sLang = (char *) malloc (len + 1);
  876. if (sLang != NULL)
  877. {
  878. strncpy (sLang, lang, len);
  879. sLang[len] = '\0';
  880. }
  881. else
  882. {
  883. errno = CEErrorMalloc;
  884. return -1;
  885. }
  886. }
  887. /*
  888. * didn't want to save the lang portion, but mark as found.
  889. */
  890. else
  891. sLang = lang;
  892. }
  893. /*
  894. * currently pointing at the dot?
  895. */
  896. if (ptr && *ptr == '.')
  897. {
  898. /*
  899. * yes save the code set
  900. */
  901. ptr++;
  902. if (subCodeSet != NULL)
  903. {
  904. sCode = strdup (ptr);
  905. if (sCode == NULL)
  906. {
  907. errno = CEErrorMalloc;
  908. return -1;
  909. }
  910. }
  911. /*
  912. * don't save the code set, but make sure we mark as found
  913. */
  914. else
  915. sCode = ptr;
  916. }
  917. /*
  918. * didn't find a code set, so save the current info.
  919. * If we haven't already processed a lang portion, save as the
  920. * lang.
  921. */
  922. else if (sLang == NULL)
  923. {
  924. if (subLang != NULL)
  925. {
  926. sLang = strdup (lang);
  927. if (sLang == NULL)
  928. {
  929. errno = CEErrorMalloc;
  930. return -1;
  931. }
  932. }
  933. else
  934. sLang = lang;
  935. }
  936. /*
  937. * otherwise this is the territory of the language. Save if desired
  938. */
  939. else if (subTer != NULL)
  940. {
  941. sTer = strdup (lang);
  942. if (sTer == NULL)
  943. {
  944. errno = CEErrorMalloc;
  945. return -1;
  946. }
  947. }
  948. }
  949. if (subLang)
  950. *subLang = sLang;
  951. if (subTer)
  952. *subTer = sTer;
  953. if (subCodeSet)
  954. *subCodeSet = sCode;
  955. return 0;
  956. }
  957. /*****************************************************************************
  958. * Function: int _DtHelpCeGetUncompressedFileName (char *name, char **ret_name)
  959. *
  960. * Parameters: name Specifies the file to open.
  961. * ret_name Returns the name of the uncompressed file.
  962. * This memory must be freed by the caller.
  963. *
  964. * Returns: 0 if required uncompress. ret_name will contain the
  965. * name of the uncompressed file. The caller is required
  966. * to free the memory.
  967. * 1 if no uncompression required. ret_name points to name.
  968. * -1 if a failure occurs
  969. *
  970. * errno Values: EINVAL Specifies an invalid parameter was
  971. * used.
  972. * CEErrorFileSeek
  973. * Specifies the seek offset was invalid.
  974. *
  975. * Purpose: Find out if a file is compressed and uncompress it if it is.
  976. *
  977. *****************************************************************************/
  978. int
  979. _DtHelpCeGetUncompressedFileName (
  980. char *name,
  981. char **ret_name )
  982. {
  983. char *inFile = NULL;
  984. char tmpName[MAXPATHLEN + 1];
  985. int result = 1;
  986. /*
  987. * check to see if the file exists in uncompressed form
  988. */
  989. *ret_name = name;
  990. if (access (name, F_OK) == -1)
  991. {
  992. /*
  993. * get a temporary name
  994. */
  995. (void) tmpnam (tmpName);
  996. /*
  997. * malloc memory for the dot Z file name.
  998. */
  999. inFile = (char *) malloc (strlen (name) + 3);
  1000. if (inFile != NULL)
  1001. {
  1002. /*
  1003. * make the dot Z file
  1004. */
  1005. strcpy (inFile, name);
  1006. strcat (inFile, ".Z");
  1007. /*
  1008. * do the uncompress
  1009. */
  1010. result = _DtHelpCeUncompressFile (inFile, tmpName);
  1011. free (inFile);
  1012. if (result != 0)
  1013. {
  1014. errno = ENOENT;
  1015. return -1;
  1016. }
  1017. *ret_name = strdup (tmpName);
  1018. if (*ret_name == NULL)
  1019. {
  1020. errno = CEErrorMalloc;
  1021. return -1;
  1022. }
  1023. }
  1024. else
  1025. {
  1026. errno = CEErrorMalloc;
  1027. return -1;
  1028. }
  1029. }
  1030. return result;
  1031. }
  1032. /******************************************************************************
  1033. * Function: int _DtHelpCeCompressPathname (char *basePath)
  1034. *
  1035. * Parameters: basePath Specifies the path for the file possibily
  1036. * containing /./, //, and /../.
  1037. *
  1038. * Return Value: 0 for success, -1 for failure.
  1039. * The number of bytes in basePath will be less than or
  1040. * equal to the number of bytes in basePath when passed
  1041. * in.
  1042. *
  1043. * errno Values: EINVAL
  1044. *
  1045. * Purpose: This function compresses directory changes found
  1046. * in a file name path.
  1047. *
  1048. ******************************************************************************/
  1049. int
  1050. _DtHelpCeCompressPathname ( char *basePath )
  1051. {
  1052. int len;
  1053. int result;
  1054. short char1;
  1055. short char2;
  1056. short char3;
  1057. char *ptr = basePath;
  1058. char *prevPtr = NULL;
  1059. if (basePath == NULL || *basePath != '/')
  1060. {
  1061. errno = EINVAL;
  1062. return -1;
  1063. }
  1064. do
  1065. {
  1066. /*
  1067. * for multi-byte environments, check how far single bytes extend.
  1068. */
  1069. char1 = False;
  1070. char2 = False;
  1071. char3 = False;
  1072. if (MB_CUR_MAX == 1 || mblen (&ptr[1], MB_CUR_MAX) == 1)
  1073. {
  1074. char1 = True;
  1075. if (MB_CUR_MAX == 1 || mblen (&ptr[2], MB_CUR_MAX) == 1)
  1076. {
  1077. char2 = True;
  1078. if (MB_CUR_MAX == 1 || mblen (&ptr[3], MB_CUR_MAX) == 1)
  1079. char3 = True;
  1080. }
  1081. }
  1082. /*
  1083. * check for //
  1084. */
  1085. if (char1 == True && ptr[1] == '/')
  1086. strcpy (ptr, (ptr + 1));
  1087. /*
  1088. * check for /./
  1089. */
  1090. else if (char2 == True && ptr[1] == '.' && ptr[2] == '/')
  1091. strcpy (ptr, (ptr + 2));
  1092. /*
  1093. * check for /../
  1094. */
  1095. else if (char3 == True && strncmp (&ptr[1], "../", 3) == 0)
  1096. {
  1097. /*
  1098. * if at the top of the path, just ignore the extra
  1099. * directory change.
  1100. */
  1101. if (prevPtr == NULL)
  1102. strcpy (ptr, (ptr + 3));
  1103. else
  1104. {
  1105. /*
  1106. * compress the /../
  1107. */
  1108. strcpy (prevPtr, (ptr + 3));
  1109. /*
  1110. * reset the current pointer
  1111. */
  1112. ptr = prevPtr;
  1113. /*
  1114. * find the previous slash
  1115. */
  1116. *ptr = '\0';
  1117. result = _DtHelpCeStrrchr(basePath,Slash,MB_CUR_MAX,&prevPtr);
  1118. if (result == -1)
  1119. return -1;
  1120. /*
  1121. * if there is no previous slash, set the pointer to
  1122. * indicate that we're at the top of the path (NULL).
  1123. */
  1124. if (result != 0)
  1125. prevPtr = NULL;
  1126. /*
  1127. * restore the slash (or null byte)
  1128. */
  1129. *ptr = '/';
  1130. }
  1131. }
  1132. else
  1133. {
  1134. /*
  1135. * remember this slash for /../ directory changes
  1136. */
  1137. prevPtr = ptr;
  1138. /*
  1139. * skip this slash, and find the next one.
  1140. */
  1141. ptr++;
  1142. result = _DtHelpCeStrcspn (ptr, "/", MB_CUR_MAX, &len);
  1143. /*
  1144. * if we run into invalid data, error
  1145. */
  1146. if (result == -1)
  1147. return -1;
  1148. ptr += len;
  1149. }
  1150. } while (*ptr != '\0');
  1151. return (0);
  1152. }
  1153. /******************************************************************************
  1154. * Function: char *_DtHelpCeTracePathName (char *path)
  1155. *
  1156. * Parameters:
  1157. * path Specifies the a path to trace and compress
  1158. *
  1159. * Return Value: The new string if successful, NULL otherwise.
  1160. * The new string is owned by the caller and contains
  1161. * an absolute pathname.
  1162. *
  1163. * errno Values: EINVAL Illegal parameter specified.
  1164. * getcwd(2) errno set via a getcwd call.
  1165. * readlink(2) errno set via a readlink call.
  1166. * DtErrorMalloc
  1167. * DtErrorExceedMaxSize The new path will exceed
  1168. * max_size.
  1169. * DtErrorIllegalPath The compression will required
  1170. * the path to change to a parent
  1171. * directory beyond the beginning
  1172. * of basePath.
  1173. *
  1174. * Purpose: This function is called to trace the path of a file.
  1175. * It can contain symbolic links, //, /./, and /../.
  1176. *
  1177. ******************************************************************************/
  1178. char *
  1179. _DtHelpCeTracePathName (char *path)
  1180. {
  1181. int result;
  1182. int len;
  1183. char c;
  1184. char *ptr;
  1185. char *prev;
  1186. char newPath [2 * MAXPATHLEN + 2];
  1187. char linkPath [MAXPATHLEN + 2];
  1188. char tempPath [MAXPATHLEN + 2];
  1189. if (path == NULL || *path == '\0')
  1190. {
  1191. errno = EINVAL;
  1192. return NULL;
  1193. }
  1194. /*
  1195. * initialize the new path
  1196. */
  1197. newPath[0] = '\0';
  1198. /*
  1199. * if the path passed in does not start with a slash,
  1200. * get the current working directory and append the path to it.
  1201. */
  1202. if ((MB_CUR_MAX == 1 || mblen(path, MB_CUR_MAX) == 1) && *path != '/')
  1203. {
  1204. if (getcwd (newPath, MAXPATHLEN) == NULL)
  1205. return NULL;
  1206. strcat (newPath, "/");
  1207. }
  1208. /*
  1209. * put the path in the working path buffer (or append it to
  1210. * the current working directory).
  1211. */
  1212. strcat (newPath, path);
  1213. /*
  1214. * Compress out the slashes and directory changes.
  1215. */
  1216. if (_DtHelpCeCompressPathname (newPath) != 0)
  1217. return NULL;
  1218. ptr = newPath;
  1219. do
  1220. {
  1221. /*
  1222. * point to the first character of the next directory
  1223. */
  1224. prev = ptr + 1;
  1225. /*
  1226. * get the next slash after that
  1227. */
  1228. result = _DtHelpCeStrcspn (prev, "/", MB_CUR_MAX, &len);
  1229. if (result == -1)
  1230. return NULL;
  1231. /*
  1232. * Found either a slash or a null byte.
  1233. * place the string terminator at this point
  1234. */
  1235. ptr = prev + len;
  1236. c = *ptr;
  1237. *ptr = '\0';
  1238. /*
  1239. * find out if this path is a symbolic link
  1240. */
  1241. result = readlink (newPath, linkPath, MAXPATHLEN);
  1242. /*
  1243. * replace the slash (or null byte).
  1244. */
  1245. *ptr = c;
  1246. /*
  1247. * check for the result of the readlink call
  1248. */
  1249. if (result == -1)
  1250. {
  1251. /*
  1252. * if this was NOT a symbolic link, errno should be EINVAL
  1253. */
  1254. if (errno != EINVAL)
  1255. return NULL;
  1256. }
  1257. else
  1258. {
  1259. /*
  1260. * put the null byte on the end of the symbolic link string.
  1261. */
  1262. linkPath [result] = '\0';
  1263. /*
  1264. * Save the rest of the string that we haven't processed
  1265. * for tacking on after the new link path has been
  1266. * dropped into the path.
  1267. */
  1268. strcpy (tempPath, ptr);
  1269. /*
  1270. * is it an absolute path? Simply replace the path
  1271. * being search with the new link path.
  1272. */
  1273. if (*linkPath == '/')
  1274. strcpy (newPath, linkPath);
  1275. else
  1276. {
  1277. /*
  1278. * this is a relative link.
  1279. * prev is looking at the first character of this directory.
  1280. * replace with the link.
  1281. */
  1282. strcpy (prev, linkPath);
  1283. }
  1284. /*
  1285. * now tack on the rest of the name
  1286. */
  1287. strcat (newPath, tempPath);
  1288. /*
  1289. * compress out the directory changes.
  1290. */
  1291. if (_DtHelpCeCompressPathname (newPath) != 0)
  1292. return NULL;
  1293. /*
  1294. * start again from the top, until we have a clean path
  1295. */
  1296. ptr = newPath;
  1297. }
  1298. } while (*ptr != '\0');
  1299. return (strdup (newPath));
  1300. }
  1301. /******************************************************************************
  1302. * Function: char *_DtHelpCeTraceFilenamePath (char *file_path)
  1303. *
  1304. * Parameters:
  1305. * file_path Specifies the a path to trace and compress
  1306. *
  1307. * Return Value: The new string if successful, NULL otherwise.
  1308. * The new string is owned by the caller and
  1309. * contains an absolute filename path.
  1310. *
  1311. * errno Values: EINVAL Illegal parameter specified.
  1312. * getcwd(2) errno set via a getcwd call.
  1313. * readlink(2) errno set via a readlink call.
  1314. * DtErrorMalloc
  1315. * DtErrorExceedMaxSize The new path will exceed
  1316. * max_size.
  1317. * DtErrorIllegalPath The compression will required
  1318. * the path to change to a parent
  1319. * directory beyond the beginning
  1320. * of basePath.
  1321. *
  1322. * Purpose: This function is called to trace a filename path.
  1323. * It can contain symbolic links, //, /./, and /../.
  1324. *
  1325. ******************************************************************************/
  1326. char *
  1327. _DtHelpCeTraceFilenamePath (char *file_path)
  1328. {
  1329. int result;
  1330. int done = False;
  1331. char *newPath;
  1332. char *oldName;
  1333. char *namePlace;
  1334. char workName [MAXPATHLEN + 2];
  1335. char newName [MAXPATHLEN + 2];
  1336. char linkName [MAXPATHLEN + 2];
  1337. if (file_path == NULL || *file_path == '\0')
  1338. {
  1339. errno = EINVAL;
  1340. return NULL;
  1341. }
  1342. workName[0] = '\0';
  1343. if ((MB_CUR_MAX == 1 || mblen(file_path, MB_CUR_MAX) == 1)
  1344. && *file_path != '/')
  1345. {
  1346. if (getcwd(workName, MAXPATHLEN) == NULL)
  1347. return NULL;
  1348. strcat(workName, "/");
  1349. }
  1350. strcat (workName, file_path);
  1351. do
  1352. {
  1353. /*
  1354. * find and save the old filename
  1355. */
  1356. result = _DtHelpCeStrrchr(workName, Slash, MB_CUR_MAX, &oldName);
  1357. if (result == -1)
  1358. return NULL;
  1359. /*
  1360. * terminate the path
  1361. */
  1362. *oldName = '\0';
  1363. /*
  1364. * trace the path, resolving the symbolic links
  1365. * and directory changes. If /filename given,
  1366. * skip the path tracing.
  1367. */
  1368. newName[0] = '\0';
  1369. if (workName[0] != '\0')
  1370. {
  1371. newPath = _DtHelpCeTracePathName(workName);
  1372. if (newPath == NULL)
  1373. return NULL;
  1374. /*
  1375. * copy the new path and free the allocated copy
  1376. */
  1377. strcpy (newName, newPath);
  1378. free (newPath);
  1379. }
  1380. /*
  1381. * replace the slash
  1382. */
  1383. *oldName = '/';
  1384. /*
  1385. * now append the slash and filename (pointed to by oldName)
  1386. * onto the end of the new path.
  1387. */
  1388. namePlace = newName + strlen (newName);
  1389. strcpy (namePlace, oldName);
  1390. /*
  1391. * See if the absolute path/filename is a symbolic link.
  1392. */
  1393. result = readlink (newName, linkName, MAXPATHLEN);
  1394. if (result == -1)
  1395. {
  1396. if (errno != EINVAL)
  1397. return NULL;
  1398. done = True;
  1399. }
  1400. else
  1401. {
  1402. /*
  1403. * put the null byte on the end of the symbolic
  1404. * link string.
  1405. */
  1406. linkName [result] = '\0';
  1407. if (*linkName == '/')
  1408. strcpy (newName, linkName);
  1409. else
  1410. {
  1411. /*
  1412. * overwrite the filename with the link
  1413. * but don't overwrite the slash.
  1414. */
  1415. strcpy ((namePlace + 1), linkName);
  1416. }
  1417. /*
  1418. * make a copy of the new name to work on
  1419. */
  1420. strcpy (workName, newName);
  1421. }
  1422. } while (!done);
  1423. return (strdup (newName));
  1424. }
  1425. /******************************************************************************
  1426. * Core Engine Semi-Public Functions
  1427. ******************************************************************************/
  1428. /*****************************************************************************
  1429. * Function: char *_DtHelpCeGetVolumeName (_DtHelpVolumeHdl volume)
  1430. *
  1431. * Parameters:
  1432. *
  1433. * Returns: ptr to the name of the volume, NULL otherwise.
  1434. *
  1435. * Purpose: Get the fully qualified volume name.
  1436. *
  1437. *****************************************************************************/
  1438. char *
  1439. _DtHelpCeGetVolumeName (
  1440. _DtHelpVolumeHdl volume_handle)
  1441. {
  1442. char *volFile;
  1443. _DtHelpProcessLock();
  1444. volFile = ((_DtHelpVolume)volume_handle)->volFile;
  1445. _DtHelpProcessUnlock();
  1446. return volFile;
  1447. } /* End __DtHelpCeGetVolumeName */
  1448. /*****************************************************************************
  1449. * Function: int _DtHelpCeFileOpenAndSeek (char *name, int offset, int fildes,
  1450. * BufFilePtr *ret_file)
  1451. *
  1452. * Parameters: name Specifies the file to open.
  1453. * offset Specifies location within the file to seek to.
  1454. *
  1455. * Returns: 0 if successful, -1 if a failure occurs
  1456. *
  1457. * errno Values: EINVAL Specifies an invalid parameter was
  1458. * used.
  1459. * CEErrorFileSeek
  1460. * Specifies the seek offset was invalid.
  1461. *
  1462. * Purpose: Open a file and seek to a specific place.
  1463. *
  1464. *****************************************************************************/
  1465. int
  1466. _DtHelpCeFileOpenAndSeek (
  1467. char *name,
  1468. int offset,
  1469. int fd,
  1470. BufFilePtr *ret_file,
  1471. time_t *ret_time)
  1472. {
  1473. unsigned char fileMagic[4];
  1474. int bytesRead;
  1475. int result = 0;
  1476. int tmpFd;
  1477. struct stat buf;
  1478. /*
  1479. * Get the file descriptor of the uncompressed file
  1480. */
  1481. tmpFd = fd;
  1482. if (fd == -1)
  1483. {
  1484. result = FileOpenRtnFd (name, &tmpFd);
  1485. if (result == -1)
  1486. return -1;
  1487. }
  1488. if (ret_time != NULL)
  1489. {
  1490. (void) fstat(tmpFd, &buf);
  1491. *ret_time = buf.st_mtime;
  1492. }
  1493. /*
  1494. * make sure we don't go past the end of the file
  1495. */
  1496. result = lseek (tmpFd, 0, SEEK_END);
  1497. if (result != -1)
  1498. {
  1499. if (result > offset)
  1500. result = lseek (tmpFd, offset, SEEK_SET);
  1501. else
  1502. {
  1503. result = -1;
  1504. errno = CEErrorFileSeek;
  1505. }
  1506. }
  1507. if (result == -1)
  1508. {
  1509. if (fd == -1)
  1510. close (tmpFd);
  1511. return -1;
  1512. }
  1513. bytesRead = read(tmpFd, fileMagic, 4);
  1514. if (bytesRead != 4)
  1515. { /* something's wrong in reading the file */
  1516. if (fd == -1)
  1517. close (tmpFd);
  1518. return -1;
  1519. }
  1520. if (!*fileMagic)
  1521. { /* started with compressed file magic number */
  1522. CECompressInfoPtr myInfo;
  1523. BufFilePtr inputRaw;
  1524. /*
  1525. * allocate the private information
  1526. */
  1527. myInfo = (CECompressInfoPtr) malloc(sizeof(CECompressInfo));
  1528. if (myInfo == NULL)
  1529. {
  1530. if (fd == -1)
  1531. close (tmpFd);
  1532. errno = CEErrorMalloc;
  1533. return -1;
  1534. }
  1535. /*
  1536. * set the information
  1537. * set the size to the maximum number of bytes we
  1538. * want to read.
  1539. */
  1540. myInfo->fd = tmpFd;
  1541. myInfo->size =
  1542. (((fileMagic[1] * 256) + fileMagic[2]) * 256) + fileMagic[3];
  1543. /*
  1544. * start with raw functionality
  1545. */
  1546. inputRaw = _DtHelpCeBufFileRdRawZ(myInfo);
  1547. if (inputRaw == NULL)
  1548. {
  1549. if (fd == -1)
  1550. close (tmpFd);
  1551. return -1;
  1552. }
  1553. *ret_file = _DtHelpCeBufFilePushZ(inputRaw);
  1554. if (*ret_file == NULL)
  1555. {
  1556. _DtHelpCeBufFileClose(inputRaw, (fd == -1 ? True : False));
  1557. return -1;
  1558. }
  1559. }
  1560. else
  1561. {
  1562. /*
  1563. * not a compressed file, back up the four bytes we read
  1564. */
  1565. result = lseek (tmpFd, offset, SEEK_SET);
  1566. if (result == -1)
  1567. {
  1568. if (fd == -1)
  1569. close (tmpFd);
  1570. return -1;
  1571. }
  1572. /*
  1573. * read with raw functionality
  1574. */
  1575. *ret_file = _DtHelpCeBufFileRdWithFd(tmpFd);
  1576. if (*ret_file == NULL)
  1577. {
  1578. if (fd == -1)
  1579. close (tmpFd);
  1580. return -1;
  1581. }
  1582. }
  1583. return 0;
  1584. } /* End of _DtHelpCeFileOpenAndSeek */
  1585. /******************************************************************************
  1586. * Core Engine Public Functions
  1587. ******************************************************************************/
  1588. /******************************************************************************
  1589. * Function: int _DtHelpOpenVolume (char *volFile, _DtHelpVolume *retVol);
  1590. *
  1591. * Parameters: volFile Specifies the name of the Help Volume file
  1592. * to load.
  1593. *
  1594. * retVol Returns the handle to the loaded volume.
  1595. * If a volume is opened several times, the
  1596. * same handle will be returned each time.
  1597. *
  1598. * Return Value: 0 if successful, -1 if a failure occurred.
  1599. *
  1600. * errno Values: EINVAL Illegal parameter specified.
  1601. * getcwd(2) errno set via a getcwd call.
  1602. * readlink(2) errno set via a readlink call.
  1603. * CEErrorMalloc
  1604. * CEErrorExceedMaxSize The new path will exceed
  1605. * max_size.
  1606. * CEErrorIllegalPath The compression will required
  1607. * the path to change to a parent
  1608. * directory beyond the beginning
  1609. * of basePath.
  1610. * CEErrorIllegalDatabaseFile
  1611. * Specifies that 'volFile' is
  1612. * an illegal database file.
  1613. *
  1614. *
  1615. * Purpose: This function must be called to open a Help Volume file
  1616. * before any of the information in the volume can be
  1617. * accessed.
  1618. *
  1619. ******************************************************************************/
  1620. int
  1621. _DtHelpOpenVolume (
  1622. char *volFile,
  1623. _DtHelpVolumeHdl *retVol)
  1624. {
  1625. int result = 0;
  1626. _DtHelpVolume vol, prevVol;
  1627. _DtHelpProcessLock();
  1628. if (volFile == NULL || retVol == NULL)
  1629. {
  1630. errno = EINVAL;
  1631. _DtHelpProcessUnlock();
  1632. return -1;
  1633. }
  1634. /*
  1635. * follow all the symbolic links and get the absolute path and filename.
  1636. */
  1637. volFile = _DtHelpCeTraceFilenamePath(volFile);
  1638. if (volFile == NULL)
  1639. {
  1640. _DtHelpProcessUnlock();
  1641. return -1;
  1642. }
  1643. /* Search the volume chain to see if it is already open. */
  1644. prevVol = NULL;
  1645. vol = volChain;
  1646. while (vol != NULL && strcmp (vol->volFile, volFile))
  1647. {
  1648. prevVol = vol;
  1649. vol = vol->nextVol;
  1650. }
  1651. if (vol)
  1652. {
  1653. vol->openCount++;
  1654. free(volFile);
  1655. }
  1656. else /* if (vol == NULL) */
  1657. {
  1658. /* If it isn't open, open it and insert it in the chain. */
  1659. result = VolumeLoad (volFile, &vol);
  1660. if (result == 0)
  1661. {
  1662. if (prevVol == NULL)
  1663. volChain = vol;
  1664. else
  1665. prevVol->nextVol = vol;
  1666. }
  1667. }
  1668. /* Return the volume handle and a status indicating success/failure. */
  1669. *retVol = (_DtHelpVolumeHdl) vol;
  1670. _DtHelpProcessUnlock();
  1671. return result;
  1672. }
  1673. /******************************************************************************
  1674. * Function: int _DtHelpCeUpVolumeOpenCnt (_DtHelpVolumeHdl vol);
  1675. *
  1676. * Parameters: vol Specifies the loaded volume.
  1677. *
  1678. * Return Value: 0 if successful, -1 if a failure occurs
  1679. *
  1680. * errno Values: EINVAL 'vol' was NULL, no volumes open or
  1681. * 'vol' does not exist.
  1682. *
  1683. * Purpose: When the volume is no longer needed, it should be
  1684. * closed with this call. If the volume has been opened
  1685. * several times, closing it will just decrement the
  1686. * reference count. When it has been closed as many times
  1687. * as it was opened, the memory it is using will be freed
  1688. * and any handles to the volume will be invalid.
  1689. *
  1690. ******************************************************************************/
  1691. int
  1692. _DtHelpCeUpVolumeOpenCnt (
  1693. _DtHelpVolumeHdl volume)
  1694. {
  1695. _DtHelpVolume prevVol;
  1696. _DtHelpVolume vol = (_DtHelpVolume)volume;
  1697. _DtHelpProcessLock();
  1698. if (vol == NULL || volChain == NULL)
  1699. {
  1700. errno = EINVAL;
  1701. _DtHelpProcessUnlock();
  1702. return (-1);
  1703. }
  1704. /*
  1705. * check to see if this volume is in our chain
  1706. */
  1707. if (vol != volChain)
  1708. {
  1709. if (CheckVolList (vol, &prevVol) == -1)
  1710. {
  1711. errno = EINVAL;
  1712. _DtHelpProcessUnlock();
  1713. return (-1);
  1714. }
  1715. }
  1716. /*
  1717. * increment it's usage count.
  1718. */
  1719. vol->openCount++;
  1720. _DtHelpProcessUnlock();
  1721. return (0);
  1722. }
  1723. /******************************************************************************
  1724. * Function: int _DtHelpCloseVolume (_DtHelpVolumeHdl vol);
  1725. *
  1726. * Parameters: vol Specifies the loaded volume.
  1727. *
  1728. * Return Value: 0 if successful, -1 if a failure occurs
  1729. *
  1730. * errno Values: EINVAL 'vol' was NULL, no volumes open or
  1731. * 'vol' does not exist.
  1732. *
  1733. * Purpose: When the volume is no longer needed, it should be
  1734. * closed with this call. If the volume has been opened
  1735. * several times, closing it will just decrement the
  1736. * reference count. When it has been closed as many times
  1737. * as it was opened, the memory it is using will be freed
  1738. * and any handles to the volume will be invalid.
  1739. *
  1740. ******************************************************************************/
  1741. int
  1742. _DtHelpCloseVolume (
  1743. _DtHelpVolumeHdl volume)
  1744. {
  1745. _DtHelpVolume prevVol;
  1746. _DtHelpVolume vol = (_DtHelpVolume)volume;
  1747. _DtHelpProcessLock();
  1748. if (vol == NULL || volChain == NULL)
  1749. {
  1750. errno = EINVAL;
  1751. _DtHelpProcessUnlock();
  1752. return (-1);
  1753. }
  1754. /*
  1755. * check to see if this volume is in our chain
  1756. */
  1757. if (vol != volChain)
  1758. {
  1759. if (CheckVolList (vol, &prevVol) == -1)
  1760. {
  1761. errno = EINVAL;
  1762. _DtHelpProcessUnlock();
  1763. return (-1);
  1764. }
  1765. }
  1766. /*
  1767. * decrement it's usage count.
  1768. */
  1769. vol->openCount--;
  1770. if (vol->openCount == 0)
  1771. {
  1772. /* The volume is no longer needed. Unlink it from the chain
  1773. and free it. */
  1774. if (vol == volChain)
  1775. volChain = volChain->nextVol;
  1776. else
  1777. prevVol->nextVol = vol->nextVol;
  1778. VolumeUnload (vol);
  1779. }
  1780. _DtHelpProcessUnlock();
  1781. return (0);
  1782. }
  1783. /*****************************************************************************
  1784. * Function: int _DtHelpCeGetTopTopicId (_DtHelpVolume vol,
  1785. * char **ret_idString)
  1786. *
  1787. * Parameters: vol Specifies the loaded volume
  1788. * ret_idString Returns the location ID of the
  1789. * the top level topic.
  1790. *
  1791. * Memory own by caller:
  1792. * ret_idString
  1793. *
  1794. * Returns: True for success, False if a failure occurs.
  1795. *
  1796. * errno Values: EINVAL Specifies an invalid parameter was
  1797. * used.
  1798. * CEErrorMissingTopTopicRes
  1799. * Specifies that the 'TopTopic/topTopic'
  1800. * resource is missing from the database.
  1801. * CEErrorMalloc
  1802. *
  1803. * Purpose: Get the information to access the top level topic.
  1804. *
  1805. *****************************************************************************/
  1806. int
  1807. _DtHelpCeGetTopTopicId (
  1808. _DtHelpVolumeHdl volume,
  1809. char **ret_idString )
  1810. {
  1811. int found = False;
  1812. _DtHelpVolume vol = (_DtHelpVolume)volume;
  1813. _DtHelpProcessLock();
  1814. if (vol == NULL || ret_idString == NULL || CheckVolList(vol, NULL) == -1)
  1815. errno = EINVAL;
  1816. else
  1817. {
  1818. /*
  1819. * What type of volume is it?
  1820. */
  1821. if (vol->sdl_flag == False)
  1822. (void) _DtHelpCeGetCcdfTopTopic(vol, ret_idString);
  1823. else
  1824. *ret_idString = _DtHelpCeGetSdlHomeTopicId((_DtHelpVolumeHdl) vol);
  1825. if (*ret_idString != NULL)
  1826. *ret_idString = strdup(*ret_idString);
  1827. if (*ret_idString != NULL)
  1828. found = True;
  1829. }
  1830. _DtHelpProcessUnlock();
  1831. return found;
  1832. } /* End _DtHelpCeGetTopTopicId */
  1833. /*****************************************************************************
  1834. * Function: int _DtHelpCeFindId (_DtHelpVolume vol, char *target_id,
  1835. * int fd,
  1836. * char *ret_name, int *ret_offset)
  1837. *
  1838. * Parameters: vol Specifies the loaded volume
  1839. * target_id Specifies target location ID
  1840. * fd Specifies the locked file descriptor.
  1841. * ret_name Returns a null terminated string
  1842. * containing a fully qualified path to
  1843. * the file that contains 'target_id'.
  1844. * ret_offset Returns the offset into 'ret_name'
  1845. * to the topic that contains 'target_id'.
  1846. *
  1847. * Memory own by caller:
  1848. * ret_name
  1849. *
  1850. * Returns: True if successful, False if a failure occurs
  1851. *
  1852. * errno Values: EINVAL Specifies an invalid parameter was
  1853. * used.
  1854. * CEErrorMalloc
  1855. * CEErrorMissingFilenameRes
  1856. * Specifies that the 'Filename/filename'
  1857. * resource for 'topic' does not exist.
  1858. * CEErrorMissingFileposRes
  1859. * If the resource is not in the
  1860. * database or if the resource NULL.
  1861. * CEErrorLocIdNotFound
  1862. * Specifies that 'locId' was not
  1863. * found.
  1864. *
  1865. * Purpose: Find which topic contains a specified locationID.
  1866. *
  1867. ********************************************************