2
0

Access.c 64 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /* $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 existence 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 == '\0')
  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. snprintf(tempPath, sizeof(tempPath), "%s", 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. snprintf(newName, sizeof(newName), "%s", 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. *****************************************************************************/
  1868. int
  1869. _DtHelpCeFindId (
  1870. _DtHelpVolumeHdl volume,
  1871. char *target_id,
  1872. int fd,
  1873. char **ret_name,
  1874. int *ret_offset )
  1875. {
  1876. _DtHelpVolume vol = (_DtHelpVolume)volume;
  1877. int result;
  1878. _DtHelpProcessLock();
  1879. /*
  1880. * check the parameters
  1881. */
  1882. if (vol == NULL || target_id == NULL || ret_name == NULL ||
  1883. ret_offset == NULL || CheckVolList (vol, NULL) == -1)
  1884. {
  1885. errno = EINVAL;
  1886. _DtHelpProcessUnlock();
  1887. return False;
  1888. }
  1889. /*
  1890. * What type of volume is it?
  1891. */
  1892. if (vol->sdl_flag == False)
  1893. {
  1894. result = _DtHelpCeFindCcdfId(vol, target_id, ret_name, ret_offset);
  1895. }
  1896. else
  1897. {
  1898. result = _DtHelpCeFindSdlId(vol, target_id, fd, ret_name, ret_offset);
  1899. }
  1900. _DtHelpProcessUnlock();
  1901. return result;
  1902. } /* End _DtHelpCeFindId */
  1903. /*****************************************************************************
  1904. * Function: int _DtHelpCeGetKeywordList (_DtHelpVolume vol, char ***ret_keywords)
  1905. *
  1906. * Parameters: vol Specifies the loaded volume
  1907. * ret_keywords Returns a NULL-terminated string array
  1908. * containing the sorted list of keywords in the
  1909. * volume. This array is NOT owned by the caller
  1910. * and should only be read or copied.
  1911. *
  1912. * Returns: The count of keywords associated with the volume if successful.
  1913. * -1 if a failure occurs;
  1914. *
  1915. * errno Values: EINVAL Specifies an invalid parameter was
  1916. * used.
  1917. * CEErrorMalloc
  1918. * CEErrorIllegalDatabaseFile
  1919. * Specifies that the keyword file is
  1920. * invalid or corrupt.
  1921. * CEErrorMissingKeywordsRes
  1922. * Specifies that the keyword file does
  1923. * not contain the 'Keywords/keywords'
  1924. * resource or the resource is NULL
  1925. *
  1926. * Purpose: Get the list of keywords contained in a volume.
  1927. *
  1928. *****************************************************************************/
  1929. int
  1930. _DtHelpCeGetKeywordList (
  1931. _DtHelpVolumeHdl volume,
  1932. char ***ret_keywords )
  1933. {
  1934. int nameCount = -1;
  1935. _DtHelpVolume vol = (_DtHelpVolume)volume;
  1936. if (vol == NULL || ret_keywords == NULL || CheckVolList (vol, NULL) == -1)
  1937. errno = EINVAL;
  1938. else if (GetVolumeKeywords (vol, ret_keywords) == 0)
  1939. {
  1940. nameCount = 0;
  1941. while (*ret_keywords && (*ret_keywords)[nameCount])
  1942. nameCount++;
  1943. }
  1944. return nameCount;
  1945. } /* End _DtHelpCeGetKeywordList */
  1946. /*****************************************************************************
  1947. * Function: int _DtHelpCeFindKeyword (_DtHelpVolume vol, char *target, char ***ret_ids)
  1948. *
  1949. * Parameters: vol Specifies the loaded volume
  1950. * target The target keyword.
  1951. * ret_ids Returns a null terminated list of location
  1952. * ids associated with the target keyword.
  1953. *
  1954. * Returns: The count of ids associated with the keyword if successful.
  1955. * -1 if a failure occurs;
  1956. *
  1957. * errno Values: EINVAL Specifies an invalid parameter was
  1958. * used.
  1959. * CEErrorNoKeywordList
  1960. * Specifies that the volume does not
  1961. * have a keyword list.
  1962. * CEErrorIllegalKeyword
  1963. * Specifies that 'target' was not
  1964. * found.
  1965. * CEErrorMalloc
  1966. * CEErrorIllegalDatabaseFile
  1967. * Specifies that the keyword file is
  1968. * invalid or corrupt.
  1969. * CEErrorMissingKeywordsRes
  1970. * Specifies that the keyword file does
  1971. * not contain the 'Keywords/keywords'
  1972. * resource or the resource is NULL
  1973. *
  1974. * Purpose: Get the list of location ids associated with a keyword
  1975. *
  1976. *****************************************************************************/
  1977. int
  1978. _DtHelpCeFindKeyword (
  1979. _DtHelpVolumeHdl volume,
  1980. char *target,
  1981. char ***ret_ids )
  1982. {
  1983. int nameCount = -1;
  1984. _DtHelpVolume vol = (_DtHelpVolume)volume;
  1985. if (vol == NULL || target == NULL || ret_ids == NULL ||
  1986. CheckVolList (vol, NULL) == -1)
  1987. errno = EINVAL;
  1988. else if (GetKeywordTopics (vol, target, ret_ids) == 0)
  1989. {
  1990. nameCount = 0;
  1991. while (*ret_ids && (*ret_ids)[nameCount])
  1992. nameCount++;
  1993. }
  1994. return nameCount;
  1995. } /* End _DtHelpCeFindKeyword */
  1996. /*****************************************************************************
  1997. * Function: int _DtHelpGetTopicTitle (
  1998. * _DtHelpVolumeHdl volume,
  1999. * char *id, char **ret_title)
  2000. *
  2001. * Parameters: volume Specifies the volume containing the id.
  2002. * id Specifies the id for the topic desired.
  2003. * ret_title Returns a null terminated string containing
  2004. * the title.
  2005. *
  2006. * Memory own by caller:
  2007. * ret_title
  2008. *
  2009. * Returns: 0 if successful, -2 if didn't find the id,
  2010. * otherwise -1.
  2011. *
  2012. * errno Values: EINVAL Specifies an invalid parameter was
  2013. * used.
  2014. *
  2015. * Purpose: Get the title of a topic.
  2016. *
  2017. *****************************************************************************/
  2018. int
  2019. _DtHelpGetTopicTitle (
  2020. _DtHelpVolumeHdl volume,
  2021. char *id,
  2022. char **ret_title)
  2023. {
  2024. int result;
  2025. char *abbrevTitle;
  2026. _DtHelpVolume vol = (_DtHelpVolume)volume;
  2027. if (volume == NULL || id == NULL ||
  2028. CheckVolList (vol, NULL) == -1 || ret_title == NULL)
  2029. {
  2030. errno = EINVAL;
  2031. return -1;
  2032. }
  2033. /*
  2034. * Try to get the title via the <TOPIC> and <ABBREV> tags.
  2035. */
  2036. result = GetTopicTitleAndAbbrev(vol, id, ret_title, &abbrevTitle);
  2037. if (result == 0)
  2038. {
  2039. /*
  2040. * If we have a abbreviated title, return it instead.
  2041. */
  2042. if (abbrevTitle)
  2043. {
  2044. if (*ret_title)
  2045. free ((char *) *ret_title);
  2046. *ret_title = abbrevTitle;
  2047. }
  2048. }
  2049. return result;
  2050. } /* End _DtHelpGetTopicTitle */
  2051. /*****************************************************************************
  2052. * Function: int _DtHelpCeMapTargetToId (_DtHelpVolume vol,
  2053. * char *target_id,
  2054. * char *ret_id)
  2055. *
  2056. * Parameters: vol Specifies the loaded volume
  2057. * target_id Specifies target location ID
  2058. * ret_id Returns the id containing the target_id.
  2059. * This memory *IS NOT* owned by the caller.
  2060. *
  2061. * Returns: 0 if successful, -1 if a failure occurs
  2062. *
  2063. * Purpose: Find which topic contains a specified locationID.
  2064. *
  2065. *****************************************************************************/
  2066. int
  2067. _DtHelpCeMapTargetToId (
  2068. _DtHelpVolumeHdl volume,
  2069. char *target_id,
  2070. char **ret_id)
  2071. {
  2072. _DtHelpVolume vol = (_DtHelpVolume)volume;
  2073. int result;
  2074. _DtHelpProcessLock();
  2075. /*
  2076. * check the parameters
  2077. */
  2078. if (vol == NULL || target_id == NULL || ret_id == NULL ||
  2079. CheckVolList (vol, NULL) == -1)
  2080. {
  2081. errno = EINVAL;
  2082. _DtHelpProcessUnlock();
  2083. return -1;
  2084. }
  2085. /*
  2086. * What type of volume is it?
  2087. */
  2088. if (vol->sdl_flag == False)
  2089. {
  2090. result = _DtHelpCeMapCcdfTargetToId(vol, target_id, ret_id);
  2091. }
  2092. else
  2093. {
  2094. result = _DtHelpCeMapIdToSdlTopicId(vol, target_id, ret_id);
  2095. }
  2096. _DtHelpProcessUnlock();
  2097. return result;
  2098. } /* End _DtHelpCeMapTargetToId */
  2099. /*****************************************************************************
  2100. * Function: char * _DtHelpGetVolumeLocale (_DtHelpVolume vol)
  2101. *
  2102. * Parameters: vol Specifies the loaded volume
  2103. *
  2104. * Returns: The pointer to the locale string if successful. Otherwise
  2105. * NULL.
  2106. *
  2107. * Purpose: Get the locale of the specified volume.
  2108. * Returns the locale in a unix specific format
  2109. * - locale[_ter][.charset] - This memory is owned by
  2110. * the caller.
  2111. *
  2112. *****************************************************************************/
  2113. char *
  2114. _DtHelpGetVolumeLocale (
  2115. _DtHelpVolumeHdl volume)
  2116. {
  2117. _DtHelpVolume vol = (_DtHelpVolume)volume;
  2118. char *result;
  2119. _DtHelpProcessLock();
  2120. /*
  2121. * check the parameters
  2122. */
  2123. if (vol == NULL || CheckVolList (vol, NULL) == -1)
  2124. {
  2125. errno = EINVAL;
  2126. _DtHelpProcessUnlock();
  2127. return NULL;
  2128. }
  2129. /*
  2130. * What type of volume is it?
  2131. */
  2132. if (vol->sdl_flag == False)
  2133. {
  2134. result = _DtHelpCeGetCcdfVolLocale(vol);
  2135. }
  2136. else
  2137. {
  2138. result = _DtHelpCeGetSdlVolumeLocale(vol);
  2139. }
  2140. _DtHelpProcessUnlock();
  2141. return result;
  2142. } /* End _DtHelpGetVolumeLocale */
  2143. /*****************************************************************************
  2144. * Function: int _DtHelpCeGetDocStamp (_DtHelpVolumeHdl volume, char **ret_doc,
  2145. * char **ret_time)
  2146. *
  2147. * Parameters: volume Specifies the loaded volume
  2148. * ret_doc Returns the doc id.
  2149. * ret_time Returns the time stamp.
  2150. *
  2151. * Memory: Caller owns the string in ret_doc and ret_time.
  2152. *
  2153. * Returns: 0 if successful, -2 if the volume does not contain
  2154. * one or the other, -1 if any other failure.
  2155. *
  2156. * Purpose: Get doc id and time stamp of a volume.
  2157. *
  2158. *****************************************************************************/
  2159. int
  2160. _DtHelpCeGetDocStamp (
  2161. _DtHelpVolumeHdl volume,
  2162. char **ret_doc,
  2163. char **ret_time)
  2164. {
  2165. _DtHelpVolume vol = (_DtHelpVolume)volume;
  2166. int result;
  2167. _DtHelpProcessLock();
  2168. /*
  2169. * check the parameters
  2170. */
  2171. if (vol == NULL || CheckVolList (vol, NULL) == -1)
  2172. {
  2173. errno = EINVAL;
  2174. _DtHelpProcessUnlock();
  2175. return 0;
  2176. }
  2177. /*
  2178. * What type of volume is it?
  2179. */
  2180. if (vol->sdl_flag == False)
  2181. {
  2182. result = _DtHelpCeGetCcdfDocStamp (vol, ret_doc, ret_time);
  2183. }
  2184. else
  2185. {
  2186. result = _DtHelpCeGetSdlDocStamp(vol, ret_doc, ret_time);
  2187. }
  2188. _DtHelpProcessUnlock();
  2189. return result;
  2190. } /* End _DtHelpCeGetDocStamp */
  2191. /*****************************************************************************
  2192. * Function: char * _DtHelpCeGetTopicChilren (_DtHelpVolumeHdl vol)
  2193. *
  2194. * Parameters: vol Specifies the loaded volume
  2195. * topic_id Speicifes the topic id of which the
  2196. * children are to be found.
  2197. * retTopics Returns the null terminated array of
  2198. * ids. This memory is owned by the caller
  2199. * and must be freed.
  2200. *
  2201. * Returns: > 0 if successful, -1 if failures.
  2202. *
  2203. * Purpose: Get the children of a topic.
  2204. *
  2205. *****************************************************************************/
  2206. int
  2207. _DtHelpCeGetTopicChildren (
  2208. _DtHelpVolumeHdl volume,
  2209. char *topic_id,
  2210. char ***retTopics)
  2211. {
  2212. _DtHelpVolume vol = (_DtHelpVolume)volume;
  2213. int result;
  2214. _DtHelpProcessLock();
  2215. /*
  2216. * check the parameters
  2217. */
  2218. if (vol == NULL || CheckVolList (vol, NULL) == -1)
  2219. {
  2220. errno = EINVAL;
  2221. _DtHelpProcessUnlock();
  2222. return -1;
  2223. }
  2224. /*
  2225. * What type of volume is it?
  2226. */
  2227. if (vol->sdl_flag == False)
  2228. {
  2229. result = _DtHelpCeGetCcdfTopicChildren(volume, topic_id, retTopics);
  2230. }
  2231. else
  2232. {
  2233. result = _DtHelpCeGetSdlTopicChildren(volume, topic_id, retTopics);
  2234. }
  2235. _DtHelpProcessUnlock();
  2236. return result;
  2237. } /* End _DtHelpCeGetTopicChildren */
  2238. /*****************************************************************************
  2239. * Function: int _DtHelpCeGetVolumeFlag (_DtHelpVolumeHdl vol)
  2240. *
  2241. * Parameters: vol Specifies the loaded volume
  2242. *
  2243. * Returns: 0 if CCDF volume, 1 if SDL, -1 if failures.
  2244. *
  2245. * Purpose: Determine the type of volume.
  2246. *
  2247. *****************************************************************************/
  2248. int
  2249. _DtHelpCeGetVolumeFlag (
  2250. _DtHelpVolumeHdl volume)
  2251. {
  2252. _DtHelpVolume vol = (_DtHelpVolume)volume;
  2253. /*
  2254. * check the parameters
  2255. */
  2256. if (vol == NULL || CheckVolList (vol, NULL) == -1)
  2257. {
  2258. errno = EINVAL;
  2259. return -1;
  2260. }
  2261. /*
  2262. * What type of volume is it?
  2263. */
  2264. return((int) vol->sdl_flag);
  2265. } /* End _DtHelpCeGetVolumeFlag */
  2266. /*****************************************************************************
  2267. * Function: int _DtHelpCeLockVolume (_DtHelpVolumeHdl vol)
  2268. *
  2269. * Parameters: vol Specifies the loaded volume
  2270. *
  2271. * Returns: > 0 if successful, -1 if failures.
  2272. *
  2273. * Purpose: Lock the volume so that it can't get change out from
  2274. * under the caller.
  2275. *
  2276. *****************************************************************************/
  2277. int
  2278. _DtHelpCeLockVolume (
  2279. _DtHelpVolumeHdl volume,
  2280. _DtHelpCeLockInfo *lock_info)
  2281. {
  2282. struct stat buf;
  2283. _DtHelpVolume vol = (_DtHelpVolume)volume;
  2284. _DtHelpProcessLock();
  2285. /*
  2286. * check the parameters
  2287. */
  2288. if (vol == NULL || CheckVolList (vol, NULL) == -1)
  2289. {
  2290. _DtHelpProcessUnlock();
  2291. return -1;
  2292. }
  2293. /*
  2294. * lock it by opening it.
  2295. */
  2296. lock_info->fd = open(vol->volFile, O_RDONLY);
  2297. if (lock_info->fd == -1)
  2298. {
  2299. _DtHelpProcessUnlock();
  2300. return -1;
  2301. }
  2302. (void) fstat(lock_info->fd, &buf);
  2303. if (buf.st_mtime != vol->check_time)
  2304. {
  2305. if (RereadVolume(vol) != 0)
  2306. {
  2307. close(lock_info->fd);
  2308. _DtHelpProcessUnlock();
  2309. return -1;
  2310. }
  2311. vol->check_time = buf.st_mtime;
  2312. }
  2313. /*
  2314. * Synthetic open
  2315. */
  2316. vol->openCount++;
  2317. lock_info->volume = volume;
  2318. _DtHelpProcessUnlock();
  2319. return 0;
  2320. } /* End _DtHelpCeLockVolume */
  2321. /*****************************************************************************
  2322. * Function: int _DtHelpCeUnlockVolume (_DtHelpVolumeHdl vol)
  2323. *
  2324. * Parameters: vol Specifies the loaded volume
  2325. *
  2326. * Returns: > 0 if successful, -1 if failures.
  2327. *
  2328. * Purpose: Unlock the volume.
  2329. *
  2330. *****************************************************************************/
  2331. int
  2332. _DtHelpCeUnlockVolume (
  2333. _DtHelpCeLockInfo lock_info)
  2334. {
  2335. _DtHelpVolume vol = (_DtHelpVolume)(lock_info.volume);
  2336. _DtHelpProcessLock();
  2337. /*
  2338. * check the parameters
  2339. */
  2340. if (vol == NULL || CheckVolList (vol, NULL) == -1)
  2341. {
  2342. _DtHelpProcessUnlock();
  2343. return -1;
  2344. }
  2345. /*
  2346. * check to see if it needs to be unlocked.
  2347. */
  2348. if (lock_info.fd != -1)
  2349. close(lock_info.fd);
  2350. /*
  2351. * Synthetic close
  2352. */
  2353. vol->openCount--;
  2354. _DtHelpProcessUnlock();
  2355. return 0;
  2356. } /* End _DtHelpCeUnlockVolume */
  2357. /*****************************************************************************
  2358. * Function: int _DtHelpCeIsTopTopic (_DtHelpVolumeHdl volume, const char *id)
  2359. *
  2360. * Parameters: vol Specifies the loaded volume
  2361. * id Specifies a location id.
  2362. *
  2363. * Returns: = 0 if successful, != 0 if failures.
  2364. *
  2365. * Purpose: Tests to see if the location id is in the top topic of
  2366. * the volume.
  2367. *
  2368. *****************************************************************************/
  2369. int
  2370. _DtHelpCeIsTopTopic (
  2371. _DtHelpVolumeHdl volume,
  2372. const char *id)
  2373. {
  2374. int result = -1;
  2375. char *topicId = NULL;
  2376. char *topId = NULL;
  2377. _DtHelpVolume vol = (_DtHelpVolume) volume;
  2378. _DtHelpProcessLock();
  2379. /*
  2380. * check the parameters
  2381. */
  2382. if (vol == NULL || CheckVolList (vol, NULL) == -1)
  2383. {
  2384. _DtHelpProcessUnlock();
  2385. return -1;
  2386. }
  2387. /*
  2388. * What type of volume is it?
  2389. */
  2390. if (vol->sdl_flag == False)
  2391. {
  2392. if (_DtHelpCeMapCcdfTargetToId(vol, id, &topicId) == 0 &&
  2393. _DtHelpCeGetCcdfTopTopic(vol, &topId) == 0)
  2394. result = _DtHelpCeStrCaseCmpLatin1(topId, topicId);
  2395. }
  2396. else if (_DtHelpCeMapIdToSdlTopicId(vol, id, &topicId) == 0)
  2397. {
  2398. topId = _DtHelpCeGetSdlHomeTopicId(volume);
  2399. if (topId != NULL)
  2400. result = _DtHelpCeStrCaseCmpLatin1(topId, topicId);
  2401. }
  2402. _DtHelpProcessUnlock();
  2403. return result;
  2404. } /* End _DtHelpCeIsTopTopic */