xref: /nrf52832-nimble/rt-thread/components/dfs/filesystems/uffs/src/uffs/uffs_fd.c (revision 104654410c56c573564690304ae786df310c91fc)
1 /*
2   This file is part of UFFS, the Ultra-low-cost Flash File System.
3 
4   Copyright (C) 2005-2009 Ricky Zheng <[email protected]>
5 
6   UFFS is free software; you can redistribute it and/or modify it under
7   the GNU Library General Public License as published by the Free Software
8   Foundation; either version 2 of the License, or (at your option) any
9   later version.
10 
11   UFFS is distributed in the hope that it will be useful, but WITHOUT
12   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   or GNU Library General Public License, as applicable, for more details.
15 
16   You should have received a copy of the GNU General Public License
17   and GNU Library General Public License along with UFFS; if not, write
18   to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19   Boston, MA  02110-1301, USA.
20 
21   As a special exception, if other files instantiate templates or use
22   macros or inline functions from this file, or you compile this file
23   and link it with other works to produce a work based on this file,
24   this file does not by itself cause the resulting work to be covered
25   by the GNU General Public License. However the source code for this
26   file must still be made available in accordance with section (3) of
27   the GNU General Public License v2.
28 
29   This exception does not invalidate any other reasons why a work based
30   on this file might be covered by the GNU General Public License.
31 */
32 
33 /**
34  * \file uffs_fd.c
35  * \brief POSIX like, hight level file operations
36  * \author Ricky Zheng, created 8th Jun, 2005
37  */
38 
39 #include <string.h>
40 #include "uffs_config.h"
41 #include "uffs/uffs_fs.h"
42 #include "uffs/uffs_fd.h"
43 #include "uffs/uffs_utils.h"
44 #include "uffs/uffs_version.h"
45 #include "uffs/uffs_mtb.h"
46 #include "uffs/uffs_public.h"
47 #include "uffs/uffs_find.h"
48 
49 #define PFX "fd  : "
50 
51 /**
52  * \brief POSIX DIR
53  */
54 struct uffs_dirSt {
55     struct uffs_ObjectSt   *obj;		/* dir object */
56     struct uffs_FindInfoSt f;			/* find info */
57     struct uffs_ObjectInfoSt info;		/* object info */
58     struct uffs_dirent dirent;			/* dir entry */
59 };
60 
61 
62 #define FD_OFFSET		3	//!< just make file handler more like POSIX (0, 1, 2 for stdin/stdout/stderr)
63 
64 #define OBJ2FD(obj)	\
65 	( \
66 		( \
67 			uffs_PoolGetIndex(uffs_GetObjectPool(), obj) | \
68 			(_fd_signature << FD_SIGNATURE_SHIFT) \
69 		) \
70 		+ FD_OFFSET \
71 	)
72 
73 /**
74  * check #fd signature, convert #fd to #obj
75  * if success, hold global file system lock, otherwise return with #ret
76  */
77 #define CHK_OBJ_LOCK(fd, obj, ret)	\
78 	do { \
79 		uffs_GlobalFsLockLock(); \
80 		fd -= FD_OFFSET; \
81 		if ( (fd >> FD_SIGNATURE_SHIFT) != _fd_signature ) { \
82 			uffs_set_error(-UEBADF); \
83 			uffs_Perror(UFFS_MSG_NOISY, "invalid fd: %d (sig: %d, expect: %d)", \
84 					fd + FD_OFFSET, fd >> FD_SIGNATURE_SHIFT, _fd_signature); \
85 			uffs_GlobalFsLockUnlock(); \
86 			return (ret); \
87 		} \
88 		fd = fd & ((1 << FD_SIGNATURE_SHIFT) - 1); \
89 		obj = (uffs_Object *)uffs_PoolGetBufByIndex(uffs_GetObjectPool(), fd); \
90 		if ((obj) == NULL || \
91 				uffs_PoolVerify(uffs_GetObjectPool(), (obj)) == U_FALSE || \
92 				uffs_PoolCheckFreeList(uffs_GetObjectPool(), (obj)) == U_TRUE) { \
93 			uffs_set_error(-UEBADF); \
94 			uffs_Perror(UFFS_MSG_NOISY, "invalid obj"); \
95 			uffs_GlobalFsLockUnlock(); \
96 			return (ret); \
97 		} \
98 	} while(0)
99 
100 /**
101  * check #dirp signature,
102  * if success, hold global file system lock,
103  * otherwise return with #ret
104  */
105 #define CHK_DIR_LOCK(dirp, ret)	\
106 	do { \
107 		uffs_GlobalFsLockLock(); \
108 		if ((dirp) == NULL || \
109 				uffs_PoolVerify(&_dir_pool, (dirp)) == U_FALSE || \
110 				uffs_PoolCheckFreeList(&_dir_pool, (dirp)) == U_TRUE) { \
111 			uffs_set_error(-UEBADF); \
112 			uffs_Perror(UFFS_MSG_NOISY, "invalid dirp"); \
113 			uffs_GlobalFsLockUnlock(); \
114 			return (ret); \
115 		} \
116 	} while(0)
117 
118 /**
119  * check #dirp signature,
120  * if success, hold global file system lock,
121  * otherwise return void
122  */
123 #define CHK_DIR_VOID_LOCK(dirp)	\
124 	do { \
125 		uffs_GlobalFsLockLock(); \
126 		if ((dirp) == NULL || \
127 				uffs_PoolVerify(&_dir_pool, (dirp)) == U_FALSE || \
128 				uffs_PoolCheckFreeList(&_dir_pool, (dirp)) == U_TRUE) { \
129 			uffs_set_error(-UEBADF); \
130 			uffs_Perror(UFFS_MSG_NOISY, "invalid dirp"); \
131 			uffs_GlobalFsLockUnlock(); \
132 			return; \
133 		} \
134 	} while(0)
135 
136 
137 static int _dir_pool_data[sizeof(uffs_DIR) * MAX_DIR_HANDLE / sizeof(int)];
138 static uffs_Pool _dir_pool;
139 static int _uffs_errno = 0;
140 
141 
142 //
143 // What is fd signature ? fd signature is for detecting file system get formated by other party.
144 //   A thread open a file, read()...sleep()...write()...sleep()...
145 //   B thread format UFFS partition, increase fd signature.
146 //   A thread ...sleep()...read() --> Opps, fd signature changed ! read() return error(expected).
147 //
148 #define MAX_FD_SIGNATURE_ROUND  (100)
149 static int _fd_signature = 0;
150 
151 //
152 // only get called when formating UFFS partition
153 //
uffs_FdSignatureIncrease(void)154 void uffs_FdSignatureIncrease(void)
155 {
156 	if (_fd_signature++ > MAX_FD_SIGNATURE_ROUND)
157 		_fd_signature = 0;
158 }
159 
160 /**
161  * initialise uffs_DIR buffers, called by UFFS internal
162  */
uffs_DirEntryBufInit(void)163 URET uffs_DirEntryBufInit(void)
164 {
165 	return uffs_PoolInit(&_dir_pool, _dir_pool_data,
166 							sizeof(_dir_pool_data),
167 							sizeof(uffs_DIR), MAX_DIR_HANDLE);
168 }
169 
170 /**
171  * Release uffs_DIR buffers, called by UFFS internal
172  */
uffs_DirEntryBufRelease(void)173 URET uffs_DirEntryBufRelease(void)
174 {
175 	return uffs_PoolRelease(&_dir_pool);
176 }
177 
178 /**
179  * Put all dir entry buf match dev
180  */
uffs_DirEntryBufPutAll(uffs_Device * dev)181 int uffs_DirEntryBufPutAll(uffs_Device *dev)
182 {
183 	int count = 0;
184 	uffs_DIR *dirp = NULL;
185 
186 	do {
187 		dirp = (uffs_DIR *) uffs_PoolFindNextAllocated(&_dir_pool, dirp);
188 		if (dirp && dirp->obj && dirp->obj->dev &&
189 				dirp->obj->dev->dev_num == dev->dev_num) {
190 			uffs_PoolPut(&_dir_pool, dirp);
191 			count++;
192 		}
193 	} while (dirp);
194 
195 	return count;
196 }
197 
198 
uffs_DirEntryBufGetPool(void)199 uffs_Pool * uffs_DirEntryBufGetPool(void)
200 {
201 	return &_dir_pool;
202 }
203 
GetDirEntry(void)204 static uffs_DIR * GetDirEntry(void)
205 {
206 	uffs_DIR *dirp = (uffs_DIR *) uffs_PoolGet(&_dir_pool);
207 
208 	if (dirp)
209 		memset(dirp, 0, sizeof(uffs_DIR));
210 
211 	return dirp;
212 }
213 
PutDirEntry(uffs_DIR * p)214 static void PutDirEntry(uffs_DIR *p)
215 {
216 	uffs_PoolPut(&_dir_pool, p);
217 }
218 
219 
220 /** get global errno
221  */
uffs_get_error(void)222 int uffs_get_error(void)
223 {
224 	return _uffs_errno;
225 }
226 
227 /** set global errno
228  */
uffs_set_error(int err)229 int uffs_set_error(int err)
230 {
231 	return (_uffs_errno = err);
232 }
233 
234 /* POSIX compliant file system APIs */
235 
uffs_open(const char * name,int oflag,...)236 int uffs_open(const char *name, int oflag, ...)
237 {
238 	uffs_Object *obj;
239 	int ret = 0;
240 
241 	uffs_GlobalFsLockLock();
242 
243 	obj = uffs_GetObject();
244 	if (obj == NULL) {
245 		uffs_set_error(-UEMFILE);
246 		ret = -1;
247 	}
248 	else {
249 		if (uffs_OpenObject(obj, name, oflag) == U_FAIL) {
250 			uffs_set_error(-uffs_GetObjectErr(obj));
251 			uffs_PutObject(obj);
252 			ret = -1;
253 		}
254 		else {
255 			ret = OBJ2FD(obj);
256 		}
257 	}
258 
259 	uffs_GlobalFsLockUnlock();
260 
261 	return ret;
262 }
263 
uffs_close(int fd)264 int uffs_close(int fd)
265 {
266 	int ret = 0;
267 	uffs_Object *obj;
268 
269 	CHK_OBJ_LOCK(fd, obj, -1);
270 
271 	uffs_ClearObjectErr(obj);
272 	if (uffs_CloseObject(obj) == U_FAIL) {
273 		uffs_set_error(-uffs_GetObjectErr(obj));
274 		ret = -1;
275 	}
276 	else {
277 		uffs_PutObject(obj);
278 		ret = 0;
279 	}
280 
281 	uffs_GlobalFsLockUnlock();
282 
283 	return ret;
284 }
285 
uffs_read(int fd,void * data,int len)286 int uffs_read(int fd, void *data, int len)
287 {
288 	int ret;
289 	uffs_Object *obj;
290 
291 	CHK_OBJ_LOCK(fd, obj, -1);
292 	uffs_ClearObjectErr(obj);
293 	ret = uffs_ReadObject(obj, data, len);
294 	uffs_set_error(-uffs_GetObjectErr(obj));
295 
296 	uffs_GlobalFsLockUnlock();
297 
298 	return ret;
299 }
300 
uffs_write(int fd,const void * data,int len)301 int uffs_write(int fd, const void *data, int len)
302 {
303 	int ret;
304 	uffs_Object *obj;
305 
306 	CHK_OBJ_LOCK(fd, obj, -1);
307 	uffs_ClearObjectErr(obj);
308 	ret = uffs_WriteObject(obj, data, len);
309 	uffs_set_error(-uffs_GetObjectErr(obj));
310 
311 	uffs_GlobalFsLockUnlock();
312 
313 	return ret;
314 }
315 
uffs_seek(int fd,long offset,int origin)316 long uffs_seek(int fd, long offset, int origin)
317 {
318 	int ret;
319 	uffs_Object *obj;
320 
321 	CHK_OBJ_LOCK(fd, obj, -1);
322 	uffs_ClearObjectErr(obj);
323 	ret = uffs_SeekObject(obj, offset, origin);
324 	uffs_set_error(-uffs_GetObjectErr(obj));
325 
326 	uffs_GlobalFsLockUnlock();
327 
328 	return ret;
329 }
330 
uffs_tell(int fd)331 long uffs_tell(int fd)
332 {
333 	long ret;
334 	uffs_Object *obj;
335 
336 	CHK_OBJ_LOCK(fd, obj, -1);
337 	uffs_ClearObjectErr(obj);
338 	ret = (long) uffs_GetCurOffset(obj);
339 	uffs_set_error(-uffs_GetObjectErr(obj));
340 
341 	uffs_GlobalFsLockUnlock();
342 
343 	return ret;
344 }
345 
uffs_eof(int fd)346 int uffs_eof(int fd)
347 {
348 	int ret;
349 	uffs_Object *obj;
350 
351 	CHK_OBJ_LOCK(fd, obj, -1);
352 	uffs_ClearObjectErr(obj);
353 	ret = uffs_EndOfFile(obj);
354 	uffs_set_error(-uffs_GetObjectErr(obj));
355 
356 	uffs_GlobalFsLockUnlock();
357 
358 	return ret;
359 }
360 
uffs_flush(int fd)361 int uffs_flush(int fd)
362 {
363 	int ret;
364 	uffs_Object *obj;
365 
366 	CHK_OBJ_LOCK(fd, obj, -1);
367 	uffs_ClearObjectErr(obj);
368 	ret = (uffs_FlushObject(obj) == U_SUCC) ? 0 : -1;
369 	uffs_set_error(-uffs_GetObjectErr(obj));
370 
371 	uffs_GlobalFsLockUnlock();
372 
373 	return ret;
374 }
375 
uffs_rename(const char * old_name,const char * new_name)376 int uffs_rename(const char *old_name, const char *new_name)
377 {
378 	int err = 0;
379 	int ret = 0;
380 
381 	uffs_GlobalFsLockLock();
382 	ret = (uffs_RenameObject(old_name, new_name, &err) == U_SUCC) ? 0 : -1;
383 	uffs_set_error(-err);
384 	uffs_GlobalFsLockUnlock();
385 
386 	return ret;
387 }
388 
uffs_remove(const char * name)389 int uffs_remove(const char *name)
390 {
391 	int err = 0;
392 	int ret = 0;
393 	struct uffs_stat st;
394 
395 	if (uffs_stat(name, &st) < 0) {
396 		err = UENOENT;
397 		ret = -1;
398 	}
399 	else if (st.st_mode & US_IFDIR) {
400 		err = UEISDIR;
401 		ret = -1;
402 	}
403 	else {
404 		uffs_GlobalFsLockLock();
405 		if (uffs_DeleteObject(name, &err) == U_SUCC) {
406 			ret = 0;
407 		}
408 		else {
409 			ret = -1;
410 		}
411 		uffs_GlobalFsLockUnlock();
412 	}
413 
414 	uffs_set_error(-err);
415 	return ret;
416 }
417 
uffs_ftruncate(int fd,long remain)418 int uffs_ftruncate(int fd, long remain)
419 {
420 	int ret;
421 	uffs_Object *obj;
422 
423 	CHK_OBJ_LOCK(fd, obj, -1);
424 	uffs_ClearObjectErr(obj);
425 	ret = (uffs_TruncateObject(obj, remain) == U_SUCC) ? 0 : -1;
426 	uffs_set_error(-uffs_GetObjectErr(obj));
427 	uffs_GlobalFsLockUnlock();
428 
429 	return ret;
430 }
431 
do_stat(uffs_Object * obj,struct uffs_stat * buf)432 static int do_stat(uffs_Object *obj, struct uffs_stat *buf)
433 {
434 	uffs_ObjectInfo info;
435 	int ret = 0;
436 	int err = 0;
437 
438 	if (uffs_GetObjectInfo(obj, &info, &err) == U_FAIL) {
439 		ret = -1;
440 	}
441 	else {
442 		buf->st_dev = obj->dev->dev_num;
443 		buf->st_ino = info.serial;
444 		buf->st_nlink = 0;
445 		buf->st_uid = 0;
446 		buf->st_gid = 0;
447 		buf->st_rdev = 0;
448 		buf->st_size = info.len;
449 		buf->st_blksize = obj->dev->com.pg_data_size;
450 		buf->st_blocks = 0;
451 		buf->st_atime = info.info.last_modify;
452 		buf->st_mtime = info.info.last_modify;
453 		buf->st_ctime = info.info.create_time;
454 		buf->st_mode = (info.info.attr & FILE_ATTR_DIR ? US_IFDIR : US_IFREG);
455 		if (info.info.attr & FILE_ATTR_WRITE)
456 			buf->st_mode |= US_IRWXU;
457 	}
458 
459 	uffs_set_error(-err);
460 	return ret;
461 }
462 
uffs_stat(const char * name,struct uffs_stat * buf)463 int uffs_stat(const char *name, struct uffs_stat *buf)
464 {
465 	uffs_Object *obj;
466 	int ret = 0;
467 	int err = 0;
468 	URET result;
469 
470 	uffs_GlobalFsLockLock();
471 
472 	obj = uffs_GetObject();
473 	if (obj) {
474 		if (*name && name[strlen(name) - 1] == '/') {
475 			result = uffs_OpenObject(obj, name, UO_RDONLY | UO_DIR);
476 		}
477 		else {
478 			if ((result = uffs_OpenObject(obj, name, UO_RDONLY)) != U_SUCC)	// try file
479 				result = uffs_OpenObject(obj, name, UO_RDONLY | UO_DIR);	// then try dir
480 		}
481 		if (result == U_SUCC) {
482 			ret = do_stat(obj, buf);
483 			uffs_CloseObject(obj);
484 		}
485 		else {
486 			err = uffs_GetObjectErr(obj);
487 			ret = -1;
488 		}
489 		uffs_PutObject(obj);
490 	}
491 	else {
492 		err = UENOMEM;
493 		ret = -1;
494 	}
495 
496 	uffs_set_error(-err);
497 	uffs_GlobalFsLockUnlock();
498 
499 	return ret;
500 }
501 
uffs_lstat(const char * name,struct uffs_stat * buf)502 int uffs_lstat(const char *name, struct uffs_stat *buf)
503 {
504 	return uffs_stat(name, buf);
505 }
506 
uffs_fstat(int fd,struct uffs_stat * buf)507 int uffs_fstat(int fd, struct uffs_stat *buf)
508 {
509 	int ret;
510 	uffs_Object *obj;
511 
512 	CHK_OBJ_LOCK(fd, obj, -1);
513 
514 	ret = do_stat(obj, buf);
515 	uffs_GlobalFsLockUnlock();
516 
517 	return ret;
518 }
519 
uffs_closedir(uffs_DIR * dirp)520 int uffs_closedir(uffs_DIR *dirp)
521 {
522 	CHK_DIR_LOCK(dirp, -1);
523 
524 	uffs_FindObjectClose(&dirp->f);
525 	if (dirp->obj) {
526 		uffs_CloseObject(dirp->obj);
527 		uffs_PutObject(dirp->obj);
528 	}
529 	PutDirEntry(dirp);
530 	uffs_GlobalFsLockUnlock();
531 
532 	return 0;
533 }
534 
uffs_opendir(const char * path)535 uffs_DIR * uffs_opendir(const char *path)
536 {
537 	int err = 0;
538 	uffs_DIR *ret = NULL;
539 	uffs_DIR *dirp;
540 
541 	uffs_GlobalFsLockLock();
542 
543 	dirp = GetDirEntry();
544 
545 	if (dirp) {
546 		dirp->obj = uffs_GetObject();
547 		if (dirp->obj) {
548 			if (uffs_OpenObject(dirp->obj, path, UO_RDONLY | UO_DIR) == U_SUCC) {
549 				if (uffs_FindObjectOpen(&dirp->f, dirp->obj) == U_SUCC) {
550 					ret = dirp;
551 					goto ext;
552 				}
553 				else {
554 					uffs_CloseObject(dirp->obj);
555 				}
556 			}
557 			else {
558 				err = uffs_GetObjectErr(dirp->obj);
559 			}
560 			uffs_PutObject(dirp->obj);
561 			dirp->obj = NULL;
562 		}
563 		else {
564 			err = UEMFILE;
565 		}
566 		PutDirEntry(dirp);
567 	}
568 	else {
569 		err = UEMFILE;
570 	}
571 ext:
572 	uffs_set_error(-err);
573 	uffs_GlobalFsLockUnlock();
574 
575 	return ret;
576 }
577 
uffs_readdir(uffs_DIR * dirp)578 struct uffs_dirent * uffs_readdir(uffs_DIR *dirp)
579 {
580 	struct uffs_dirent *ent = NULL;
581 
582 	CHK_DIR_LOCK(dirp, NULL);
583 
584 	if (uffs_FindObjectNext(&dirp->info, &dirp->f) == U_SUCC) {
585 		ent = &dirp->dirent;
586 		ent->d_ino = dirp->info.serial;
587 		ent->d_namelen = dirp->info.info.name_len < (sizeof(ent->d_name) - 1) ? dirp->info.info.name_len : (sizeof(ent->d_name) - 1);
588 		memcpy(ent->d_name, dirp->info.info.name, ent->d_namelen);
589 		ent->d_name[ent->d_namelen] = '\0';
590 		ent->d_off = dirp->f.pos;
591 		ent->d_reclen = sizeof(struct uffs_dirent);
592 		ent->d_type = dirp->info.info.attr;
593 	}
594 	uffs_GlobalFsLockUnlock();
595 
596 	return ent;
597 }
598 
uffs_rewinddir(uffs_DIR * dirp)599 void uffs_rewinddir(uffs_DIR *dirp)
600 {
601 	CHK_DIR_VOID_LOCK(dirp);
602 
603 	uffs_FindObjectRewind(&dirp->f);
604 
605 	uffs_GlobalFsLockUnlock();
606 }
607 
608 
uffs_mkdir(const char * name,...)609 int uffs_mkdir(const char *name, ...)
610 {
611 	uffs_Object *obj;
612 	int ret = 0;
613 	int err = 0;
614 
615 	uffs_GlobalFsLockLock();
616 
617 	obj = uffs_GetObject();
618 	if (obj) {
619 		if (uffs_CreateObject(obj, name, UO_CREATE|UO_DIR) != U_SUCC) {
620 			err = obj->err;
621 			ret = -1;
622 		}
623 		else {
624 			uffs_CloseObject(obj);
625 			ret = 0;
626 		}
627 		uffs_PutObject(obj);
628 	}
629 	else {
630 		err = UEMFILE;
631 		ret = -1;
632 	}
633 
634 	uffs_set_error(-err);
635 	uffs_GlobalFsLockUnlock();
636 
637 	return ret;
638 }
639 
uffs_rmdir(const char * name)640 int uffs_rmdir(const char *name)
641 {
642 	int err = 0;
643 	int ret = 0;
644 	struct uffs_stat st;
645 
646 	if (uffs_stat(name, &st) < 0) {
647 		err = UENOENT;
648 		ret = -1;
649 	}
650 	else if ((st.st_mode & US_IFDIR) == 0) {
651 		err = UENOTDIR;
652 		ret = -1;
653 	}
654 	else {
655 		uffs_GlobalFsLockLock();
656 		if (uffs_DeleteObject(name, &err) == U_SUCC) {
657 			ret = 0;
658 		}
659 		else {
660 			ret = -1;
661 		}
662 		uffs_GlobalFsLockUnlock();
663 	}
664 	uffs_set_error(-err);
665 	return ret;
666 }
667 
uffs_version(void)668 int uffs_version(void)
669 {
670 	return uffs_GetVersion();
671 }
672 
uffs_format(const char * mount_point)673 int uffs_format(const char *mount_point)
674 {
675 	uffs_Device *dev = NULL;
676 	URET ret = U_FAIL;
677 
678 	dev = uffs_GetDeviceFromMountPoint(mount_point);
679 	if (dev) {
680 		uffs_GlobalFsLockLock();
681 		ret = uffs_FormatDevice(dev, U_TRUE);
682 		uffs_GlobalFsLockUnlock();
683 	}
684 
685 	return ret == U_SUCC ? 0 : -1;
686 }
687 
uffs_space_total(const char * mount_point)688 long uffs_space_total(const char *mount_point)
689 {
690 	uffs_Device *dev = NULL;
691 	long ret = -1L;
692 
693 	dev = uffs_GetDeviceFromMountPoint(mount_point);
694 	if (dev) {
695 		uffs_GlobalFsLockLock();
696 		ret = (long) uffs_GetDeviceTotal(dev);
697 		uffs_GlobalFsLockUnlock();
698 	}
699 
700 	return ret;
701 }
702 
uffs_space_used(const char * mount_point)703 long uffs_space_used(const char *mount_point)
704 {
705 	uffs_Device *dev = NULL;
706 	long ret = -1L;
707 
708 	dev = uffs_GetDeviceFromMountPoint(mount_point);
709 	if (dev) {
710 		uffs_GlobalFsLockLock();
711 		ret = (long) uffs_GetDeviceUsed(dev);
712 		uffs_GlobalFsLockUnlock();
713 	}
714 
715 	return ret;
716 }
717 
uffs_space_free(const char * mount_point)718 long uffs_space_free(const char *mount_point)
719 {
720 	uffs_Device *dev = NULL;
721 	long ret = -1L;
722 
723 	dev = uffs_GetDeviceFromMountPoint(mount_point);
724 	if (dev) {
725 		uffs_GlobalFsLockLock();
726 		ret = (long) uffs_GetDeviceFree(dev);
727 		uffs_GlobalFsLockUnlock();
728 	}
729 
730 	return ret;
731 }
732 
733 
uffs_flush_all(const char * mount_point)734 void uffs_flush_all(const char *mount_point)
735 {
736 	uffs_Device *dev = NULL;
737 
738 	dev = uffs_GetDeviceFromMountPoint(mount_point);
739 	if (dev) {
740 		uffs_GlobalFsLockLock();
741 		uffs_BufFlushAll(dev);
742 		uffs_PutDevice(dev);
743 		uffs_GlobalFsLockUnlock();
744 	}
745 }
746 
747