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