xref: /nrf52832-nimble/rt-thread/components/dfs/filesystems/uffs/src/emu/test_cmds.c (revision 104654410c56c573564690304ae786df310c91fc)
1*10465441SEvalZero /*
2*10465441SEvalZero   This file is part of UFFS, the Ultra-low-cost Flash File System.
3*10465441SEvalZero 
4*10465441SEvalZero   Copyright (C) 2005-2009 Ricky Zheng <[email protected]>
5*10465441SEvalZero 
6*10465441SEvalZero   UFFS is free software; you can redistribute it and/or modify it under
7*10465441SEvalZero   the GNU Library General Public License as published by the Free Software
8*10465441SEvalZero   Foundation; either version 2 of the License, or (at your option) any
9*10465441SEvalZero   later version.
10*10465441SEvalZero 
11*10465441SEvalZero   UFFS is distributed in the hope that it will be useful, but WITHOUT
12*10465441SEvalZero   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13*10465441SEvalZero   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14*10465441SEvalZero   or GNU Library General Public License, as applicable, for more details.
15*10465441SEvalZero 
16*10465441SEvalZero   You should have received a copy of the GNU General Public License
17*10465441SEvalZero   and GNU Library General Public License along with UFFS; if not, write
18*10465441SEvalZero   to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19*10465441SEvalZero   Boston, MA  02110-1301, USA.
20*10465441SEvalZero 
21*10465441SEvalZero   As a special exception, if other files instantiate templates or use
22*10465441SEvalZero   macros or inline functions from this file, or you compile this file
23*10465441SEvalZero   and link it with other works to produce a work based on this file,
24*10465441SEvalZero   this file does not by itself cause the resulting work to be covered
25*10465441SEvalZero   by the GNU General Public License. However the source code for this
26*10465441SEvalZero   file must still be made available in accordance with section (3) of
27*10465441SEvalZero   the GNU General Public License v2.
28*10465441SEvalZero 
29*10465441SEvalZero   This exception does not invalidate any other reasons why a work based
30*10465441SEvalZero   on this file might be covered by the GNU General Public License.
31*10465441SEvalZero */
32*10465441SEvalZero 
33*10465441SEvalZero /**
34*10465441SEvalZero  * \file test_cmds.c
35*10465441SEvalZero  * \brief commands for test uffs
36*10465441SEvalZero  * \author Ricky Zheng
37*10465441SEvalZero  */
38*10465441SEvalZero #include <stdio.h>
39*10465441SEvalZero #include <string.h>
40*10465441SEvalZero #include <stdlib.h>
41*10465441SEvalZero #include "uffs_config.h"
42*10465441SEvalZero #include "uffs/uffs_public.h"
43*10465441SEvalZero #include "uffs/uffs_fd.h"
44*10465441SEvalZero #include "uffs/uffs_utils.h"
45*10465441SEvalZero #include "uffs/uffs_core.h"
46*10465441SEvalZero #include "uffs/uffs_mtb.h"
47*10465441SEvalZero #include "uffs/uffs_find.h"
48*10465441SEvalZero #include "uffs/uffs_badblock.h"
49*10465441SEvalZero #include "cmdline.h"
50*10465441SEvalZero #include "api_test.h"
51*10465441SEvalZero 
52*10465441SEvalZero #define PFX "test: "
53*10465441SEvalZero 
54*10465441SEvalZero #define	MAX_TEST_BUF_LEN	8192
55*10465441SEvalZero 
56*10465441SEvalZero #define SEQ_INIT	10
57*10465441SEvalZero #define SEQ_MOD_LEN	120
58*10465441SEvalZero 
59*10465441SEvalZero #define MSG(msg,...) uffs_PerrorRaw(UFFS_MSG_NORMAL, msg, ## __VA_ARGS__)
60*10465441SEvalZero #define MSGLN(msg,...) uffs_Perror(UFFS_MSG_NORMAL, msg, ## __VA_ARGS__)
61*10465441SEvalZero 
62*10465441SEvalZero 
memcp_seq(void * des,int size,int start_pos)63*10465441SEvalZero static void memcp_seq(void *des, int size, int start_pos)
64*10465441SEvalZero {
65*10465441SEvalZero 	int i;
66*10465441SEvalZero 	u8 *p = (u8 *)des;
67*10465441SEvalZero 
68*10465441SEvalZero 	for (i = 0; i < size; i++, p++) {
69*10465441SEvalZero 		*p = (start_pos + SEQ_INIT + i) % SEQ_MOD_LEN;
70*10465441SEvalZero 	}
71*10465441SEvalZero }
72*10465441SEvalZero 
check_entry_exist(const char * name)73*10465441SEvalZero static UBOOL check_entry_exist(const char *name)
74*10465441SEvalZero {
75*10465441SEvalZero 	struct uffs_stat sb;
76*10465441SEvalZero 
77*10465441SEvalZero 	return uffs_stat(name, &sb) < 0 ? U_FALSE : U_TRUE;
78*10465441SEvalZero }
79*10465441SEvalZero 
do_write_test_file(int fd,int size)80*10465441SEvalZero static URET do_write_test_file(int fd, int size)
81*10465441SEvalZero {
82*10465441SEvalZero 	long pos;
83*10465441SEvalZero 	unsigned char buf[100];
84*10465441SEvalZero 	int len;
85*10465441SEvalZero 
86*10465441SEvalZero 	while (size > 0) {
87*10465441SEvalZero 		pos = uffs_seek(fd, 0, USEEK_CUR);
88*10465441SEvalZero 		len = (size > sizeof(buf) ? sizeof(buf) : size);
89*10465441SEvalZero 		memcp_seq(buf, len, pos);
90*10465441SEvalZero 		if (uffs_write(fd, buf, len) != len) {
91*10465441SEvalZero 			MSGLN("Write file failed, size %d at %d", len, pos);
92*10465441SEvalZero 			return U_FAIL;
93*10465441SEvalZero 		}
94*10465441SEvalZero 		size -= len;
95*10465441SEvalZero 	}
96*10465441SEvalZero 
97*10465441SEvalZero 	return U_SUCC;
98*10465441SEvalZero }
99*10465441SEvalZero 
test_write_file(const char * file_name,int pos,int size)100*10465441SEvalZero static URET test_write_file(const char *file_name, int pos, int size)
101*10465441SEvalZero {
102*10465441SEvalZero 	int ret = U_FAIL;
103*10465441SEvalZero 	int fd = -1;
104*10465441SEvalZero 
105*10465441SEvalZero 	if ((fd = uffs_open(file_name, UO_RDWR|UO_CREATE)) < 0) {
106*10465441SEvalZero 		MSGLN("Can't open file %s for write.", file_name);
107*10465441SEvalZero 		goto test_exit;
108*10465441SEvalZero 	}
109*10465441SEvalZero 
110*10465441SEvalZero 	if (uffs_seek(fd, pos, USEEK_SET) != pos) {
111*10465441SEvalZero 		MSGLN("Can't seek file %s at pos %d", file_name, pos);
112*10465441SEvalZero 		goto test_failed;
113*10465441SEvalZero 	}
114*10465441SEvalZero 
115*10465441SEvalZero 	if (do_write_test_file(fd, size) == U_FAIL) {
116*10465441SEvalZero 		MSGLN("Write file %s failed.", file_name);
117*10465441SEvalZero 		goto test_failed;
118*10465441SEvalZero 	}
119*10465441SEvalZero 	ret = U_SUCC;
120*10465441SEvalZero 
121*10465441SEvalZero test_failed:
122*10465441SEvalZero 	uffs_close(fd);
123*10465441SEvalZero 
124*10465441SEvalZero test_exit:
125*10465441SEvalZero 
126*10465441SEvalZero 	return ret;
127*10465441SEvalZero }
128*10465441SEvalZero 
129*10465441SEvalZero 
test_verify_file(const char * file_name,UBOOL noecc)130*10465441SEvalZero static URET test_verify_file(const char *file_name, UBOOL noecc)
131*10465441SEvalZero {
132*10465441SEvalZero 	int fd;
133*10465441SEvalZero 	int ret = U_FAIL;
134*10465441SEvalZero 	unsigned char buf[100];
135*10465441SEvalZero 	int i, pos, len;
136*10465441SEvalZero 	u8 x;
137*10465441SEvalZero 
138*10465441SEvalZero 	if ((fd = uffs_open(file_name, (noecc ? UO_RDONLY|UO_NOECC : UO_RDONLY))) < 0) {
139*10465441SEvalZero 		MSGLN("Can't open file %s for read.", file_name);
140*10465441SEvalZero 		goto test_exit;
141*10465441SEvalZero 	}
142*10465441SEvalZero 
143*10465441SEvalZero 	pos = 0;
144*10465441SEvalZero 	while (!uffs_eof(fd)) {
145*10465441SEvalZero 		len = uffs_read(fd, buf, sizeof(buf));
146*10465441SEvalZero 		if (len <= 0)
147*10465441SEvalZero 			goto test_failed;
148*10465441SEvalZero 		for (i = 0; i < len; i++) {
149*10465441SEvalZero 			x = (SEQ_INIT + pos + i) % SEQ_MOD_LEN;
150*10465441SEvalZero 			if (buf[i] != x) {
151*10465441SEvalZero 				MSGLN("Verify file %s failed at: %d, expect 0x%02x but got 0x%02x", file_name, pos + i, x, buf[i]);
152*10465441SEvalZero 				goto test_failed;
153*10465441SEvalZero 			}
154*10465441SEvalZero 		}
155*10465441SEvalZero 		pos += len;
156*10465441SEvalZero 	}
157*10465441SEvalZero 
158*10465441SEvalZero 	if (pos != uffs_seek(fd, 0, USEEK_END)) {
159*10465441SEvalZero 		MSGLN("Verify file %s failed. invalid file length.", file_name);
160*10465441SEvalZero 		goto test_failed;
161*10465441SEvalZero 	}
162*10465441SEvalZero 
163*10465441SEvalZero 	MSGLN("Verify file %s succ.", file_name);
164*10465441SEvalZero 	ret = U_SUCC;
165*10465441SEvalZero 
166*10465441SEvalZero test_failed:
167*10465441SEvalZero 	uffs_close(fd);
168*10465441SEvalZero 
169*10465441SEvalZero test_exit:
170*10465441SEvalZero 
171*10465441SEvalZero 	return ret;
172*10465441SEvalZero }
173*10465441SEvalZero 
test_append_file(const char * file_name,int size)174*10465441SEvalZero static URET test_append_file(const char *file_name, int size)
175*10465441SEvalZero {
176*10465441SEvalZero 	int ret = U_FAIL;
177*10465441SEvalZero 	int fd = -1;
178*10465441SEvalZero 
179*10465441SEvalZero 	if ((fd = uffs_open(file_name, UO_RDWR|UO_APPEND|UO_CREATE)) < 0) {
180*10465441SEvalZero 		MSGLN("Can't open file %s for append.", file_name);
181*10465441SEvalZero 		goto test_exit;
182*10465441SEvalZero 	}
183*10465441SEvalZero 
184*10465441SEvalZero 	uffs_seek(fd, 0, USEEK_END);
185*10465441SEvalZero 
186*10465441SEvalZero 	if (do_write_test_file(fd, size) == U_FAIL) {
187*10465441SEvalZero 		MSGLN("Write file %s failed.", file_name);
188*10465441SEvalZero 		goto test_failed;
189*10465441SEvalZero 	}
190*10465441SEvalZero 	ret = U_SUCC;
191*10465441SEvalZero 
192*10465441SEvalZero test_failed:
193*10465441SEvalZero 	uffs_close(fd);
194*10465441SEvalZero 
195*10465441SEvalZero test_exit:
196*10465441SEvalZero 
197*10465441SEvalZero 	return ret;
198*10465441SEvalZero }
199*10465441SEvalZero 
200*10465441SEvalZero 
201*10465441SEvalZero /* test create file, write file and read back */
cmd_t1(int argc,char * argv[])202*10465441SEvalZero static int cmd_t1(int argc, char *argv[])
203*10465441SEvalZero {
204*10465441SEvalZero 	int fd;
205*10465441SEvalZero 	URET ret;
206*10465441SEvalZero 	char buf[100];
207*10465441SEvalZero 	const char *name;
208*10465441SEvalZero 
209*10465441SEvalZero 	if (argc < 2) {
210*10465441SEvalZero 		return CLI_INVALID_ARG;
211*10465441SEvalZero 	}
212*10465441SEvalZero 
213*10465441SEvalZero 	name = argv[1];
214*10465441SEvalZero 
215*10465441SEvalZero 	fd = uffs_open(name, UO_RDWR|UO_CREATE|UO_TRUNC);
216*10465441SEvalZero 	if (fd < 0) {
217*10465441SEvalZero 		MSGLN("Can't open %s", name);
218*10465441SEvalZero 		goto fail;
219*10465441SEvalZero 	}
220*10465441SEvalZero 
221*10465441SEvalZero 	sprintf(buf, "123456789ABCDEF");
222*10465441SEvalZero 	ret = uffs_write(fd, buf, strlen(buf));
223*10465441SEvalZero 	MSGLN("write %d bytes to file, content: %s", ret, buf);
224*10465441SEvalZero 
225*10465441SEvalZero 	ret = uffs_seek(fd, 3, USEEK_SET);
226*10465441SEvalZero 	MSGLN("new file position: %d", ret);
227*10465441SEvalZero 
228*10465441SEvalZero 	memset(buf, 0, sizeof(buf));
229*10465441SEvalZero 	ret = uffs_read(fd, buf, 5);
230*10465441SEvalZero 	MSGLN("read %d bytes, content: %s", ret, buf);
231*10465441SEvalZero 
232*10465441SEvalZero 	uffs_close(fd);
233*10465441SEvalZero 
234*10465441SEvalZero 	return 0;
235*10465441SEvalZero fail:
236*10465441SEvalZero 
237*10465441SEvalZero 	return -1;
238*10465441SEvalZero }
239*10465441SEvalZero 
240*10465441SEvalZero 
DoTest2(void)241*10465441SEvalZero static URET DoTest2(void)
242*10465441SEvalZero {
243*10465441SEvalZero 	int fd = -1;
244*10465441SEvalZero 	URET ret = U_FAIL;
245*10465441SEvalZero 	char buf[100], buf_1[100];
246*10465441SEvalZero 
247*10465441SEvalZero 	fd = uffs_open("/abc/", UO_RDWR|UO_DIR);
248*10465441SEvalZero 	if (fd < 0) {
249*10465441SEvalZero 		MSGLN("Can't open dir abc, err: %d", uffs_get_error());
250*10465441SEvalZero 		MSGLN("Try to create a new one...");
251*10465441SEvalZero 		fd = uffs_open("/abc/", UO_RDWR|UO_CREATE|UO_DIR);
252*10465441SEvalZero 		if (fd < 0) {
253*10465441SEvalZero 			MSGLN("Can't create new dir /abc/");
254*10465441SEvalZero 			goto exit_test;
255*10465441SEvalZero 		}
256*10465441SEvalZero 		else {
257*10465441SEvalZero 			uffs_close(fd);
258*10465441SEvalZero 		}
259*10465441SEvalZero 	}
260*10465441SEvalZero 	else {
261*10465441SEvalZero 		uffs_close(fd);
262*10465441SEvalZero 	}
263*10465441SEvalZero 
264*10465441SEvalZero 	fd = uffs_open("/abc/test.txt", UO_RDWR|UO_CREATE);
265*10465441SEvalZero 	if (fd < 0) {
266*10465441SEvalZero 		MSGLN("Can't open /abc/test.txt");
267*10465441SEvalZero 		goto exit_test;
268*10465441SEvalZero 	}
269*10465441SEvalZero 
270*10465441SEvalZero 	sprintf(buf, "123456789ABCDEF");
271*10465441SEvalZero 	ret = uffs_write(fd, buf, strlen(buf));
272*10465441SEvalZero 	MSGLN("write %d bytes to file, content: %s", ret, buf);
273*10465441SEvalZero 
274*10465441SEvalZero 	ret = uffs_seek(fd, 3, USEEK_SET);
275*10465441SEvalZero 	MSGLN("new file position: %d", ret);
276*10465441SEvalZero 
277*10465441SEvalZero 	memset(buf_1, 0, sizeof(buf_1));
278*10465441SEvalZero 	ret = uffs_read(fd, buf_1, 5);
279*10465441SEvalZero 	MSGLN("read %d bytes, content: %s", ret, buf_1);
280*10465441SEvalZero 
281*10465441SEvalZero 	if (memcmp(buf + 3, buf_1, 5) != 0) {
282*10465441SEvalZero 		ret = U_FAIL;
283*10465441SEvalZero 	}
284*10465441SEvalZero 	else {
285*10465441SEvalZero 		ret = U_SUCC;
286*10465441SEvalZero 	}
287*10465441SEvalZero 
288*10465441SEvalZero 	uffs_close(fd);
289*10465441SEvalZero 
290*10465441SEvalZero exit_test:
291*10465441SEvalZero 
292*10465441SEvalZero 	return ret;
293*10465441SEvalZero }
294*10465441SEvalZero 
295*10465441SEvalZero 
cmd_t2(int argc,char * argv[])296*10465441SEvalZero static int cmd_t2(int argc, char *argv[])
297*10465441SEvalZero {
298*10465441SEvalZero 	URET ret;
299*10465441SEvalZero 	MSGLN("Test return: %s !", (ret = DoTest2()) == U_SUCC ? "succ" : "failed");
300*10465441SEvalZero 
301*10465441SEvalZero 	return (ret == U_SUCC) ? 0 : -1;
302*10465441SEvalZero }
303*10465441SEvalZero 
304*10465441SEvalZero 
cmd_VerifyFile(int argc,char * argv[])305*10465441SEvalZero static int cmd_VerifyFile(int argc, char *argv[])
306*10465441SEvalZero {
307*10465441SEvalZero 	const char *name;
308*10465441SEvalZero 	UBOOL noecc = U_FALSE;
309*10465441SEvalZero 
310*10465441SEvalZero 	if (argc < 2) {
311*10465441SEvalZero 		return CLI_INVALID_ARG;
312*10465441SEvalZero 	}
313*10465441SEvalZero 
314*10465441SEvalZero 	name = argv[1];
315*10465441SEvalZero 	if (argc > 2 && strcmp(argv[2], "noecc") == 0) {
316*10465441SEvalZero 		noecc = U_TRUE;
317*10465441SEvalZero 	}
318*10465441SEvalZero 
319*10465441SEvalZero 	MSGLN("Check file %s ... ", name);
320*10465441SEvalZero 	if (test_verify_file(name, noecc) != U_SUCC) {
321*10465441SEvalZero 		MSGLN("Verify file %s failed.", name);
322*10465441SEvalZero 		return -1;
323*10465441SEvalZero 	}
324*10465441SEvalZero 
325*10465441SEvalZero 	return 0;
326*10465441SEvalZero }
327*10465441SEvalZero 
328*10465441SEvalZero /* Test file append and 'random' write */
cmd_t3(int argc,char * argv[])329*10465441SEvalZero static int cmd_t3(int argc, char *argv[])
330*10465441SEvalZero {
331*10465441SEvalZero 	const char *name;
332*10465441SEvalZero 	int i;
333*10465441SEvalZero 	UBOOL noecc = U_FALSE;
334*10465441SEvalZero 	int write_test_seq[] = { 20, 10, 500, 40, 1140, 900, 329, 4560, 352, 1100 };
335*10465441SEvalZero 
336*10465441SEvalZero 	if (argc < 2) {
337*10465441SEvalZero 		return CLI_INVALID_ARG;
338*10465441SEvalZero 	}
339*10465441SEvalZero 
340*10465441SEvalZero 	name = argv[1];
341*10465441SEvalZero 	if (argv[2] && strcmp(argv[2], "noecc") == 0) {
342*10465441SEvalZero 		noecc = U_TRUE;
343*10465441SEvalZero 	}
344*10465441SEvalZero 
345*10465441SEvalZero 	if (check_entry_exist(name)) {
346*10465441SEvalZero 		MSGLN("Check file %s ... ", name);
347*10465441SEvalZero 		if (test_verify_file(name, noecc) != U_SUCC) {
348*10465441SEvalZero 			MSGLN("Verify file %s failed.", name);
349*10465441SEvalZero 			return -1;
350*10465441SEvalZero 		}
351*10465441SEvalZero 	}
352*10465441SEvalZero 
353*10465441SEvalZero 	MSGLN("Test append file %s ...", name);
354*10465441SEvalZero 	for (i = 1; i < 500; i += 29) {
355*10465441SEvalZero 		if (test_append_file(name, i) != U_SUCC) {
356*10465441SEvalZero 			MSGLN("Append file %s test failed at %d !", name, i);
357*10465441SEvalZero 			return -1;
358*10465441SEvalZero 		}
359*10465441SEvalZero 	}
360*10465441SEvalZero 
361*10465441SEvalZero 	MSGLN("Check file %s ... ", name);
362*10465441SEvalZero 	if (test_verify_file(name, noecc) != U_SUCC) {
363*10465441SEvalZero 		MSGLN("Verify file %s failed.", name);
364*10465441SEvalZero 		return -1;
365*10465441SEvalZero 	}
366*10465441SEvalZero 
367*10465441SEvalZero 	MSGLN("Test write file ...");
368*10465441SEvalZero 	for (i = 0; i < sizeof(write_test_seq) / sizeof(int) - 1; i++) {
369*10465441SEvalZero 		if (test_write_file(name, write_test_seq[i], write_test_seq[i+1]) != U_SUCC) {
370*10465441SEvalZero 			MSGLN("Test write file failed !");
371*10465441SEvalZero 			return -1;
372*10465441SEvalZero 		}
373*10465441SEvalZero 	}
374*10465441SEvalZero 
375*10465441SEvalZero 	MSGLN("Check file %s ... ", name);
376*10465441SEvalZero 	if (test_verify_file(name, noecc) != U_SUCC) {
377*10465441SEvalZero 		MSGLN("Verify file %s failed.", name);
378*10465441SEvalZero 		return -1;
379*10465441SEvalZero 	}
380*10465441SEvalZero 
381*10465441SEvalZero 	MSGLN("Test succ !");
382*10465441SEvalZero 
383*10465441SEvalZero 	return 0;
384*10465441SEvalZero }
385*10465441SEvalZero 
386*10465441SEvalZero /* open two files and test write */
cmd_t4(int argc,char * argv[])387*10465441SEvalZero static int cmd_t4(int argc, char *argv[])
388*10465441SEvalZero {
389*10465441SEvalZero 	int fd1 = -1, fd2 = -1;
390*10465441SEvalZero 
391*10465441SEvalZero 	MSGLN("open /a ...");
392*10465441SEvalZero 	if ((fd1 = uffs_open("/a", UO_RDWR | UO_CREATE)) < 0) {
393*10465441SEvalZero 		MSGLN("Can't open /a");
394*10465441SEvalZero 		goto fail_exit;
395*10465441SEvalZero 	}
396*10465441SEvalZero 
397*10465441SEvalZero 	MSGLN("open /b ...");
398*10465441SEvalZero 	if ((fd2 = uffs_open("/b", UO_RDWR | UO_CREATE)) < 0) {
399*10465441SEvalZero 		MSGLN("Can't open /b");
400*10465441SEvalZero 		uffs_close(fd1);
401*10465441SEvalZero 		goto fail_exit;
402*10465441SEvalZero 	}
403*10465441SEvalZero 
404*10465441SEvalZero 	MSGLN("write (1) to /a ...");
405*10465441SEvalZero 	uffs_write(fd1, "Hello,", 6);
406*10465441SEvalZero 	MSGLN("write (1) to /b ...");
407*10465441SEvalZero 	uffs_write(fd2, "Hello,", 6);
408*10465441SEvalZero 	MSGLN("write (2) to /a ...");
409*10465441SEvalZero 	uffs_write(fd1, "World.", 6);
410*10465441SEvalZero 	MSGLN("write (2) to /b ...");
411*10465441SEvalZero 	uffs_write(fd2, "World.", 6);
412*10465441SEvalZero 	MSGLN("close /a ...");
413*10465441SEvalZero 	uffs_close(fd1);
414*10465441SEvalZero 	MSGLN("close /b ...");
415*10465441SEvalZero 	uffs_close(fd2);
416*10465441SEvalZero 
417*10465441SEvalZero 	return 0;
418*10465441SEvalZero 
419*10465441SEvalZero fail_exit:
420*10465441SEvalZero 	return -1;
421*10465441SEvalZero }
422*10465441SEvalZero 
423*10465441SEvalZero /* test appending file */
cmd_t5(int argc,char * argv[])424*10465441SEvalZero static int cmd_t5(int argc, char *argv[])
425*10465441SEvalZero {
426*10465441SEvalZero 	int fd = -1;
427*10465441SEvalZero 	URET ret;
428*10465441SEvalZero 	char buf[100];
429*10465441SEvalZero 	const char *name;
430*10465441SEvalZero 
431*10465441SEvalZero 	if (argc < 2) {
432*10465441SEvalZero 		return CLI_INVALID_ARG;
433*10465441SEvalZero 	}
434*10465441SEvalZero 
435*10465441SEvalZero 	name = argv[1];
436*10465441SEvalZero 
437*10465441SEvalZero 	fd = uffs_open(name, UO_RDWR|UO_APPEND);
438*10465441SEvalZero 	if (fd < 0) {
439*10465441SEvalZero 		MSGLN("Can't open %s", name);
440*10465441SEvalZero 		goto fail;
441*10465441SEvalZero 	}
442*10465441SEvalZero 
443*10465441SEvalZero 	sprintf(buf, "append test...");
444*10465441SEvalZero 	ret = uffs_write(fd, buf, strlen(buf));
445*10465441SEvalZero 	if (ret != strlen(buf)) {
446*10465441SEvalZero 		MSGLN("write file failed, %d/%d", ret, strlen(buf));
447*10465441SEvalZero 		ret = -1;
448*10465441SEvalZero 	}
449*10465441SEvalZero 	else {
450*10465441SEvalZero 		MSGLN("write %d bytes to file, content: %s", ret, buf);
451*10465441SEvalZero 		ret = 0;
452*10465441SEvalZero 	}
453*10465441SEvalZero 
454*10465441SEvalZero 	uffs_close(fd);
455*10465441SEvalZero 
456*10465441SEvalZero 	return ret;
457*10465441SEvalZero fail:
458*10465441SEvalZero 	return -1;
459*10465441SEvalZero }
460*10465441SEvalZero 
461*10465441SEvalZero 
462*10465441SEvalZero /* usage: t_pgrw
463*10465441SEvalZero  *
464*10465441SEvalZero  * This test case test page read/write
465*10465441SEvalZero  */
cmd_TestPageReadWrite(int argc,char * argv[])466*10465441SEvalZero static int cmd_TestPageReadWrite(int argc, char *argv[])
467*10465441SEvalZero {
468*10465441SEvalZero 	TreeNode *node = NULL;
469*10465441SEvalZero 	uffs_Device *dev;
470*10465441SEvalZero 	uffs_Tags local_tag;
471*10465441SEvalZero 	uffs_Tags *tag = &local_tag;
472*10465441SEvalZero 	int ret;
473*10465441SEvalZero 	u16 block;
474*10465441SEvalZero 	u16 page;
475*10465441SEvalZero 	uffs_Buf *buf = NULL;
476*10465441SEvalZero 
477*10465441SEvalZero 	u32 i;
478*10465441SEvalZero 	int rc = -1;
479*10465441SEvalZero 
480*10465441SEvalZero 	dev = uffs_GetDeviceFromMountPoint("/");
481*10465441SEvalZero 	if (!dev)
482*10465441SEvalZero 		goto ext;
483*10465441SEvalZero 
484*10465441SEvalZero 	buf = uffs_BufClone(dev, NULL);
485*10465441SEvalZero 	if (!buf)
486*10465441SEvalZero 		goto ext;
487*10465441SEvalZero 
488*10465441SEvalZero 	node = uffs_TreeGetErasedNode(dev);
489*10465441SEvalZero 	if (!node) {
490*10465441SEvalZero 		MSGLN("no free block ?");
491*10465441SEvalZero 		goto ext;
492*10465441SEvalZero 	}
493*10465441SEvalZero 
494*10465441SEvalZero 	for (i = 0; i < dev->com.pg_data_size; i++) {
495*10465441SEvalZero 		buf->data[i] = i & 0xFF;
496*10465441SEvalZero 	}
497*10465441SEvalZero 
498*10465441SEvalZero 	block = node->u.list.block;
499*10465441SEvalZero 	page = 1;
500*10465441SEvalZero 
501*10465441SEvalZero 	TAG_DIRTY_BIT(tag) = TAG_DIRTY;
502*10465441SEvalZero 	TAG_VALID_BIT(tag) = TAG_VALID;
503*10465441SEvalZero 	TAG_DATA_LEN(tag) = dev->com.pg_data_size;
504*10465441SEvalZero 	TAG_TYPE(tag) = UFFS_TYPE_DATA;
505*10465441SEvalZero 	TAG_PAGE_ID(tag) = 3;
506*10465441SEvalZero 	TAG_PARENT(tag) = 100;
507*10465441SEvalZero 	TAG_SERIAL(tag) = 10;
508*10465441SEvalZero 	TAG_BLOCK_TS(tag) = 1;
509*10465441SEvalZero 	SEAL_TAG(tag);
510*10465441SEvalZero 
511*10465441SEvalZero 	ret = uffs_FlashWritePageCombine(dev, block, page, buf, tag);
512*10465441SEvalZero 	if (UFFS_FLASH_HAVE_ERR(ret)) {
513*10465441SEvalZero 		MSGLN("Write page error: %d", ret);
514*10465441SEvalZero 		goto ext;
515*10465441SEvalZero 	}
516*10465441SEvalZero 
517*10465441SEvalZero 	ret = uffs_FlashReadPage(dev, block, page, buf, U_FALSE);
518*10465441SEvalZero 	if (UFFS_FLASH_HAVE_ERR(ret)) {
519*10465441SEvalZero 		MSGLN("Read page error: %d", ret);
520*10465441SEvalZero 		goto ext;
521*10465441SEvalZero 	}
522*10465441SEvalZero 
523*10465441SEvalZero 	for (i = 0; i < dev->com.pg_data_size; i++) {
524*10465441SEvalZero 		if (buf->data[i] != (i & 0xFF)) {
525*10465441SEvalZero 			MSGLN("Data verify fail at: %d", i);
526*10465441SEvalZero 			goto ext;
527*10465441SEvalZero 		}
528*10465441SEvalZero 	}
529*10465441SEvalZero 
530*10465441SEvalZero 	ret = uffs_FlashReadPageTag(dev, block, page, tag);
531*10465441SEvalZero 	if (UFFS_FLASH_HAVE_ERR(ret)) {
532*10465441SEvalZero 		MSGLN("Read tag (page spare) error: %d", ret);
533*10465441SEvalZero 		goto ext;
534*10465441SEvalZero 	}
535*10465441SEvalZero 
536*10465441SEvalZero 	// verify tag:
537*10465441SEvalZero 	if (!TAG_IS_SEALED(tag)) {
538*10465441SEvalZero 		MSGLN("not sealed ? Tag verify fail!");
539*10465441SEvalZero 		goto ext;
540*10465441SEvalZero 	}
541*10465441SEvalZero 
542*10465441SEvalZero 	if (!TAG_IS_DIRTY(tag)) {
543*10465441SEvalZero 		MSGLN("not dirty ? Tag verify fail!");
544*10465441SEvalZero 		goto ext;
545*10465441SEvalZero 	}
546*10465441SEvalZero 
547*10465441SEvalZero 	if (!TAG_IS_VALID(tag)) {
548*10465441SEvalZero 		MSGLN("not valid ? Tag verify fail!");
549*10465441SEvalZero 		goto ext;
550*10465441SEvalZero 	}
551*10465441SEvalZero 
552*10465441SEvalZero 	if (TAG_DATA_LEN(tag) != dev->com.pg_data_size ||
553*10465441SEvalZero 		TAG_TYPE(tag) != UFFS_TYPE_DATA ||
554*10465441SEvalZero 		TAG_PAGE_ID(tag) != 3 ||
555*10465441SEvalZero 		TAG_PARENT(tag) != 100 ||
556*10465441SEvalZero 		TAG_SERIAL(tag) != 10 ||
557*10465441SEvalZero 		TAG_BLOCK_TS(tag) != 1) {
558*10465441SEvalZero 
559*10465441SEvalZero 		MSGLN("Tag verify fail!");
560*10465441SEvalZero 		goto ext;
561*10465441SEvalZero 	}
562*10465441SEvalZero 
563*10465441SEvalZero 	MSGLN("Page read/write test succ.");
564*10465441SEvalZero 	rc = 0;
565*10465441SEvalZero 
566*10465441SEvalZero ext:
567*10465441SEvalZero 	if (node) {
568*10465441SEvalZero 		uffs_FlashEraseBlock(dev, node->u.list.block);
569*10465441SEvalZero 		if (HAVE_BADBLOCK(dev))
570*10465441SEvalZero 			uffs_BadBlockProcess(dev, node);
571*10465441SEvalZero 		else
572*10465441SEvalZero 			uffs_TreeInsertToErasedListTail(dev, node);
573*10465441SEvalZero 	}
574*10465441SEvalZero 
575*10465441SEvalZero 	if (dev)
576*10465441SEvalZero 		uffs_PutDevice(dev);
577*10465441SEvalZero 
578*10465441SEvalZero 	if (buf)
579*10465441SEvalZero 		uffs_BufFreeClone(dev, buf);
580*10465441SEvalZero 
581*10465441SEvalZero 	return rc;
582*10465441SEvalZero }
583*10465441SEvalZero 
584*10465441SEvalZero /* t_format : test format partition */
cmd_TestFormat(int argc,char * argv[])585*10465441SEvalZero static int cmd_TestFormat(int argc, char *argv[])
586*10465441SEvalZero {
587*10465441SEvalZero 	URET ret;
588*10465441SEvalZero 	const char *mount = "/";
589*10465441SEvalZero 	uffs_Device *dev;
590*10465441SEvalZero 	UBOOL force = U_FALSE;
591*10465441SEvalZero 	const char *test_file = "/a.txt";
592*10465441SEvalZero 	int fd;
593*10465441SEvalZero 	int rc = -1;
594*10465441SEvalZero 
595*10465441SEvalZero 	if (argc > 1) {
596*10465441SEvalZero 		mount = argv[1];
597*10465441SEvalZero 		if (argc > 2 && strcmp(argv[2], "-f") == 0)
598*10465441SEvalZero 			force = U_TRUE;
599*10465441SEvalZero 	}
600*10465441SEvalZero 
601*10465441SEvalZero 	fd = uffs_open(test_file, UO_RDWR | UO_CREATE);
602*10465441SEvalZero 	if (fd < 0) {
603*10465441SEvalZero 		MSGLN("can't create test file %s", test_file);
604*10465441SEvalZero 		goto ext;
605*10465441SEvalZero 	}
606*10465441SEvalZero 
607*10465441SEvalZero 	MSGLN("Formating %s ... ", mount);
608*10465441SEvalZero 
609*10465441SEvalZero 	dev = uffs_GetDeviceFromMountPoint(mount);
610*10465441SEvalZero 	if (dev == NULL) {
611*10465441SEvalZero 		MSGLN("Can't get device from mount point.");
612*10465441SEvalZero 		goto ext;
613*10465441SEvalZero 	}
614*10465441SEvalZero 	else {
615*10465441SEvalZero 		ret = uffs_FormatDevice(dev, force);
616*10465441SEvalZero 		if (ret != U_SUCC) {
617*10465441SEvalZero 			MSGLN("Format fail.");
618*10465441SEvalZero 		}
619*10465441SEvalZero 		else {
620*10465441SEvalZero 			MSGLN("Format succ.");
621*10465441SEvalZero 			rc = 0;
622*10465441SEvalZero 		}
623*10465441SEvalZero 		uffs_PutDevice(dev);
624*10465441SEvalZero 	}
625*10465441SEvalZero 
626*10465441SEvalZero 	uffs_close(fd);  // this should fail on signature check !
627*10465441SEvalZero ext:
628*10465441SEvalZero 	return rc;
629*10465441SEvalZero }
630*10465441SEvalZero 
631*10465441SEvalZero 
632*10465441SEvalZero 
633*10465441SEvalZero /**
634*10465441SEvalZero  * usage: t_pfs <start> <n>
635*10465441SEvalZero  *
636*10465441SEvalZero  * for example: t_pfs /x/ 100
637*10465441SEvalZero  *
638*10465441SEvalZero  * This test case performs:
639*10465441SEvalZero  *   1) create <n> files under <start>, write full file name as file content
640*10465441SEvalZero  *   2) list files under <start>, check files are all listed once
641*10465441SEvalZero  *   3) check file content aganist file name
642*10465441SEvalZero  *   4) delete files on success
643*10465441SEvalZero  */
cmd_TestPopulateFiles(int argc,char * argv[])644*10465441SEvalZero static int cmd_TestPopulateFiles(int argc, char *argv[])
645*10465441SEvalZero {
646*10465441SEvalZero 	const char *start = "/";
647*10465441SEvalZero 	int count = 80;
648*10465441SEvalZero 	int i, fd, num;
649*10465441SEvalZero 	char name[128];
650*10465441SEvalZero 	char buf[128];
651*10465441SEvalZero 	uffs_DIR *dirp;
652*10465441SEvalZero 	struct uffs_dirent *ent;
653*10465441SEvalZero 	unsigned long bitmap[50] = {0};	// one bit per file, maximu 32*50 = 1600 files
654*10465441SEvalZero 	UBOOL succ = U_TRUE;
655*10465441SEvalZero 
656*10465441SEvalZero #define SBIT(n) bitmap[(n)/(sizeof(bitmap[0]) * 8)] |= (1 << ((n) % (sizeof(bitmap[0]) * 8)))
657*10465441SEvalZero #define GBIT(n) (bitmap[(n)/(sizeof(bitmap[0]) * 8)] & (1 << ((n) % (sizeof(bitmap[0]) * 8))))
658*10465441SEvalZero 
659*10465441SEvalZero 	if (argc > 1) {
660*10465441SEvalZero 		start = argv[1];
661*10465441SEvalZero 		if (argc > 2) {
662*10465441SEvalZero 			count = strtol(argv[2], NULL, 10);
663*10465441SEvalZero 		}
664*10465441SEvalZero 	}
665*10465441SEvalZero 
666*10465441SEvalZero 	if (count > sizeof(bitmap) * 8)
667*10465441SEvalZero 		count = sizeof(bitmap) * 8;
668*10465441SEvalZero 
669*10465441SEvalZero 	for (i = 0, fd = -1; i < count; i++) {
670*10465441SEvalZero 		sprintf(name, "%sFile%03d", start, i);
671*10465441SEvalZero 		fd = uffs_open(name, UO_RDWR|UO_CREATE|UO_TRUNC);
672*10465441SEvalZero 		if (fd < 0) {
673*10465441SEvalZero 			MSGLN("Create file %s failed", name);
674*10465441SEvalZero 			break;
675*10465441SEvalZero 		}
676*10465441SEvalZero 		if (uffs_write(fd, name, strlen(name)) != strlen(name)) { // write full path name to file
677*10465441SEvalZero 			MSGLN("Write to file %s failed", name);
678*10465441SEvalZero 			uffs_close(fd);
679*10465441SEvalZero 			break;
680*10465441SEvalZero 		}
681*10465441SEvalZero 		uffs_close(fd);
682*10465441SEvalZero 	}
683*10465441SEvalZero 
684*10465441SEvalZero 	if (i < count) {
685*10465441SEvalZero 		// not success, need to clean up
686*10465441SEvalZero 		for (; i >= 0; i--) {
687*10465441SEvalZero 			sprintf(name, "%sFile%03d", start, i);
688*10465441SEvalZero 			if (uffs_remove(name) < 0)
689*10465441SEvalZero 				MSGLN("Delete file %s failed", name);
690*10465441SEvalZero 		}
691*10465441SEvalZero 		succ = U_FALSE;
692*10465441SEvalZero 		goto ext;
693*10465441SEvalZero 	}
694*10465441SEvalZero 
695*10465441SEvalZero 	MSGLN("%d files created.", count);
696*10465441SEvalZero 
697*10465441SEvalZero 	// list files
698*10465441SEvalZero 	dirp = uffs_opendir(start);
699*10465441SEvalZero 	if (dirp == NULL) {
700*10465441SEvalZero 		MSGLN("Can't open dir %s !", start);
701*10465441SEvalZero 		succ = U_FALSE;
702*10465441SEvalZero 		goto ext;
703*10465441SEvalZero 	}
704*10465441SEvalZero 	ent = uffs_readdir(dirp);
705*10465441SEvalZero 	while (ent && succ) {
706*10465441SEvalZero 
707*10465441SEvalZero 		if (!(ent->d_type & FILE_ATTR_DIR) &&					// not a dir
708*10465441SEvalZero 			ent->d_namelen == strlen("File000") &&				// check file name length
709*10465441SEvalZero 			memcmp(ent->d_name, "File", strlen("File")) == 0) {	// file name start with "File"
710*10465441SEvalZero 
711*10465441SEvalZero 			MSGLN("List entry %s", ent->d_name);
712*10465441SEvalZero 
713*10465441SEvalZero 			num = strtol(ent->d_name + 4, NULL, 10);
714*10465441SEvalZero 			if (GBIT(num)) {
715*10465441SEvalZero 				// file already listed ?
716*10465441SEvalZero 				MSGLN("File %d listed twice !", ent->d_name);
717*10465441SEvalZero 				succ = U_FALSE;
718*10465441SEvalZero 				break;
719*10465441SEvalZero 			}
720*10465441SEvalZero 			SBIT(num);
721*10465441SEvalZero 
722*10465441SEvalZero 			// check file content
723*10465441SEvalZero 			sprintf(name, "%s%s", start, ent->d_name);
724*10465441SEvalZero 			fd = uffs_open(name, UO_RDONLY);
725*10465441SEvalZero 			if (fd < 0) {
726*10465441SEvalZero 				MSGLN("Open file %d for read failed !", name);
727*10465441SEvalZero 			}
728*10465441SEvalZero 			else {
729*10465441SEvalZero 				memset(buf, 0, sizeof(buf));
730*10465441SEvalZero 				num = uffs_read(fd, buf, sizeof(buf));
731*10465441SEvalZero 				if (num != strlen(name)) {
732*10465441SEvalZero 					MSGLN("%s Read data length expect %d but got %d !", name, strlen(name), num);
733*10465441SEvalZero 					succ = U_FALSE;
734*10465441SEvalZero 				}
735*10465441SEvalZero 				else {
736*10465441SEvalZero 					if (memcmp(name, buf, num) != 0) {
737*10465441SEvalZero 						MSGLN("File %s have wrong content '%s' !", name, buf);
738*10465441SEvalZero 						succ = U_FALSE;
739*10465441SEvalZero 					}
740*10465441SEvalZero 				}
741*10465441SEvalZero 				uffs_close(fd);
742*10465441SEvalZero 			}
743*10465441SEvalZero 		}
744*10465441SEvalZero 		ent = uffs_readdir(dirp);
745*10465441SEvalZero 	}
746*10465441SEvalZero 	uffs_closedir(dirp);
747*10465441SEvalZero 
748*10465441SEvalZero 	// check absent files
749*10465441SEvalZero 	for (i = 0; i < count; i++) {
750*10465441SEvalZero 		if (GBIT(i) == 0) {
751*10465441SEvalZero 			sprintf(name, "%sFile%03d", start, i);
752*10465441SEvalZero 			MSGLN("File %s not listed !", name);
753*10465441SEvalZero 			succ = U_FALSE;
754*10465441SEvalZero 		}
755*10465441SEvalZero 	}
756*10465441SEvalZero 
757*10465441SEvalZero 	// delete files if pass the test
758*10465441SEvalZero 	for (i = 0; succ && i < count; i++) {
759*10465441SEvalZero 		sprintf(name, "%sFile%03d", start, i);
760*10465441SEvalZero 		if (uffs_remove(name) < 0) {
761*10465441SEvalZero 			MSGLN("Delete file %s failed", name);
762*10465441SEvalZero 			succ = U_FALSE;
763*10465441SEvalZero 		}
764*10465441SEvalZero 	}
765*10465441SEvalZero 
766*10465441SEvalZero ext:
767*10465441SEvalZero 	MSGLN("Populate files test %s !", succ ? "SUCC" : "FAILED");
768*10465441SEvalZero 	return succ ? 0 : -1;
769*10465441SEvalZero 
770*10465441SEvalZero }
771*10465441SEvalZero 
772*10465441SEvalZero /**
773*10465441SEvalZero  * Open <file> with <oflag>, save fd to $1
774*10465441SEvalZero  *
775*10465441SEvalZero  *		t_open <oflag> <file>
776*10465441SEvalZero  */
cmd_topen(int argc,char * argv[])777*10465441SEvalZero static int cmd_topen(int argc, char *argv[])
778*10465441SEvalZero {
779*10465441SEvalZero 	int fd;
780*10465441SEvalZero 	const char *name;
781*10465441SEvalZero 	char *p;
782*10465441SEvalZero 	int oflag = 0;
783*10465441SEvalZero 
784*10465441SEvalZero 	CHK_ARGC(3, 3);
785*10465441SEvalZero 
786*10465441SEvalZero 	name = argv[2];
787*10465441SEvalZero 	p = argv[1];
788*10465441SEvalZero 	while(*p) {
789*10465441SEvalZero 		switch(*p++) {
790*10465441SEvalZero 		case 'a':
791*10465441SEvalZero 			oflag |= UO_APPEND;
792*10465441SEvalZero 			break;
793*10465441SEvalZero 		case 'c':
794*10465441SEvalZero 			oflag |= UO_CREATE;
795*10465441SEvalZero 			break;
796*10465441SEvalZero 		case 't':
797*10465441SEvalZero 			oflag |= UO_TRUNC;
798*10465441SEvalZero 			break;
799*10465441SEvalZero 		case 'w':
800*10465441SEvalZero 			oflag |= UO_RDWR;
801*10465441SEvalZero 			break;
802*10465441SEvalZero 		case 'r':
803*10465441SEvalZero 			oflag |= UO_RDONLY;
804*10465441SEvalZero 			break;
805*10465441SEvalZero 		}
806*10465441SEvalZero 	}
807*10465441SEvalZero 
808*10465441SEvalZero 	fd = uffs_open(name, oflag);
809*10465441SEvalZero 
810*10465441SEvalZero 	if (fd >= 0) {
811*10465441SEvalZero 		cli_env_set('1', fd);
812*10465441SEvalZero 		return 0;
813*10465441SEvalZero 	}
814*10465441SEvalZero 	else {
815*10465441SEvalZero 		return -1;
816*10465441SEvalZero 	}
817*10465441SEvalZero }
818*10465441SEvalZero 
819*10465441SEvalZero /**
820*10465441SEvalZero  * seek file pointer
821*10465441SEvalZero  *	t_seek <fd> <offset> [<origin>]
822*10465441SEvalZero  * if success, $1 = file position after seek
823*10465441SEvalZero  */
cmd_tseek(int argc,char * argv[])824*10465441SEvalZero static int cmd_tseek(int argc, char *argv[])
825*10465441SEvalZero {
826*10465441SEvalZero 	int origin = USEEK_SET;
827*10465441SEvalZero 	int offset;
828*10465441SEvalZero 	int fd;
829*10465441SEvalZero 	int ret;
830*10465441SEvalZero 
831*10465441SEvalZero 	CHK_ARGC(3, 4);
832*10465441SEvalZero 
833*10465441SEvalZero 	if (sscanf(argv[1], "%d", &fd) != 1 ||
834*10465441SEvalZero 		sscanf(argv[2], "%d", &offset) != 1)
835*10465441SEvalZero 	{
836*10465441SEvalZero 		return CLI_INVALID_ARG;
837*10465441SEvalZero 	}
838*10465441SEvalZero 
839*10465441SEvalZero 	if (argc > 3) {
840*10465441SEvalZero 		switch(argv[3][0]) {
841*10465441SEvalZero 		case 's':
842*10465441SEvalZero 			origin = USEEK_SET;
843*10465441SEvalZero 			break;
844*10465441SEvalZero 		case 'c':
845*10465441SEvalZero 			origin = USEEK_CUR;
846*10465441SEvalZero 			break;
847*10465441SEvalZero 		case 'e':
848*10465441SEvalZero 			origin = USEEK_END;
849*10465441SEvalZero 			break;
850*10465441SEvalZero 		default:
851*10465441SEvalZero 			return CLI_INVALID_ARG;
852*10465441SEvalZero 		}
853*10465441SEvalZero 	}
854*10465441SEvalZero 
855*10465441SEvalZero 	ret = uffs_seek(fd, offset, origin);
856*10465441SEvalZero 	if (ret >= 0) {
857*10465441SEvalZero 		cli_env_set('1', ret);
858*10465441SEvalZero 		return 0;
859*10465441SEvalZero 	}
860*10465441SEvalZero 	else {
861*10465441SEvalZero 		return -1;
862*10465441SEvalZero 	}
863*10465441SEvalZero }
864*10465441SEvalZero 
865*10465441SEvalZero /**
866*10465441SEvalZero  * close file
867*10465441SEvalZero  *	t_close <fd>
868*10465441SEvalZero  */
cmd_tclose(int argc,char * argv[])869*10465441SEvalZero static int cmd_tclose(int argc, char *argv[])
870*10465441SEvalZero {
871*10465441SEvalZero 	int fd;
872*10465441SEvalZero 
873*10465441SEvalZero 	CHK_ARGC(2, 2);
874*10465441SEvalZero 
875*10465441SEvalZero 	if (sscanf(argv[1], "%d", &fd) == 1) {
876*10465441SEvalZero 		return uffs_close(fd);
877*10465441SEvalZero 	}
878*10465441SEvalZero 	else
879*10465441SEvalZero 		return -1;
880*10465441SEvalZero }
881*10465441SEvalZero 
882*10465441SEvalZero /**
883*10465441SEvalZero  * write file
884*10465441SEvalZero  *	t_write <fd> <txt> [..]
885*10465441SEvalZero  */
cmd_twrite(int argc,char * argv[])886*10465441SEvalZero static int cmd_twrite(int argc, char *argv[])
887*10465441SEvalZero {
888*10465441SEvalZero 	int fd;
889*10465441SEvalZero 	int i, len = 0;
890*10465441SEvalZero 	int ret = 0;
891*10465441SEvalZero 
892*10465441SEvalZero 	CHK_ARGC(3, 0);
893*10465441SEvalZero 	if (sscanf(argv[1], "%d", &fd) != 1) {
894*10465441SEvalZero 		return -1;
895*10465441SEvalZero 	}
896*10465441SEvalZero 	else {
897*10465441SEvalZero 		for (i = 2; i < argc; i++) {
898*10465441SEvalZero 			len = strlen(argv[i]);
899*10465441SEvalZero 			if (uffs_write(fd, argv[i], len) != len) {
900*10465441SEvalZero 				ret = -1;
901*10465441SEvalZero 				break;
902*10465441SEvalZero 			}
903*10465441SEvalZero 		}
904*10465441SEvalZero 	}
905*10465441SEvalZero 
906*10465441SEvalZero 	if (ret == 0)
907*10465441SEvalZero 		cli_env_set('1', len);
908*10465441SEvalZero 
909*10465441SEvalZero 	return ret;
910*10465441SEvalZero }
911*10465441SEvalZero 
912*10465441SEvalZero /**
913*10465441SEvalZero  * read and check seq file
914*10465441SEvalZero  *	t_check_seq <fd> <size>
915*10465441SEvalZero  */
cmd_tcheck_seq(int argc,char * argv[])916*10465441SEvalZero static int cmd_tcheck_seq(int argc, char *argv[])
917*10465441SEvalZero {
918*10465441SEvalZero 	int fd;
919*10465441SEvalZero 	int len, size;
920*10465441SEvalZero 	int ret = 0, r_ret = 0;
921*10465441SEvalZero 	long pos;
922*10465441SEvalZero 	u8 buf[MAX_TEST_BUF_LEN];
923*10465441SEvalZero 	int i;
924*10465441SEvalZero 	u8 x;
925*10465441SEvalZero 
926*10465441SEvalZero 	CHK_ARGC(3, 3);
927*10465441SEvalZero 
928*10465441SEvalZero 	if (sscanf(argv[1], "%d", &fd) != 1) {
929*10465441SEvalZero 		return -1;
930*10465441SEvalZero 	}
931*10465441SEvalZero 
932*10465441SEvalZero 	if (sscanf(argv[2], "%d", &len) != 1) {
933*10465441SEvalZero 		return -1;
934*10465441SEvalZero 	}
935*10465441SEvalZero 
936*10465441SEvalZero 	pos = uffs_tell(fd);
937*10465441SEvalZero 	while (len > 0) {
938*10465441SEvalZero 		size = (len > sizeof(buf) ? sizeof(buf) : len);
939*10465441SEvalZero 		if ((r_ret = uffs_read(fd, buf, size)) < 0) {
940*10465441SEvalZero 			MSGLN("Read fail! fd = %d, size = %d, pos = %ld", fd, size, pos);
941*10465441SEvalZero 			ret = -1;
942*10465441SEvalZero 			break;
943*10465441SEvalZero 		}
944*10465441SEvalZero 
945*10465441SEvalZero 		// check seq
946*10465441SEvalZero 		for (i = 0; i < r_ret; i++) {
947*10465441SEvalZero 			x = (pos + SEQ_INIT + i) % SEQ_MOD_LEN;
948*10465441SEvalZero 			if (buf[i] != x) {
949*10465441SEvalZero 				MSGLN("Check fail! fd = %d, pos = %ld (expect 0x%02x but 0x%02x)\n", fd, pos + i, x, buf[i]);
950*10465441SEvalZero 				ret = -1;
951*10465441SEvalZero 				break;
952*10465441SEvalZero 			}
953*10465441SEvalZero 		}
954*10465441SEvalZero 
955*10465441SEvalZero 		if (ret < 0)
956*10465441SEvalZero 			break;
957*10465441SEvalZero 
958*10465441SEvalZero 		len -= r_ret;
959*10465441SEvalZero 		pos += r_ret;
960*10465441SEvalZero 	}
961*10465441SEvalZero 
962*10465441SEvalZero 	return ret;
963*10465441SEvalZero }
964*10465441SEvalZero 
965*10465441SEvalZero 
966*10465441SEvalZero 
967*10465441SEvalZero /**
968*10465441SEvalZero  * write random seq to file
969*10465441SEvalZero  *	t_write_seq <fd> <size>
970*10465441SEvalZero  */
cmd_twrite_seq(int argc,char * argv[])971*10465441SEvalZero static int cmd_twrite_seq(int argc, char *argv[])
972*10465441SEvalZero {
973*10465441SEvalZero 	int fd;
974*10465441SEvalZero 	int len = 0, size = 0;
975*10465441SEvalZero 	long pos = 0;
976*10465441SEvalZero 	int ret = 0, w_ret = 0;
977*10465441SEvalZero 	u8 buf[MAX_TEST_BUF_LEN];
978*10465441SEvalZero 
979*10465441SEvalZero 	CHK_ARGC(3, 3);
980*10465441SEvalZero 	if (sscanf(argv[1], "%d", &fd) != 1) {
981*10465441SEvalZero 		return -1;
982*10465441SEvalZero 	}
983*10465441SEvalZero 
984*10465441SEvalZero 	if (sscanf(argv[2], "%d", &len) != 1) {
985*10465441SEvalZero 		return -1;
986*10465441SEvalZero 	}
987*10465441SEvalZero 
988*10465441SEvalZero 	pos = uffs_tell(fd);
989*10465441SEvalZero 	while (len > 0) {
990*10465441SEvalZero 		size = (len < sizeof(buf) ? len : sizeof(buf));
991*10465441SEvalZero 		memcp_seq(buf, size, pos);
992*10465441SEvalZero 		if ((w_ret = uffs_write(fd, buf, size)) < 0) {
993*10465441SEvalZero 			MSGLN("write fail! fd = %d, size = %d, pos = %ld", fd, size, pos);
994*10465441SEvalZero 			ret = -1;
995*10465441SEvalZero 			break;
996*10465441SEvalZero 		}
997*10465441SEvalZero 		pos += w_ret;
998*10465441SEvalZero 		len -= w_ret;
999*10465441SEvalZero 	}
1000*10465441SEvalZero 
1001*10465441SEvalZero 	if (ret == 0)
1002*10465441SEvalZero 		cli_env_set('1', len);
1003*10465441SEvalZero 
1004*10465441SEvalZero 	return ret;
1005*10465441SEvalZero }
1006*10465441SEvalZero 
1007*10465441SEvalZero 
1008*10465441SEvalZero /**
1009*10465441SEvalZero  * read and check file
1010*10465441SEvalZero  *	t_read <fd> <txt>
1011*10465441SEvalZero  */
cmd_tread(int argc,char * argv[])1012*10465441SEvalZero static int cmd_tread(int argc, char *argv[])
1013*10465441SEvalZero {
1014*10465441SEvalZero 	int fd;
1015*10465441SEvalZero 	int len, n;
1016*10465441SEvalZero 	int ret = 0;
1017*10465441SEvalZero 	char buf[64];
1018*10465441SEvalZero 	char *p;
1019*10465441SEvalZero 
1020*10465441SEvalZero 	CHK_ARGC(3, 3);
1021*10465441SEvalZero 
1022*10465441SEvalZero 	if (sscanf(argv[1], "%d", &fd) != 1) {
1023*10465441SEvalZero 		return -1;
1024*10465441SEvalZero 	}
1025*10465441SEvalZero 	else {
1026*10465441SEvalZero 		len = strlen(argv[2]);
1027*10465441SEvalZero 		n = 0;
1028*10465441SEvalZero 		p = argv[2];
1029*10465441SEvalZero 		while (n < len) {
1030*10465441SEvalZero 			n = (len > sizeof(buf) ? sizeof(buf) : len);
1031*10465441SEvalZero 			if (uffs_read(fd, buf, n) != n ||
1032*10465441SEvalZero 				memcmp(buf, p, n) != 0) {
1033*10465441SEvalZero 				ret = -1;
1034*10465441SEvalZero 				break;
1035*10465441SEvalZero 			}
1036*10465441SEvalZero 			len -= n;
1037*10465441SEvalZero 			p += n;
1038*10465441SEvalZero 		}
1039*10465441SEvalZero 	}
1040*10465441SEvalZero 
1041*10465441SEvalZero 	return ret;
1042*10465441SEvalZero }
1043*10465441SEvalZero 
1044*10465441SEvalZero 
do_dump_page(uffs_Device * dev,uffs_Buf * buf)1045*10465441SEvalZero static void do_dump_page(uffs_Device *dev, uffs_Buf *buf)
1046*10465441SEvalZero {
1047*10465441SEvalZero 	int i, j;
1048*10465441SEvalZero 	const int line = 16;
1049*10465441SEvalZero 	struct uffs_MiniHeaderSt *header = (struct uffs_MiniHeaderSt *)buf->header;
1050*10465441SEvalZero 	MSG("  header.status = %d\n", header->status);
1051*10465441SEvalZero 	if (header->status != 0xFF) {
1052*10465441SEvalZero 		for (i = 0; i < 64; i += line) {
1053*10465441SEvalZero 			MSG("    ");
1054*10465441SEvalZero 			for (j = 0; j < line; j++)
1055*10465441SEvalZero 				MSG("%02X ", buf->header[i+j]);
1056*10465441SEvalZero 			MSG("\n");
1057*10465441SEvalZero 		}
1058*10465441SEvalZero 		MSG("\n");
1059*10465441SEvalZero 	}
1060*10465441SEvalZero }
1061*10465441SEvalZero 
do_dump_tag(uffs_Device * dev,uffs_Tags * tag)1062*10465441SEvalZero static void do_dump_tag(uffs_Device *dev, uffs_Tags *tag)
1063*10465441SEvalZero {
1064*10465441SEvalZero 	MSG("  tag sealed: %s\n", TAG_IS_SEALED(tag) ? "yes" : "no");
1065*10465441SEvalZero 	if (TAG_IS_GOOD(tag)) {
1066*10465441SEvalZero 		if (TAG_IS_DIRTY(tag)) {
1067*10465441SEvalZero 			MSG("    block_ts = %d\n", tag->s.block_ts);
1068*10465441SEvalZero 			MSG("    type = %d\n", tag->s.type);
1069*10465441SEvalZero 			MSG("    dirty = %d\n", tag->s.dirty);
1070*10465441SEvalZero 			MSG("    page_id = %d\n", tag->s.page_id);
1071*10465441SEvalZero 			MSG("    serial = %d\n", tag->s.serial);
1072*10465441SEvalZero 			MSG("    parent = %d\n", tag->s.parent);
1073*10465441SEvalZero 			MSG("    data_len = %d\n", tag->s.data_len);
1074*10465441SEvalZero 		}
1075*10465441SEvalZero 		else {
1076*10465441SEvalZero 			MSG("  tag is GOOD but NOT DIRTY !!!???\n");
1077*10465441SEvalZero 		}
1078*10465441SEvalZero 	}
1079*10465441SEvalZero 	else if (TAG_IS_SEALED(tag)) {
1080*10465441SEvalZero 		MSG(" tag is INVALID\n");
1081*10465441SEvalZero 	}
1082*10465441SEvalZero }
1083*10465441SEvalZero 
do_dump_device(uffs_Device * dev)1084*10465441SEvalZero static void do_dump_device(uffs_Device *dev)
1085*10465441SEvalZero {
1086*10465441SEvalZero 	URET ret;
1087*10465441SEvalZero 	int block, page;
1088*10465441SEvalZero 	uffs_Tags tag;
1089*10465441SEvalZero 	uffs_Buf *buf;
1090*10465441SEvalZero 
1091*10465441SEvalZero 	buf = uffs_BufClone(dev, NULL);
1092*10465441SEvalZero 	if (buf == NULL) {
1093*10465441SEvalZero 		MSGLN("Can't clone buf");
1094*10465441SEvalZero 		return;
1095*10465441SEvalZero 	}
1096*10465441SEvalZero 
1097*10465441SEvalZero 	for (block = dev->par.start; block <= dev->par.end; block++) {
1098*10465441SEvalZero 		MSG("---- block %d ----\n", block);
1099*10465441SEvalZero 		for (page = 0; page < dev->attr->pages_per_block; page++) {
1100*10465441SEvalZero 			MSG("  == page %d ==\n", page);
1101*10465441SEvalZero 			ret = uffs_FlashReadPage(dev, block, page, buf, U_FALSE);
1102*10465441SEvalZero 			if (UFFS_FLASH_HAVE_ERR(ret)) {
1103*10465441SEvalZero 				MSG(" !!! Read page failed, ret = %d !!!\n", ret);
1104*10465441SEvalZero 			}
1105*10465441SEvalZero 			else {
1106*10465441SEvalZero 				do_dump_page(dev, buf);
1107*10465441SEvalZero 				if (buf->header[0] != 0xFF) {
1108*10465441SEvalZero 					ret = uffs_FlashReadPageTag(dev, block, page, &tag);
1109*10465441SEvalZero 					if (UFFS_FLASH_HAVE_ERR(ret)) {
1110*10465441SEvalZero 						MSG(" !!! Read TAG failed, ret = %d !!!\n", ret);
1111*10465441SEvalZero 					}
1112*10465441SEvalZero 					else {
1113*10465441SEvalZero 						do_dump_tag(dev, &tag);
1114*10465441SEvalZero 					}
1115*10465441SEvalZero 				}
1116*10465441SEvalZero 			}
1117*10465441SEvalZero 		}
1118*10465441SEvalZero 	}
1119*10465441SEvalZero 	uffs_BufFreeClone(dev, buf);
1120*10465441SEvalZero }
1121*10465441SEvalZero 
cmd_dump(int argc,char * argv[])1122*10465441SEvalZero static int cmd_dump(int argc, char *argv[])
1123*10465441SEvalZero {
1124*10465441SEvalZero 	const char *mount = "/";
1125*10465441SEvalZero 	uffs_Device *dev;
1126*10465441SEvalZero 
1127*10465441SEvalZero 	if (argc > 1) {
1128*10465441SEvalZero 		mount = argv[1];
1129*10465441SEvalZero 	}
1130*10465441SEvalZero 
1131*10465441SEvalZero 	MSGLN("Dumping %s ... ", mount);
1132*10465441SEvalZero 
1133*10465441SEvalZero 	dev = uffs_GetDeviceFromMountPoint(mount);
1134*10465441SEvalZero 	if (dev == NULL) {
1135*10465441SEvalZero 		MSGLN("Can't get device from mount point.");
1136*10465441SEvalZero 	}
1137*10465441SEvalZero 	else {
1138*10465441SEvalZero 		do_dump_device(dev);
1139*10465441SEvalZero 		uffs_PutDevice(dev);
1140*10465441SEvalZero 	}
1141*10465441SEvalZero 
1142*10465441SEvalZero 	return 0;
1143*10465441SEvalZero }
1144*10465441SEvalZero 
cmd_apisrv(int argc,char * argv[])1145*10465441SEvalZero static int cmd_apisrv(int argc, char *argv[])
1146*10465441SEvalZero {
1147*10465441SEvalZero 	return api_server_start();
1148*10465441SEvalZero }
1149*10465441SEvalZero 
1150*10465441SEvalZero static const struct cli_command test_cmds[] =
1151*10465441SEvalZero {
1152*10465441SEvalZero     { cmd_t1,					"t1",			"<name>",			"test 1" },
1153*10465441SEvalZero     { cmd_t2,					"t2",			NULL,				"test 2" },
1154*10465441SEvalZero     { cmd_t3,					"t3",			"<name> [<noecc>]",	"test 3" },
1155*10465441SEvalZero     { cmd_t4,					"t4",			NULL,				"test 4" },
1156*10465441SEvalZero     { cmd_t5,					"t5",			"<name>",			"test 5" },
1157*10465441SEvalZero     { cmd_TestPageReadWrite,	"t_pgrw",		NULL,				"test page read/write" },
1158*10465441SEvalZero     { cmd_TestFormat,			"t_format",		NULL,				"test format file system" },
1159*10465441SEvalZero 	{ cmd_TestPopulateFiles,	"t_pfs",		"[<start> [<n>]]",	"test populate <n> files under <start>" },
1160*10465441SEvalZero 	{ cmd_VerifyFile,			"t_vf",			"<file> [<noecc>]", "verify file" },
1161*10465441SEvalZero 
1162*10465441SEvalZero 	{ cmd_topen,				"t_open",		"<oflg> <file>",	"open file, fd save to $1", },
1163*10465441SEvalZero 	{ cmd_tread,				"t_read",		"<fd> <txt>",		"read <fd> and check against <txt>", },
1164*10465441SEvalZero 	{ cmd_tcheck_seq,			"t_check_seq",	"<fd> <size>",		"read seq file <fd> and check", },
1165*10465441SEvalZero 	{ cmd_twrite,				"t_write",		"<fd> <txt> [...]",	"write <fd>", },
1166*10465441SEvalZero 	{ cmd_twrite_seq,			"t_write_seq",	"<fd> <size>",	"write seq file <fd>", },
1167*10465441SEvalZero 	{ cmd_tseek,				"t_seek",		"<fd> <offset> [<origin>]",	"seek <fd> file pointer to <offset> from <origin>", },
1168*10465441SEvalZero 	{ cmd_tclose,				"t_close",		"<fd>",				"close <fd>", },
1169*10465441SEvalZero 	{ cmd_dump,					"dump",			"<mount>",			"dump <mount>", },
1170*10465441SEvalZero 
1171*10465441SEvalZero 	{ cmd_apisrv,				"apisrv",		NULL,				"start API test server", },
1172*10465441SEvalZero 
1173*10465441SEvalZero     { NULL, NULL, NULL, NULL }
1174*10465441SEvalZero };
1175*10465441SEvalZero 
1176*10465441SEvalZero static struct cli_commandset test_cmdset = {
1177*10465441SEvalZero 	test_cmds,
1178*10465441SEvalZero };
1179*10465441SEvalZero 
get_test_cmds()1180*10465441SEvalZero struct cli_commandset * get_test_cmds()
1181*10465441SEvalZero {
1182*10465441SEvalZero 	return &test_cmdset;
1183*10465441SEvalZero };
1184*10465441SEvalZero 
1185*10465441SEvalZero 
1186*10465441SEvalZero 
1187