• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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