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_FileCommon.c
19 * @brief        File common for Android
20 * @note         This file implements functions used by both the file writer
21 *               and file reader.
22 ************************************************************************
23*/
24
25#ifndef USE_STAGEFRIGHT_CODECS
26#error "USE_STAGEFRIGHT_CODECS is not defined"
27#endif /*USE_STAGEFRIGHT_CODECS*/
28
29#ifdef UTF_CONVERSION
30#include <string.h>
31#endif /*UTF_CONVERSION*/
32
33#include <sys/stat.h>
34#include <errno.h>
35
36#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE
37#include "M4OSA_Semaphore.h"
38#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */
39
40
41#include "M4OSA_Debug.h"
42#include "M4OSA_FileCommon.h"
43#include "M4OSA_FileCommon_priv.h"
44#include "M4OSA_Memory.h"
45#include "M4OSA_CharStar.h"
46
47/**
48 ************************************************************************
49 * @brief      This function opens the provided URL and returns its context.
50 *             If an error occured, the context is set to NULL.
51 * @param      core_id: (IN) Core ID of the caller (M4OSA_FILE_READER or M4OSA_FILE_WRITER)
52 * @param      context: (OUT) Context of the core file reader
53 * @param      url: (IN) URL of the input file
54 * @param      fileModeAccess: (IN) File mode access
55 * @return     M4NO_ERROR: there is no error
56 * @return     M4ERR_PARAMETER: at least one parameter is NULL
57 * @return     M4ERR_ALLOC: there is no more memory available
58 * @return     M4ERR_NOT_IMPLEMENTED: the URL does not match with the supported
59 *             file
60 * @return     M4ERR_FILE_NOT_FOUND: the file cannot be found
61 * @return     M4ERR_FILE_LOCKED: the file is locked by an other
62 *             application/process
63 * @return     M4ERR_FILE_BAD_MODE_ACCESS: the file mode access is not correct
64 ************************************************************************
65*/
66M4OSA_ERR M4OSA_fileCommonOpen(M4OSA_UInt16 core_id, M4OSA_Context* pContext,
67                               M4OSA_Char* pUrl, M4OSA_FileModeAccess fileModeAccess)
68{
69
70    M4OSA_Int32 i            = 0;
71    M4OSA_Int32 iMode        = 0;
72    M4OSA_Int32 iSize        = 0;
73    M4OSA_Int32 iSavePos    = 0;
74
75    M4OSA_Char  mode[4]            = "";
76    M4OSA_Char* pReadString        = (M4OSA_Char*)"r";
77    M4OSA_Char* pWriteString    = (M4OSA_Char*)"w";
78    M4OSA_Char* pAppendString    = (M4OSA_Char*)"a";
79    M4OSA_Char* pBinaryString    = (M4OSA_Char*)"b";
80    M4OSA_Char* pPlusString        = (M4OSA_Char*)"+";
81
82    M4OSA_ERR err = M4NO_ERROR;
83
84    FILE* pFileHandler = M4OSA_NULL;
85    M4OSA_FileContext *pFileContext    = M4OSA_NULL;
86
87
88#ifdef UTF_CONVERSION
89    /*FB: to test the UTF16->UTF8 conversion into Video Artist*/
90    /*Convert the URL from UTF16 to UTF8*/
91    M4OSA_Void* tempConversionBuf;
92    M4OSA_UInt32 tempConversionSize = 1000;
93
94    tempConversionBuf = (M4OSA_Char*)M4OSA_32bitAlignedMalloc(tempConversionSize +1, 0, "conversion buf");
95    if(tempConversionBuf == M4OSA_NULL)
96    {
97        M4OSA_TRACE1_0("Error when allocating conversion buffer\n");
98        return M4ERR_PARAMETER;
99    }
100    M4OSA_ToUTF8_OSAL(pUrl, tempConversionBuf, &tempConversionSize);
101    ((M4OSA_Char*)tempConversionBuf)[tempConversionSize ] = '\0';
102
103    printf("file open %s\n", tempConversionBuf);
104#endif /*UTF CONVERSION*/
105
106    M4OSA_TRACE3_4("M4OSA_fileCommonOpen\t\tM4OSA_UInt16 %d\tM4OSA_Context* 0x%x\t"
107        "M4OSA_Char* %s\tfileModeAccess %d", core_id, pContext, pUrl, fileModeAccess);
108
109    M4OSA_DEBUG_IF2(M4OSA_NULL == pContext,    M4ERR_PARAMETER,    "M4OSA_fileCommonOpen: pContext is M4OSA_NULL");
110    M4OSA_DEBUG_IF2(M4OSA_NULL == pUrl,        M4ERR_PARAMETER,    "M4OSA_fileCommonOpen: pUrl  is M4OSA_NULL");
111    M4OSA_DEBUG_IF2(0 == fileModeAccess,    M4ERR_PARAMETER,    "M4OSA_fileCommonOpen: fileModeAccess is 0");
112
113    /* Read mode not set for the reader */
114    M4OSA_DEBUG_IF1((M4OSA_FILE_READER == core_id) && !(fileModeAccess & M4OSA_kFileRead),
115        M4ERR_FILE_BAD_MODE_ACCESS, "M4OSA_fileCommonOpen: M4OSA_kFileRead");
116
117    /* Read mode not set for the reader */
118    M4OSA_DEBUG_IF1((M4OSA_FILE_READER == core_id) && !(fileModeAccess & M4OSA_kFileRead),
119        M4ERR_FILE_BAD_MODE_ACCESS, "M4OSA_fileCommonOpen: M4OSA_kFileRead");
120
121    /* M4OSAfileReadOpen cannot be used with Write file mode access */
122    M4OSA_DEBUG_IF1((M4OSA_FILE_READER == core_id) && (fileModeAccess & M4OSA_kFileWrite),
123        M4ERR_FILE_BAD_MODE_ACCESS, "M4OSA_fileCommonOpen: M4OSA_kFileWrite");
124
125    /* Append and Create flags cannot be used with Read */
126    M4OSA_DEBUG_IF1((M4OSA_FILE_READER == core_id) && (fileModeAccess & M4OSA_kFileAppend),
127        M4ERR_FILE_BAD_MODE_ACCESS, "M4OSA_fileCommonOpen: M4OSA_kFileAppend");
128
129    M4OSA_DEBUG_IF1((M4OSA_FILE_READER == core_id) && (fileModeAccess & M4OSA_kFileCreate),
130        M4ERR_FILE_BAD_MODE_ACCESS, "M4OSA_fileCommonOpen: M4OSA_kFileCreate");
131
132    /* Write mode not set for the writer */
133    M4OSA_DEBUG_IF1((M4OSA_FILE_WRITER == core_id) && !(fileModeAccess & M4OSA_kFileWrite),
134        M4ERR_FILE_BAD_MODE_ACCESS, "M4OSA_fileCommonOpen: M4OSA_kFileWrite");
135
136    /* Create flag necessary for opening file */
137    if ((fileModeAccess & M4OSA_kFileRead) &&
138        (fileModeAccess & M4OSA_kFileWrite)&&(fileModeAccess & M4OSA_kFileCreate))
139    {
140        strncat((char *)mode, (const char *)pWriteString, (size_t)1);
141        strncat((char *)mode, (const char *)pPlusString, (size_t)1);
142    }
143    else
144    {
145        if(fileModeAccess & M4OSA_kFileAppend)
146        {
147            strncat((char *)mode, (const char *)pAppendString, (size_t)1);
148        }
149        else if(fileModeAccess & M4OSA_kFileRead)
150        {
151            strncat((char *)mode, (const char *)pReadString, (size_t)1);
152        }
153        else if(fileModeAccess & M4OSA_kFileWrite)
154        {
155            strncat((char *)mode, (const char *)pWriteString, (size_t)1);
156        }
157
158        if((fileModeAccess & M4OSA_kFileRead)&&(fileModeAccess & M4OSA_kFileWrite))
159        {
160            strncat((char *)mode,(const char *)pPlusString, (size_t)1);
161        }
162    }
163
164    if(!(fileModeAccess & M4OSA_kFileIsTextMode))
165    {
166        strncat((char *)mode, (const char *)pBinaryString,(size_t)1);
167    }
168
169    /*Open the file*/
170
171#ifdef UTF_CONVERSION
172    /*Open the converted path*/
173    pFileHandler = fopen((const char *)tempConversionBuf, (const char *)mode);
174    /*Free the temporary decoded buffer*/
175    free(tempConversionBuf);
176#else /* UTF_CONVERSION */
177    pFileHandler = fopen((const char *)pUrl, (const char *)mode);
178#endif /* UTF_CONVERSION */
179
180    if (M4OSA_NULL == pFileHandler)
181    {
182        switch(errno)
183        {
184        case ENOENT:
185            {
186                M4OSA_DEBUG(M4ERR_FILE_NOT_FOUND, "M4OSA_fileCommonOpen: No such file or directory");
187                M4OSA_TRACE1_1("File not found: %s", pUrl);
188                return M4ERR_FILE_NOT_FOUND;
189            }
190        case EACCES:
191            {
192                M4OSA_DEBUG(M4ERR_FILE_LOCKED, "M4OSA_fileCommonOpen: Permission denied");
193                return M4ERR_FILE_LOCKED;
194            }
195         case EINVAL:
196         {
197            M4OSA_DEBUG(M4ERR_FILE_BAD_MODE_ACCESS, "M4OSA_fileCommonOpen: Invalid Argument");
198            return M4ERR_FILE_BAD_MODE_ACCESS;
199         }
200        case EMFILE:
201         case ENOSPC:
202        case ENOMEM:
203            {
204                M4OSA_DEBUG(M4ERR_ALLOC, "M4OSA_fileCommonOpen: Too many open files");
205                return M4ERR_ALLOC;
206            }
207        default:
208            {
209                M4OSA_DEBUG(M4ERR_NOT_IMPLEMENTED, "M4OSA_fileCommonOpen");
210                return M4ERR_NOT_IMPLEMENTED;
211            }
212        }
213    }
214
215    /* Allocate the file context */
216    pFileContext = (M4OSA_FileContext*) M4OSA_32bitAlignedMalloc(sizeof(M4OSA_FileContext),
217                    core_id, (M4OSA_Char*)"M4OSA_fileCommonOpen: file context");
218    if (M4OSA_NULL == pFileContext)
219    {
220        fclose(pFileHandler);
221        M4OSA_DEBUG(M4ERR_ALLOC, "M4OSA_fileCommonOpen");
222        return M4ERR_ALLOC;
223    }
224
225    pFileContext->file_desc        = pFileHandler;
226    pFileContext->access_mode    = fileModeAccess;
227    pFileContext->current_seek    = SeekNone;
228    pFileContext->b_is_end_of_file    = M4OSA_FALSE;
229
230    /**
231     * Note: Never use this expression "i = (value1 == value2) ? x: y;"
232     * because that doens't compile on other platforms (ADS for example)
233     * Use: if(value1 == value2)
234     *        { i= x; ..etc
235     */
236    pFileContext->coreID_write = 0;
237    pFileContext->coreID_read = 0;
238    pFileContext->m_DescrModeAccess = M4OSA_kDescNoneAccess;
239
240    if (M4OSA_FILE_READER == core_id)
241    {
242        pFileContext->coreID_read = core_id;
243        pFileContext->m_DescrModeAccess = M4OSA_kDescReadAccess;
244    }
245    else if (M4OSA_FILE_WRITER == core_id)
246    {
247        pFileContext->coreID_write = core_id;
248        pFileContext->m_DescrModeAccess = M4OSA_kDescWriteAccess;
249    }
250
251    pFileContext->read_position = 0;
252    pFileContext->write_position = 0;
253
254    /* Allocate the memory to store the URL string */
255    pFileContext->url_name = (M4OSA_Char*) M4OSA_32bitAlignedMalloc(strlen((const char *)pUrl)+1,
256                        core_id, (M4OSA_Char*)"M4OSA_fileCommonOpen: URL name");
257    if (M4OSA_NULL == pFileContext->url_name)
258    {
259        fclose(pFileHandler);
260        free(pFileContext);
261        M4OSA_DEBUG(M4ERR_ALLOC, "M4OSA_fileCommonOpen");
262        return M4ERR_ALLOC;
263    }
264    M4OSA_chrNCopy(pFileContext->url_name, pUrl, strlen((const char *)pUrl)+1);
265
266    /* Get the file name */
267    err = M4OSA_fileCommonGetFilename(pUrl, &pFileContext->file_name);
268    if(M4NO_ERROR != err)
269    {
270        fclose(pFileHandler);
271        free(pFileContext->url_name);
272        free(pFileContext);
273        M4OSA_DEBUG(err, "M4OSA_fileCommonOpen");
274        return err;
275    }
276
277#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE
278    M4OSA_semaphoreOpen(&(pFileContext->semaphore_context), 1); /* Allocate the semaphore */
279#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */
280
281
282
283#ifdef USE_STAGEFRIGHT_CODECS
284    // Workaround for file system bug on Stingray/Honeycomb where a file re-created will keep
285    // the original file's size filled with 0s. Do not seek to the end to avoid ill effects
286    if(fileModeAccess & M4OSA_kFileAppend) {
287        /* Get the file size */
288        iSavePos = ftell(pFileHandler);            /*    1- Check the first position */
289        fseek(pFileHandler, 0, SEEK_END);        /*    2- Go to the end of the file*/
290        iSize = ftell(pFileHandler);            /*    3- Check the file size        */
291        fseek(pFileHandler, iSavePos, SEEK_SET);/*    4- go to the first position */
292    } else {
293        iSize = 0;
294    }
295#else /* USE_STAGEFRIGHT_CODECS */
296    /* Get the file size */
297    iSavePos = ftell(pFileHandler);            /*    1- Check the first position */
298    fseek(pFileHandler, 0, SEEK_END);        /*    2- Go to the end of the file*/
299    iSize = ftell(pFileHandler);            /*    3- Check the file size        */
300    fseek(pFileHandler, iSavePos, SEEK_SET);/*    4- go to the first position */
301#endif /* USE_STAGEFRIGHT_CODECS */
302
303
304
305    /* Warning possible overflow if the file is higher than 2GBytes */
306    pFileContext->file_size = iSize;
307
308    *pContext = pFileContext;
309
310    return M4NO_ERROR;
311}
312
313
314/**
315 ************************************************************************
316 * @brief      This function convert from UTF16 to UTF8
317 * @param      pBufferIn: (IN) UTF16 input path
318 * @param      pBufferOut: (OUT) UTF8 output path
319 * @param      bufferOutSize: (IN/OUT) size of the output path
320 * @return     M4NO_ERROR: there is no error
321 * @return     M4ERR_PARAMETER: the output path size is not enough to contain
322 *               the decoded path
323 ************************************************************************
324*/
325#ifdef UTF_CONVERSION
326M4OSA_ERR M4OSA_ToUTF8_OSAL (M4OSA_Void   *pBufferIn, M4OSA_UInt8  *pBufferOut,
327                                                    M4OSA_UInt32 *bufferOutSize)
328{
329    M4OSA_UInt16 i;
330    wchar_t      *w_str = (wchar_t *) pBufferIn;
331    M4OSA_UInt32 len, size_needed, size_given;
332    if (pBufferIn == NULL)
333    {
334        *pBufferOut=NULL;
335        *bufferOutSize=1;
336    }
337    else
338    {
339        len         = wcslen(w_str);
340        size_needed = len+1;
341        size_given  = *bufferOutSize;
342
343       *bufferOutSize=size_needed;
344        if (size_given < size_needed )
345        {
346            return M4ERR_PARAMETER;
347        }
348        else
349        {
350            for (i=0; i<len; i++)
351            {
352                pBufferOut[i]=(M4OSA_UInt8)w_str[i];
353            }
354            pBufferOut[len]=0;
355        }
356    }
357    return M4NO_ERROR;
358}
359#endif /*UTF CONVERSION*/
360
361/**
362 ************************************************************************
363 * @brief      This function seeks at the provided position.
364 * @param      context: (IN/OUT) Context of the core file reader
365 * @param      seekMode: (IN) Seek access mode
366 * @param      position: (IN/OUT) Position in the file
367 * @return     M4NO_ERROR: there is no error
368 * @return     M4ERR_PARAMETER: at least one parameter is NULL
369 * @return     M4ERR_BAD_CONTEXT: provided context is not a valid one
370 * @return     M4ERR_ALLOC: there is no more memory available
371 * @return     M4ERR_FILE_INVALID_POSITION: the position cannot be reached
372 ************************************************************************
373*/
374M4OSA_ERR M4OSA_fileCommonSeek(M4OSA_Context pContext,
375                               M4OSA_FileSeekAccessMode seekMode,
376                               M4OSA_FilePosition* pFilePos)
377{
378    M4OSA_FileContext* pFileContext = pContext;
379    M4OSA_FilePosition fpos_current;
380    M4OSA_FilePosition fpos_seek;
381    M4OSA_FilePosition fpos_null = 0;
382    M4OSA_FilePosition fpos_neg_un = -1;
383    M4OSA_FilePosition fpos_file_size;
384    M4OSA_FilePosition fpos_seek_from_beginning;
385
386    M4OSA_TRACE3_3("M4OSA_fileCommonSeek\t\tM4OSA_Context 0x%x\t M4OSA_FileSeekAccessMode %d\tM4OSA_FilePosition* 0x%x",
387        pContext, seekMode, pFilePos);
388
389    M4OSA_DEBUG_IF2(M4OSA_NULL == pContext, M4ERR_PARAMETER, "M4OSA_fileCommonSeek");
390    M4OSA_DEBUG_IF2(0 == seekMode, M4ERR_PARAMETER, "M4OSA_fileCommonSeek");
391    M4OSA_DEBUG_IF2(M4OSA_NULL == pFilePos, M4ERR_PARAMETER, "M4OSA_fileCommonSeek");
392
393    fpos_file_size = pFileContext->file_size;
394
395    if(SeekRead == pFileContext->current_seek)
396    {
397        fpos_current = pFileContext->read_position;
398    }
399    else if(SeekWrite == pFileContext->current_seek)
400    {
401        fpos_current = pFileContext->write_position;
402    }
403    else
404    {
405        fpos_current = 0;
406    }
407
408    switch(seekMode)
409    {
410    case M4OSA_kFileSeekCurrent:
411        {
412            fpos_seek = *pFilePos;
413            break;
414        }
415    case M4OSA_kFileSeekBeginning:
416        {
417            fpos_seek = *pFilePos - fpos_current;
418            break;
419        }
420    case M4OSA_kFileSeekEnd:
421        {
422            fpos_seek = *pFilePos + fpos_file_size - fpos_current;
423            break;
424        }
425    default:
426        {
427            return M4ERR_PARAMETER;
428        }
429    }
430
431    fpos_seek_from_beginning = fpos_current + fpos_seek;
432
433    if(fseek(pFileContext->file_desc, fpos_seek, SEEK_CUR) != 0)
434    {
435        switch(errno)
436        {
437        case EINVAL:
438            {
439            /* meaning the value for origin is invalid or the position
440                specified by offset is before the beginning of the file */
441                return M4ERR_FILE_INVALID_POSITION;
442            }
443
444        case EBADF:
445        default:
446            {
447                return M4ERR_BAD_CONTEXT;/* file handle is invalid */
448            }
449        }
450    }
451
452    /* Set the returned position from the beginning of the file */
453    *pFilePos = fpos_seek_from_beginning;
454
455    /* SEEK done, reset end of file value */
456    pFileContext->b_is_end_of_file = M4OSA_FALSE;
457
458    return M4NO_ERROR;
459}
460
461
462/**
463 ************************************************************************
464 * @brief      This function asks to close the file (associated to the context)
465 * @note       The context of the core file reader/writer is freed.
466 * @param      context: (IN/OUT) Context of the core file reader
467 * @return     M4NO_ERROR: there is no error
468 * @return     M4ERR_PARAMETER: at least one parameter is NULL
469 * @return     M4ERR_BAD_CONTEXT: provided context is not a valid one
470 * @return     M4ERR_ALLOC: there is no more memory available
471 ************************************************************************
472*/
473
474M4OSA_ERR M4OSA_fileCommonClose(M4OSA_UInt16 core_id, M4OSA_Context pContext)
475{
476    M4OSA_FileContext* pFileContext = pContext;
477    M4OSA_Int32 i32_err_code=0;
478
479    M4OSA_TRACE3_2("M4OSA_fileCommonClose\tM4OSA_UInt16 %d\tM4OSA_Context 0x%x",
480                                                             core_id, pContext);
481    M4OSA_DEBUG_IF2(M4OSA_NULL == pContext,
482              M4ERR_PARAMETER, "M4OSA_fileCommonClose: pContext is M4OSA_NULL");
483#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE
484    M4OSA_DEBUG_IF2(M4OSA_NULL == pFileContext->semaphore_context, M4ERR_BAD_CONTEXT,
485                     "M4OSA_fileCommonClose: semaphore_context is M4OSA_NULL");
486#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */
487
488    free(pFileContext->url_name);
489    pFileContext->url_name = M4OSA_NULL;
490
491    free(pFileContext->file_name);
492    pFileContext->file_name = M4OSA_NULL;
493
494    i32_err_code = fclose(pFileContext->file_desc);
495
496    pFileContext->file_desc = M4OSA_NULL;
497
498#ifdef M4OSA_FILE_BLOCK_WITH_SEMAPHORE
499    M4OSA_semaphoreClose(pFileContext->semaphore_context);/* free the semaphore */
500#endif /* M4OSA_FILE_BLOCK_WITH_SEMAPHORE */
501
502    free(pFileContext);
503
504    if (i32_err_code != 0)
505    {
506        M4OSA_DEBUG(M4ERR_BAD_CONTEXT, "M4OSA_fileCommonClose");
507        return M4ERR_BAD_CONTEXT;
508    }
509
510    return M4NO_ERROR;
511}
512
513
514/**
515 ************************************************************************
516 * @brief      This function gets the file attributes (associated to the
517 *             context)
518 * @param      context: (IN) Context of the core file reader
519 * @param      attribute: (OUT) The file attribute (allocated by the caller)
520 * @return     M4NO_ERROR: there is no error
521 * @return     M4ERR_PARAMETER: at least one parameter is NULL
522 * @return     M4ERR_BAD_CONTEXT: provided context is not a valid one
523 ************************************************************************
524*/
525M4OSA_ERR M4OSA_fileCommonGetAttribute(M4OSA_Context pContext, M4OSA_FileAttribute* pAttribute)
526{
527
528    M4OSA_FileContext* fileContext = pContext;
529
530    struct stat TheStat;
531
532    M4OSA_TRACE3_2("M4OSA_fileCommonGetAttribute\tM4OSA_Context 0x%x\t"
533        "M4OSA_FileAttribute* 0x%x", pContext, pAttribute);
534
535    M4OSA_DEBUG_IF2(M4OSA_NULL == pContext,        M4ERR_PARAMETER, "M4OSA_fileCommonGetAttribute");
536    M4OSA_DEBUG_IF2(M4OSA_NULL == pAttribute,    M4ERR_PARAMETER, "M4OSA_fileCommonGetAttribute");
537
538    if(stat((char*)fileContext->url_name, &TheStat) != 0)
539    {
540        M4OSA_DEBUG(M4ERR_BAD_CONTEXT, "M4OSA_fileCommonGetAttribute");
541        return M4ERR_BAD_CONTEXT;
542    }
543
544    pAttribute->creationDate.time = (M4OSA_Time)TheStat.st_ctime;
545    pAttribute->lastAccessDate.time = (M4OSA_Time)TheStat.st_atime;
546    pAttribute->modifiedDate.time = (M4OSA_Time)TheStat.st_mtime;
547
548    pAttribute->creationDate.timeScale = 1;
549    pAttribute->lastAccessDate.timeScale = 1;
550    pAttribute->modifiedDate.timeScale = 1;
551
552    pAttribute->creationDate.referenceYear = 1970;
553    pAttribute->lastAccessDate.referenceYear = 1970;
554    pAttribute->modifiedDate.referenceYear = 1970;
555
556    pAttribute->modeAccess = fileContext->access_mode;
557
558    return M4NO_ERROR;
559}
560
561/**
562 ************************************************************************
563 * @brief      This function gets the file URL (associated to the context).
564 * @note
565 * @param      context: (IN) Context of the core file reader
566 * @param      url: (OUT) The buffer containing the URL (allocated by
567 *             M4OSA_fileCommonGetURL)
568 * @return     M4NO_ERROR: there is no error
569 * @return     M4ERR_PARAMETER: at least one parameter is NULL
570 * @return     M4ERR_BAD_CONTEXT: provided context is not a valid one
571 * @return     M4ERR_ALLOC: there is no more memory available
572 ************************************************************************
573*/
574M4OSA_ERR M4OSA_fileCommonGetURL(M4OSA_Context pContext, M4OSA_Char** pUrl)
575{
576    M4OSA_FileContext* pFileContext = pContext;
577    M4OSA_UInt32    uiLength;
578
579    M4OSA_TRACE3_2("M4OSA_fileCommonGetURL\tM4OSA_Context 0x%x\tM4OSA_Char** 0x%x",
580                    pContext, pUrl);
581
582    M4OSA_DEBUG_IF2(M4OSA_NULL == pContext,    M4ERR_PARAMETER,
583                              "M4OSA_fileCommonGetURL: pContext is M4OSA_NULL");
584    M4OSA_DEBUG_IF2(M4OSA_NULL == pUrl,    M4ERR_PARAMETER,
585                                  "M4OSA_fileCommonGetURL: pUrl is M4OSA_NULL");
586
587    uiLength = strlen((const char *)pFileContext->url_name)+1;
588
589    /* Allocate the memory to store the url_name */
590    *pUrl = (M4OSA_Char*)M4OSA_32bitAlignedMalloc(uiLength, M4OSA_FILE_COMMON,
591                                    (M4OSA_Char*)"M4OSA_fileCommonGetURL: url");
592    if(M4OSA_NULL == *pUrl)
593    {
594        M4OSA_DEBUG(M4ERR_ALLOC, "M4OSA_fileCommonGetURL");
595        return M4ERR_ALLOC;
596    }
597
598    M4OSA_chrNCopy(*pUrl, pFileContext->url_name, uiLength);
599
600    return M4NO_ERROR;
601}
602
603
604/**
605 ************************************************************************
606 * @brief      This function gets a string containing the file name associated
607 *             to the input URL.
608 * @note       The user should not forget to delete the output string using
609 *             M4OSA_strDestroy
610 * @param      pUrl:            (IN) The buffer containing the URL
611 * @param      pFileName:    (OUT) The string containing the URL. It is
612 *                            allocated inside this function
613 * @return     M4NO_ERROR: there is no error
614 * @return     M4ERR_NOT_IMPLEMENTED: the URL does not match with the supported
615 *             file
616 * @return     M4ERR_ALLOC: there is no more memory available
617 ************************************************************************
618*/
619M4OSA_ERR M4OSA_fileCommonGetFilename(M4OSA_Char* pUrl, M4OSA_Char** pFileName)
620{
621    M4OSA_Int32 i            = 0;
622    M4OSA_Int32 iUrlLen        = 0;
623    M4OSA_Int32 FileNameLen = 0;
624
625    M4OSA_Char* ptrUrl        = M4OSA_NULL;
626    M4OSA_Char* ptrFilename    = M4OSA_NULL;
627
628    M4OSA_TRACE3_2("M4OSA_fileCommonGetURL\tM4OSA_Char* %s\tM4OSA_Char** 0x%x",
629                                                               pUrl, pFileName);
630
631    M4OSA_DEBUG_IF2(M4OSA_NULL == pUrl,    M4ERR_PARAMETER,
632                             "M4OSA_fileCommonGetFilename: pUrl is M4OSA_NULL");
633    M4OSA_DEBUG_IF2(M4OSA_NULL == pFileName,    M4ERR_PARAMETER,
634                        "M4OSA_fileCommonGetFilename: pFileName is M4OSA_NULL");
635
636    *pFileName = M4OSA_NULL;
637
638    /*Parse URL*/
639    iUrlLen = strlen((const char *)pUrl);
640    for(i=iUrlLen-1; i>=0; i--)
641    {
642        if (pUrl[i] != '\\' && pUrl[i] != '/')
643        {
644            FileNameLen++;
645        }
646        else
647        {
648            break; /* find the beginning of the file name */
649        }
650    }
651
652    ptrFilename = (M4OSA_Char*) M4OSA_32bitAlignedMalloc(FileNameLen+1, M4OSA_FILE_COMMON,
653                    (M4OSA_Char*)"M4OSA_fileCommonGetFilename: Filename string");
654    if (ptrFilename == M4OSA_NULL)
655    {
656        M4OSA_DEBUG(M4ERR_ALLOC, "M4OSA_fileCommonGetFilename");
657        return M4ERR_ALLOC;
658    }
659
660    ptrUrl = pUrl + (iUrlLen - FileNameLen);
661    M4OSA_chrNCopy(ptrFilename, ptrUrl, FileNameLen+1);
662
663    *pFileName = ptrFilename;
664
665    return M4NO_ERROR;
666}
667
668