1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16/**
17************************************************************************
18 * @file         M4OSA_FileReader.c
19 * @author       Cedric Lecoutre (cedric.lecoutre@philips.com)
20 *               Laurent Fay (laurent.fay@philips.com)
21 * @par Org:     Philips Digital Systems Laboratories - Paris (PDSL-P)
22 * @brief        File reader for Android
23 * @note         This file implements functions to read a file.
24 ************************************************************************
25*/
26
27
28#include "M4OSA_Debug.h"
29#include "M4OSA_FileCommon_priv.h"
30#include "M4OSA_FileReader.h"
31#include "M4OSA_FileReader_priv.h"
32#include "M4OSA_Memory.h"
33
34#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE
35#include "M4OSA_Semaphore.h"
36#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */
37
38
39/**
40************************************************************************
41* @brief      This function opens the provided URL and returns its context.
42*             If an error occured, the context is set to NULL.
43* @param      context: (OUT) Context of the core file reader
44* @param      url: (IN) URL of the input file
45* @param      fileModeAccess: (IN) File mode access
46* @return     M4NO_ERROR: there is no error
47* @return     M4ERR_PARAMETER: at least one parameter is NULL
48* @return     M4ERR_ALLOC: there is no more memory available
49* @return     M4ERR_NOT_IMPLEMENTED: the URL does not match with the supported
50*             file
51* @return     M4ERR_FILE_NOT_FOUND: the file cannot be found
52* @return     M4ERR_FILE_LOCKED: the file is locked by an other
53*             application/process
54* @return     M4ERR_FILE_BAD_MODE_ACCESS: the file mode access is not correct
55************************************************************************
56*/
57M4OSA_ERR M4OSA_fileReadOpen(M4OSA_Context* pContext, M4OSA_Void* pFileDescriptor,
58                             M4OSA_UInt32 fileModeAccess)
59{
60    M4OSA_TRACE1_3("M4OSA_fileReadOpen : pC = 0x%p  fd = 0x%p  mode = %lu",
61                                     pContext, pFileDescriptor, fileModeAccess);
62
63    return M4OSA_fileCommonOpen(M4OSA_FILE_READER, pContext,
64                                               pFileDescriptor, fileModeAccess);
65}
66
67/**
68************************************************************************
69* @brief      This function reads the 'size' bytes in the core file reader
70*             (selected by its 'context') and writes the data to the 'data'
71*             pointer.
72* @note       If 'size' byte cannot be read in the core file reader, 'size'
73*             parameter is updated to match the correct
74* @note       number of read bytes.
75* @param      context: (IN/OUT) Context of the core file reader
76* @param      buffer: (OUT) Data pointer of the read data
77* @param      size: (IN/OUT) Size of the data to read (in bytes)
78* @return     M4NO_ERROR: there is no error
79* @return     M4ERR_PARAMETER: at least one parameter is NULL
80* @return     M4ERR_BAD_CONTEXT: provided context is not a valid one
81* @return     M4ERR_ALLOC: there is no more memory available
82* @return     M4WAR_NO_DATA_YET: there is no enough data to fill the 'data'
83*             buffer, so the size parameter has been updated.
84************************************************************************
85*/
86M4OSA_ERR M4OSA_fileReadData(M4OSA_Context pContext, M4OSA_MemAddr8 data,
87                                                            M4OSA_UInt32* pSize)
88{
89    M4OSA_FileContext* pFileContext = pContext;
90    M4OSA_ERR    err = M4NO_ERROR;
91    M4OSA_Int32    uiSizeRead;
92
93    M4OSA_TRACE2_2("M4OSA_fileReadData : data = 0x%p  size = %lu",
94                                    data, (M4OSA_NULL != pSize) ? (*pSize) : 0);
95
96    M4OSA_DEBUG_IF2(M4OSA_NULL == pContext, M4ERR_PARAMETER,
97                                  "M4OSA_fileReadData: pContext is M4OSA_NULL");
98    M4OSA_DEBUG_IF2(M4OSA_NULL == data, M4ERR_PARAMETER,
99                                      "M4OSA_fileReadData: data is M4OSA_NULL");
100    M4OSA_DEBUG_IF2(M4OSA_NULL == pSize, M4ERR_PARAMETER,
101                                     "M4OSA_fileReadData: pSize is M4OSA_NULL");
102#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE
103    M4OSA_DEBUG_IF2(M4OSA_NULL == pFileContext->semaphore_context,
104      M4ERR_BAD_CONTEXT, "M4OSA_fileReadData: semaphore_context is M4OSA_NULL");
105#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */
106
107    if(M4OSA_kDescRWAccess == pFileContext->m_DescrModeAccess) /* read write */
108    {
109        uiSizeRead = fread(data, sizeof(M4OSA_Char), *pSize,
110                                                       pFileContext->file_desc);
111        if(-1 == uiSizeRead)
112        {
113            /* handle is invalid, or the file is not open for reading, or the file is locked */
114            *pSize = 0;
115            err = M4ERR_BAD_CONTEXT;
116        }
117        else
118        {
119            pFileContext->read_position = pFileContext->read_position + uiSizeRead;
120            if ((M4OSA_UInt32)uiSizeRead < *pSize)
121            {
122                *pSize = uiSizeRead;
123                /* This is the end of file */
124                pFileContext->b_is_end_of_file = M4OSA_TRUE;
125                err = M4WAR_NO_DATA_YET;
126            }
127            else
128            {
129                *pSize = uiSizeRead;
130            }
131        }
132
133        return err;
134    }
135
136#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE
137    M4OSA_semaphoreWait(pFileContext->semaphore_context, M4OSA_WAIT_FOREVER);
138#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */
139
140    if(pFileContext->current_seek != SeekRead)
141    {
142        /* fseek to the last read position */
143        err = M4OSA_fileCommonSeek(pContext, M4OSA_kFileSeekBeginning,
144                                                &(pFileContext->read_position));
145        if(M4OSA_ERR_IS_ERROR(err))
146        {
147            M4OSA_DEBUG(err, "M4OSA_fileReadData: M4OSA_fileCommonSeek");
148
149#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE
150            M4OSA_semaphorePost(pFileContext->semaphore_context);
151#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */
152
153            return err;
154        }
155
156        pFileContext->current_seek = SeekRead;
157    }
158
159    /* Read data */
160    uiSizeRead = fread(data, sizeof(M4OSA_Char), *pSize,
161                                                       pFileContext->file_desc);
162    if(-1 == uiSizeRead)
163    {
164        /* handle is invalid, or the file is not open for reading,
165         or the file is locked */
166        *pSize = 0;
167        err = M4ERR_BAD_CONTEXT;
168    }
169    else
170    {
171        pFileContext->read_position = pFileContext->read_position + uiSizeRead;
172        if ((M4OSA_UInt32)uiSizeRead < *pSize)
173        {
174            *pSize = uiSizeRead;
175
176            /* This is the end of file */
177            pFileContext->b_is_end_of_file = M4OSA_TRUE;
178
179            err = M4WAR_NO_DATA_YET;
180        }
181        else
182        {
183            *pSize = uiSizeRead;
184        }
185    }
186
187#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE
188    M4OSA_semaphorePost(pFileContext->semaphore_context);
189#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */
190
191
192    return err;
193}
194
195
196/**
197************************************************************************
198 * @brief      This function seeks at the provided position in the core file
199 *             reader (selected by its 'context'). The position is related to
200 *             the seekMode parameter it can be either from the beginning, from
201 *             the end or from the current postion. To support large file
202 *             access (more than 2GBytes), the position is provided on a 64
203 *             bits.
204 * @note       If this function returns an error the current position pointer
205 *             in the file must not change. Else the current
206 *             position pointer must be updated.
207 * @param      context: (IN/OUT) Context of the core file reader
208 * @param      seekMode: (IN) Seek access mode
209 * @param      position: (IN/OUT) Position in the file
210 * @return     M4NO_ERROR: there is no error
211 * @return     M4ERR_PARAMETER: at least one parameter is NULL
212 * @return     M4ERR_BAD_CONTEXT: provided context is not a valid one
213 * @return     M4ERR_ALLOC: there is no more memory available
214 * @return     M4ERR_FILE_INVALID_POSITION: the position cannot be reached
215 ************************************************************************
216*/
217
218M4OSA_ERR M4OSA_fileReadSeek(M4OSA_Context pContext, M4OSA_FileSeekAccessMode seekMode,
219                             M4OSA_FilePosition* pPosition)
220{
221    M4OSA_FileContext* pFileContext = (M4OSA_FileContext*)pContext;
222    M4OSA_ERR err;
223
224    M4OSA_TRACE2_2("M4OSA_fileReadSeek : mode = %d  pos = %lu", seekMode,
225                                  (pPosition != M4OSA_NULL) ? (*pPosition) : 0);
226
227    M4OSA_DEBUG_IF2(M4OSA_NULL == pContext, M4ERR_PARAMETER,
228                                  "M4OSA_fileReadSeek: pContext is M4OSA_NULL");
229    M4OSA_DEBUG_IF2(0 == seekMode, M4ERR_PARAMETER,
230                                           "M4OSA_fileReadSeek: seekMode is 0");
231    M4OSA_DEBUG_IF2(M4OSA_NULL == pPosition, M4ERR_PARAMETER,
232                                 "M4OSA_fileReadSeek: pPosition is M4OSA_NULL");
233#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE
234    M4OSA_DEBUG_IF2(M4OSA_NULL == pFileContext->semaphore_context,
235      M4ERR_BAD_CONTEXT, "M4OSA_fileReadSeek: semaphore_context is M4OSA_NULL");
236#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */
237
238    if (M4OSA_kDescRWAccess == pFileContext->m_DescrModeAccess)
239    {
240         M4OSA_UInt32    SeekModeOption;
241         /* Go to the desired position */
242        if (M4OSA_kFileSeekBeginning == seekMode)
243        {
244            SeekModeOption = SEEK_SET;
245        }
246        else if (M4OSA_kFileSeekEnd == seekMode)
247        {
248            SeekModeOption = SEEK_END;
249        }
250        else if (M4OSA_kFileSeekCurrent == seekMode)
251        {
252            SeekModeOption = SEEK_CUR;
253        }
254        else
255        {
256            M4OSA_TRACE1_0("M4OSA_fileReadSeek: END WITH ERROR !!! (CONVERION ERROR FOR THE SEEK MODE)");
257            return M4ERR_PARAMETER;
258        }
259
260        /**
261         * Go to the desired position */
262        err = fseek(pFileContext->file_desc, *pPosition, SeekModeOption);
263        if(err != 0)
264        {
265            /* converts the error to PSW format*/
266            err=((M4OSA_UInt32)(M4_ERR)<<30)+(((M4OSA_FILE_WRITER)&0x003FFF)<<16)+(M4OSA_Int16)(err);
267            M4OSA_TRACE1_1("M4OSA_FileReadSeek error:%x",err);
268        }
269        else
270        {
271            return M4NO_ERROR;
272        }
273
274        /* Return without error */
275        return err;
276    }
277
278
279#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE
280    M4OSA_semaphoreWait(pFileContext->semaphore_context, M4OSA_WAIT_FOREVER);
281#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */
282
283    if(pFileContext->current_seek != SeekRead)
284    {
285
286        /* fseek to the last read position */
287        err = M4OSA_fileCommonSeek(pContext, M4OSA_kFileSeekBeginning,
288                                                &(pFileContext->read_position));
289        if(M4OSA_ERR_IS_ERROR(err))
290        {
291            M4OSA_DEBUG(err, "M4OSA_fileReadData: M4OSA_fileCommonSeek");
292
293#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE
294            M4OSA_semaphorePost(pFileContext->semaphore_context);
295#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */
296
297            return err;
298        }
299
300        pFileContext->current_seek = SeekRead;
301    }
302
303    err = M4OSA_fileCommonSeek(pContext, seekMode, pPosition);
304    if(M4OSA_ERR_IS_ERROR(err))
305    {
306        M4OSA_DEBUG(err, "M4OSA_fileReadData: M4OSA_fileCommonSeek");
307    }
308    else
309    {
310        pFileContext->read_position = *pPosition;
311    }
312
313#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE
314    M4OSA_semaphorePost(pFileContext->semaphore_context);
315#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */
316
317    return err;
318}
319
320
321/**
322 ************************************************************************
323 * @brief      This function asks the core file reader to close the file
324 *             (associated to the context).
325 * @note       The context of the core file reader is freed.
326 * @param      pContext: (IN/OUT) Context of the core file reader
327 * @return     M4NO_ERROR: there is no error
328 * @return     M4ERR_PARAMETER: at least one parameter is NULL
329 * @return     M4ERR_BAD_CONTEXT: provided context is not a valid one
330 * @return     M4ERR_ALLOC: there is no more memory available
331 ************************************************************************
332*/
333M4OSA_ERR M4OSA_fileReadClose(M4OSA_Context pContext)
334{
335    M4OSA_FileContext* pFileContext = (M4OSA_FileContext*)pContext;
336
337    M4OSA_TRACE1_1("M4OSA_fileReadClose : pC = 0x%p", pContext);
338
339    M4OSA_DEBUG_IF2(M4OSA_NULL == pContext, M4ERR_PARAMETER,
340                                 "M4OSA_fileReadClose: pContext is M4OSA_NULL");
341
342    if(M4OSA_FILE_WRITER == pFileContext->coreID_write)
343    {
344        return M4NO_ERROR;
345    }
346
347    return M4OSA_fileCommonClose(M4OSA_FILE_READER, pContext);
348}
349
350
351
352
353/**
354 ************************************************************************
355 * @brief      This function asks the core file reader to return the value
356 *             associated with the optionID. The caller is responsible for
357 *             allocating/de-allocating the memory of the value field.
358 * @note       'value' must be cast according to the type related to the
359 *             optionID As the caller is responsible for
360 *             allocating/de-allocating the 'value' field, the callee must copy
361 *             this field to its internal variable.
362 * @param      pContext: (IN/OUT) Context of the core file reader
363 * @param      pOptionID: (IN) ID of the option
364 * @param      pOptionValue: (OUT) Value of the option
365 * @return     M4NO_ERROR: there is no error
366 * @return     M4ERR_PARAMETER: at least one parameter is NULL
367 * @return     M4ERR_BAD_CONTEXT: provided context is not a valid one
368 * @return     M4ERR_BAD_OPTION_ID: the optionID is not a valid one
369 * @return     M4ERR_WRITE_ONLY: this option is a write only one
370 * @return     M4ERR_NOT_IMPLEMENTED: this option is not implemented
371 ************************************************************************
372*/
373M4OSA_ERR M4OSA_fileReadGetOption(M4OSA_Context pContext, M4OSA_FileReadOptionID optionID,
374                                  M4OSA_DataOption* pOptionValue)
375{
376    M4OSA_FileContext* pFileContext = pContext;
377
378    M4OSA_TRACE2_1("M4OSA_fileReadGetOption : option = 0x%x", optionID);
379
380    M4OSA_DEBUG_IF2(M4OSA_NULL == pContext, M4ERR_PARAMETER,
381                             "M4OSA_fileReadGetOption: pContext is M4OSA_NULL");
382    M4OSA_DEBUG_IF2(optionID == 0, M4ERR_PARAMETER,
383                                      "M4OSA_fileReadGetOption: optionID is 0");
384    M4OSA_DEBUG_IF2(M4OSA_NULL == pOptionValue, M4ERR_PARAMETER,
385                         "M4OSA_fileReadGetOption: pOptionValue is M4OSA_NULL");
386
387    M4OSA_DEBUG_IF2(!M4OSA_OPTION_ID_IS_COREID(optionID, M4OSA_FILE_READER),
388                                M4ERR_BAD_OPTION_ID, "M4OSA_fileReadGetOption");
389    M4OSA_DEBUG_IF2(!M4OSA_OPTION_ID_IS_READABLE(optionID),
390                                   M4ERR_WRITE_ONLY, "M4OSA_fileReadGetOption");
391#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE
392    M4OSA_DEBUG_IF2(M4OSA_NULL == pFileContext->semaphore_context,
393                                  M4ERR_BAD_CONTEXT,
394                                  "M4OSA_fileReadGetOption: semaphore_context is M4OSA_NULL");
395#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */
396
397    switch(optionID)
398    {
399#if(M4OSA_OPTIONID_FILE_READ_GET_FILE_POSITION == M4OSA_TRUE)
400    case M4OSA_kFileReadGetFilePosition:
401        {
402            M4OSA_FilePosition* pPosition = (M4OSA_FilePosition*)pOptionValue;
403
404#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE
405            M4OSA_semaphoreWait(pFileContext->semaphore_context, M4OSA_WAIT_FOREVER);
406#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */
407
408            *pPosition = pFileContext->read_position;
409
410#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE
411            M4OSA_semaphorePost(pFileContext->semaphore_context);
412#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */
413
414            return M4NO_ERROR;
415        }
416#endif /*M4OSA_OPTIONID_FILE_READ_GET_FILE_POSITION*/
417
418#if(M4OSA_OPTIONID_FILE_READ_IS_EOF == M4OSA_TRUE)
419    case M4OSA_kFileReadIsEOF:
420        {
421            M4OSA_Bool* bIsEndOfFile = (M4OSA_Bool*)pOptionValue;
422
423#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE
424            M4OSA_semaphoreWait(pFileContext->semaphore_context, M4OSA_WAIT_FOREVER);
425#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */
426
427            *bIsEndOfFile = pFileContext->b_is_end_of_file;
428
429#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE
430            M4OSA_semaphorePost(pFileContext->semaphore_context);
431#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */
432
433            return M4NO_ERROR;
434        }
435#endif /*M4OSA_OPTIONID_FILE_READ_IS_EOF*/
436
437
438#if(M4OSA_OPTIONID_FILE_READ_GET_FILE_SIZE == M4OSA_TRUE)
439    case M4OSA_kFileReadGetFileSize:
440        {
441            M4OSA_FilePosition* pPosition = (M4OSA_FilePosition*)pOptionValue;
442            M4OSA_Int32 iSavePos    = 0;
443            M4OSA_Int32 iSize        = 0;
444
445#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE
446            M4OSA_semaphoreWait(pFileContext->semaphore_context, M4OSA_WAIT_FOREVER);
447#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */
448            /**
449            * Bugfix: update the file size.
450            * When a file is in read mode, may be another application is writing in.
451            * So, we have to update the file size */
452            iSavePos = ftell(pFileContext->file_desc);            /*1- Check the first position */
453            fseek(pFileContext->file_desc, 0, SEEK_END);        /*2- Go to the end of the file */
454            iSize = ftell(pFileContext->file_desc);                /*3- Check the file size*/
455            fseek(pFileContext->file_desc, iSavePos, SEEK_SET);    /*4- go to the first position*/
456            pFileContext->file_size = iSize;
457
458            *pPosition = pFileContext->file_size;
459
460#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE
461            M4OSA_semaphorePost(pFileContext->semaphore_context);
462#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */
463
464            return M4NO_ERROR;
465        }
466#endif /*M4OSA_OPTIONID_FILE_READ_GET_FILE_SIZE*/
467
468#if(M4OSA_OPTIONID_FILE_READ_GET_FILE_ATTRIBUTE == M4OSA_TRUE)
469    case M4OSA_kFileReadGetFileAttribute:
470        {
471            return M4OSA_fileCommonGetAttribute(pContext,
472                                            (M4OSA_FileAttribute*)pOptionValue);
473        }
474#endif /*M4OSA_OPTIONID_FILE_READ_GET_FILE_ATTRIBUTE*/
475
476#if(M4OSA_OPTIONID_FILE_READ_GET_URL == M4OSA_TRUE)
477    case M4OSA_kFileReadGetURL:
478        {
479            return M4OSA_fileCommonGetURL(pContext, (M4OSA_Char**)pOptionValue);
480        }
481#endif /*M4OSA_OPTIONID_FILE_READ_GET_URL*/
482
483        case M4OSA_kFileReadLockMode:
484        {
485            *(M4OSA_UInt32*)pOptionValue = pFileContext->m_uiLockMode;
486            return M4NO_ERROR;
487        }
488    }
489
490    M4OSA_DEBUG(M4ERR_NOT_IMPLEMENTED, "M4OSA_fileReadGetOption");
491
492    return M4ERR_NOT_IMPLEMENTED;
493}
494
495/**
496 ************************************************************************
497 * @fn         M4OSA_ERR M4OSA_fileReadSetOption (M4OSA_Context context,
498 *                       M4OSA_OptionID optionID, M4OSA_DataOption optionValue))
499 * @brief      This function asks the core file reader to set the value associated with the optionID.
500 *             The caller is responsible for allocating/de-allocating the memory of the value field.
501 * @note       As the caller is responsible for allocating/de-allocating the 'value' field, the callee must copy this field
502 *             to its internal variable.
503 * @param      pContext: (IN/OUT) Context of the core file reader
504 * @param      optionID: (IN) ID of the option
505 * @param      value: (IN) Value of the option
506 * @return     M4NO_ERROR: there is no error
507 * @return     M4ERR_PARAMETER: at least one parameter is NULL
508 * @return     M4ERR_BAD_CONTEXT: provided context is not a valid one
509 * @return     M4ERR_BAD_OPTION_ID: the optionID is not a valid one
510 * @return     M4ERR_READ_ONLY: this option is a read only one
511 * @return     M4ERR_NOT_IMPLEMENTED: this option is not implemented
512 ************************************************************************
513*/
514M4OSA_ERR M4OSA_fileReadSetOption(M4OSA_Context pContext,
515                                  M4OSA_FileReadOptionID optionID,
516                                  M4OSA_DataOption optionValue)
517{
518    M4OSA_FileContext* pFileContext = pContext;
519
520    M4OSA_TRACE2_1("M4OSA_fileReadSetOption : option = 0x%x", optionID);
521
522    M4OSA_DEBUG_IF2(M4OSA_NULL == pContext, M4ERR_PARAMETER,
523                             "M4OSA_fileReadSetOption: pContext is M4OSA_NULL");
524    M4OSA_DEBUG_IF2(0 == optionID, M4ERR_PARAMETER,
525                                                     "M4OSA_fileReadSetOption");
526    M4OSA_DEBUG_IF2(!M4OSA_OPTION_ID_IS_COREID(optionID, M4OSA_FILE_READER),
527                                M4ERR_BAD_OPTION_ID, "M4OSA_fileReadSetOption");
528
529    M4OSA_DEBUG_IF2(!M4OSA_OPTION_ID_IS_WRITABLE(optionID),
530                                    M4ERR_READ_ONLY, "M4OSA_fileReadSetOption");
531#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE
532    M4OSA_DEBUG_IF2(M4OSA_NULL == pFileContext->semaphore_context,
533                                  M4ERR_BAD_CONTEXT,
534                                  "M4OSA_fileReadSetOption: semaphore_context is M4OSA_NULL");
535#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */
536
537    switch(optionID)
538    {
539        case M4OSA_kFileReadLockMode:
540        {
541            pFileContext->m_uiLockMode= (M4OSA_UInt32)*(M4OSA_UInt32*)optionValue;
542            return M4NO_ERROR;
543        }
544        default:
545            M4OSA_DEBUG(M4ERR_NOT_IMPLEMENTED, "M4OSA_fileReadSetOption");
546            return M4ERR_NOT_IMPLEMENTED;
547    }
548}
549
550