Exemplo n.º 1
0
/**
 * find the matched mount point from a given full absolute path.
 *
 * \param[in] path full path
 * \return the length of mount point.
 */
int uffs_GetMatchedMountPointSize(const char *path)
{
	int pos;
	uffs_Device *dev;

	if (path[0] != '/')
		return 0;

	pos = strlen(path);

	while (pos > 0) {
		if ((dev = uffs_GetDeviceFromMountPointEx(path, pos)) != NULL ) {
			uffs_PutDevice(dev);
			return pos;
		}
		else {
			if (path[pos-1] == '/') 
				pos--;
			//back forward search the next '/'
			for (; pos > 0 && path[pos-1] != '/'; pos--)
				;
		}
	}

	return pos;
}
Exemplo n.º 2
0
/*
 * 函数功能: 格式化分区
 * 输入参数: 分区名称
 * 返回参数: 
 */
int uffs_format(const char *name)
{
	int ret;
	const char *mount = "/";
	uffs_Device *dev;

	if(name) 
	{
		mount = name;
	}

	dev = uffs_GetDeviceFromMountPoint(mount);
	if(dev == NULL) 
	{
		uffs_Perror(UFFS_ERR_NORMAL, "Can't get device from mount point.");
	}
	else 
	{
		if(dev->ref_count == 1) 
		{
			ret = uffs_FormatDevice(dev);
			uffs_Perror(UFFS_ERR_NORMAL, "Format %s.",ret==RT_EOK?"succ":"fail");
		}
		else 
		{
			uffs_Perror(UFFS_ERR_NORMAL, "dev->ref_count: %d, can't format this device.", dev->ref_count);
		}
		uffs_PutDevice(dev);
	}
	return TRUE;	
}
/** dump [<mount>] */
static int cmd_dump(int argc, char *argv[])
{
	uffs_Device *dev;
	uffs_FileEmu *emu;
	const char *mount = "/";
	const char *dump_file = "dump.txt";

	if (argc > 1) {
		mount = argv[1];
		if (argc > 2)
			dump_file = argv[2];
	}

	dev = uffs_GetDeviceFromMountPoint(mount);
	if (dev == NULL) {
		MSGLN("Can't get device from mount point %s", mount);
		return -1;
	}

	emu = (uffs_FileEmu *)(dev->attr->_private);
	emu->dump_fp = fopen(dump_file, "w");

	uffs_DumpDevice(dev, dump_msg_to_stdout);

	if (emu->dump_fp)
		fclose(emu->dump_fp);

	uffs_PutDevice(dev);

	return 0;
}
/** format [<mount>] */
static int cmd_format(int argc, char *argv[])
{
	URET ret;
	const char *mount = "/";
	uffs_Device *dev;
	UBOOL force = U_FALSE;

	if (argc > 1) {
		mount = argv[1];
		if (argc > 2 && strcmp(argv[2], "-f") == 0)
			force = U_TRUE;
	}
	MSGLN("Formating %s ... ", mount);

	dev = uffs_GetDeviceFromMountPoint(mount);
	if (dev == NULL) {
		MSGLN("Can't get device from mount point.");
		return -1;
	}
	else {
		ret = uffs_FormatDevice(dev, force);
		if (ret != U_SUCC) {
			MSGLN("Format fail.");
			return -1;
		}
		else {
			MSGLN("Format succ.");
		}
		uffs_PutDevice(dev);
	}

	return 0;
}
Exemplo n.º 5
0
Arquivo: uffs_fs.c Projeto: mazj/uffs
/**
 * Parse the full path name, initialize obj.
 *
 * \param[out] obj object to be initialize.
 * \param[in] name full path name.
 *
 * \return U_SUCC if the name is parsed correctly,
 *			 U_FAIL if failed, and obj->err is set.
 *
 *	\note the following fields in obj will be initialized:
 *			obj->dev
 *			obj->parent
 *			obj->name
 *			obj->name_len
 */
