2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: ilefs.c /main/3 1995/10/23 15:47:01 rswiston $ */
24 /**---------------------------------------------------------------------
26 *** (c)Copyright 1992 Hewlett-Packard Co.
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).
38 ***-------------------------------------------------------------------*/
43 #include "ilcontext.h"
45 #include "ilpipeint.h"
48 /* Beginning of file and file type recs - separate so list heads are smaller. */
50 ilObjectRec o; /* std header: MUST BE FIRST */
51 struct _ilEFSFileTypeRec *pNext, *pPrev; /* forward / back ptrs */
52 } ilEFSHeaderRec, *ilEFSHeaderPtr;
54 /* Private definition of an ilEFSFileType: an IL object. */
55 typedef struct _ilEFSFileTypeRec {
56 ilEFSHeaderRec h; /* header: MUST BE FIRST */
57 ilEFSFileTypeInfo info; /* public file type info */
58 } ilEFSFileTypeRec, *ilEFSFileTypePtr;
61 /* EFS private data, hung off of context.pAlloc[IL_CONTEXT_ALLOC_EFS]. */
63 ilEFSHeaderRec fileTypeHead; /* list of active file types */
64 ilEFSHeaderRec replacedFileTypeHead; /* list of replaced file types */
65 } ilEFSPrivateRec, *ilEFSPrivatePtr;
68 /* Private definition of an ilEFSFile: an IL object. */
70 ilObjectRec o; /* std header: MUST BE FIRST */
71 ilEFSFileInfo info; /* public file type info */
72 ilEFSFileTypePtr pFileType; /* convenience: ptr to file type */
73 } ilEFSFileRec, *ilEFSFilePtr;
76 /* Add _pFileType in front of element _pNextFileType */
77 #define LINK_FILE_TYPE(_pFileType, _pNextFileType) { \
78 (_pFileType)->h.pNext = (_pNextFileType); \
79 (_pFileType)->h.pPrev = (_pNextFileType)->h.pPrev; \
80 (_pFileType)->h.pPrev->h.pNext = (_pFileType); \
81 (_pNextFileType)->h.pPrev = (_pFileType); \
84 /* Remove the given file type from its linked list */
85 #define UNLINK_FILE_TYPE(_pFileType) { \
86 (_pFileType)->h.pPrev->h.pNext = (_pFileType)->h.pNext; \
87 (_pFileType)->h.pNext->h.pPrev = (_pFileType)->h.pPrev; \
90 /* Return true if given two strings are equal */
91 #define STRING_EQUAL(str, cmpstr) (strcmp ((str), (cmpstr)) == 0)
94 Called by the IL when EFS function is called. Calls the individual
95 Init() function for each file type to be supported by EFS.
97 extern ilBool _ilefsInitStandardFiles (
102 /* ------------------------ ilInitEFS ---------------------------------- */
103 /* Init EFS if not already inited (non-null ptr off of context.)
104 Return ptr to EFS context private or null if error.
106 static ilEFSPrivatePtr ilInitEFS (
110 register ilEFSPrivatePtr pPriv;
112 /* If EFS file type data not present malloc and zero it, and then point
113 context pAlloc to it - if not, could recurse forever.
115 context->error = IL_OK;
116 pPriv = (ilEFSPrivatePtr)((ilContextPtr)context)->pAlloc[IL_CONTEXT_ALLOC_EFS];
118 pPriv = (ilEFSPrivatePtr)IL_MALLOC (sizeof (ilEFSPrivateRec));
120 context->error = IL_ERROR_MALLOC;
121 return (ilEFSPrivatePtr)NULL;
123 ((ilContextPtr)context)->pAlloc[IL_CONTEXT_ALLOC_EFS] = (ilPtr)pPriv;
125 /* Init file type list to null. */
126 pPriv->fileTypeHead.pNext = pPriv->fileTypeHead.pPrev =
127 (ilEFSFileTypePtr)&pPriv->fileTypeHead;
128 pPriv->replacedFileTypeHead.pNext = pPriv->replacedFileTypeHead.pPrev =
129 (ilEFSFileTypePtr)&pPriv->replacedFileTypeHead;
131 /* Call to external lib(s) to callback and add each file type */
132 if (!_ilefsInitStandardFiles (context)) {
134 return (ilEFSPrivatePtr)NULL;
141 /* ================================== FILE TYPE CODE =============================== */
143 /* ------------------------ ilFindFileType ---------------------------------- */
144 /* Find the file type with the given "name" in the list of file types whose
145 head is pointed to by "pListHead". Return ptr to found file type or null.
147 static ilEFSFileTypePtr ilFindFileType (
149 ilEFSFileTypePtr pListHead
152 register ilEFSFileTypePtr pFileType;
154 pFileType = pListHead->h.pNext;
155 while (pFileType != pListHead) {
156 if (STRING_EQUAL (name, pFileType->info.name))
157 return pFileType; /* found, EXIT */
158 pFileType = pFileType->h.pNext;
160 return (ilEFSFileTypePtr)NULL; /* not found, return null */
164 /* ------------------------ ilAddFileTypeToList --------------------------- */
165 /* Add the file type pointed to by "pFileType" to the list of file types whose
166 head is pointed to by "pListHead". Element is placed in list based its
169 static void ilAddFileTypeToList (
170 register ilEFSFileTypePtr pFileType,
171 ilEFSFileTypePtr pListHead
174 register ilEFSFileTypePtr pListFileType;
175 register int checkOrder;
177 checkOrder = pFileType->info.checkOrder;
178 pListFileType = pListHead->h.pNext;
179 while (pListFileType != pListHead) {
180 if (checkOrder > pListFileType->info.checkOrder)
181 break; /* spot found; break */
182 pListFileType = pListFileType->h.pNext;
184 LINK_FILE_TYPE (pFileType, pListFileType) /* insert in front of pListFileType */
188 /* ------------------------ ilEFSAddFileType ---------------------------- */
189 /* Public function: see spec.
192 /* Object Destroy() function for file type objects. */
193 static void ilDestroyFileType (
194 register ilEFSFileTypePtr pFileType
197 ilEFSPrivatePtr pPriv;
198 register ilEFSFileTypePtr pReplaced;
200 pPriv = (ilEFSPrivatePtr)
201 ((ilContextPtr)(pFileType->h.o.p.context))->pAlloc[IL_CONTEXT_ALLOC_EFS];
203 /* Remove file type from its current list. Search the "replaced" list for a
204 file type of same name; if found, move it from replaced to active list.
206 UNLINK_FILE_TYPE (pFileType)
207 pReplaced = ilFindFileType (pFileType->info.name,
208 (ilEFSFileTypePtr)&pPriv->replacedFileTypeHead);
210 UNLINK_FILE_TYPE (pReplaced)
211 ilAddFileTypeToList (pReplaced, (ilEFSFileTypePtr)&pPriv->fileTypeHead);
216 ilEFSFileType ilEFSAddFileType (
218 register ilEFSFileTypeInfo *pInfo,
222 ilEFSPrivatePtr pPriv;
224 register ilEFSFileTypePtr pFileType, pReplace;
225 register unsigned long openModes;
227 /* masks for defined bits in ilEFSFileTypeInfo - others invalid */
228 #define OPEN_MODE_MASKS (1<<IL_EFS_READ | 1<<IL_EFS_READ_SEQUENTIAL | 1<<IL_EFS_WRITE)
229 #define ATTRIBUTES_MASKS (IL_EFS_MULTI_PAGE_READS | IL_EFS_MULTI_PAGE_WRITES | \
230 IL_EFS_MASK_READS | IL_EFS_MASK_WRITES | IL_EFS_SCALEABLE_READS)
233 context->error = IL_ERROR_PAR_NOT_ZERO;
234 return (ilEFSFileType)NULL;
237 /* Validate *pInfo: strings present, unused mask bits zero, functions right. */
238 if ((strlen (pInfo->name) > (IL_EFS_MAX_NAME_CHARS - 1))
239 || (strlen (pInfo->displayName) > (IL_EFS_MAX_DISPLAY_NAME_CHARS - 1))
240 || (pInfo->nExtensions > IL_EFS_MAX_EXTENSIONS))
241 goto badFileTypeInfo;
243 for (i = 0; i < pInfo->nExtensions; i++)
244 if (strlen (pInfo->extensions[i]) > (IL_EFS_MAX_EXTENSION_CHARS - 1))
245 goto badFileTypeInfo;
247 openModes = pInfo->openModes;
248 if ((openModes & ~OPEN_MODE_MASKS)
249 || (pInfo->attributes & ~ATTRIBUTES_MASKS))
250 goto badFileTypeInfo;
252 if (((!pInfo->Open || !pInfo->Open) && openModes)
253 || (!pInfo->Seek && (openModes & 1<<IL_EFS_READ)
254 && (pInfo->attributes & IL_EFS_MULTI_PAGE_READS))
255 || ((!pInfo->GetPageInfo || !pInfo->ReadImage)
256 && (openModes & (1<<IL_EFS_READ | 1<<IL_EFS_READ_SEQUENTIAL)))
257 || (!pInfo->WriteImage && (openModes & 1<<IL_EFS_WRITE)))
258 goto badFileTypeInfo;
260 for (i = 0; i < IL_EFS_TYPE_RESERVED_SIZE; i++)
261 if (pInfo->reserved[i] != 0)
262 goto badFileTypeInfo;
264 /* Init EFS file types if not already inited. */
265 if (!(pPriv = ilInitEFS (context)))
266 return (ilEFSFileType)NULL;
268 /* Create a file type object, exit if failure. Set *pInfo into it. */
269 pFileType = (ilEFSFileTypePtr)_ilCreateObject (context, IL_EFS_FILE_TYPE,
270 ilDestroyFileType, sizeof (ilEFSFileTypeRec));
271 if (!pFileType) return (ilEFSFileType)NULL;
272 pFileType->info = *pInfo;
274 /* Search the active list for file type with same name. If found, remove it
275 from active list and add to replaced list, in front of any with same name.
277 pReplace = ilFindFileType (pFileType->info.name,
278 (ilEFSFileTypePtr)&pPriv->fileTypeHead);
280 ilEFSFileTypePtr pReplaceFront;
281 UNLINK_FILE_TYPE (pReplace)
282 pReplaceFront = ilFindFileType (pFileType->info.name,
283 (ilEFSFileTypePtr)&pPriv->fileTypeHead);
285 pReplaceFront = (ilEFSFileTypePtr)&pPriv->fileTypeHead;
286 LINK_FILE_TYPE (pReplace, pReplaceFront)
289 /* Add the file type to the active list */
290 ilAddFileTypeToList (pFileType, (ilEFSFileTypePtr)&pPriv->fileTypeHead);
292 context->error = IL_OK;
293 return (ilEFSFileType)pFileType;
295 /* goto point if invalid file type info: return error. */
297 context->error = IL_ERROR_EFS_FILE_TYPE_INFO;
298 return (ilEFSFileType)NULL;
302 /* ------------------------ ilEFSGetFileTypeInfo ---------------------------- */
303 /* Public function: see spec.
305 ilBool ilEFSGetFileTypeInfo (
306 ilEFSFileType fileType,
307 ilEFSFileTypeInfo *pInfo
310 register ilEFSFileTypePtr pFileType;
312 pFileType = (ilEFSFileTypePtr)fileType;
313 if (pFileType->h.o.p.objectType != IL_EFS_FILE_TYPE) {
314 pFileType->h.o.p.context->error = IL_ERROR_OBJECT_TYPE;
318 *pInfo = pFileType->info;
319 pFileType->h.o.p.context->error = IL_OK;
324 /* ------------------------ ilEFSListFileTypes ------------------------------ */
325 /* Public function: see spec.
327 ilBool ilEFSListFileTypes (
330 ilEFSFileType **pfileTypes
333 ilEFSPrivatePtr pPriv;
334 register int nFileTypes;
335 register ilEFSFileTypePtr pFileType;
336 register ilEFSFileType *pfileType;
339 *pfileTypes = (ilEFSFileType *)NULL;
341 /* Init EFS file types if not already inited. */
342 if (!(pPriv = ilInitEFS (context)))
345 /* Count the number of file types in the list */
347 pFileType = pPriv->fileTypeHead.pNext;
348 while (pFileType != (ilEFSFileTypePtr)&pPriv->fileTypeHead) {
349 pFileType = pFileType->h.pNext;
353 /* Malloc space for returned file types - use malloc(); caller uses free().
354 If no file types, still malloc something to return non-null ptr.
356 pfileType = (ilEFSFileType *)malloc ((nFileTypes > 0) ?
357 nFileTypes * sizeof (ilEFSFileType) : 4);
359 context->error = IL_ERROR_MALLOC;
363 /* Return # of file types; traverse list to return ptrs to them. */
364 *pfileTypes = pfileType;
365 *pNFileTypes = nFileTypes;
366 pFileType = pPriv->fileTypeHead.pNext;
367 while (nFileTypes-- > 0) {
368 *pfileType++ = (ilEFSFileType)pFileType;
369 pFileType = pFileType->h.pNext;
372 context->error = IL_OK;
377 /* =================================== FILE CODE ================================== */
380 /* --------------------------- ilEFSOpenFile ------------------------------- */
381 /* Public function: see spec.
384 /* Object Destroy() function for file objects. */
385 static void ilDestroyFile (
389 register ilEFSFileTypePtr pFileType;
391 /* Get ptr to file type; if null, file not actually open yet; skip Close() */
392 pFileType = (ilEFSFileTypePtr)pFile->info.fileType;
394 (*pFileType->info.Close) (pFile);
398 ilEFSFile ilEFSOpen (
401 unsigned int openMode,
402 unsigned long searchOptions,
407 ilEFSPrivatePtr pPriv;
408 register ilEFSFilePtr pFile;
409 register ilEFSFileTypePtr pFileType, pListHead;
413 char extension [IL_EFS_MAX_EXTENSION_CHARS];
415 /* Validate pOptions, openMode (set readOpen true if a read). */
416 context->error = IL_OK;
418 context->error = IL_ERROR_PAR_NOT_ZERO;
419 return (ilEFSFileType)NULL;
423 case IL_EFS_READ_SEQUENTIAL:
424 readOpen = TRUE; break;
426 readOpen = FALSE; break;
428 context->error = IL_ERROR_EFS_OPEN_MODE;
429 return (ilEFSFile)NULL;
432 /* Init EFS file types if not already inited. */
433 if (!(pPriv = ilInitEFS (context)))
434 return (ilEFSFile)NULL;
436 /* Add a file type object - goto openError to destroy it if an error later. */
437 pFile = (ilEFSFilePtr)_ilCreateObject (context, IL_EFS_FILE, ilDestroyFile,
438 sizeof (ilEFSFileRec));
439 if (!pFile) return (ilEFSFile)NULL;
441 /* Find pFileType for this file, searches enabled by mask in searchOptions.
442 First try typeName, if non-null. When found at any point: if openMode
443 not supported, error - except for checking mode - else call Open() for
444 the file type. If it returns any error other than "not mine" abort.
446 pFileType = (ilEFSFileTypePtr)NULL;
447 pListHead = (ilEFSFileTypePtr)&pPriv->fileTypeHead;
448 if (typeName && (searchOptions & IL_EFS_BY_TYPE_NAME)) {
449 pFileType = ilFindFileType (typeName, pListHead);
450 if (pFileType) { /* file type found */
451 if (!(pFileType->info.openModes & (1 << openMode))) {
452 context->error = IL_ERROR_EFS_OPEN_MODE;
455 pOpenPriv = (*pFileType->info.Open) (pFileType, fileName, openMode, &nPages);
457 if (context->error == IL_ERROR_EFS_NOT_MINE)
458 pFileType = (ilEFSFileTypePtr)NULL; /* try next search method */
461 pFile->info.howFound = IL_EFS_BY_CHECKING;
463 } /* END open by type name */
466 /* If not found, search for extension if enabled. */
467 if (!pFileType && (searchOptions & IL_EFS_BY_EXTENSION)) {
469 register ilEFSFileTypePtr pSearch;
472 pExtension = strrchr (fileName, '.');
473 if (pExtension) { /* is a "." in fileName */
474 pExtension++; /* point past "." */
475 nChars = strlen (pExtension);
476 if (nChars > (IL_EFS_MAX_EXTENSION_CHARS - 1))
477 nChars = IL_EFS_MAX_EXTENSION_CHARS - 1;
478 bcopy (pExtension, extension, nChars); /* extract "extension" */
479 extension [nChars] = 0;
481 /* Search list for extension match until pFileType found or list done */
482 pSearch = pListHead->h.pNext;
483 while (!pFileType && (pSearch != pListHead)) {
484 register int nExtensions = pSearch->info.nExtensions;
485 while (nExtensions-- > 0)
486 if (STRING_EQUAL (extension, pSearch->info.extensions[nExtensions])) {
487 pFileType = pSearch; /* extension found; quit */
488 pFile->info.howFound = IL_EFS_BY_CHECKING;
491 pSearch = pSearch->h.pNext;
494 if (!(pFileType->info.openModes & (1 << openMode))) {
495 context->error = IL_ERROR_EFS_OPEN_MODE;
498 pOpenPriv = (*pFileType->info.Open) (pFileType, fileName, openMode, &nPages);
500 if (context->error == IL_ERROR_EFS_NOT_MINE)
501 pFileType = (ilEFSFileTypePtr)NULL;
505 } /* END have extension */
506 } /* END open by extension */
509 /* If not found, search by checking if a read openMode. For each file type,
510 try open if enabled (checkOrder != 0) and openMode supported for file type.
512 if (!pFileType && readOpen && (searchOptions & IL_EFS_BY_CHECKING)) {
513 register ilEFSFileTypePtr pSearch;
515 pSearch = pListHead->h.pNext;
516 while (pSearch != pListHead) {
517 if (pSearch->info.checkOrder && (pSearch->info.openModes & (1 << openMode))) {
518 pOpenPriv = (*pSearch->info.Open) (pSearch, fileName, openMode, &nPages);
520 pFileType = pSearch; /* found right file type; break */
521 pFile->info.howFound = IL_EFS_BY_CHECKING;
524 else if (context->error != IL_ERROR_EFS_NOT_MINE)
525 goto openError; /* some error; give up */
527 pSearch = pSearch->h.pNext;
529 } /* END open by checking */
531 /* If not found above, error: can't find file type handler for this file. */
533 context->error = IL_ERROR_EFS_NO_FILE_TYPE;
537 /* File type found. Fill in info for the file, return pFile. The object's
538 pPrivate is set to the ptr returned from file type's Open().
540 pFile->o.p.pPrivate = pOpenPriv;
541 pFile->info.fileType = (ilEFSFileType)pFileType;
542 pFile->info.openMode = openMode;
543 pFile->info.attributes = pFileType->info.attributes;
544 pFile->info.nPages = nPages;
545 pFile->pFileType = pFileType;
547 context->error = IL_OK;
548 return (ilEFSFile)pFile; /* success; return file */
550 /* openError: goto here on error after file object created. The Open() was not
551 successful, so set fileType to null so ilDestroyFile() does not call Close().
555 error = context->error; /* save error code */
556 pFile->info.fileType = (ilEFSFileType)NULL;
557 ilDestroyObject ((ilObject)pFile);
558 context->error = error; /* restore error code */
559 return (ilEFSFile)NULL;
564 /* ------------------------ ilEFSGetFileInfo ---------------------------- */
565 /* Public function: see spec.
567 ilBool ilEFSGetFileInfo (
569 ilEFSFileInfo *pInfo /* RETURNED */
572 register ilEFSFilePtr pFile;
574 pFile = (ilEFSFilePtr)file;
575 if (pFile->o.p.objectType != IL_EFS_FILE) {
576 pFile->o.p.context->error = IL_ERROR_OBJECT_TYPE;
580 /* Return file info; fill in "inUse": file in use if refCount > 1 */
581 *pInfo = pFile->info;
582 pInfo->inUse = (pFile->o.refCount > 1);
583 pFile->o.p.context->error = IL_OK;
588 /* ------------------------ ilEFSSeek ---------------------------- */
589 /* Public function: see spec.
597 register ilEFSFilePtr pFile;
599 pFile = (ilEFSFilePtr)file;
601 pFile->o.p.context->error = IL_ERROR_PAR_NOT_ZERO;
604 if (pFile->o.p.objectType != IL_EFS_FILE) {
605 pFile->o.p.context->error = IL_ERROR_OBJECT_TYPE;
609 /* Validate that file was opened for random read; error if not. */
610 if (pFile->info.openMode != IL_EFS_READ) {
611 pFile->o.p.context->error = IL_ERROR_EFS_OPEN_MODE;
615 /* Call Seek() only if multi-page reads supported; not error if not. */
616 pFile->o.p.context->error = IL_OK;
617 if (!(pFile->info.attributes & IL_EFS_MULTI_PAGE_READS))
619 else return (*pFile->pFileType->info.Seek) (file, page);
623 /* ------------------------ ilEFSGetPageInfo ---------------------------- */
624 /* Public function: see spec.
626 ilBool ilEFSGetPageInfo (
631 register ilEFSFilePtr pFile;
633 pFile = (ilEFSFilePtr)file;
634 if (pFile->o.p.objectType != IL_EFS_FILE) {
635 pFile->o.p.context->error = IL_ERROR_OBJECT_TYPE;
639 /* Validate that file was opened for read; call GetPageInfo() if so. */
640 if ((pFile->info.openMode != IL_EFS_READ)
641 && (pFile->info.openMode != IL_EFS_READ_SEQUENTIAL)) {
642 pFile->o.p.context->error = IL_ERROR_EFS_OPEN_MODE;
646 pFile->o.p.context->error = IL_OK;
647 return (*pFile->pFileType->info.GetPageInfo) (file, pInfo);
651 /* ------------------------ ilEFSReadImage ---------------------------- */
652 /* Public function: see spec.
654 ilBool ilEFSReadImage (
657 unsigned int readMode,
663 register ilEFSFilePtr pFile;
665 pFile = (ilEFSFilePtr)file;
667 pFile->o.p.context->error = IL_ERROR_PAR_NOT_ZERO;
670 if ((pipe->objectType != IL_PIPE) || (pFile->o.p.objectType != IL_EFS_FILE)) {
671 pFile->o.p.context->error = IL_ERROR_OBJECT_TYPE;
675 /* Validate readMode: mask allowed only if supported by file type. */
677 case IL_EFS_READ_MAIN:
679 case IL_EFS_READ_MASK:
680 if (pFile->pFileType->info.attributes & IL_EFS_MASK_READS)
681 break; /* else fall thru for error */
683 pFile->o.p.context->error = IL_ERROR_EFS_READ_MODE;
687 /* Validate that file was opened for read. */
688 if ((pFile->info.openMode != IL_EFS_READ)
689 && (pFile->info.openMode != IL_EFS_READ_SEQUENTIAL)) {
690 pFile->o.p.context->error = IL_ERROR_EFS_OPEN_MODE;
694 /* If pipe element added successfully inc file's refCount to mark in use,
695 and add file to list of objects to be destroyed when pipe emptied.
697 pFile->o.p.context->error = IL_OK;
698 if ((*pFile->pFileType->info.ReadImage) (pipe, file, readMode, width, height)) {
700 return _ilAddPipeDestroyObject (pipe, (ilObject)pFile);
706 /* ------------------------ ilEFSWriteImage ---------------------------- */
707 /* Public function: see spec.
709 ilBool ilEFSWriteImage (
714 ilClientImage maskImage,
718 register ilEFSFilePtr pFile;
720 pFile = (ilEFSFilePtr)file;
722 pFile->o.p.context->error = IL_ERROR_PAR_NOT_ZERO;
725 if ((pipe->objectType != IL_PIPE) || (pFile->o.p.objectType != IL_EFS_FILE)) {
726 pFile->o.p.context->error = IL_ERROR_OBJECT_TYPE;
730 /* Validate that file was opened for write. */
731 if (pFile->info.openMode != IL_EFS_WRITE) {
732 pFile->o.p.context->error = IL_ERROR_EFS_OPEN_MODE;
736 /* If file type doesnt handle masks, ignore maskImage, else validate it */
738 if (!(pFile->pFileType->info.attributes & IL_EFS_MASK_WRITES))
739 maskImage = (ilClientImage)NULL;
742 register const ilImageDes *pDes;
743 register const ilImageFormat *pFormat;
745 if (!ilQueryClientImage (maskImage, &pInfo, 0))
748 pFormat = pInfo->pFormat;
749 if ((pDes->compression != IL_UNCOMPRESSED)
750 || (pDes->nSamplesPerPixel != 1)
751 || (pFormat->rowBitAlign != 32)
752 || (pFormat->nBitsPerSample[0] != 1)) {
753 pFile->o.p.context->error = IL_ERROR_EFS_OPEN_MODE;
759 /* If pipe element added successfully inc file's refCount to mark in use,
760 and add file/maskImage to list of objects to be destroyed when pipe emptied.
762 pFile->o.p.context->error = IL_OK;
763 if ((*pFile->pFileType->info.WriteImage) (pipe, file, xRes, yRes, maskImage)) {
765 ((ilObjectPtr)maskImage)->refCount++;
766 _ilAddPipeDestroyObject (pipe, maskImage);
769 return _ilAddPipeDestroyObject (pipe, (ilObject)pFile);