Home | History | Annotate | Download | only in co
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 2009-2012 Broadcom Corporation
      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 #include <stdio.h>
     19 #include <errno.h>
     20 #include <fcntl.h>
     21 #include <sys/types.h>
     22 #include <sys/stat.h>
     23 #include <sys/statfs.h>
     24 #include <sys/vfs.h>
     25 #include <unistd.h>
     26 #include <dirent.h>
     27 #include <time.h>
     28 #include <limits.h>
     29 #include "gki.h"
     30 #include "bta_fs_co.h"
     31 #include "bta_fs_ci.h"
     32 #include <inttypes.h>
     33 
     34 #ifndef AID_SYSTEM
     35 #define AID_SYSTEM        1000
     36 #define AID_BLUETOOTH     1002
     37 #define AID_SDCARD_RW     1015
     38 #define AID_MISC          9998
     39 #endif
     40 
     41 #define FAT_FS 0x4d44
     42 const unsigned short BT_UID= AID_BLUETOOTH;
     43 const unsigned short BT_GID= AID_BLUETOOTH;
     44 
     45 /* enable additional debugging traces that should be compiled out by default! */
     46 #ifndef BTA_FS_DEBUG
     47 #define BTA_FS_DEBUG TRUE
     48 #define LOG_TAG  "BTA_FS_CO"
     49 #define LOGI(format, ...)  fprintf (stdout, LOG_TAG format"\n", ## __VA_ARGS__)
     50 #endif
     51 
     52 #if (defined BTA_PBS_INCLUDED) && (BTA_PBS_INCLUDED == TRUE)
     53 extern const tBTA_PBS_CFG bta_pbs_cfg;
     54 #endif
     55 
     56 
     57 
     58 static int del_path (const char *path)
     59 {
     60     DIR *dir;
     61     struct dirent *de;
     62     int ret = 0;
     63     char nameBuffer[PATH_MAX] = {0};
     64     struct stat statBuffer;
     65     BTIF_TRACE_DEBUG1("in del_path for path:%s", path);
     66     dir = opendir(path);
     67 
     68     if (dir == NULL) {
     69         BTIF_TRACE_DEBUG1("opendir failed on path:%s", path);
     70         return -1;
     71     }
     72 
     73     char *filenameOffset;
     74 
     75     strncpy(nameBuffer, path, PATH_MAX - 1);
     76     strcat(nameBuffer, "/");
     77     int nameLen = strlen(nameBuffer);
     78     filenameOffset = nameBuffer + nameLen;
     79 
     80     for (;;) {
     81         de = readdir(dir);
     82 
     83         if (de == NULL) {
     84             BTIF_TRACE_DEBUG1("readdir failed for path:%s", path);
     85             //ret = -1;
     86             break;
     87         }
     88 
     89         if (0 == strcmp(de->d_name, ".") || 0 == strcmp(de->d_name, ".."))
     90            continue;
     91 
     92         if((int)strlen(de->d_name) > PATH_MAX - nameLen) {
     93             BTIF_TRACE_DEBUG1("d_name len:%d is too big", strlen(de->d_name));
     94             ret = -1;
     95             break;
     96         }
     97 
     98         strcpy(filenameOffset, de->d_name);
     99 
    100         ret = lstat (nameBuffer, &statBuffer);
    101 
    102         if (ret != 0) {
    103             BTIF_TRACE_DEBUG1("lstat failed for path:%s", nameBuffer);
    104             break;
    105         }
    106 
    107         if(S_ISDIR(statBuffer.st_mode)) {
    108 
    109             ret = del_path(nameBuffer);
    110             if(ret != 0)
    111                 break;
    112         } else {
    113             ret = unlink(nameBuffer);
    114             if (ret != 0) {
    115                 BTIF_TRACE_DEBUG1("unlink failed for path:%s", nameBuffer);
    116                 break;
    117             }
    118         }
    119     }
    120 
    121     closedir(dir);
    122     if(ret == 0) {
    123         ret = rmdir(path);
    124         BTIF_TRACE_DEBUG2("rmdir return:%d for path:%s", ret, path);
    125     }
    126 
    127     return ret;
    128 
    129 }
    130 
    131 inline int getAccess(int accType, struct stat *buffer, char *p_path)
    132 {
    133 
    134     struct statfs fsbuffer;
    135     int idType;
    136 
    137     if(! buffer)
    138 	return BTA_FS_CO_FAIL;
    139 
    140     //idType= (buffer->st_uid== BT_UID) ? 1 : (buffer->st_uid== BT_GID) ? 2 : 3;
    141     if(buffer->st_uid == BT_UID)
    142         idType = 1;
    143     else if(buffer->st_gid == BT_GID ||
    144             buffer->st_gid == AID_SYSTEM ||
    145             buffer->st_gid == AID_MISC ||
    146             buffer->st_gid == AID_SDCARD_RW)
    147         idType = 2;
    148     else idType = 3;
    149 
    150     if(statfs(p_path, &fsbuffer)==0)
    151     {
    152         if(fsbuffer.f_type == FAT_FS)
    153 	    return BTA_FS_CO_OK;
    154     }
    155     else {
    156         return BTA_FS_CO_FAIL;
    157     }
    158 
    159     switch(accType) {
    160         case 4:
    161 	if(idType== 1) {	//Id is User Id
    162 	   if(buffer-> st_mode & S_IRUSR)
    163 	       return BTA_FS_CO_OK;
    164 	}
    165 	else if(idType==2) {   //Id is Group Id
    166 	    if(buffer-> st_mode & S_IRGRP)
    167 	       return BTA_FS_CO_OK;
    168 	}
    169 	else {			//Id is Others
    170 	    if(buffer-> st_mode & S_IROTH)
    171 	       return BTA_FS_CO_OK;
    172 	}
    173 	break;
    174 
    175 	case 6:
    176 	if(idType== 1) {	//Id is User Id
    177 	   if((buffer-> st_mode & S_IRUSR) && (buffer-> st_mode & S_IWUSR))
    178 	       return BTA_FS_CO_OK;
    179 	}
    180 	else if(idType==2) {   //Id is Group Id
    181 	    if((buffer-> st_mode & S_IRGRP) && (buffer-> st_mode & S_IWGRP))
    182 	       return BTA_FS_CO_OK;
    183 	}
    184 	else {			//Id is Others
    185 	    if((buffer-> st_mode & S_IROTH) && (buffer-> st_mode & S_IWOTH))
    186 	       return BTA_FS_CO_OK;
    187 	}
    188 	break;
    189 
    190 	default:
    191 	return BTA_FS_CO_OK;
    192     }
    193     BTIF_TRACE_DEBUG0("*************FTP- Access Failed **********");
    194     return BTA_FS_CO_EACCES;
    195 }
    196 
    197 
    198 /*****************************************************************************
    199 **  Function Declarations
    200 *****************************************************************************/
    201 
    202 /*******************************************************************************
    203 **
    204 ** Function         bta_fs_convert_oflags
    205 **
    206 ** Description      This function converts the open flags from BTA into MFS.
    207 **
    208 ** Returns          BTA FS status value.
    209 **
    210 *******************************************************************************/
    211 int bta_fs_convert_bta_oflags(int bta_oflags)
    212 {
    213     int oflags = 0; /* Initially read only */
    214 
    215     /* Only one of these can be set: Read Only, Read/Write, or Write Only */
    216     if (bta_oflags & BTA_FS_O_RDWR)
    217         oflags |= O_RDWR;
    218     else if (bta_oflags & BTA_FS_O_WRONLY)
    219         oflags |= O_WRONLY;
    220 
    221     /* OR in any other flags that are set by BTA */
    222     if (bta_oflags & BTA_FS_O_CREAT)
    223         oflags |= O_CREAT;
    224 
    225     if (bta_oflags & BTA_FS_O_EXCL)
    226         oflags |= O_EXCL;
    227 
    228     if (bta_oflags & BTA_FS_O_TRUNC)
    229         oflags |= O_TRUNC;
    230 
    231     return (oflags);
    232 }
    233 
    234 
    235 
    236 /*******************************************************************************
    237  **
    238  ** Function        btapp_fs_check_space
    239  **
    240  ** Description     determines access and if there is enough space for given files size on given path
    241  **
    242  ** Parameters      p_path  - Fully qualified path and file name.
    243  **                           WARNING: file name is stripped off! so it must be present!
    244  **                 size    - size of file to put (0 if unavailable or not applicable)
    245  **                 app_id  - in case application specific treatement is required (e.g opp versus ftp)
    246  ** Returns         0 if enough space, otherwise errno failure codes
    247  **
    248  *******************************************************************************/
    249 static int btapp_fs_check_space( const char *p_path, const UINT32 size, const UINT8 app_id )
    250 {
    251 
    252     unsigned long long max_space;
    253     struct statfs fs_buffer;
    254     int err = 0;
    255     char *p_dir;
    256     char *p_end;
    257 
    258     if(size==BTA_FS_LEN_UNKNOWN)
    259         return 0;
    260     /* fail silently in case of no memory. write will catch if not enough space */
    261 
    262     if (NULL != (p_dir = (char *) GKI_getbuf(strlen(p_path) + 1)))
    263     {
    264         strcpy(p_dir, p_path);
    265         if (NULL != (p_end = strrchr(p_dir, '/')))
    266         {
    267 
    268             *p_end = '\0';
    269             /* get fs info and calculate available space. if not enough, the fs error EFBIG is returned */
    270 
    271             if (0 == statfs(p_dir, &fs_buffer))
    272             {
    273 
    274                 max_space = fs_buffer.f_bavail * fs_buffer.f_bsize;
    275 #if (BTA_FS_DEBUG==TRUE)
    276                 BTIF_TRACE_DEBUG2("btapp_fs_enough_space(file size: %d): (uint)max_size: %u", size, (UINT32)max_space);
    277 #endif
    278                 if (max_space < size)
    279                     err = EFBIG;
    280             }
    281             else
    282             {
    283                 err = errno;
    284                 BTIF_TRACE_WARNING1("btapp_fs_enough_space(): statfs() failed with err: %d", err);
    285             }
    286         }
    287         else
    288         {
    289             err = ENOENT;
    290         }
    291         GKI_freebuf(p_dir);
    292     }
    293     else
    294     {
    295         err = ENOMEM;
    296     }
    297     return err;
    298 
    299 } /* btapp_fs_check_access_space() */
    300 
    301 
    302 /*******************************************************************************
    303 **
    304 ** Function         bta_fs_co_open
    305 **
    306 ** Description      This function is executed by BTA when a file is opened.
    307 **                  The phone uses this function to open
    308 **                  a file for reading or writing.
    309 **
    310 ** Parameters       p_path  - Fully qualified path and file name.
    311 **                  oflags  - permissions and mode (see constants above)
    312 **                  size    - size of file to put (0 if unavailable or not applicable)
    313 **                  evt     - event that must be passed into the call-in function.
    314 **                  app_id  - application ID specified in the enable functions.
    315 **                            It can be used to identify which profile is the caller
    316 **                            of the call-out function.
    317 **
    318 ** Returns          void
    319 **
    320 **                  Note: Upon completion of the request, a file descriptor (int),
    321 **                        if successful, and an error code (tBTA_FS_CO_STATUS)
    322 **                        are returned in the call-in function, bta_fs_ci_open().
    323 **
    324 *******************************************************************************/
    325 
    326 void bta_fs_co_open(const char *p_path, int oflags, UINT32 size, UINT16 evt,
    327                     UINT8 app_id)
    328 {
    329 
    330     tBTA_FS_CO_STATUS  status;
    331     UINT32  file_size = 0;
    332     struct  stat file_stat;
    333     int fd = -1;
    334     int err = 0;
    335 
    336     /* Convert BTA oflags into os specific flags */
    337     oflags = bta_fs_convert_bta_oflags(oflags);
    338 
    339     /* check available space in case of write access. oflags are in OS format! */
    340     if (oflags & (O_RDWR|O_WRONLY))
    341     {
    342         err = btapp_fs_check_space(p_path, size, app_id);
    343     }
    344 
    345     if ( 0==err )
    346     {
    347         if ((fd = open(p_path, oflags | O_NONBLOCK, 0666)) >= 0)
    348         {
    349             if (fstat(fd, &file_stat) == 0)
    350             {
    351                 file_size = file_stat.st_size;
    352                 if (oflags & O_CREAT)
    353                 {
    354                     fchown(fd, BT_UID, BT_GID);
    355                     BTIF_TRACE_DEBUG0("\n ******CHANGED OWNERSHIP SUCCESSFULLY**********");
    356                 }
    357             }
    358         }
    359 
    360         else
    361         {
    362             err = errno;
    363         }
    364     }
    365 
    366     BTIF_TRACE_DEBUG4("[CO] bta_fs_co_open: handle:%d err:%d, flags:%x, app id:%d",
    367             fd, err, oflags, app_id);
    368     BTIF_TRACE_DEBUG1("file=%s", p_path);
    369 
    370     /* convert fs error into bta_fs err. erro is set by first call to enough space to a valid value
    371      * and needs only updating in case of error. This reports correct failure to remote obex! */
    372 
    373     switch (err)
    374     {
    375 
    376     case 0:
    377         status = BTA_FS_CO_OK;
    378         break;
    379     case EACCES:
    380         status = BTA_FS_CO_EACCES;
    381         break;
    382     case EFBIG: /* file to big for available fs space */
    383         status = BTA_FS_CO_ENOSPACE;
    384         break;
    385     default:
    386         status = BTA_FS_CO_FAIL;
    387         break;
    388     }
    389     bta_fs_ci_open(fd, status, file_size, evt);
    390 }
    391 
    392 /*******************************************************************************
    393 **
    394 ** Function         bta_fs_co_close
    395 **
    396 ** Description      This function is called by BTA when a connection to a
    397 **                  client is closed.
    398 **
    399 ** Parameters       fd      - file descriptor of file to close.
    400 **                  app_id  - application ID specified in the enable functions.
    401 **                            It can be used to identify which profile is the caller
    402 **                            of the call-out function.
    403 **
    404 ** Returns          (tBTA_FS_CO_STATUS) status of the call.
    405 **                      [BTA_FS_CO_OK if successful],
    406 **                      [BTA_FS_CO_FAIL if failed  ]
    407 **
    408 *******************************************************************************/
    409 tBTA_FS_CO_STATUS bta_fs_co_close(int fd, UINT8 app_id)
    410 {
    411     tBTA_FS_CO_STATUS status = BTA_FS_CO_OK;
    412     int err;
    413 
    414     BTIF_TRACE_DEBUG2("[CO] bta_fs_co_close: handle:%d, app id:%d",
    415         fd, app_id);
    416     if (close (fd) < 0)
    417     {
    418         err = errno;
    419         status = BTA_FS_CO_FAIL;
    420         BTIF_TRACE_WARNING3("[CO] bta_fs_co_close: handle:%d error=%d app_id:%d", fd, err, app_id);
    421     }
    422 
    423     return (status);
    424 }
    425 
    426 /*******************************************************************************
    427 **
    428 ** Function         bta_fs_co_read
    429 **
    430 ** Description      This function is called by BTA to read in data from the
    431 **                  previously opened file on the phone.
    432 **
    433 ** Parameters       fd      - file descriptor of file to read from.
    434 **                  p_buf   - buffer to read the data into.
    435 **                  nbytes  - number of bytes to read into the buffer.
    436 **                  evt     - event that must be passed into the call-in function.
    437 **                  ssn     - session sequence number. Ignored, if bta_fs_co_open
    438 **							  was not called with BTA_FS_CO_RELIABLE.
    439 **                  app_id  - application ID specified in the enable functions.
    440 **                            It can be used to identify which profile is the caller
    441 **                            of the call-out function.
    442 **
    443 ** Returns          void
    444 **
    445 **                  Note: Upon completion of the request, bta_fs_ci_read() is
    446 **                        called with the buffer of data, along with the number
    447 **                        of bytes read into the buffer, and a status.  The
    448 **                        call-in function should only be called when ALL requested
    449 **                        bytes have been read, the end of file has been detected,
    450 **                        or an error has occurred.
    451 **
    452 *******************************************************************************/
    453 void bta_fs_co_read(int fd, UINT8 *p_buf, UINT16 nbytes, UINT16 evt, UINT8 ssn, UINT8 app_id)
    454 {
    455     tBTA_FS_CO_STATUS  status = BTA_FS_CO_OK;
    456     INT32   num_read;
    457     int     err;
    458 
    459     if ((num_read = read (fd, p_buf, nbytes)) < 0)
    460     {
    461         err = errno;
    462         status = BTA_FS_CO_FAIL;
    463         BTIF_TRACE_WARNING3("[CO] bta_fs_co_read: handle:%d error=%d app_id:%d",
    464                             fd, err, app_id);
    465     }
    466     else if (num_read < nbytes)
    467         status = BTA_FS_CO_EOF;
    468 
    469     bta_fs_ci_read(fd, (UINT16)num_read, status, evt);
    470 }
    471 
    472 /*******************************************************************************
    473 **
    474 ** Function         bta_fs_co_write
    475 **
    476 ** Description      This function is called by io to send file data to the
    477 **                  phone.
    478 **
    479 ** Parameters       fd      - file descriptor of file to write to.
    480 **                  p_buf   - buffer to read the data from.
    481 **                  nbytes  - number of bytes to write out to the file.
    482 **                  evt     - event that must be passed into the call-in function.
    483 **                  ssn     - session sequence number. Ignored, if bta_fs_co_open
    484 **							  was not called with BTA_FS_CO_RELIABLE.
    485 **                  app_id  - application ID specified in the enable functions.
    486 **                            It can be used to identify which profile is the caller
    487 **                            of the call-out function.
    488 **
    489 ** Returns          void
    490 **
    491 **                  Note: Upon completion of the request, bta_fs_ci_write() is
    492 **                        called with the file descriptor and the status.  The
    493 **                        call-in function should only be called when ALL requested
    494 **                        bytes have been written, or an error has been detected,
    495 **
    496 *******************************************************************************/
    497 void bta_fs_co_write(int fd, const UINT8 *p_buf, UINT16 nbytes, UINT16 evt,
    498                      UINT8 ssn, UINT8 app_id)
    499 {
    500     tBTA_FS_CO_STATUS  status = BTA_FS_CO_OK;
    501     INT32   num_written;
    502     int     err=0;
    503 
    504     if ((num_written = write (fd, p_buf, nbytes)) < 0)
    505     {
    506         err = errno;
    507         status = BTA_FS_CO_FAIL;
    508     }
    509 /*    BTIF_TRACE_DEBUG3("[CO] bta_fs_co_write: handle:%d error=%d, num_written:%d", fd, err, num_written);*/
    510 
    511     bta_fs_ci_write(fd, status, evt);
    512 }
    513 
    514 /*******************************************************************************
    515 **
    516 ** Function         bta_fs_co_seek
    517 **
    518 ** Description      This function is called by io to move the file pointer
    519 **                  of a previously opened file to the specified location for
    520 **                  the next read or write operation.
    521 **
    522 ** Parameters       fd      - file descriptor of file.
    523 **                  offset  - Number of bytes from origin.
    524 **                  origin  - Initial position.
    525 **
    526 ** Returns          void
    527 **
    528 *******************************************************************************/
    529 void bta_fs_co_seek (int fd, INT32 offset, INT16 origin, UINT8 app_id)
    530 {
    531     lseek(fd, offset, origin);
    532 }
    533 
    534 /*******************************************************************************
    535 **
    536 ** Function         bta_fs_co_access
    537 **
    538 ** Description      This function is called to check the existence of
    539 **                  a file or directory, and return whether or not it is a
    540 **                  directory or length of the file.
    541 **
    542 ** Parameters       p_path   - (input) file or directory to access (fully qualified path).
    543 **                  mode     - (input) [BTA_FS_ACC_EXIST, BTA_FS_ACC_READ, or BTA_FS_ACC_RDWR]
    544 **                  p_is_dir - (output) returns TRUE if p_path specifies a directory.
    545 **                  app_id   - (input) application ID specified in the enable functions.
    546 **                                     It can be used to identify which profile is the caller
    547 **                                     of the call-out function.
    548 **
    549 ** Returns          (tBTA_FS_CO_STATUS) status of the call.
    550 **                   [BTA_FS_CO_OK if it exists]
    551 **                   [BTA_FS_CO_EACCES if permissions are wrong]
    552 **                   [BTA_FS_CO_FAIL if it does not exist]
    553 **
    554 *******************************************************************************/
    555 tBTA_FS_CO_STATUS bta_fs_co_access(const char *p_path, int mode, BOOLEAN *p_is_dir,
    556                                    UINT8 app_id)
    557 {
    558     int err;
    559     int os_mode = 0;
    560     tBTA_FS_CO_STATUS status = BTA_FS_CO_OK;
    561     struct stat buffer;
    562 
    563     #if (TRUE==BTA_FS_DEBUG)
    564     LOGI("***********CHECKING ACCESS TO = %s", p_path);
    565     #endif
    566 
    567     #if (defined BTA_PBS_INCLUDED) && (BTA_PBS_INCLUDED == TRUE)
    568 
    569     if (app_id == UI_PBS_ID)
    570     {
    571 
    572         *p_is_dir = TRUE;
    573 
    574         #if (TRUE==BTA_FS_DEBUG)
    575         LOGI("***********SUPPORTED REPO = %d", bta_pbs_cfg.supported_repositories);
    576         #endif
    577         //Check if SIM contact requested,  and if so if it's supported.
    578         //If not, return error!
    579         if (strstr(p_path,"SIM1") && !(bta_pbs_cfg.supported_repositories & 0x2)) {
    580             LOGI("***********RETURNING FAIL!");
    581             return BTA_FS_CO_FAIL;
    582         }
    583 
    584         #if (TRUE==BTA_FS_DEBUG)
    585         LOGI("***********RETURNING success!");
    586         #endif
    587         return (status);
    588     }
    589     #endif
    590 
    591 
    592     *p_is_dir = FALSE;
    593 
    594     if (mode == BTA_FS_ACC_RDWR)
    595         os_mode = 6;
    596     else if (mode == BTA_FS_ACC_READ)
    597         os_mode = 4;
    598 
    599     if (stat(p_path, &buffer) == 0)
    600     {
    601 	/* Determine if the object is a file or directory */
    602         if (S_ISDIR(buffer.st_mode))
    603             *p_is_dir = TRUE;
    604     }
    605     else
    606     {
    607 	BTIF_TRACE_DEBUG0("stat() failed! ");
    608         return BTA_FS_CO_FAIL;
    609     }
    610 
    611     status=getAccess (os_mode, &buffer, (char*)p_path);
    612     return (status);
    613 }
    614 
    615 /*******************************************************************************
    616 **
    617 ** Function         bta_fs_co_mkdir
    618 **
    619 ** Description      This function is called to create a directory with
    620 **                  the pathname given by path. The pathname is a null terminated
    621 **                  string. All components of the path must already exist.
    622 **
    623 ** Parameters       p_path   - (input) name of directory to create (fully qualified path).
    624 **                  app_id   - (input) application ID specified in the enable functions.
    625 **                                     It can be used to identify which profile is the caller
    626 **                                     of the call-out function.
    627 **
    628 ** Returns          (tBTA_FS_CO_STATUS) status of the call.
    629 **                  [BTA_FS_CO_OK if successful]
    630 **                  [BTA_FS_CO_FAIL if unsuccessful]
    631 **
    632 *******************************************************************************/
    633 tBTA_FS_CO_STATUS bta_fs_co_mkdir(const char *p_path, UINT8 app_id)
    634 {
    635     int err;
    636     tBTA_FS_CO_STATUS status = BTA_FS_CO_OK;
    637 
    638     if ((mkdir (p_path, 0666)) != 0)
    639     {
    640         err = errno;
    641         status = BTA_FS_CO_FAIL;
    642         BTIF_TRACE_WARNING3("[CO] bta_fs_co_mkdir: error=%d, path [%s] app_id:%d",
    643                             err, p_path, app_id);
    644     }
    645     return (status);
    646 }
    647 
    648 /*******************************************************************************
    649 **
    650 ** Function         bta_fs_co_rmdir
    651 **
    652 ** Description      This function is called to remove a directory whose
    653 **                  name is given by path. The directory must be empty.
    654 **
    655 ** Parameters       p_path   - (input) name of directory to remove (fully qualified path).
    656 **                  app_id   - (input) application ID specified in the enable functions.
    657 **                                     It can be used to identify which profile is the caller
    658 **                                     of the call-out function.
    659 **
    660 ** Returns          (tBTA_FS_CO_STATUS) status of the call.
    661 **                      [BTA_FS_CO_OK if successful]
    662 **                      [BTA_FS_CO_EACCES if read-only]
    663 **                      [BTA_FS_CO_ENOTEMPTY if directory is not empty]
    664 **                      [BTA_FS_CO_FAIL otherwise]
    665 **
    666 *******************************************************************************/
    667 tBTA_FS_CO_STATUS bta_fs_co_rmdir(const char *p_path, UINT8 app_id)
    668 {
    669     int err, path_len;
    670     tBTA_FS_CO_STATUS status = BTA_FS_CO_OK;
    671     struct stat buffer;
    672     char *dirName, *tmp = NULL;
    673 
    674     path_len = strlen( p_path )+1;
    675     BTIF_TRACE_DEBUG2( "bta_fs_co_rmdir( app_id: %d ): path_len: %d", app_id, path_len );
    676 #if (TRUE==BTA_FS_DEBUG)
    677     BTIF_TRACE_DEBUG1( "bta_fs_co_rmdir():path_len: %d, p_path", app_id );
    678     BTIF_TRACE_DEBUG0( p_path );
    679 #endif
    680 
    681     /* allocate a temp buffer for path with 0 char. make sure not to crash if path is too big! */
    682     dirName = (char*) calloc(1, path_len+1);
    683     if ( NULL != dirName )
    684     {
    685         strcpy( dirName, p_path );
    686     }
    687     else
    688     {
    689         BTIF_TRACE_WARNING2( "bta_fs_co_rmdir( app_id: %d ) for path_len: %d::out of memory",
    690                              app_id, path_len );
    691         return BTA_FS_CO_FAIL;
    692     }
    693 
    694     if (NULL!= (tmp = strrchr(dirName, '/')))
    695     {
    696         *tmp = '\0';
    697     }
    698     if (stat(dirName, &buffer) == 0)
    699     {
    700         status = getAccess(6, &buffer, dirName);
    701     }
    702     else
    703     {
    704         free(dirName);
    705 #if (TRUE==BTA_FS_DEBUG)
    706         BTIF_TRACE_WARNING0( "bta_fs_co_rmdir()::stat(dirName) failed" );
    707 #endif
    708         return BTA_FS_CO_FAIL;
    709     }
    710 
    711     free(dirName);
    712     if (status != BTA_FS_CO_OK)
    713     {
    714 #if (TRUE==BTA_FS_DEBUG)
    715         BTIF_TRACE_WARNING0( "bta_fs_co_rmdir()::getAccess(dirName) FAILED");
    716 #endif
    717         return status;
    718     }
    719 
    720     if (stat(p_path, &buffer) == 0)
    721     {
    722         status = getAccess(6, &buffer, (char*)p_path);
    723     }
    724     else
    725     {
    726 #if (TRUE==BTA_FS_DEBUG)
    727         BTIF_TRACE_WARNING0( "bta_fs_co_rmdir()::stat(p_path) FAILED");
    728 #endif
    729         return BTA_FS_CO_FAIL;
    730     }
    731 
    732     if (status != BTA_FS_CO_OK)
    733     {
    734 #if (TRUE==BTA_FS_DEBUG)
    735         BTIF_TRACE_DEBUG0( "bta_fs_co_rmdir()::getAccess(p_path) FAILED");
    736 #endif
    737         return status;
    738     }
    739     //if ((rmdir (p_path)) != 0)
    740     if (del_path(p_path) != 0)
    741     {
    742         err = errno;
    743         BTIF_TRACE_WARNING1( "bta_fs_co_rmdir():rmdir/del_path FAILED with err: %d", err );
    744         if (err == EACCES)
    745             status = BTA_FS_CO_EACCES;
    746         else if (err == ENOTEMPTY)
    747             status = BTA_FS_CO_ENOTEMPTY;
    748         else
    749             status = BTA_FS_CO_FAIL;
    750     }
    751     return (status);
    752 }
    753 
    754 /*******************************************************************************
    755 **
    756 ** Function         bta_fs_co_unlink
    757 **
    758 ** Description      This function is called to remove a file whose name
    759 **                  is given by p_path.
    760 **
    761 ** Parameters       p_path   - (input) name of file to remove (fully qualified path).
    762 **                  app_id   - (input) application ID specified in the enable functions.
    763 **                                     It can be used to identify which profile is the caller
    764 **                                     of the call-out function.
    765 **
    766 ** Returns          (tBTA_FS_CO_STATUS) status of the call.
    767 **                      [BTA_FS_CO_OK if successful]
    768 **                      [BTA_FS_CO_EACCES if read-only]
    769 **                      [BTA_FS_CO_FAIL otherwise]
    770 **
    771 *******************************************************************************/
    772 tBTA_FS_CO_STATUS bta_fs_co_unlink(const char *p_path, UINT8 app_id)
    773 {
    774     BTIF_TRACE_DEBUG0("bta_fs_co_unlink");
    775     int err;
    776     tBTA_FS_CO_STATUS status = BTA_FS_CO_OK;
    777     char *dirName, *tmp=NULL;
    778     struct stat buffer;
    779 
    780     if(! p_path)
    781         return BTA_FS_CO_FAIL;
    782 
    783     /* buffer needs to be NULL terminated - so add one more byte to be zero'd out */
    784 #if 0
    785     dirName= (char*) calloc(1, strlen(p_path));  /* <--- this can cause problems  */
    786 #else
    787     dirName= (char*) calloc(1, strlen(p_path) + 1);
    788 #endif
    789 
    790     strncpy(dirName, p_path, strlen(p_path));
    791     if((tmp=strrchr(dirName, '/')))
    792     {
    793 	    *tmp='\0';
    794     }
    795     if (stat(dirName, &buffer) == 0)
    796     {
    797         status=getAccess (6, &buffer, dirName);
    798         free(dirName);
    799     }
    800     else
    801     {
    802         BTIF_TRACE_DEBUG0("stat() failed! ");
    803         free(dirName);
    804         return BTA_FS_CO_FAIL;
    805     }
    806 
    807     if(status!= BTA_FS_CO_OK)
    808 	return status;
    809 
    810     if ((unlink (p_path)) != 0)
    811     {
    812         err = errno;
    813         if (err == EACCES)
    814             status = BTA_FS_CO_EACCES;
    815         else
    816             status = BTA_FS_CO_FAIL;
    817     }
    818     return (status);
    819 
    820 }
    821 
    822 /*******************************************************************************
    823 **
    824 ** Function         bta_fs_co_getdirentry
    825 **
    826 ** Description      This function is called to get a directory entry for the
    827 **                  specified p_path.  The first/next directory should be filled
    828 **                  into the location specified by p_entry.
    829 **
    830 ** Parameters       p_path      - directory to search (Fully qualified path)
    831 **                  first_item  - TRUE if first search, FALSE if next search
    832 **                                      (p_cur contains previous)
    833 **                  p_entry (input/output) - Points to last entry data (valid when
    834 **                                           first_item is FALSE)
    835 **                  evt     - event that must be passed into the call-in function.
    836 **                  app_id  - application ID specified in the enable functions.
    837 **                            It can be used to identify which profile is the caller
    838 **                            of the call-out function.
    839 **
    840 ** Returns          void
    841 **
    842 **                  Note: Upon completion of the request, the status is passed
    843 **                        in the bta_fs_ci_direntry() call-in function.
    844 **                        BTA_FS_CO_OK is returned when p_entry is valid,
    845 **                        BTA_FS_CO_EODIR is returned when no more entries [finished]
    846 **                        BTA_FS_CO_FAIL is returned if an error occurred
    847 **
    848 *******************************************************************************/
    849 void bta_fs_co_getdirentry(const char *p_path, BOOLEAN first_item,
    850                            tBTA_FS_DIRENTRY *p_entry, UINT16 evt, UINT8 app_id)
    851 {
    852     tBTA_FS_CO_STATUS    co_status = BTA_FS_CO_FAIL;
    853     int                  status = -1;    /* '0' - success, '-1' - fail */
    854     struct tm           *p_tm;
    855     DIR *dir;
    856     struct dirent *dirent;
    857     struct stat buf;
    858     char fullname[500];
    859 
    860     BTIF_TRACE_DEBUG0("Entered bta_fs_co_getdirentry");
    861 
    862     /* First item is to be retrieved */
    863     if (first_item)
    864     {
    865         BTIF_TRACE_DEBUG1("bta_fs_co_getdirentry: path = %s", p_path);
    866 
    867         dir = opendir(p_path);
    868         if(dir == NULL)
    869         {
    870      	    BTIF_TRACE_DEBUG1("bta_fs_co_getdirentry: dir is NULL so error out with errno=%d", errno);
    871             co_status = BTA_FS_CO_EODIR;
    872             bta_fs_ci_direntry(co_status, evt);
    873             return;
    874         }
    875 
    876         BTIF_TRACE_DEBUG1("bta_fs_co_getdirentry: dir = %p", dir);
    877         if((dirent = readdir(dir)) != NULL)
    878         {
    879             p_entry->refdata = (UINT32) dir;     /* Save this for future searches */
    880             status = 0;
    881             BTIF_TRACE_DEBUG1("bta_fs_co_getdirentry: dirent = %p", dirent);
    882         }
    883         else
    884         {
    885             BTIF_TRACE_DEBUG1("bta_fs_co_getdirentry: dirent = %p", dirent);
    886             /* Close the search if there are no more items */
    887             closedir( (DIR*) p_entry->refdata);
    888             co_status = BTA_FS_CO_EODIR;
    889         }
    890     }
    891     else    /* Get the next entry based on the p_ref data from previous search */
    892     {
    893         if ((dirent = readdir((DIR*)p_entry->refdata))  == NULL)
    894         {
    895             /* Close the search if there are no more items */
    896             closedir( (DIR*) p_entry->refdata);
    897             co_status = BTA_FS_CO_EODIR;
    898             BTIF_TRACE_DEBUG1("bta_fs_co_getdirentry: dirent = %p", dirent);
    899         }
    900         else
    901         {
    902             BTIF_TRACE_DEBUG1("bta_fs_co_getdirentry: dirent = %p", dirent);
    903             status = 0;
    904         }
    905     }
    906 
    907     if (status == 0)
    908     {
    909         BTIF_TRACE_DEBUG0("bta_fs_co_getdirentry: status = 0");
    910 
    911         sprintf(fullname, "%s/%s", p_path,  dirent->d_name);
    912 
    913         /* Load new values into the return structure (refdata is left untouched) */
    914         if (stat(fullname, &buf) == 0) {
    915             p_entry->filesize = buf.st_size;
    916             p_entry->mode = 0; /* Default is normal read/write file access */
    917 
    918             if (S_ISDIR(buf.st_mode))
    919                 p_entry->mode |= BTA_FS_A_DIR;
    920             else
    921                 p_entry->mode |= BTA_FS_A_RDONLY;
    922 
    923             strcpy(p_entry->p_name, dirent->d_name);
    924 #if 0
    925             fprintf(stderr, "bta_fs_co_getdirentry(): %s %9d %d\n",
    926                             dirent->d_name,
    927                             buf.st_size,
    928                             p_entry->mode);
    929 #endif
    930             p_tm = localtime((const time_t*)&buf.st_mtime);
    931             if (p_tm != NULL)
    932             {
    933                 sprintf(p_entry->crtime, "%04d%02d%02dT%02d%02d%02dZ",
    934                         p_tm->tm_year + 1900,   /* Base Year ISO 6201 */
    935                         p_tm->tm_mon + 1,       /* month starts at 0 */
    936                         p_tm->tm_mday,
    937                         p_tm->tm_hour,
    938                         p_tm->tm_min,
    939                         p_tm->tm_sec);
    940             }
    941             else
    942                 p_entry->crtime[0] = '\0';  /* No valid time */
    943 #if 0
    944             fprintf(stderr, "bta_fs_co_getdirentry(): %s %9d %d %s\n",
    945                             dirent->d_name,
    946                             p_entry->filesize,
    947                             p_entry->mode,
    948                             p_entry->crtime);
    949 #endif
    950             co_status = BTA_FS_CO_OK;
    951         } else {
    952             BTIF_TRACE_WARNING0("stat() failed! ");
    953             co_status = BTA_FS_CO_EACCES;
    954         }
    955     }
    956     BTIF_TRACE_DEBUG0("bta_fs_co_getdirentry: calling bta_fs_ci_getdirentry");
    957 
    958     bta_fs_ci_direntry(co_status, evt);
    959 }
    960 
    961 
    962 
    963 
    964 /*******************************************************************************
    965 **
    966 ** Function         bta_fs_co_setdir
    967 **
    968 ** Description      This function is executed by BTA when the server changes the
    969 **                  local path
    970 **
    971 ** Parameters       p_path  - the new path.
    972 **                  app_id  - application ID specified in the enable functions.
    973 **                            It can be used to identify which profile is the caller
    974 **                            of the call-out function.
    975 **
    976 ** Returns          void
    977 **
    978 *******************************************************************************/
    979 void bta_fs_co_setdir(const char *p_path, UINT8 app_id)
    980 {
    981     BTIF_TRACE_DEBUG2("Entered %s. New path: %s", __FUNCTION__, p_path);
    982 }
    983 
    984 /*******************************************************************************
    985 ** OBEX14 Reliable Session not supported. Stub associated callouts.
    986 ******************************************************************************/
    987 
    988 /*******************************************************************************
    989 **
    990 ** Function         bta_fs_co_resume
    991 **
    992 ** Description      This function is executed by BTA when resuming a session.
    993 **                  This is used to retrieve the session ID and related information
    994 **
    995 ** Parameters       evt     - event that must be passed into the call-in function.
    996 **                  app_id  - application ID specified in the enable functions.
    997 **                            It can be used to identify which profile is the caller
    998 **                            of the call-out function.
    999 **
   1000 ** Returns          void
   1001 **
   1002 **                  Note: Upon completion of the request, the related session information,
   1003 **                        if successful, and an error code (tBTA_FS_CO_STATUS)
   1004 **                        are returned in the call-in function, bta_fs_ci_resume().
   1005 **
   1006 *******************************************************************************/
   1007 void bta_fs_co_resume(UINT16 evt, UINT8 app_id)
   1008 {
   1009     BTIF_TRACE_WARNING0("[CO] bta_fs_co_resume - NOT implemented");
   1010 }
   1011 
   1012 /*******************************************************************************
   1013 **
   1014 ** Function         bta_fs_co_set_perms
   1015 **
   1016 ** Description      This function is called to set the permission a file/directory
   1017 **                  with name as p_src_path.
   1018 **
   1019 ** Parameters       p_src_path  - (input) name of file/directory to set permission (fully qualified path).
   1020 **                  p_perms     - the permission .
   1021 **                  app_id   - (input) application ID specified in the enable functions.
   1022 **                                     It can be used to identify which profile is the caller
   1023 **                                     of the call-out function.
   1024 **
   1025 ** Returns          (tBTA_FS_CO_STATUS) status of the call.
   1026 **                      [BTA_FS_CO_OK if successful]
   1027 **                      [BTA_FS_CO_EACCES if p_dest_path already exists or could not be created (invalid path);
   1028 **                                        or p_src_path is a directory and p_dest_path specifies a different path. ]
   1029 **                      [BTA_FS_CO_FAIL otherwise]
   1030 **
   1031 *******************************************************************************/
   1032 void bta_fs_co_set_perms(const char *p_src_path,  UINT8 *p_perms, UINT16 evt, UINT8 app_id)
   1033 {
   1034     BTIF_TRACE_WARNING0("[CO] bta_fs_co_set_perms - NOT implemented");
   1035 }
   1036 
   1037 /*******************************************************************************
   1038 **
   1039 ** Function         bta_fs_co_rename
   1040 **
   1041 ** Description      This function is called to move a file/directory whose
   1042 **                  name is given by p_src_path to p_dest_path.
   1043 **
   1044 ** Parameters       p_src_path  - (input) name of file/directory to be moved (fully qualified path).
   1045 **                  p_dest_path - (input) new name of file/directory(fully qualified path).
   1046 **                  p_perms     - the permission of the new object.
   1047 **                  app_id   - (input) application ID specified in the enable functions.
   1048 **                                     It can be used to identify which profile is the caller
   1049 **                                     of the call-out function.
   1050 **
   1051 ** Returns          (tBTA_FS_CO_STATUS) status of the call.
   1052 **                      [BTA_FS_CO_OK if successful]
   1053 **                      [BTA_FS_CO_EACCES if p_dest_path already exists or could not be created (invalid path);
   1054 **                                        or p_src_path is a directory and p_dest_path specifies a different path. ]
   1055 **                      [BTA_FS_CO_FAIL otherwise]
   1056 **
   1057 *******************************************************************************/
   1058 void bta_fs_co_rename(const char *p_src_path, const char *p_dest_path, UINT8 *p_perms, UINT16 evt, UINT8 app_id)
   1059 {
   1060     BTIF_TRACE_WARNING0("[CO] bta_fs_co_rename - NOT implemented");
   1061 }
   1062 
   1063 /*******************************************************************************
   1064 **
   1065 ** Function         bta_fs_co_copy
   1066 **
   1067 ** Description      This function is called to copy a file/directory whose
   1068 **                  name is given by p_src_path to p_dest_path.
   1069 **
   1070 ** Parameters       p_src_path  - (input) name of file/directory to be copied (fully qualified path).
   1071 **                  p_dest_path - (input) new name of file/directory(fully qualified path).
   1072 **                  p_perms     - the permission of the new object.
   1073 **                  evt     - event that must be passed into the call-in function.
   1074 **                  app_id   - (input) application ID specified in the enable functions.
   1075 **                                     It can be used to identify which profile is the caller
   1076 **                                     of the call-out function.
   1077 **
   1078 ** Returns          (tBTA_FS_CO_STATUS) status of the call.
   1079 **                      [BTA_FS_CO_OK if successful]
   1080 **                      [BTA_FS_CO_EIS_DIR if p_src_path is a folder]
   1081 **                      [BTA_FS_CO_EACCES if p_dest_path already exists or could not be created (invalid path);
   1082 **                                        or p_src_path is a directory and p_dest_path specifies a different path. ]
   1083 **                      [BTA_FS_CO_FAIL otherwise]
   1084 **
   1085 *******************************************************************************/
   1086 void bta_fs_co_copy(const char *p_src_path, const char *p_dest_path, UINT8 *p_perms, UINT16 evt, UINT8 app_id)
   1087 {
   1088     BTIF_TRACE_WARNING0("[CO] bta_fs_co_copy - NOT implemented");
   1089 }
   1090 
   1091 /*******************************************************************************
   1092 **
   1093 ** Function         bta_fs_co_resume_op
   1094 **
   1095 ** Description      This function is executed by BTA when a reliable session is
   1096 **                  resumed and there was an interrupted operation.
   1097 **
   1098 ** Parameters       offset  - the session ID and related information.
   1099 **                  evt     - event that must be passed into the call-in function.
   1100 **                  app_id  - application ID specified in the enable functions.
   1101 **                            It can be used to identify which profile is the caller
   1102 **                            of the call-out function.
   1103 **
   1104 ** Returns          void
   1105 **
   1106 *******************************************************************************/
   1107 void bta_fs_co_resume_op(UINT32 offset, UINT16 evt, UINT8 app_id)
   1108 {
   1109     BTIF_TRACE_WARNING0("[CO] bta_fs_co_resume_op - NOT implemented");
   1110 }
   1111 
   1112 
   1113 /*******************************************************************************
   1114 **
   1115 ** Function         bta_fs_co_session_info
   1116 **
   1117 ** Description      This function is executed by BTA when a reliable session is
   1118 **                  established (p_sess_info != NULL) or ended (p_sess_info == NULL).
   1119 **
   1120 ** Parameters       bd_addr     - the peer address
   1121 **                  p_sess_info - the session ID and related information.
   1122 **                  app_id  - application ID specified in the enable functions.
   1123 **                            It can be used to identify which profile is the caller
   1124 **                            of the call-out function.
   1125 **
   1126 ** Returns          void
   1127 **
   1128 *******************************************************************************/
   1129 void bta_fs_co_session_info(BD_ADDR bd_addr, UINT8 *p_sess_info, UINT8 ssn,
   1130                                            tBTA_FS_CO_SESS_ST new_st, char *p_path, UINT8 *p_info, UINT8 app_id)
   1131 {
   1132     BTIF_TRACE_WARNING0("[CO] bta_fs_co_session_info - NOT implemented");
   1133 }
   1134 
   1135 
   1136 /*******************************************************************************
   1137 **
   1138 ** Function         bta_fs_co_suspend
   1139 **
   1140 ** Description      This function is executed by BTA when a reliable session is
   1141 **                  suspended.
   1142 **
   1143 ** Parameters       bd_addr - the peer address
   1144 **                  ssn     - the session sequence number.
   1145 **                  info    - the BTA specific information (like last active operation).
   1146 **                  p_offset- the location to receive object offset of the suspended session
   1147 **                  app_id  - application ID specified in the enable functions.
   1148 **                            It can be used to identify which profile is the caller
   1149 **                            of the call-out function.
   1150 **
   1151 ** Returns          void
   1152 **
   1153 *******************************************************************************/
   1154 void bta_fs_co_suspend(BD_ADDR bd_addr, UINT8 *p_sess_info, UINT8 ssn,
   1155                                       UINT32 *p_timeout, UINT32 *p_offset, UINT8 info, UINT8 app_id)
   1156 {
   1157     BTIF_TRACE_WARNING0("[CO] bta_fs_co_suspend - NOT implemented");
   1158 }
   1159 
   1160 /*******************************************************************************
   1161 **
   1162 ** Function         bta_fs_co_sess_ssn
   1163 **
   1164 ** Description      This function is executed by BTA when resuming a session.
   1165 **                  This is used to inform call-out module if the ssn/file offset
   1166 **                  needs to be adjusted.
   1167 **
   1168 ** Parameters       ssn     - the session sequence number of the first request
   1169 **                            after resume.
   1170 **                  app_id  - application ID specified in the enable functions.
   1171 **                            It can be used to identify which profile is the caller
   1172 **                            of the call-out function.
   1173 **
   1174 ** Returns          void
   1175 **
   1176 *******************************************************************************/
   1177 void bta_fs_co_sess_ssn(int fd, UINT8 ssn, UINT8 app_id)
   1178 {
   1179     BTIF_TRACE_WARNING0("[CO] bta_fs_co_suspend - NOT implemented");
   1180 }
   1181 
   1182