URET uffs_ParseObject(uffs_Object *obj, const char *name)
{
	int len, m_len, d_len;
	uffs_Device *dev;
	const char *start, *p, *dname;
	u16 dir;
	TreeNode *node;
	u16 sum;

	if (uffs_ReInitObject(obj) == U_FAIL)
		return U_FAIL;

	len = strlen(name);
	m_len = uffs_GetMatchedMountPointSize(name);
	dev = uffs_GetDeviceFromMountPointEx(name, m_len);

	if (dev) {
		start = name + m_len;
		d_len = GetDirLengthFromPath(start, len - m_len);
		p = start;
		obj->dev = dev;
		if (m_len == len) {
			obj->parent = PARENT_OF_ROOT;
			obj->name = NULL;
			obj->name_len = 0;
		}
		else {
			dir = ROOT_DIR_SERIAL;
			dname = start;
			while (p - start < d_len) {
				while (*p != '/') p++;
				sum = uffs_MakeSum16(dname, p - dname);
				node = uffs_TreeFindDirNodeByName(dev, dname, p - dname, sum, dir);
				if (node == NULL) {
					obj->err = UENOENT;
					break;
				}
				else {
					dir = node->u.dir.serial;
					p++; // skip the '/'
					dname = p;
				}
			}
			obj->parent = dir;
			obj->name = start + (d_len > 0 ? d_len + 1 : 0);
			obj->name_len = len - (d_len > 0 ? d_len + 1 : 0) - m_len;
		}

		if (obj->err != UENOERR) {
			uffs_PutDevice(obj->dev);
			obj->dev = NULL;
		}
	}
	else {
		obj->err = UENOENT;
	}

	return (obj->err == UENOERR ? U_SUCC : U_FAIL);
}
/** print block wear-leveling information
 *		wl [<mount>]
 */
