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 43const unsigned short BT_UID= AID_BLUETOOTH; 44const 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) 54extern const tBTA_PBS_CFG bta_pbs_cfg; 55#endif 56 57 58 59static 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 132inline 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*******************************************************************************/ 212int 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 *******************************************************************************/ 250static 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 327void 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*******************************************************************************/ 410tBTA_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*******************************************************************************/ 454void 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*******************************************************************************/ 499void 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*******************************************************************************/ 533void 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*******************************************************************************/ 560tBTA_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*******************************************************************************/ 639tBTA_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*******************************************************************************/ 673tBTA_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*******************************************************************************/ 778tBTA_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*******************************************************************************/ 856void 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*******************************************************************************/ 987void 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*******************************************************************************/ 1018void 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*******************************************************************************/ 1046void 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*******************************************************************************/ 1077void 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*******************************************************************************/ 1111void 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*******************************************************************************/ 1138void 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*******************************************************************************/ 1164void 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*******************************************************************************/ 1197void 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*******************************************************************************/ 1228void 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