ilefs.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773
  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: ilefs.c /main/3 1995/10/23 15:47:01 rswiston $ */
  24. /**---------------------------------------------------------------------
  25. ***
  26. *** (c)Copyright 1992 Hewlett-Packard Co.
  27. ***
  28. *** RESTRICTED RIGHTS LEGEND
  29. *** Use, duplication, or disclosure by the U.S. Government is subject to
  30. *** restrictions as set forth in sub-paragraph (c)(1)(ii) of the Rights in
  31. *** Technical Data and Computer Software clause in DFARS 252.227-7013.
  32. *** Hewlett-Packard Company
  33. *** 3000 Hanover Street
  34. *** Palo Alto, CA 94304 U.S.A.
  35. *** Rights for non-DOD U.S. Government Departments and Agencies are as set
  36. *** forth in FAR 52.227-19(c)(1,2).
  37. ***
  38. ***-------------------------------------------------------------------*/
  39. #include <string.h>
  40. #include "ilint.h"
  41. #include "ilcontext.h"
  42. #include "ilefs.h"
  43. #include "ilpipeint.h"
  44. #include "ilerrors.h"
  45. /* Beginning of file and file type recs - separate so list heads are smaller. */
  46. typedef struct {
  47. ilObjectRec o; /* std header: MUST BE FIRST */
  48. struct _ilEFSFileTypeRec *pNext, *pPrev; /* forward / back ptrs */
  49. } ilEFSHeaderRec, *ilEFSHeaderPtr;
  50. /* Private definition of an ilEFSFileType: an IL object. */
  51. typedef struct _ilEFSFileTypeRec {
  52. ilEFSHeaderRec h; /* header: MUST BE FIRST */
  53. ilEFSFileTypeInfo info; /* public file type info */
  54. } ilEFSFileTypeRec, *ilEFSFileTypePtr;
  55. /* EFS private data, hung off of context.pAlloc[IL_CONTEXT_ALLOC_EFS]. */
  56. typedef struct {
  57. ilEFSHeaderRec fileTypeHead; /* list of active file types */
  58. ilEFSHeaderRec replacedFileTypeHead; /* list of replaced file types */
  59. } ilEFSPrivateRec, *ilEFSPrivatePtr;
  60. /* Private definition of an ilEFSFile: an IL object. */
  61. typedef struct {
  62. ilObjectRec o; /* std header: MUST BE FIRST */
  63. ilEFSFileInfo info; /* public file type info */
  64. ilEFSFileTypePtr pFileType; /* convenience: ptr to file type */
  65. } ilEFSFileRec, *ilEFSFilePtr;
  66. /* Add _pFileType in front of element _pNextFileType */
  67. #define LINK_FILE_TYPE(_pFileType, _pNextFileType) { \
  68. (_pFileType)->h.pNext = (_pNextFileType); \
  69. (_pFileType)->h.pPrev = (_pNextFileType)->h.pPrev; \
  70. (_pFileType)->h.pPrev->h.pNext = (_pFileType); \
  71. (_pNextFileType)->h.pPrev = (_pFileType); \
  72. }
  73. /* Remove the given file type from its linked list */
  74. #define UNLINK_FILE_TYPE(_pFileType) { \
  75. (_pFileType)->h.pPrev->h.pNext = (_pFileType)->h.pNext; \
  76. (_pFileType)->h.pNext->h.pPrev = (_pFileType)->h.pPrev; \
  77. }
  78. /* Return true if given two strings are equal */
  79. #define STRING_EQUAL(str, cmpstr) (strcmp ((str), (cmpstr)) == 0)
  80. /* In efsinit.c :
  81. Called by the IL when EFS function is called. Calls the individual
  82. Init() function for each file type to be supported by EFS.
  83. */
  84. extern ilBool _ilefsInitStandardFiles (
  85. ilContext context
  86. );
  87. /* ------------------------ ilInitEFS ---------------------------------- */
  88. /* Init EFS if not already inited (non-null ptr off of context.)
  89. Return ptr to EFS context private or null if error.
  90. */
  91. static ilEFSPrivatePtr ilInitEFS (
  92. ilContext context
  93. )
  94. {
  95. register ilEFSPrivatePtr pPriv;
  96. /* If EFS file type data not present malloc and zero it, and then point
  97. context pAlloc to it - if not, could recurse forever.
  98. */
  99. context->error = IL_OK;
  100. pPriv = (ilEFSPrivatePtr)((ilContextPtr)context)->pAlloc[IL_CONTEXT_ALLOC_EFS];
  101. if (!pPriv) {
  102. pPriv = (ilEFSPrivatePtr)IL_MALLOC (sizeof (ilEFSPrivateRec));
  103. if (!pPriv) {
  104. context->error = IL_ERROR_MALLOC;
  105. return (ilEFSPrivatePtr)NULL;
  106. }
  107. ((ilContextPtr)context)->pAlloc[IL_CONTEXT_ALLOC_EFS] = (ilPtr)pPriv;
  108. /* Init file type list to null. */
  109. pPriv->fileTypeHead.pNext = pPriv->fileTypeHead.pPrev =
  110. (ilEFSFileTypePtr)&pPriv->fileTypeHead;
  111. pPriv->replacedFileTypeHead.pNext = pPriv->replacedFileTypeHead.pPrev =
  112. (ilEFSFileTypePtr)&pPriv->replacedFileTypeHead;
  113. /* Call to external lib(s) to callback and add each file type */
  114. if (!_ilefsInitStandardFiles (context)) {
  115. IL_FREE (pPriv);
  116. return (ilEFSPrivatePtr)NULL;
  117. }
  118. }
  119. return pPriv;
  120. }
  121. /* ================================== FILE TYPE CODE =============================== */
  122. /* ------------------------ ilFindFileType ---------------------------------- */
  123. /* Find the file type with the given "name" in the list of file types whose
  124. head is pointed to by "pListHead". Return ptr to found file type or null.
  125. */
  126. static ilEFSFileTypePtr ilFindFileType (
  127. char *name,
  128. ilEFSFileTypePtr pListHead
  129. )
  130. {
  131. register ilEFSFileTypePtr pFileType;
  132. pFileType = pListHead->h.pNext;
  133. while (pFileType != pListHead) {
  134. if (STRING_EQUAL (name, pFileType->info.name))
  135. return pFileType; /* found, EXIT */
  136. pFileType = pFileType->h.pNext;
  137. }
  138. return (ilEFSFileTypePtr)NULL; /* not found, return null */
  139. }
  140. /* ------------------------ ilAddFileTypeToList --------------------------- */
  141. /* Add the file type pointed to by "pFileType" to the list of file types whose
  142. head is pointed to by "pListHead". Element is placed in list based its
  143. checkOrder.
  144. */
  145. static void ilAddFileTypeToList (
  146. register ilEFSFileTypePtr pFileType,
  147. ilEFSFileTypePtr pListHead
  148. )
  149. {
  150. register ilEFSFileTypePtr pListFileType;
  151. register int checkOrder;
  152. checkOrder = pFileType->info.checkOrder;
  153. pListFileType = pListHead->h.pNext;
  154. while (pListFileType != pListHead) {
  155. if (checkOrder > pListFileType->info.checkOrder)
  156. break; /* spot found; break */
  157. pListFileType = pListFileType->h.pNext;
  158. }
  159. LINK_FILE_TYPE (pFileType, pListFileType) /* insert in front of pListFileType */
  160. }
  161. /* ------------------------ ilEFSAddFileType ---------------------------- */
  162. /* Public function: see spec.
  163. */
  164. /* Object Destroy() function for file type objects. */
  165. static void ilDestroyFileType (
  166. register ilEFSFileTypePtr pFileType
  167. )
  168. {
  169. ilEFSPrivatePtr pPriv;
  170. register ilEFSFileTypePtr pReplaced;
  171. pPriv = (ilEFSPrivatePtr)
  172. ((ilContextPtr)(pFileType->h.o.p.context))->pAlloc[IL_CONTEXT_ALLOC_EFS];
  173. /* Remove file type from its current list. Search the "replaced" list for a
  174. file type of same name; if found, move it from replaced to active list.
  175. */
  176. UNLINK_FILE_TYPE (pFileType)
  177. pReplaced = ilFindFileType (pFileType->info.name,
  178. (ilEFSFileTypePtr)&pPriv->replacedFileTypeHead);
  179. if (pReplaced) {
  180. UNLINK_FILE_TYPE (pReplaced)
  181. ilAddFileTypeToList (pReplaced, (ilEFSFileTypePtr)&pPriv->fileTypeHead);
  182. }
  183. }
  184. ilEFSFileType ilEFSAddFileType (
  185. ilContext context,
  186. register ilEFSFileTypeInfo *pInfo,
  187. void *pOptions
  188. )
  189. {
  190. ilEFSPrivatePtr pPriv;
  191. int i;
  192. register ilEFSFileTypePtr pFileType, pReplace;
  193. register unsigned long openModes;
  194. /* masks for defined bits in ilEFSFileTypeInfo - others invalid */
  195. #define OPEN_MODE_MASKS (1<<IL_EFS_READ | 1<<IL_EFS_READ_SEQUENTIAL | 1<<IL_EFS_WRITE)
  196. #define ATTRIBUTES_MASKS (IL_EFS_MULTI_PAGE_READS | IL_EFS_MULTI_PAGE_WRITES | \
  197. IL_EFS_MASK_READS | IL_EFS_MASK_WRITES | IL_EFS_SCALEABLE_READS)
  198. if (pOptions) {
  199. context->error = IL_ERROR_PAR_NOT_ZERO;
  200. return (ilEFSFileType)NULL;
  201. }
  202. /* Validate *pInfo: strings present, unused mask bits zero, functions right. */
  203. if ((strlen (pInfo->name) > (IL_EFS_MAX_NAME_CHARS - 1))
  204. || (strlen (pInfo->displayName) > (IL_EFS_MAX_DISPLAY_NAME_CHARS - 1))
  205. || (pInfo->nExtensions > IL_EFS_MAX_EXTENSIONS))
  206. goto badFileTypeInfo;
  207. for (i = 0; i < pInfo->nExtensions; i++)
  208. if (strlen (pInfo->extensions[i]) > (IL_EFS_MAX_EXTENSION_CHARS - 1))
  209. goto badFileTypeInfo;
  210. openModes = pInfo->openModes;
  211. if ((openModes & ~OPEN_MODE_MASKS)
  212. || (pInfo->attributes & ~ATTRIBUTES_MASKS))
  213. goto badFileTypeInfo;
  214. if (((!pInfo->Open || !pInfo->Open) && openModes)
  215. || (!pInfo->Seek && (openModes & 1<<IL_EFS_READ)
  216. && (pInfo->attributes & IL_EFS_MULTI_PAGE_READS))
  217. || ((!pInfo->GetPageInfo || !pInfo->ReadImage)
  218. && (openModes & (1<<IL_EFS_READ | 1<<IL_EFS_READ_SEQUENTIAL)))
  219. || (!pInfo->WriteImage && (openModes & 1<<IL_EFS_WRITE)))
  220. goto badFileTypeInfo;
  221. for (i = 0; i < IL_EFS_TYPE_RESERVED_SIZE; i++)
  222. if (pInfo->reserved[i] != 0)
  223. goto badFileTypeInfo;
  224. /* Init EFS file types if not already inited. */
  225. if (!(pPriv = ilInitEFS (context)))
  226. return (ilEFSFileType)NULL;
  227. /* Create a file type object, exit if failure. Set *pInfo into it. */
  228. pFileType = (ilEFSFileTypePtr)_ilCreateObject (context, IL_EFS_FILE_TYPE,
  229. ilDestroyFileType, sizeof (ilEFSFileTypeRec));
  230. if (!pFileType) return (ilEFSFileType)NULL;
  231. pFileType->info = *pInfo;
  232. /* Search the active list for file type with same name. If found, remove it
  233. from active list and add to replaced list, in front of any with same name.
  234. */
  235. pReplace = ilFindFileType (pFileType->info.name,
  236. (ilEFSFileTypePtr)&pPriv->fileTypeHead);
  237. if (pReplace) {
  238. ilEFSFileTypePtr pReplaceFront;
  239. UNLINK_FILE_TYPE (pReplace)
  240. pReplaceFront = ilFindFileType (pFileType->info.name,
  241. (ilEFSFileTypePtr)&pPriv->fileTypeHead);
  242. if (!pReplaceFront)
  243. pReplaceFront = (ilEFSFileTypePtr)&pPriv->fileTypeHead;
  244. LINK_FILE_TYPE (pReplace, pReplaceFront)
  245. }
  246. /* Add the file type to the active list */
  247. ilAddFileTypeToList (pFileType, (ilEFSFileTypePtr)&pPriv->fileTypeHead);
  248. context->error = IL_OK;
  249. return (ilEFSFileType)pFileType;
  250. /* goto point if invalid file type info: return error. */
  251. badFileTypeInfo:
  252. context->error = IL_ERROR_EFS_FILE_TYPE_INFO;
  253. return (ilEFSFileType)NULL;
  254. }
  255. /* ------------------------ ilEFSGetFileTypeInfo ---------------------------- */
  256. /* Public function: see spec.
  257. */
  258. ilBool ilEFSGetFileTypeInfo (
  259. ilEFSFileType fileType,
  260. ilEFSFileTypeInfo *pInfo
  261. )
  262. {
  263. register ilEFSFileTypePtr pFileType;
  264. pFileType = (ilEFSFileTypePtr)fileType;
  265. if (pFileType->h.o.p.objectType != IL_EFS_FILE_TYPE) {
  266. pFileType->h.o.p.context->error = IL_ERROR_OBJECT_TYPE;
  267. return FALSE;
  268. }
  269. *pInfo = pFileType->info;
  270. pFileType->h.o.p.context->error = IL_OK;
  271. return TRUE;
  272. }
  273. /* ------------------------ ilEFSListFileTypes ------------------------------ */
  274. /* Public function: see spec.
  275. */
  276. ilBool ilEFSListFileTypes (
  277. ilContext context,
  278. int *pNFileTypes,
  279. ilEFSFileType **pfileTypes
  280. )
  281. {
  282. ilEFSPrivatePtr pPriv;
  283. register int nFileTypes;
  284. register ilEFSFileTypePtr pFileType;
  285. register ilEFSFileType *pfileType;
  286. *pNFileTypes = 0;
  287. *pfileTypes = (ilEFSFileType *)NULL;
  288. /* Init EFS file types if not already inited. */
  289. if (!(pPriv = ilInitEFS (context)))
  290. return FALSE;
  291. /* Count the number of file types in the list */
  292. nFileTypes = 0;
  293. pFileType = pPriv->fileTypeHead.pNext;
  294. while (pFileType != (ilEFSFileTypePtr)&pPriv->fileTypeHead) {
  295. pFileType = pFileType->h.pNext;
  296. nFileTypes++;
  297. }
  298. /* Malloc space for returned file types - use malloc(); caller uses free().
  299. If no file types, still malloc something to return non-null ptr.
  300. */
  301. pfileType = (ilEFSFileType *)malloc ((nFileTypes > 0) ?
  302. nFileTypes * sizeof (ilEFSFileType) : 4);
  303. if (!pfileType) {
  304. context->error = IL_ERROR_MALLOC;
  305. return FALSE;
  306. }
  307. /* Return # of file types; traverse list to return ptrs to them. */
  308. *pfileTypes = pfileType;
  309. *pNFileTypes = nFileTypes;
  310. pFileType = pPriv->fileTypeHead.pNext;
  311. while (nFileTypes-- > 0) {
  312. *pfileType++ = (ilEFSFileType)pFileType;
  313. pFileType = pFileType->h.pNext;
  314. }
  315. context->error = IL_OK;
  316. return TRUE;
  317. }
  318. /* =================================== FILE CODE ================================== */
  319. /* --------------------------- ilEFSOpenFile ------------------------------- */
  320. /* Public function: see spec.
  321. */
  322. /* Object Destroy() function for file objects. */
  323. static void ilDestroyFile (
  324. ilEFSFilePtr pFile
  325. )
  326. {
  327. register ilEFSFileTypePtr pFileType;
  328. /* Get ptr to file type; if null, file not actually open yet; skip Close() */
  329. pFileType = (ilEFSFileTypePtr)pFile->info.fileType;
  330. if (pFileType)
  331. (*pFileType->info.Close) (pFile);
  332. }
  333. ilEFSFile ilEFSOpen (
  334. ilContext context,
  335. char *fileName,
  336. unsigned int openMode,
  337. unsigned long searchOptions,
  338. char *typeName,
  339. void *pOptions
  340. )
  341. {
  342. ilEFSPrivatePtr pPriv;
  343. register ilEFSFilePtr pFile;
  344. register ilEFSFileTypePtr pFileType, pListHead;
  345. ilBool readOpen;
  346. long nPages;
  347. ilPtr pOpenPriv;
  348. char extension [IL_EFS_MAX_EXTENSION_CHARS];
  349. /* Validate pOptions, openMode (set readOpen true if a read). */
  350. context->error = IL_OK;
  351. if (pOptions) {
  352. context->error = IL_ERROR_PAR_NOT_ZERO;
  353. return (ilEFSFileType)NULL;
  354. }
  355. switch (openMode) {
  356. case IL_EFS_READ:
  357. case IL_EFS_READ_SEQUENTIAL:
  358. readOpen = TRUE; break;
  359. case IL_EFS_WRITE:
  360. readOpen = FALSE; break;
  361. default:
  362. context->error = IL_ERROR_EFS_OPEN_MODE;
  363. return (ilEFSFile)NULL;
  364. }
  365. /* Init EFS file types if not already inited. */
  366. if (!(pPriv = ilInitEFS (context)))
  367. return (ilEFSFile)NULL;
  368. /* Add a file type object - goto openError to destroy it if an error later. */
  369. pFile = (ilEFSFilePtr)_ilCreateObject (context, IL_EFS_FILE, ilDestroyFile,
  370. sizeof (ilEFSFileRec));
  371. if (!pFile) return (ilEFSFile)NULL;
  372. /* Find pFileType for this file, searches enabled by mask in searchOptions.
  373. First try typeName, if non-null. When found at any point: if openMode
  374. not supported, error - except for checking mode - else call Open() for
  375. the file type. If it returns any error other than "not mine" abort.
  376. */
  377. pFileType = (ilEFSFileTypePtr)NULL;
  378. pListHead = (ilEFSFileTypePtr)&pPriv->fileTypeHead;
  379. if (typeName && (searchOptions & IL_EFS_BY_TYPE_NAME)) {
  380. pFileType = ilFindFileType (typeName, pListHead);
  381. if (pFileType) { /* file type found */
  382. if (!(pFileType->info.openModes & (1 << openMode))) {
  383. context->error = IL_ERROR_EFS_OPEN_MODE;
  384. goto openError;
  385. }
  386. pOpenPriv = (*pFileType->info.Open) (pFileType, fileName, openMode, &nPages);
  387. if (!pOpenPriv) {
  388. if (context->error == IL_ERROR_EFS_NOT_MINE)
  389. pFileType = (ilEFSFileTypePtr)NULL; /* try next search method */
  390. else goto openError;
  391. }
  392. pFile->info.howFound = IL_EFS_BY_CHECKING;
  393. }
  394. } /* END open by type name */
  395. /* If not found, search for extension if enabled. */
  396. if (!pFileType && (searchOptions & IL_EFS_BY_EXTENSION)) {
  397. char *pExtension;
  398. register ilEFSFileTypePtr pSearch;
  399. int nChars;
  400. pExtension = strrchr (fileName, '.');
  401. if (pExtension) { /* is a "." in fileName */
  402. pExtension++; /* point past "." */
  403. nChars = strlen (pExtension);
  404. if (nChars > (IL_EFS_MAX_EXTENSION_CHARS - 1))
  405. nChars = IL_EFS_MAX_EXTENSION_CHARS - 1;
  406. bcopy (pExtension, extension, nChars); /* extract "extension" */
  407. extension [nChars] = 0;
  408. /* Search list for extension match until pFileType found or list done */
  409. pSearch = pListHead->h.pNext;
  410. while (!pFileType && (pSearch != pListHead)) {
  411. register int nExtensions = pSearch->info.nExtensions;
  412. while (nExtensions-- > 0)
  413. if (STRING_EQUAL (extension, pSearch->info.extensions[nExtensions])) {
  414. pFileType = pSearch; /* extension found; quit */
  415. pFile->info.howFound = IL_EFS_BY_CHECKING;
  416. break;
  417. }
  418. pSearch = pSearch->h.pNext;
  419. }
  420. if (pFileType) {
  421. if (!(pFileType->info.openModes & (1 << openMode))) {
  422. context->error = IL_ERROR_EFS_OPEN_MODE;
  423. goto openError;
  424. }
  425. pOpenPriv = (*pFileType->info.Open) (pFileType, fileName, openMode, &nPages);
  426. if (!pOpenPriv) {
  427. if (context->error == IL_ERROR_EFS_NOT_MINE)
  428. pFileType = (ilEFSFileTypePtr)NULL;
  429. else goto openError;
  430. }
  431. }
  432. } /* END have extension */
  433. } /* END open by extension */
  434. /* If not found, search by checking if a read openMode. For each file type,
  435. try open if enabled (checkOrder != 0) and openMode supported for file type.
  436. */
  437. if (!pFileType && readOpen && (searchOptions & IL_EFS_BY_CHECKING)) {
  438. register ilEFSFileTypePtr pSearch;
  439. pSearch = pListHead->h.pNext;
  440. while (pSearch != pListHead) {
  441. if (pSearch->info.checkOrder && (pSearch->info.openModes & (1 << openMode))) {
  442. pOpenPriv = (*pSearch->info.Open) (pSearch, fileName, openMode, &nPages);
  443. if (pOpenPriv) {
  444. pFileType = pSearch; /* found right file type; break */
  445. pFile->info.howFound = IL_EFS_BY_CHECKING;
  446. break;
  447. }
  448. else if (context->error != IL_ERROR_EFS_NOT_MINE)
  449. goto openError; /* some error; give up */
  450. }
  451. pSearch = pSearch->h.pNext;
  452. }
  453. } /* END open by checking */
  454. /* If not found above, error: can't find file type handler for this file. */
  455. if (!pFileType) {
  456. context->error = IL_ERROR_EFS_NO_FILE_TYPE;
  457. goto openError;
  458. }
  459. /* File type found. Fill in info for the file, return pFile. The object's
  460. pPrivate is set to the ptr returned from file type's Open().
  461. */
  462. pFile->o.p.pPrivate = pOpenPriv;
  463. pFile->info.fileType = (ilEFSFileType)pFileType;
  464. pFile->info.openMode = openMode;
  465. pFile->info.attributes = pFileType->info.attributes;
  466. pFile->info.nPages = nPages;
  467. pFile->pFileType = pFileType;
  468. context->error = IL_OK;
  469. return (ilEFSFile)pFile; /* success; return file */
  470. /* openError: goto here on error after file object created. The Open() was not
  471. successful, so set fileType to null so ilDestroyFile() does not call Close().
  472. */
  473. openError:
  474. { ilError error;
  475. error = context->error; /* save error code */
  476. pFile->info.fileType = (ilEFSFileType)NULL;
  477. ilDestroyObject ((ilObject)pFile);
  478. context->error = error; /* restore error code */
  479. return (ilEFSFile)NULL;
  480. }
  481. }
  482. /* ------------------------ ilEFSGetFileInfo ---------------------------- */
  483. /* Public function: see spec.
  484. */
  485. ilBool ilEFSGetFileInfo (
  486. ilEFSFile file,
  487. ilEFSFileInfo *pInfo /* RETURNED */
  488. )
  489. {
  490. register ilEFSFilePtr pFile;
  491. pFile = (ilEFSFilePtr)file;
  492. if (pFile->o.p.objectType != IL_EFS_FILE) {
  493. pFile->o.p.context->error = IL_ERROR_OBJECT_TYPE;
  494. return FALSE;
  495. }
  496. /* Return file info; fill in "inUse": file in use if refCount > 1 */
  497. *pInfo = pFile->info;
  498. pInfo->inUse = (pFile->o.refCount > 1);
  499. pFile->o.p.context->error = IL_OK;
  500. return TRUE;
  501. }
  502. /* ------------------------ ilEFSSeek ---------------------------- */
  503. /* Public function: see spec.
  504. */
  505. ilBool ilEFSSeek (
  506. ilEFSFile file,
  507. long page,
  508. void *pOptions
  509. )
  510. {
  511. register ilEFSFilePtr pFile;
  512. pFile = (ilEFSFilePtr)file;
  513. if (pOptions) {
  514. pFile->o.p.context->error = IL_ERROR_PAR_NOT_ZERO;
  515. return FALSE;
  516. }
  517. if (pFile->o.p.objectType != IL_EFS_FILE) {
  518. pFile->o.p.context->error = IL_ERROR_OBJECT_TYPE;
  519. return FALSE;
  520. }
  521. /* Validate that file was opened for random read; error if not. */
  522. if (pFile->info.openMode != IL_EFS_READ) {
  523. pFile->o.p.context->error = IL_ERROR_EFS_OPEN_MODE;
  524. return FALSE;
  525. }
  526. /* Call Seek() only if multi-page reads supported; not error if not. */
  527. pFile->o.p.context->error = IL_OK;
  528. if (!(pFile->info.attributes & IL_EFS_MULTI_PAGE_READS))
  529. return TRUE;
  530. else return (*pFile->pFileType->info.Seek) (file, page);
  531. }
  532. /* ------------------------ ilEFSGetPageInfo ---------------------------- */
  533. /* Public function: see spec.
  534. */
  535. ilBool ilEFSGetPageInfo (
  536. ilEFSFile file,
  537. ilEFSPageInfo *pInfo
  538. )
  539. {
  540. register ilEFSFilePtr pFile;
  541. pFile = (ilEFSFilePtr)file;
  542. if (pFile->o.p.objectType != IL_EFS_FILE) {
  543. pFile->o.p.context->error = IL_ERROR_OBJECT_TYPE;
  544. return FALSE;
  545. }
  546. /* Validate that file was opened for read; call GetPageInfo() if so. */
  547. if ((pFile->info.openMode != IL_EFS_READ)
  548. && (pFile->info.openMode != IL_EFS_READ_SEQUENTIAL)) {
  549. pFile->o.p.context->error = IL_ERROR_EFS_OPEN_MODE;
  550. return FALSE;
  551. }
  552. pFile->o.p.context->error = IL_OK;
  553. return (*pFile->pFileType->info.GetPageInfo) (file, pInfo);
  554. }
  555. /* ------------------------ ilEFSReadImage ---------------------------- */
  556. /* Public function: see spec.
  557. */
  558. ilBool ilEFSReadImage (
  559. ilPipe pipe,
  560. ilEFSFile file,
  561. unsigned int readMode,
  562. long width,
  563. long height,
  564. void *pOptions
  565. )
  566. {
  567. register ilEFSFilePtr pFile;
  568. pFile = (ilEFSFilePtr)file;
  569. if (pOptions) {
  570. pFile->o.p.context->error = IL_ERROR_PAR_NOT_ZERO;
  571. return FALSE;
  572. }
  573. if ((pipe->objectType != IL_PIPE) || (pFile->o.p.objectType != IL_EFS_FILE)) {
  574. pFile->o.p.context->error = IL_ERROR_OBJECT_TYPE;
  575. return FALSE;
  576. }
  577. /* Validate readMode: mask allowed only if supported by file type. */
  578. switch (readMode) {
  579. case IL_EFS_READ_MAIN:
  580. break;
  581. case IL_EFS_READ_MASK:
  582. if (pFile->pFileType->info.attributes & IL_EFS_MASK_READS)
  583. break; /* else fall thru for error */
  584. default:
  585. pFile->o.p.context->error = IL_ERROR_EFS_READ_MODE;
  586. return FALSE;
  587. }
  588. /* Validate that file was opened for read. */
  589. if ((pFile->info.openMode != IL_EFS_READ)
  590. && (pFile->info.openMode != IL_EFS_READ_SEQUENTIAL)) {
  591. pFile->o.p.context->error = IL_ERROR_EFS_OPEN_MODE;
  592. return FALSE;
  593. }
  594. /* If pipe element added successfully inc file's refCount to mark in use,
  595. and add file to list of objects to be destroyed when pipe emptied.
  596. */
  597. pFile->o.p.context->error = IL_OK;
  598. if ((*pFile->pFileType->info.ReadImage) (pipe, file, readMode, width, height)) {
  599. pFile->o.refCount++;
  600. return _ilAddPipeDestroyObject (pipe, (ilObject)pFile);
  601. }
  602. else return FALSE;
  603. }
  604. /* ------------------------ ilEFSWriteImage ---------------------------- */
  605. /* Public function: see spec.
  606. */
  607. ilBool ilEFSWriteImage (
  608. ilPipe pipe,
  609. ilEFSFile file,
  610. long xRes,
  611. long yRes,
  612. ilClientImage maskImage,
  613. void *pOptions
  614. )
  615. {
  616. register ilEFSFilePtr pFile;
  617. pFile = (ilEFSFilePtr)file;
  618. if (pOptions) {
  619. pFile->o.p.context->error = IL_ERROR_PAR_NOT_ZERO;
  620. return FALSE;
  621. }
  622. if ((pipe->objectType != IL_PIPE) || (pFile->o.p.objectType != IL_EFS_FILE)) {
  623. pFile->o.p.context->error = IL_ERROR_OBJECT_TYPE;
  624. return FALSE;
  625. }
  626. /* Validate that file was opened for write. */
  627. if (pFile->info.openMode != IL_EFS_WRITE) {
  628. pFile->o.p.context->error = IL_ERROR_EFS_OPEN_MODE;
  629. return FALSE;
  630. }
  631. /* If file type doesnt handle masks, ignore maskImage, else validate it */
  632. if (maskImage) {
  633. if (!(pFile->pFileType->info.attributes & IL_EFS_MASK_WRITES))
  634. maskImage = (ilClientImage)NULL;
  635. else {
  636. ilImageInfo *pInfo;
  637. register const ilImageDes *pDes;
  638. register const ilImageFormat *pFormat;
  639. if (!ilQueryClientImage (maskImage, &pInfo, 0))
  640. return FALSE;
  641. pDes = pInfo->pDes;
  642. pFormat = pInfo->pFormat;
  643. if ((pDes->compression != IL_UNCOMPRESSED)
  644. || (pDes->nSamplesPerPixel != 1)
  645. || (pFormat->rowBitAlign != 32)
  646. || (pFormat->nBitsPerSample[0] != 1)) {
  647. pFile->o.p.context->error = IL_ERROR_EFS_OPEN_MODE;
  648. return FALSE;
  649. }
  650. }
  651. }
  652. /* If pipe element added successfully inc file's refCount to mark in use,
  653. and add file/maskImage to list of objects to be destroyed when pipe emptied.
  654. */
  655. pFile->o.p.context->error = IL_OK;
  656. if ((*pFile->pFileType->info.WriteImage) (pipe, file, xRes, yRes, maskImage)) {
  657. if (maskImage) {
  658. ((ilObjectPtr)maskImage)->refCount++;
  659. _ilAddPipeDestroyObject (pipe, maskImage);
  660. }
  661. pFile->o.refCount++;
  662. return _ilAddPipeDestroyObject (pipe, (ilObject)pFile);
  663. }
  664. else return FALSE;
  665. }