static int cmd_wl(int argc, char *argv[])
{
	const char *mount = "/";
	uffs_Device *dev;
	struct uffs_PartitionSt *par;
	uffs_FileEmu *emu;
	int i, max;
	u32 n;

#define NUM_PER_LINE	10

	CHK_ARGC(1, 2);

	if (argc > 1) {
		mount = argv[1];
	}

	dev = uffs_GetDeviceFromMountPoint(mount);
	if (dev == NULL) {
		MSGLN("Can't get device from mount point %s", mount);
		return -1;
	}

	par = &dev->par;
	emu = (uffs_FileEmu *)(dev->attr->_private);
	max = -1;

	for (i = 0; i < par->end - par->start; i++) {
		if ((i % NUM_PER_LINE) == 0) {
			MSG("%04d:", i + par->start);
		}
		n = i + par->start;
		max = (max == -1 ? n :
				(emu->em_monitor_block[n] > emu->em_monitor_block[max] ? n : max)
			   );
		MSG(" %4d", emu->em_monitor_block[n]);
		if (uffs_TreeFindBadNodeByBlock(dev, n))
			MSG("%c", 'x');
		else if (uffs_TreeFindErasedNodeByBlock(dev, n))
			MSG("%c", ' ');
		else
			MSG("%c", '.');
		if (((i + 1) % NUM_PER_LINE) == 0)
			MSG("\n");
	}
	MSG("\n");
	MSG("Total blocks %d, peak erase count %d at block %d\n",
		par->end - par->start, max == -1 ? 0 : emu->em_monitor_block[max], max);

	uffs_PutDevice(dev);

	return 0;
}
void uffs_flush_all(const char *mount_point)
{
	uffs_Device *dev = NULL;

	dev = uffs_GetDeviceFromMountPoint(mount_point);
	if (dev) {
		uffs_GlobalFsLockLock();
		uffs_BufFlushAll(dev);
		uffs_PutDevice(dev);
		uffs_GlobalFsLockUnlock();
	}
}
Exemplo n.º 8
0
int uffs_format(const char *mount_point)
{
	uffs_Device *dev = NULL;
	URET ret = U_FAIL;

	uffs_GlobalFsLockLock();
	dev = uffs_GetDeviceFromMountPoint(mount_point);
	if (dev) {
		ret = uffs_FormatDeviceEx(dev, U_TRUE, U_FALSE);
		uffs_PutDevice(dev);
	}
	uffs_GlobalFsLockUnlock();

	return ret == U_SUCC ? 0 : -1;
}
Exemplo n.º 9
0
long uffs_space_free(const char *mount_point)
{
	uffs_Device *dev = NULL;
	long ret = -1L;

	uffs_GlobalFsLockLock();
	dev = uffs_GetDeviceFromMountPoint(mount_point);
	if (dev) {
		ret = (long) uffs_GetDeviceFree(dev);
		uffs_PutDevice(dev);
	}
	uffs_GlobalFsLockUnlock();

	return ret;
}
Exemplo n.º 10
0
Arquivo: uffs_fs.c Projeto: mazj/uffs
static void do_ReleaseObjectResource(uffs_Object *obj)
{
	if (obj) {
		if (obj->dev) {
			if (HAVE_BADBLOCK(obj->dev))
				uffs_BadBlockRecover(obj->dev);
			if (obj->dev_lock_count > 0) {
				uffs_ObjectDevUnLock(obj);
			}
			uffs_PutDevice(obj->dev);
			obj->dev = NULL;
			obj->open_succ = U_FALSE;
		}
	}
}
Exemplo n.º 11
0
/* t_format : test format partition */
static int cmd_TestFormat(int argc, char *argv[])
{
	URET ret;
	const char *mount = "/";
	uffs_Device *dev;
	UBOOL force = U_FALSE;
	const char *test_file = "/a.txt";
	int fd;
	int rc = -1;

	if (argc > 1) {
		mount = argv[1];
		if (argc > 2 && strcmp(argv[2], "-f") == 0)
			force = U_TRUE;
	}

	fd = uffs_open(test_file, UO_RDWR | UO_CREATE);
	if (fd < 0) {
		MSGLN("can't create test file %s", test_file);
		goto ext;
	}

	MSGLN("Formating %s ... ", mount);

	dev = uffs_GetDeviceFromMountPoint(mount);
	if (dev == NULL) {
		MSGLN("Can't get device from mount point.");
		goto ext;
	}
	else {
		ret = uffs_FormatDevice(dev, force);
		if (ret != U_SUCC) {
			MSGLN("Format fail.");
		}
		else {
			MSGLN("Format succ.");
			rc = 0;
		}
		uffs_PutDevice(dev);
	}

	uffs_close(fd);  // this should fail on signature check !
ext:
	return rc;
}
/** inspect buffers
 *		inspb [<mount>]
 */
static int cmd_inspb(int argc, char *argv[])
{
	uffs_Device *dev;
	const char *mount = "/";

	CHK_ARGC(1, 2);

	dev = uffs_GetDeviceFromMountPoint(mount);
	if (dev == NULL) {
		MSGLN("Can't get device from mount point %s", mount);
		return -1;
	}
	uffs_BufInspect(dev);
	uffs_PutDevice(dev);

	return 0;

}
Exemplo n.º 13
0
static BOOL cmdTestFormat(const char *tail)
{
	URET ret;
	const char *mount = "/";
	uffs_Device *dev;
	const char *next;
	UBOOL force = U_FALSE;
	const char *test_file = "/a.txt";
	int fd;

	if (tail) {
		mount = cli_getparam(tail, &next);
		if (next && strcmp(next, "-f") == 0)
			force = U_TRUE;
	}

	fd = uffs_open(test_file, UO_RDWR | UO_CREATE);
	if (fd < 0) {
		MSGLN("can't create test file %s", test_file);
		return U_TRUE;
	}

	MSGLN("Formating %s ... ", mount);

	dev = uffs_GetDeviceFromMountPoint(mount);
	if (dev == NULL) {
		MSGLN("Can't get device from mount point.");
	}
	else {
		ret = uffs_FormatDevice(dev, force);
		if (ret != U_SUCC) {
			MSGLN("Format fail.");
		}
		else {
			MSGLN("Format succ.");
		}
		uffs_PutDevice(dev);
	}

	uffs_close(fd);  // this should fail on signature check !

	return TRUE;
}
Exemplo n.º 14
0
static int cmd_dump(int argc, char *argv[])
{
	const char *mount = "/";
	uffs_Device *dev;

	if (argc > 1) {
		mount = argv[1];
	}

	MSGLN("Dumping %s ... ", mount);

	dev = uffs_GetDeviceFromMountPoint(mount);
	if (dev == NULL) {
		MSGLN("Can't get device from mount point.");
	}
	else {
		do_dump_device(dev);
		uffs_PutDevice(dev);
	}

	return 0;
}
Exemplo n.º 15
0
Arquivo: uffs_fs.c Projeto: mazj/uffs
/**
 * create a new object and open it if success
 */
