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