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