URET uffs_CreateObject(uffs_Object *obj, const char *fullname, int oflag)
{
	URET ret = U_FAIL;

	oflag |= UO_CREATE;

	if (uffs_ParseObject(obj, fullname) == U_SUCC)
		uffs_CreateObjectEx(obj, obj->dev, obj->parent,
								obj->name, obj->name_len, oflag);

	if (obj->err == UENOERR) {
		ret = U_SUCC;
	}
	else {
		if (obj->dev) {
			uffs_PutDevice(obj->dev);
			obj->dev = NULL;
		}
		ret = U_FAIL;
	}

	return ret;
}
/** st [<mount>] */
static int cmd_st(int argc, char *argv[])
{
	uffs_Device *dev;
	const char *mount = "/";
	uffs_FlashStat *s;
	TreeNode *node;

	if (argc > 1) {
		mount = argv[1];
	}

	dev = uffs_GetDeviceFromMountPoint(mount);
	if (dev == NULL) {
		MSGLN("Can't get device from mount point %s", mount);
		return -1;
	}

	s = &(dev->st);

	MSG("----------- basic info -----------" TENDSTR);
	MSG("TreeNode size:         %d" TENDSTR, sizeof(TreeNode));
	MSG("TagStore size:         %d" TENDSTR, sizeof(struct uffs_TagStoreSt));
	MSG("MaxCachedBlockInfo:    %d" TENDSTR, dev->cfg.bc_caches);
	MSG("MaxPageBuffers:        %d" TENDSTR, dev->cfg.page_buffers);
	MSG("MaxDirtyPagesPerBlock: %d" TENDSTR, dev->cfg.dirty_pages);
	MSG("MaxPathLength:         %d" TENDSTR, MAX_PATH_LENGTH);
	MSG("MaxObjectHandles:      %d" TENDSTR, MAX_OBJECT_HANDLE);
	MSG("FreeObjectHandles:     %d" TENDSTR, uffs_GetFreeObjectHandlers());
	MSG("MaxDirHandles:         %d" TENDSTR, MAX_DIR_HANDLE);
	MSG("FreeDirHandles:        %d" TENDSTR, uffs_PoolGetFreeCount(uffs_DirEntryBufGetPool()));

	MSG("----------- statistics for '%s' -----------" TENDSTR, mount);
	MSG("Device Ref:            %d" TENDSTR, dev->ref_count);
	MSG("Block Erased:          %d" TENDSTR, s->block_erase_count);
	MSG("Write Page:            %d" TENDSTR, s->page_write_count);
	MSG("Write Spare:           %d" TENDSTR, s->spare_write_count);
	MSG("Read Page:             %d" TENDSTR, s->page_read_count - s->page_header_read_count);
	MSG("Read Header:           %d" TENDSTR, s->page_header_read_count);
	MSG("Read Spare:            %d" TENDSTR, s->spare_read_count);
	MSG("I/O Read:              %lu" TENDSTR, s->io_read);
	MSG("I/O Write:             %lu" TENDSTR, s->io_write);

	MSG("--------- partition info for '%s' ---------" TENDSTR, mount);
	MSG("Space total:           %d" TENDSTR, uffs_GetDeviceTotal(dev));
	MSG("Space used:            %d" TENDSTR, uffs_GetDeviceUsed(dev));
	MSG("Space free:            %d" TENDSTR, uffs_GetDeviceFree(dev));
	MSG("Page Size:             %d" TENDSTR, dev->attr->page_data_size);
	MSG("Spare Size:            %d" TENDSTR, dev->attr->spare_size);
	MSG("Pages Per Block:       %d" TENDSTR, dev->attr->pages_per_block);
	MSG("Block size:            %d" TENDSTR, dev->attr->page_data_size * dev->attr->pages_per_block);
	MSG("Total blocks:          %d of %d" TENDSTR, (dev->par.end - dev->par.start + 1), dev->attr->total_blocks);
	if (dev->tree.bad) {
		MSG("Bad blocks: ");
		node = dev->tree.bad;
		while(node) {
			MSG("%d, ", node->u.list.block);
			node = node->u.list.next;
		}
		MSG(TENDSTR);
	}

	uffs_PutDevice(dev);

	return 0;

}
Exemplo n.º 17
0
/* usage: t_pgrw
 *
 * This test case test page read/write
 */
