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