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
del_path(const char * path)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
getAccess(int accType,struct stat * buffer,char * p_path)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 *******************************************************************************/
bta_fs_convert_bta_oflags(int bta_oflags)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 *******************************************************************************/
btapp_fs_check_space(const char * p_path,const UINT32 size,const UINT8 app_id)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
bta_fs_co_open(const char * p_path,int oflags,UINT32 size,UINT16 evt,UINT8 app_id)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 *******************************************************************************/
bta_fs_co_close(int fd,UINT8 app_id)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 *******************************************************************************/
bta_fs_co_read(int fd,UINT8 * p_buf,UINT16 nbytes,UINT16 evt,UINT8 ssn,UINT8 app_id)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 *******************************************************************************/
bta_fs_co_write(int fd,const UINT8 * p_buf,UINT16 nbytes,UINT16 evt,UINT8 ssn,UINT8 app_id)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 *******************************************************************************/
bta_fs_co_seek(int fd,INT32 offset,INT16 origin,UINT8 app_id)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 *******************************************************************************/
bta_fs_co_access(const char * p_path,int mode,BOOLEAN * p_is_dir,UINT8 app_id)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 *******************************************************************************/
bta_fs_co_mkdir(const char * p_path,UINT8 app_id)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 *******************************************************************************/
bta_fs_co_rmdir(const char * p_path,UINT8 app_id)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 *******************************************************************************/
bta_fs_co_unlink(const char * p_path,UINT8 app_id)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 *******************************************************************************/
bta_fs_co_getdirentry(const char * p_path,BOOLEAN first_item,tBTA_FS_DIRENTRY * p_entry,UINT16 evt,UINT8 app_id)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 *******************************************************************************/
bta_fs_co_setdir(const char * p_path,UINT8 app_id)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 *******************************************************************************/
bta_fs_co_resume(UINT16 evt,UINT8 app_id)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 *******************************************************************************/
bta_fs_co_set_perms(const char * p_src_path,UINT8 * p_perms,UINT16 evt,UINT8 app_id)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 *******************************************************************************/
bta_fs_co_rename(const char * p_src_path,const char * p_dest_path,UINT8 * p_perms,UINT16 evt,UINT8 app_id)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 *******************************************************************************/
bta_fs_co_copy(const char * p_src_path,const char * p_dest_path,UINT8 * p_perms,UINT16 evt,UINT8 app_id)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 *******************************************************************************/
bta_fs_co_resume_op(UINT32 offset,UINT16 evt,UINT8 app_id)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 *******************************************************************************/
bta_fs_co_session_info(BD_ADDR bd_addr,UINT8 * p_sess_info,UINT8 ssn,tBTA_FS_CO_SESS_ST new_st,char * p_path,UINT8 * p_info,UINT8 app_id)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 *******************************************************************************/
bta_fs_co_suspend(BD_ADDR bd_addr,UINT8 * p_sess_info,UINT8 ssn,UINT32 * p_timeout,UINT32 * p_offset,UINT8 info,UINT8 app_id)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 *******************************************************************************/
bta_fs_co_sess_ssn(int fd,UINT8 ssn,UINT8 app_id)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