static BOOL cmdTestPageReadWrite(const char *tail)
{
	TreeNode *node;
	uffs_Device *dev;
	uffs_Tags local_tag;
	uffs_Tags *tag = &local_tag;
	int ret;
	u16 block;
	u16 page;
	uffs_Buf *buf;

	u32 i;

	dev = uffs_GetDeviceFromMountPoint("/");
	if (!dev)
		goto ext;

	buf = uffs_BufClone(dev, NULL);
	if (!buf)
		goto ext;

	node = uffs_TreeGetErasedNode(dev);
	if (!node) {
		MSGLN("no free block ?");
		goto ext;
	}

	for (i = 0; i < dev->com.pg_data_size; i++) {
		buf->data[i] = i & 0xFF;
	}

	block = node->u.list.block;
	page = 1;

	TAG_DATA_LEN(tag) = dev->com.pg_data_size;
	TAG_TYPE(tag) = UFFS_TYPE_DATA;
	TAG_PAGE_ID(tag) = 3;
	TAG_PARENT(tag) = 100;
	TAG_SERIAL(tag) = 10;
	TAG_BLOCK_TS(tag) = 1;

	ret = uffs_FlashWritePageCombine(dev, block, page, buf, tag);
	if (UFFS_FLASH_HAVE_ERR(ret)) {
		MSGLN("Write page error: %d", ret);
		goto ext;
	}

	ret = uffs_FlashReadPage(dev, block, page, buf);
	if (UFFS_FLASH_HAVE_ERR(ret)) {
		MSGLN("Read page error: %d", ret);
		goto ext;
	}

	for (i = 0; i < dev->com.pg_data_size; i++) {
		if (buf->data[i] != (i & 0xFF)) {
			MSGLN("Data verify fail at: %d", i);
			goto ext;
		}
	}

	ret = uffs_FlashReadPageTag(dev, block, page, tag);
	if (UFFS_FLASH_HAVE_ERR(ret)) {
		MSGLN("Read tag (page spare) error: %d", ret);
		goto ext;
	}
	
	// verify tag:
	if (!TAG_IS_DIRTY(tag)) {
		MSGLN("not dirty ? Tag verify fail!");
		goto ext;
	}

	if (!TAG_IS_VALID(tag)) {
		MSGLN("not valid ? Tag verify fail!");
		goto ext;
	}

	if (TAG_DATA_LEN(tag) != dev->com.pg_data_size ||
		TAG_TYPE(tag) != UFFS_TYPE_DATA ||
		TAG_PAGE_ID(tag) != 3 ||
		TAG_PARENT(tag) != 100 ||
		TAG_SERIAL(tag) != 10 ||
		TAG_BLOCK_TS(tag) != 1) {

		MSGLN("Tag verify fail!");
		goto ext;
	}

	MSGLN("Page read/write test succ.");

ext:
	if (node) {
		uffs_FlashEraseBlock(dev, node->u.list.block);
		if (HAVE_BADBLOCK(dev))
			uffs_BadBlockProcess(dev, node);
		else
			uffs_InsertToErasedListHead(dev, node);
	}

	if (dev)
		uffs_PutDevice(dev);

	if (buf)
		uffs_BufFreeClone(dev, buf);

	return TRUE;
}
Exemplo n.º 18
0
/* usage: t_pgrw
 *
 * This test case test page read/write
 */
