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