static int cmd_TestPageReadWrite(int argc, char *argv[])
{
	TreeNode *node = NULL;
	uffs_Device *dev;
	uffs_Tags local_tag;
	uffs_Tags *tag = &local_tag;
	int ret;
	u16 block;
	u16 page;
	uffs_Buf *buf = NULL;

	u32 i;
	int rc = -1;

	dev = uffs_GetDeviceFromMountPoint("/");
	if (!dev)
		goto ext;

	buf = uffs_BufClone(dev, NULL);
	if (!buf)
		goto ext;

	node = uffs_TreeGetErasedNode(dev);
	if (!node) {
		MSGLN("no free block ?");
		goto ext;
	}

	for (i = 0; i < dev->com.pg_data_size; i++) {
		buf->data[i] = i & 0xFF;
	}

	block = node->u.list.block;
	page = 1;

	TAG_DIRTY_BIT(tag) = TAG_DIRTY;
	TAG_VALID_BIT(tag) = TAG_VALID;
	TAG_DATA_LEN(tag) = dev->com.pg_data_size;
	TAG_TYPE(tag) = UFFS_TYPE_DATA;
	TAG_PAGE_ID(tag) = 3;
	TAG_PARENT(tag) = 100;
	TAG_SERIAL(tag) = 10;
	TAG_BLOCK_TS(tag) = 1;
	SEAL_TAG(tag);

	ret = uffs_FlashWritePageCombine(dev, block, page, buf, tag);
	if (UFFS_FLASH_HAVE_ERR(ret)) {
		MSGLN("Write page error: %d", ret);
		goto ext;
	}

	ret = uffs_FlashReadPage(dev, block, page, buf, U_FALSE);
	if (UFFS_FLASH_HAVE_ERR(ret)) {
		MSGLN("Read page error: %d", ret);
		goto ext;
	}

	for (i = 0; i < dev->com.pg_data_size; i++) {
		if (buf->data[i] != (i & 0xFF)) {
			MSGLN("Data verify fail at: %d", i);
			goto ext;
		}
	}

	ret = uffs_FlashReadPageTag(dev, block, page, tag);
	if (UFFS_FLASH_HAVE_ERR(ret)) {
		MSGLN("Read tag (page spare) error: %d", ret);
		goto ext;
	}
	
	// verify tag:
	if (!TAG_IS_SEALED(tag)) {
		MSGLN("not sealed ? Tag verify fail!");
		goto ext;
	}

	if (!TAG_IS_DIRTY(tag)) {
		MSGLN("not dirty ? Tag verify fail!");
		goto ext;
	}

	if (!TAG_IS_VALID(tag)) {
		MSGLN("not valid ? Tag verify fail!");
		goto ext;
	}

	if (TAG_DATA_LEN(tag) != dev->com.pg_data_size ||
		TAG_TYPE(tag) != UFFS_TYPE_DATA ||
		TAG_PAGE_ID(tag) != 3 ||
		TAG_PARENT(tag) != 100 ||
		TAG_SERIAL(tag) != 10 ||
		TAG_BLOCK_TS(tag) != 1) {

		MSGLN("Tag verify fail!");
		goto ext;
	}

	MSGLN("Page read/write test succ.");
	rc = 0;

ext:
	if (node) {
		uffs_TreeEraseNode(dev, node);
		uffs_TreeInsertToErasedListTail(dev, node);
	}

	if (dev)
		uffs_PutDevice(dev);

	if (buf)
		uffs_BufFreeClone(dev, buf);

	return rc;
}
Exemplo n.º 19
0
/*
 * This verify the bug fixed by commit dede97b1.
 * The bug caused a clone buf failure and UFFS complain something like "no enough free pages for clone!".
 */
static int cmd_t_dede97b1(int argc, char *argv[])
{
	// assume:
	//	total page buf: 40
	//	page size: 512
	//  pages per block: 32
	//  spare size: 16
	
#define LEN_A (508 * 30) // 30 pages
#define LEN_B (508 * 10) // 10 pages

	int fd = -1;
	URET ret = -1;
	const int START_A = 508 * 31;			// the second block
	const int START_B = START_A + 508 * 32; // the third block
	const char *name;
	char buf_a[LEN_A];
	char buf_b[LEN_B];

	uffs_Device *dev;
	const char *mount = "/";

	if (argc < 2) {
		return CLI_INVALID_ARG;
	}

	name = argv[1];

	fd = uffs_open(name, UO_RDWR);
	if (fd < 0) {
		MSGLN("Can't open %s", name);
		goto ext;
	}

	///
	/// READ A
	///

	ret = uffs_seek(fd, START_A, USEEK_SET);
	if (ret != START_A) {
		MSGLN("lseek return %d\n", ret);
		goto ext;
	}

	sprintf(buf_a, "start test, read %d bytes...", LEN_A);
	ret = uffs_read(fd, buf_a, LEN_A);
	if (ret != LEN_A) {
		MSGLN("read file failed, ret = %d", ret);
		ret = -1;
		goto ext;
	}
	else {
		MSGLN("read %d bytes succ.", ret);
	}

	MSGLN("now print buf status:");
	dev = uffs_GetDeviceFromMountPoint(mount);
	if (dev == NULL) {
		MSGLN("Can't get device from mount point %s", mount);
		ret = -1;
		goto ext;
	}
	uffs_BufInspect(dev);
	uffs_PutDevice(dev);

	///
	/// READ B
	///

	ret = uffs_seek(fd, START_B, USEEK_SET);
	if (ret != START_B) {
		MSGLN("lseek return %d\n", ret);
		goto ext;
	}

	sprintf(buf_b, "start test, read %d bytes...", LEN_B);
	ret = uffs_read(fd, buf_b, LEN_B);
	if (ret != LEN_B) {
		MSGLN("read file failed, ret = %d", ret);
		ret = -1;
		goto ext;
	}
	else {
		MSGLN("read %d bytes succ.", ret);
	}

	MSGLN("now print buf status:");
	dev = uffs_GetDeviceFromMountPoint(mount);
	if (dev == NULL) {
		MSGLN("Can't get device from mount point %s", mount);
		ret = -1;
		goto ext;
	}
	uffs_BufInspect(dev);
	uffs_PutDevice(dev);


	///
	/// WRITE A
	///

	ret = uffs_seek(fd, START_A, USEEK_SET);
	if (ret != START_A) {
		MSGLN("lseek return %d\n", ret);
		goto ext;
	}

	MSGLN("now try write %d bytes...", LEN_A);
	ret = uffs_write(fd, buf_a, LEN_A);
	if (ret != LEN_A) {
		MSGLN("write %d bytes failed, return %d\n", LEN_A, ret);
		ret = -1;
		goto ext;
	}

	MSGLN("now print buf status again:");
	dev = uffs_GetDeviceFromMountPoint(mount);
	if (dev == NULL) {
		MSGLN("Can't get device from mount point %s", mount);
		ret = -1;
		goto ext;
	}
	uffs_BufInspect(dev);
	uffs_PutDevice(dev);

	///
	/// WRITE B
	///

	ret = uffs_seek(fd, START_B, USEEK_SET);
	if (ret != START_B) {
		MSGLN("lseek return %d\n", ret);
		goto ext;
	}

	MSGLN("now try write %d bytes...", LEN_B);
	ret = uffs_write(fd, buf_b, LEN_B);
	if (ret != LEN_B) {
		MSGLN("write %d bytes failed, return %d\n", LEN_B, ret);
		ret = -1;
		goto ext;
	}

	MSGLN("now print buf status again:");
	dev = uffs_GetDeviceFromMountPoint(mount);
	if (dev == NULL) {
		MSGLN("Can't get device from mount point %s", mount);
		ret = -1;
		goto ext;
	}
	uffs_BufInspect(dev);
	uffs_PutDevice(dev);

	ret = 0;
	MSGLN("test completed.");

ext:
	if (fd >= 0)
		uffs_close(fd);

	return ret;
}