xref: /nrf52832-nimble/rt-thread/components/dfs/filesystems/uffs/src/emu/helper_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 helper_cmds.c
35*10465441SEvalZero  * \brief helper commands for test uffs
36*10465441SEvalZero  * \author Ricky Zheng
37*10465441SEvalZero  */
38*10465441SEvalZero #include <stdio.h>
39*10465441SEvalZero #include <string.h>
40*10465441SEvalZero #include <stdarg.h>
41*10465441SEvalZero #include <stdlib.h>
42*10465441SEvalZero #include "uffs_config.h"
43*10465441SEvalZero #include "uffs/uffs_public.h"
44*10465441SEvalZero #include "uffs/uffs_fs.h"
45*10465441SEvalZero #include "uffs/uffs_utils.h"
46*10465441SEvalZero #include "uffs/uffs_core.h"
47*10465441SEvalZero #include "uffs/uffs_mtb.h"
48*10465441SEvalZero #include "uffs/uffs_find.h"
49*10465441SEvalZero #include "cmdline.h"
50*10465441SEvalZero #include "uffs/uffs_fd.h"
51*10465441SEvalZero #include "uffs/uffs_mtb.h"
52*10465441SEvalZero #include "uffs_fileem.h"
53*10465441SEvalZero 
54*10465441SEvalZero #define PFX "cmd : "
55*10465441SEvalZero 
56*10465441SEvalZero #define MAX_PATH_LENGTH 128
57*10465441SEvalZero 
58*10465441SEvalZero #define MSGLN(msg,...) uffs_Perror(UFFS_MSG_NORMAL, msg, ## __VA_ARGS__)
59*10465441SEvalZero #define MSG(msg,...) uffs_PerrorRaw(UFFS_MSG_NORMAL, msg, ## __VA_ARGS__)
60*10465441SEvalZero 
61*10465441SEvalZero /** format [<mount>] */
cmd_format(int argc,char * argv[])62*10465441SEvalZero static int cmd_format(int argc, char *argv[])
63*10465441SEvalZero {
64*10465441SEvalZero 	URET ret;
65*10465441SEvalZero 	const char *mount = "/";
66*10465441SEvalZero 	uffs_Device *dev;
67*10465441SEvalZero 	UBOOL force = U_FALSE;
68*10465441SEvalZero 
69*10465441SEvalZero 	if (argc > 1) {
70*10465441SEvalZero 		mount = argv[1];
71*10465441SEvalZero 		if (argc > 2 && strcmp(argv[2], "-f") == 0)
72*10465441SEvalZero 			force = U_TRUE;
73*10465441SEvalZero 	}
74*10465441SEvalZero 	MSGLN("Formating %s ... ", mount);
75*10465441SEvalZero 
76*10465441SEvalZero 	dev = uffs_GetDeviceFromMountPoint(mount);
77*10465441SEvalZero 	if (dev == NULL) {
78*10465441SEvalZero 		MSGLN("Can't get device from mount point.");
79*10465441SEvalZero 		return -1;
80*10465441SEvalZero 	}
81*10465441SEvalZero 	else {
82*10465441SEvalZero 		ret = uffs_FormatDevice(dev, force);
83*10465441SEvalZero 		if (ret != U_SUCC) {
84*10465441SEvalZero 			MSGLN("Format fail.");
85*10465441SEvalZero 			return -1;
86*10465441SEvalZero 		}
87*10465441SEvalZero 		else {
88*10465441SEvalZero 			MSGLN("Format succ.");
89*10465441SEvalZero 		}
90*10465441SEvalZero 		uffs_PutDevice(dev);
91*10465441SEvalZero 	}
92*10465441SEvalZero 
93*10465441SEvalZero 	return 0;
94*10465441SEvalZero }
95*10465441SEvalZero 
96*10465441SEvalZero /** mkf <file> */
cmd_mkf(int argc,char * argv[])97*10465441SEvalZero static int cmd_mkf(int argc, char *argv[])
98*10465441SEvalZero {
99*10465441SEvalZero 	int fd;
100*10465441SEvalZero 	const char *name;
101*10465441SEvalZero 	int oflags = UO_RDWR | UO_CREATE;
102*10465441SEvalZero 
103*10465441SEvalZero 	CHK_ARGC(2, 2);
104*10465441SEvalZero 
105*10465441SEvalZero 	name = argv[1];
106*10465441SEvalZero 	fd = uffs_open(name, oflags);
107*10465441SEvalZero 	if (fd < 0) {
108*10465441SEvalZero 		MSGLN("Create %s fail, err: %d", name, uffs_get_error());
109*10465441SEvalZero 		return -1;
110*10465441SEvalZero 	}
111*10465441SEvalZero 	else {
112*10465441SEvalZero 		MSGLN("Create %s succ.", name);
113*10465441SEvalZero 		uffs_close(fd);
114*10465441SEvalZero 	}
115*10465441SEvalZero 
116*10465441SEvalZero 	return 0;
117*10465441SEvalZero }
118*10465441SEvalZero 
119*10465441SEvalZero /** mkdir <dir> */
cmd_mkdir(int argc,char * argv[])120*10465441SEvalZero static int cmd_mkdir(int argc, char *argv[])
121*10465441SEvalZero {
122*10465441SEvalZero 	const char *name;
123*10465441SEvalZero 
124*10465441SEvalZero 	CHK_ARGC(2, 0);
125*10465441SEvalZero 
126*10465441SEvalZero 	name = argv[1];
127*10465441SEvalZero 
128*10465441SEvalZero 	if (uffs_mkdir(name) < 0) {
129*10465441SEvalZero 		MSGLN("Create %s fail, err: %d", name, uffs_get_error());
130*10465441SEvalZero 		return -1;
131*10465441SEvalZero 	}
132*10465441SEvalZero 	else {
133*10465441SEvalZero 		MSGLN("Create %s succ.", name);
134*10465441SEvalZero 	}
135*10465441SEvalZero 
136*10465441SEvalZero 	return 0;
137*10465441SEvalZero }
138*10465441SEvalZero 
139*10465441SEvalZero 
CountObjectUnder(const char * dir)140*10465441SEvalZero static int CountObjectUnder(const char *dir)
141*10465441SEvalZero {
142*10465441SEvalZero 	int count = 0;
143*10465441SEvalZero 	uffs_DIR *dirp;
144*10465441SEvalZero 
145*10465441SEvalZero 	dirp = uffs_opendir(dir);
146*10465441SEvalZero 	if (dirp) {
147*10465441SEvalZero 		while (uffs_readdir(dirp) != NULL)
148*10465441SEvalZero 			count++;
149*10465441SEvalZero 		uffs_closedir(dirp);
150*10465441SEvalZero 	}
151*10465441SEvalZero 	return count;
152*10465441SEvalZero }
153*10465441SEvalZero 
cmd_pwd(int argc,char * argv[])154*10465441SEvalZero static int cmd_pwd(int argc, char *argv[])
155*10465441SEvalZero {
156*10465441SEvalZero 	MSGLN("not supported.");
157*10465441SEvalZero 	return 0;
158*10465441SEvalZero }
159*10465441SEvalZero 
cmd_cd(int argc,char * argv[])160*10465441SEvalZero static int cmd_cd(int argc, char *argv[])
161*10465441SEvalZero {
162*10465441SEvalZero 	MSGLN("Not supported");
163*10465441SEvalZero 	return 0;
164*10465441SEvalZero }
165*10465441SEvalZero 
166*10465441SEvalZero /** ls [<dir>] */
cmd_ls(int argc,char * argv[])167*10465441SEvalZero static int cmd_ls(int argc, char *argv[])
168*10465441SEvalZero {
169*10465441SEvalZero 	uffs_DIR *dirp;
170*10465441SEvalZero 	struct uffs_dirent *ent;
171*10465441SEvalZero 	struct uffs_stat stat_buf;
172*10465441SEvalZero 	int count = 0;
173*10465441SEvalZero 	char buf[MAX_PATH_LENGTH+2];
174*10465441SEvalZero 	const char *name = "/";
175*10465441SEvalZero 	char *sub;
176*10465441SEvalZero 	int ret = 0;
177*10465441SEvalZero 
178*10465441SEvalZero 	CHK_ARGC(1, 2);
179*10465441SEvalZero 
180*10465441SEvalZero 	if (argc > 1)
181*10465441SEvalZero 		name = argv[1];
182*10465441SEvalZero 
183*10465441SEvalZero 	dirp = uffs_opendir(name);
184*10465441SEvalZero 	if (dirp == NULL) {
185*10465441SEvalZero 		MSGLN("Can't open '%s' for list", name);
186*10465441SEvalZero 		ret = -1;
187*10465441SEvalZero 	}
188*10465441SEvalZero 	else {
189*10465441SEvalZero 		MSG("------name-----------size---------serial-----" TENDSTR);
190*10465441SEvalZero 		ent = uffs_readdir(dirp);
191*10465441SEvalZero 		while (ent) {
192*10465441SEvalZero 			MSG("%9s", ent->d_name);
193*10465441SEvalZero 			strcpy(buf, name);
194*10465441SEvalZero 			sub = buf;
195*10465441SEvalZero 			if (name[strlen(name)-1] != '/')
196*10465441SEvalZero 				sub = strcat(buf, "/");
197*10465441SEvalZero 			sub = strcat(sub, ent->d_name);
198*10465441SEvalZero 			if (ent->d_type & FILE_ATTR_DIR) {
199*10465441SEvalZero 				sub = strcat(sub, "/");
200*10465441SEvalZero 				MSG("/  \t<%8d>", CountObjectUnder(sub));
201*10465441SEvalZero 			}
202*10465441SEvalZero 			else {
203*10465441SEvalZero 				uffs_stat(sub, &stat_buf);
204*10465441SEvalZero 				MSG("   \t %8d ", stat_buf.st_size);
205*10465441SEvalZero 			}
206*10465441SEvalZero 			MSG("\t%6d" TENDSTR, ent->d_ino);
207*10465441SEvalZero 			count++;
208*10465441SEvalZero 			ent = uffs_readdir(dirp);
209*10465441SEvalZero 		}
210*10465441SEvalZero 
211*10465441SEvalZero 		uffs_closedir(dirp);
212*10465441SEvalZero 
213*10465441SEvalZero 		MSG("Total: %d objects." TENDSTR, count);
214*10465441SEvalZero 	}
215*10465441SEvalZero 
216*10465441SEvalZero 	return ret;
217*10465441SEvalZero }
218*10465441SEvalZero 
219*10465441SEvalZero /** rm <obj> */
cmd_rm(int argc,char * argv[])220*10465441SEvalZero static int cmd_rm(int argc, char *argv[])
221*10465441SEvalZero {
222*10465441SEvalZero 	const char *name = NULL;
223*10465441SEvalZero 	int ret = 0;
224*10465441SEvalZero 	struct uffs_stat st;
225*10465441SEvalZero 
226*10465441SEvalZero 	CHK_ARGC(2, 2);
227*10465441SEvalZero 
228*10465441SEvalZero 	name = argv[1];
229*10465441SEvalZero 
230*10465441SEvalZero 	ret = uffs_stat(name, &st);
231*10465441SEvalZero 	if (ret < 0) {
232*10465441SEvalZero 		MSGLN("Can't stat '%s'", name);
233*10465441SEvalZero 		return ret;
234*10465441SEvalZero 	}
235*10465441SEvalZero 
236*10465441SEvalZero 	if (st.st_mode & US_IFDIR) {
237*10465441SEvalZero 		ret = uffs_rmdir(name);
238*10465441SEvalZero 	}
239*10465441SEvalZero 	else {
240*10465441SEvalZero 		ret = uffs_remove(name);
241*10465441SEvalZero 	}
242*10465441SEvalZero 
243*10465441SEvalZero 	if (ret == 0)
244*10465441SEvalZero 		MSGLN("Delete '%s' succ.", name);
245*10465441SEvalZero 	else
246*10465441SEvalZero 		MSGLN("Delete '%s' fail!", name);
247*10465441SEvalZero 
248*10465441SEvalZero 	return ret;
249*10465441SEvalZero }
250*10465441SEvalZero 
251*10465441SEvalZero /** ren|mv <old> <new> */
cmd_ren(int argc,char * argv[])252*10465441SEvalZero static int cmd_ren(int argc, char *argv[])
253*10465441SEvalZero {
254*10465441SEvalZero 	const char *oldname;
255*10465441SEvalZero 	const char *newname;
256*10465441SEvalZero 	int ret;
257*10465441SEvalZero 
258*10465441SEvalZero 	CHK_ARGC(3, 3);
259*10465441SEvalZero 
260*10465441SEvalZero 	oldname = argv[1];
261*10465441SEvalZero 	newname = argv[2];
262*10465441SEvalZero 
263*10465441SEvalZero 	if ((ret = uffs_rename(oldname, newname)) == 0) {
264*10465441SEvalZero 		MSGLN("Rename from '%s' to '%s' succ.", oldname, newname);
265*10465441SEvalZero 	}
266*10465441SEvalZero 	else {
267*10465441SEvalZero 		MSGLN("Rename from '%s' to '%s' fail!", oldname, newname);
268*10465441SEvalZero 	}
269*10465441SEvalZero 
270*10465441SEvalZero 	return ret;
271*10465441SEvalZero }
272*10465441SEvalZero 
dump_msg_to_stdout(struct uffs_DeviceSt * dev,const char * fmt,...)273*10465441SEvalZero static void dump_msg_to_stdout(struct uffs_DeviceSt *dev, const char *fmt, ...)
274*10465441SEvalZero {
275*10465441SEvalZero 	uffs_FileEmu *emu = (uffs_FileEmu *)(dev->attr->_private);
276*10465441SEvalZero 	va_list args;
277*10465441SEvalZero 
278*10465441SEvalZero 	va_start(args, fmt);
279*10465441SEvalZero 	//vprintf(fmt, args);
280*10465441SEvalZero 	if (emu && emu->dump_fp)
281*10465441SEvalZero 		vfprintf(emu->dump_fp, fmt, args);
282*10465441SEvalZero 	va_end(args);
283*10465441SEvalZero }
284*10465441SEvalZero 
285*10465441SEvalZero /** dump [<mount>] */
cmd_dump(int argc,char * argv[])286*10465441SEvalZero static int cmd_dump(int argc, char *argv[])
287*10465441SEvalZero {
288*10465441SEvalZero 	uffs_Device *dev;
289*10465441SEvalZero 	uffs_FileEmu *emu;
290*10465441SEvalZero 	const char *mount = "/";
291*10465441SEvalZero 	const char *dump_file = "dump.txt";
292*10465441SEvalZero 
293*10465441SEvalZero 	if (argc > 1) {
294*10465441SEvalZero 		mount = argv[1];
295*10465441SEvalZero 		if (argc > 2)
296*10465441SEvalZero 			dump_file = argv[2];
297*10465441SEvalZero 	}
298*10465441SEvalZero 
299*10465441SEvalZero 	dev = uffs_GetDeviceFromMountPoint(mount);
300*10465441SEvalZero 	if (dev == NULL) {
301*10465441SEvalZero 		MSGLN("Can't get device from mount point %s", mount);
302*10465441SEvalZero 		return -1;
303*10465441SEvalZero 	}
304*10465441SEvalZero 
305*10465441SEvalZero 	emu = (uffs_FileEmu *)(dev->attr->_private);
306*10465441SEvalZero 	emu->dump_fp = fopen(dump_file, "w");
307*10465441SEvalZero 
308*10465441SEvalZero 	uffs_DumpDevice(dev, dump_msg_to_stdout);
309*10465441SEvalZero 
310*10465441SEvalZero 	if (emu->dump_fp)
311*10465441SEvalZero 		fclose(emu->dump_fp);
312*10465441SEvalZero 
313*10465441SEvalZero 	uffs_PutDevice(dev);
314*10465441SEvalZero 
315*10465441SEvalZero 	return 0;
316*10465441SEvalZero }
317*10465441SEvalZero 
318*10465441SEvalZero /** st [<mount>] */
cmd_st(int argc,char * argv[])319*10465441SEvalZero static int cmd_st(int argc, char *argv[])
320*10465441SEvalZero {
321*10465441SEvalZero 	uffs_Device *dev;
322*10465441SEvalZero 	const char *mount = "/";
323*10465441SEvalZero 	uffs_FlashStat *s;
324*10465441SEvalZero 	TreeNode *node;
325*10465441SEvalZero 
326*10465441SEvalZero 	if (argc > 1) {
327*10465441SEvalZero 		mount = argv[1];
328*10465441SEvalZero 	}
329*10465441SEvalZero 
330*10465441SEvalZero 	dev = uffs_GetDeviceFromMountPoint(mount);
331*10465441SEvalZero 	if (dev == NULL) {
332*10465441SEvalZero 		MSGLN("Can't get device from mount point %s", mount);
333*10465441SEvalZero 		return -1;
334*10465441SEvalZero 	}
335*10465441SEvalZero 
336*10465441SEvalZero 	s = &(dev->st);
337*10465441SEvalZero 
338*10465441SEvalZero 	MSG("----------- basic info -----------" TENDSTR);
339*10465441SEvalZero 	MSG("TreeNode size:         %d" TENDSTR, sizeof(TreeNode));
340*10465441SEvalZero 	MSG("TagStore size:         %d" TENDSTR, sizeof(struct uffs_TagStoreSt));
341*10465441SEvalZero 	MSG("MaxCachedBlockInfo:    %d" TENDSTR, dev->cfg.bc_caches);
342*10465441SEvalZero 	MSG("MaxPageBuffers:        %d" TENDSTR, dev->cfg.page_buffers);
343*10465441SEvalZero 	MSG("MaxDirtyPagesPerBlock: %d" TENDSTR, dev->cfg.dirty_pages);
344*10465441SEvalZero 	MSG("MaxPathLength:         %d" TENDSTR, MAX_PATH_LENGTH);
345*10465441SEvalZero 	MSG("MaxObjectHandles:      %d" TENDSTR, MAX_OBJECT_HANDLE);
346*10465441SEvalZero 	MSG("FreeObjectHandles:     %d" TENDSTR, uffs_GetFreeObjectHandlers());
347*10465441SEvalZero 	MSG("MaxDirHandles:         %d" TENDSTR, MAX_DIR_HANDLE);
348*10465441SEvalZero 	MSG("FreeDirHandles:        %d" TENDSTR, uffs_PoolGetFreeCount(uffs_DirEntryBufGetPool()));
349*10465441SEvalZero 
350*10465441SEvalZero 	MSG("----------- statistics for '%s' -----------" TENDSTR, mount);
351*10465441SEvalZero 	MSG("Device Ref:            %d" TENDSTR, dev->ref_count);
352*10465441SEvalZero 	MSG("Block Erased:          %d" TENDSTR, s->block_erase_count);
353*10465441SEvalZero 	MSG("Write Page:            %d" TENDSTR, s->page_write_count);
354*10465441SEvalZero 	MSG("Write Spare:           %d" TENDSTR, s->spare_write_count);
355*10465441SEvalZero 	MSG("Read Page:             %d" TENDSTR, s->page_read_count - s->page_header_read_count);
356*10465441SEvalZero 	MSG("Read Header:           %d" TENDSTR, s->page_header_read_count);
357*10465441SEvalZero 	MSG("Read Spare:            %d" TENDSTR, s->spare_read_count);
358*10465441SEvalZero 	MSG("I/O Read:              %lu" TENDSTR, s->io_read);
359*10465441SEvalZero 	MSG("I/O Write:             %lu" TENDSTR, s->io_write);
360*10465441SEvalZero 
361*10465441SEvalZero 	MSG("--------- partition info for '%s' ---------" TENDSTR, mount);
362*10465441SEvalZero 	MSG("Space total:           %d" TENDSTR, uffs_GetDeviceTotal(dev));
363*10465441SEvalZero 	MSG("Space used:            %d" TENDSTR, uffs_GetDeviceUsed(dev));
364*10465441SEvalZero 	MSG("Space free:            %d" TENDSTR, uffs_GetDeviceFree(dev));
365*10465441SEvalZero 	MSG("Page Size:             %d" TENDSTR, dev->attr->page_data_size);
366*10465441SEvalZero 	MSG("Spare Size:            %d" TENDSTR, dev->attr->spare_size);
367*10465441SEvalZero 	MSG("Pages Per Block:       %d" TENDSTR, dev->attr->pages_per_block);
368*10465441SEvalZero 	MSG("Block size:            %d" TENDSTR, dev->attr->page_data_size * dev->attr->pages_per_block);
369*10465441SEvalZero 	MSG("Total blocks:          %d of %d" TENDSTR, (dev->par.end - dev->par.start + 1), dev->attr->total_blocks);
370*10465441SEvalZero 	if (dev->tree.bad) {
371*10465441SEvalZero 		MSG("Bad blocks: ");
372*10465441SEvalZero 		node = dev->tree.bad;
373*10465441SEvalZero 		while(node) {
374*10465441SEvalZero 			MSG("%d, ", node->u.list.block);
375*10465441SEvalZero 			node = node->u.list.next;
376*10465441SEvalZero 		}
377*10465441SEvalZero 		MSG(TENDSTR);
378*10465441SEvalZero 	}
379*10465441SEvalZero 
380*10465441SEvalZero 	uffs_PutDevice(dev);
381*10465441SEvalZero 
382*10465441SEvalZero 	return 0;
383*10465441SEvalZero 
384*10465441SEvalZero }
385*10465441SEvalZero 
386*10465441SEvalZero /** cp <src> <des> */
cmd_cp(int argc,char * argv[])387*10465441SEvalZero static int cmd_cp(int argc, char *argv[])
388*10465441SEvalZero {
389*10465441SEvalZero 	const char *src;
390*10465441SEvalZero 	const char *des;
391*10465441SEvalZero 	char buf[100];
392*10465441SEvalZero 	int fd1 = -1, fd2 = -1;
393*10465441SEvalZero 	int len;
394*10465441SEvalZero 	BOOL src_local = FALSE, des_local = FALSE;
395*10465441SEvalZero 	FILE *fp1 = NULL, *fp2 = NULL;
396*10465441SEvalZero 	int ret = -1;
397*10465441SEvalZero 
398*10465441SEvalZero 	CHK_ARGC(3, 3);
399*10465441SEvalZero 
400*10465441SEvalZero 	src = argv[1];
401*10465441SEvalZero 	des = argv[2];
402*10465441SEvalZero 
403*10465441SEvalZero 	if (memcmp(src, "::", 2) == 0) {
404*10465441SEvalZero 		src += 2;
405*10465441SEvalZero 		src_local = TRUE;
406*10465441SEvalZero 	}
407*10465441SEvalZero 	if (memcmp(des, "::", 2) == 0) {
408*10465441SEvalZero 		des += 2;
409*10465441SEvalZero 		des_local = TRUE;
410*10465441SEvalZero 	}
411*10465441SEvalZero 
412*10465441SEvalZero 	if (src_local) {
413*10465441SEvalZero 		if ((fp1 = fopen(src, "rb")) == NULL) {
414*10465441SEvalZero 			MSGLN("Can't open %s for copy.", src);
415*10465441SEvalZero 			goto fail_ext;
416*10465441SEvalZero 		}
417*10465441SEvalZero 	}
418*10465441SEvalZero 	else {
419*10465441SEvalZero 		if ((fd1 = uffs_open(src, UO_RDONLY)) < 0) {
420*10465441SEvalZero 			MSGLN("Can't open %s for copy.", src);
421*10465441SEvalZero 			goto fail_ext;
422*10465441SEvalZero 		}
423*10465441SEvalZero 	}
424*10465441SEvalZero 
425*10465441SEvalZero 	if (des_local) {
426*10465441SEvalZero 		if ((fp2 = fopen(des, "wb")) == NULL) {
427*10465441SEvalZero 			MSGLN("Can't open %s for copy.", des);
428*10465441SEvalZero 			goto fail_ext;
429*10465441SEvalZero 		}
430*10465441SEvalZero 	}
431*10465441SEvalZero 	else {
432*10465441SEvalZero 		if ((fd2 = uffs_open(des, UO_RDWR|UO_CREATE|UO_TRUNC)) < 0) {
433*10465441SEvalZero 			MSGLN("Can't open %s for copy.", des);
434*10465441SEvalZero 			goto fail_ext;
435*10465441SEvalZero 		}
436*10465441SEvalZero 	}
437*10465441SEvalZero 
438*10465441SEvalZero 	ret = 0;
439*10465441SEvalZero 	while (	(src_local ? (feof(fp1) == 0) : (uffs_eof(fd1) == 0)) ) {
440*10465441SEvalZero 		ret = -1;
441*10465441SEvalZero 		if (src_local) {
442*10465441SEvalZero 			len = fread(buf, 1, sizeof(buf), fp1);
443*10465441SEvalZero 		}
444*10465441SEvalZero 		else {
445*10465441SEvalZero 			len = uffs_read(fd1, buf, sizeof(buf));
446*10465441SEvalZero 		}
447*10465441SEvalZero 		if (len == 0) {
448*10465441SEvalZero 			ret = -1;
449*10465441SEvalZero 			break;
450*10465441SEvalZero 		}
451*10465441SEvalZero 		if (len < 0) {
452*10465441SEvalZero 			MSGLN("read file %s fail ?", src);
453*10465441SEvalZero 			break;
454*10465441SEvalZero 		}
455*10465441SEvalZero 		if (des_local) {
456*10465441SEvalZero 			if ((int)fwrite(buf, 1, len, fp2) != len) {
457*10465441SEvalZero 				MSGLN("write file %s fail ? ", des);
458*10465441SEvalZero 				break;
459*10465441SEvalZero 			}
460*10465441SEvalZero 		}
461*10465441SEvalZero 		else {
462*10465441SEvalZero 			if (uffs_write(fd2, buf, len) != len) {
463*10465441SEvalZero 				MSGLN("write file %s fail ? ", des);
464*10465441SEvalZero 				break;
465*10465441SEvalZero 			}
466*10465441SEvalZero 		}
467*10465441SEvalZero 		ret = 0;
468*10465441SEvalZero 	}
469*10465441SEvalZero 
470*10465441SEvalZero fail_ext:
471*10465441SEvalZero 	if (fd1 > 0)
472*10465441SEvalZero 		uffs_close(fd1);
473*10465441SEvalZero 	if (fd2 > 0)
474*10465441SEvalZero 		uffs_close(fd2);
475*10465441SEvalZero 	if (fp1)
476*10465441SEvalZero 		fclose(fp1);
477*10465441SEvalZero 	if (fp2)
478*10465441SEvalZero 		fclose(fp2);
479*10465441SEvalZero 
480*10465441SEvalZero 	return ret;
481*10465441SEvalZero }
482*10465441SEvalZero 
483*10465441SEvalZero /** cat <file> [<offset>] [<size>] */
cmd_cat(int argc,char * argv[])484*10465441SEvalZero static int cmd_cat(int argc, char *argv[])
485*10465441SEvalZero {
486*10465441SEvalZero 	int fd;
487*10465441SEvalZero 	const char *name = NULL;
488*10465441SEvalZero 	char buf[100];
489*10465441SEvalZero 	int start = 0, size = 0, printed = 0, n, len;
490*10465441SEvalZero 	int ret = -1;
491*10465441SEvalZero 
492*10465441SEvalZero 	CHK_ARGC(2, 4);
493*10465441SEvalZero 
494*10465441SEvalZero 	name = argv[1];
495*10465441SEvalZero 
496*10465441SEvalZero 	if ((fd = uffs_open(name, UO_RDONLY)) < 0) {
497*10465441SEvalZero 		MSGLN("Can't open %s", name);
498*10465441SEvalZero 		goto fail;
499*10465441SEvalZero 	}
500*10465441SEvalZero 
501*10465441SEvalZero 	if (argc > 2) {
502*10465441SEvalZero 		start = strtol(argv[2], NULL, 10);
503*10465441SEvalZero 		if (argc > 3) size = strtol(argv[3], NULL, 10);
504*10465441SEvalZero 	}
505*10465441SEvalZero 
506*10465441SEvalZero 	if (start >= 0)
507*10465441SEvalZero 		uffs_seek(fd, start, USEEK_SET);
508*10465441SEvalZero 	else
509*10465441SEvalZero 		uffs_seek(fd, -start, USEEK_END);
510*10465441SEvalZero 
511*10465441SEvalZero 	while (uffs_eof(fd) == 0) {
512*10465441SEvalZero 		len = uffs_read(fd, buf, sizeof(buf) - 1);
513*10465441SEvalZero 		if (len == 0)
514*10465441SEvalZero 			break;
515*10465441SEvalZero 		if (len > 0) {
516*10465441SEvalZero 			if (size == 0 || printed < size) {
517*10465441SEvalZero 				n = (size == 0 ? len : (size - printed > len ? len : size - printed));
518*10465441SEvalZero 				buf[n] = 0;
519*10465441SEvalZero 				MSG("%s", buf);
520*10465441SEvalZero 				printed += n;
521*10465441SEvalZero 			}
522*10465441SEvalZero 			else {
523*10465441SEvalZero 				break;
524*10465441SEvalZero 			}
525*10465441SEvalZero 		}
526*10465441SEvalZero 	}
527*10465441SEvalZero 	MSG(TENDSTR);
528*10465441SEvalZero 	uffs_close(fd);
529*10465441SEvalZero 
530*10465441SEvalZero 	ret = 0;
531*10465441SEvalZero fail:
532*10465441SEvalZero 
533*10465441SEvalZero 	return ret;
534*10465441SEvalZero }
535*10465441SEvalZero 
536*10465441SEvalZero /** mount partition or show mounted partitions
537*10465441SEvalZero  *		mount [<mount>]
538*10465441SEvalZero  */
cmd_mount(int argc,char * argv[])539*10465441SEvalZero static int cmd_mount(int argc, char *argv[])
540*10465441SEvalZero {
541*10465441SEvalZero 	uffs_MountTable *tab;
542*10465441SEvalZero 	const char *mount = NULL;
543*10465441SEvalZero 
544*10465441SEvalZero 	if (argc == 1) {
545*10465441SEvalZero 		tab = uffs_MtbGetMounted();
546*10465441SEvalZero 		while (tab) {
547*10465441SEvalZero 			MSG(" %s : (%d) ~ (%d)\n", tab->mount, tab->start_block, tab->end_block);
548*10465441SEvalZero 			tab = tab->next;
549*10465441SEvalZero 		}
550*10465441SEvalZero 	}
551*10465441SEvalZero 	else {
552*10465441SEvalZero 		mount = argv[1];
553*10465441SEvalZero 		if (uffs_Mount(mount) < 0) {
554*10465441SEvalZero 			MSGLN("Can't mount %s", mount);
555*10465441SEvalZero 			return -1;
556*10465441SEvalZero 		}
557*10465441SEvalZero 	}
558*10465441SEvalZero 	return 0;
559*10465441SEvalZero }
560*10465441SEvalZero 
561*10465441SEvalZero /** unmount parition or show unmounted partitions
562*10465441SEvalZero  *		umount [<mount>]
563*10465441SEvalZero  */
cmd_unmount(int argc,char * argv[])564*10465441SEvalZero static int cmd_unmount(int argc, char *argv[])
565*10465441SEvalZero {
566*10465441SEvalZero 	uffs_MountTable *tab;
567*10465441SEvalZero 	const char *mount = NULL;
568*10465441SEvalZero 
569*10465441SEvalZero 	if (argc == 1) {
570*10465441SEvalZero 		tab = uffs_MtbGetUnMounted();
571*10465441SEvalZero 		while (tab) {
572*10465441SEvalZero 			MSG(" %s : (%d) ~ (%d)\n", tab->mount, tab->start_block, tab->end_block);
573*10465441SEvalZero 			tab = tab->next;
574*10465441SEvalZero 		}
575*10465441SEvalZero 	}
576*10465441SEvalZero 	else {
577*10465441SEvalZero 		mount = argv[1];
578*10465441SEvalZero 		if (uffs_UnMount(mount) < 0) {
579*10465441SEvalZero 			MSGLN("Can't unmount %s", mount);
580*10465441SEvalZero 			return -1;
581*10465441SEvalZero 		}
582*10465441SEvalZero 	}
583*10465441SEvalZero 
584*10465441SEvalZero 	return 0;
585*10465441SEvalZero }
586*10465441SEvalZero 
587*10465441SEvalZero /** inspect buffers
588*10465441SEvalZero  *		inspb [<mount>]
589*10465441SEvalZero  */
cmd_inspb(int argc,char * argv[])590*10465441SEvalZero static int cmd_inspb(int argc, char *argv[])
591*10465441SEvalZero {
592*10465441SEvalZero 	uffs_Device *dev;
593*10465441SEvalZero 	const char *mount = "/";
594*10465441SEvalZero 
595*10465441SEvalZero 	CHK_ARGC(1, 2);
596*10465441SEvalZero 
597*10465441SEvalZero 	dev = uffs_GetDeviceFromMountPoint(mount);
598*10465441SEvalZero 	if (dev == NULL) {
599*10465441SEvalZero 		MSGLN("Can't get device from mount point %s", mount);
600*10465441SEvalZero 		return -1;
601*10465441SEvalZero 	}
602*10465441SEvalZero 	uffs_BufInspect(dev);
603*10465441SEvalZero 	uffs_PutDevice(dev);
604*10465441SEvalZero 
605*10465441SEvalZero 	return 0;
606*10465441SEvalZero 
607*10465441SEvalZero }
608*10465441SEvalZero 
609*10465441SEvalZero /** print block wear-leveling information
610*10465441SEvalZero  *		wl [<mount>]
611*10465441SEvalZero  */
cmd_wl(int argc,char * argv[])612*10465441SEvalZero static int cmd_wl(int argc, char *argv[])
613*10465441SEvalZero {
614*10465441SEvalZero 	const char *mount = "/";
615*10465441SEvalZero 	uffs_Device *dev;
616*10465441SEvalZero 	struct uffs_PartitionSt *par;
617*10465441SEvalZero 	uffs_FileEmu *emu;
618*10465441SEvalZero 	int i, max;
619*10465441SEvalZero 	u32 n;
620*10465441SEvalZero 
621*10465441SEvalZero #define NUM_PER_LINE	10
622*10465441SEvalZero 
623*10465441SEvalZero 	CHK_ARGC(1, 2);
624*10465441SEvalZero 
625*10465441SEvalZero 	if (argc > 1) {
626*10465441SEvalZero 		mount = argv[1];
627*10465441SEvalZero 	}
628*10465441SEvalZero 
629*10465441SEvalZero 	dev = uffs_GetDeviceFromMountPoint(mount);
630*10465441SEvalZero 	if (dev == NULL) {
631*10465441SEvalZero 		MSGLN("Can't get device from mount point %s", mount);
632*10465441SEvalZero 		return -1;
633*10465441SEvalZero 	}
634*10465441SEvalZero 
635*10465441SEvalZero 	par = &dev->par;
636*10465441SEvalZero 	emu = (uffs_FileEmu *)(dev->attr->_private);
637*10465441SEvalZero 	max = -1;
638*10465441SEvalZero 
639*10465441SEvalZero 	for (i = 0; i < par->end - par->start; i++) {
640*10465441SEvalZero 		if ((i % NUM_PER_LINE) == 0) {
641*10465441SEvalZero 			MSG("%04d:", i + par->start);
642*10465441SEvalZero 		}
643*10465441SEvalZero 		n = i + par->start;
644*10465441SEvalZero 		max = (max == -1 ? n :
645*10465441SEvalZero 				(emu->em_monitor_block[n] > emu->em_monitor_block[max] ? n : max)
646*10465441SEvalZero 			   );
647*10465441SEvalZero 		MSG(" %4d", emu->em_monitor_block[n]);
648*10465441SEvalZero 		if (uffs_TreeFindBadNodeByBlock(dev, n))
649*10465441SEvalZero 			MSG("%c", 'x');
650*10465441SEvalZero 		else if (uffs_TreeFindErasedNodeByBlock(dev, n))
651*10465441SEvalZero 			MSG("%c", ' ');
652*10465441SEvalZero 		else
653*10465441SEvalZero 			MSG("%c", '.');
654*10465441SEvalZero 		if (((i + 1) % NUM_PER_LINE) == 0)
655*10465441SEvalZero 			MSG("\n");
656*10465441SEvalZero 	}
657*10465441SEvalZero 	MSG("\n");
658*10465441SEvalZero 	MSG("Total blocks %d, peak erase count %d at block %d\n",
659*10465441SEvalZero 		par->end - par->start, max == -1 ? 0 : emu->em_monitor_block[max], max);
660*10465441SEvalZero 
661*10465441SEvalZero 	uffs_PutDevice(dev);
662*10465441SEvalZero 
663*10465441SEvalZero 	return 0;
664*10465441SEvalZero }
665*10465441SEvalZero 
666*10465441SEvalZero static const struct cli_command helper_cmds[] =
667*10465441SEvalZero {
668*10465441SEvalZero     { cmd_format,	"format",		"[<mount>]",		"Format device" },
669*10465441SEvalZero     { cmd_mkf,		"mkfile",		"<name>",			"create a new file" },
670*10465441SEvalZero     { cmd_mkdir,	"mkdir",		"<name>",			"create a new directory" },
671*10465441SEvalZero     { cmd_rm,		"rm",			"<name>",			"delete file/directory" },
672*10465441SEvalZero     { cmd_ren,		"mv|ren",		"<old> <new>",		"rename file/directory" },
673*10465441SEvalZero     { cmd_ls,		"ls",			"<dir>",			"list dirs and files" },
674*10465441SEvalZero     { cmd_st,		"info|st",		"<mount>",			"show statistic infomation" },
675*10465441SEvalZero     { cmd_cp,		"cp",			"<src> <des>",		"copy files. the local file name start with '::'" },
676*10465441SEvalZero     { cmd_cat,		"cat",			"<name>",			"show file content" },
677*10465441SEvalZero     { cmd_pwd,		"pwd",			NULL,				"show current dir" },
678*10465441SEvalZero     { cmd_cd,		"cd",			"<path>",			"change current dir" },
679*10465441SEvalZero     { cmd_mount,	"mount",		"[<mount>]",		"mount partition or list mounted partitions" },
680*10465441SEvalZero     { cmd_unmount,	"umount",		"[<mount>]",		"unmount partition" },
681*10465441SEvalZero 	{ cmd_dump,		"dump",			"[<mount>]",		"dump file system", },
682*10465441SEvalZero 	{ cmd_wl,		"wl",			"[<mount>]",		"show block wear-leveling info", },
683*10465441SEvalZero 	{ cmd_inspb,	"inspb",		"[<mount>]",		"inspect buffer", },
684*10465441SEvalZero     { NULL, NULL, NULL, NULL }
685*10465441SEvalZero };
686*10465441SEvalZero 
687*10465441SEvalZero static struct cli_commandset helper_cmdset = {
688*10465441SEvalZero 	helper_cmds,
689*10465441SEvalZero };
690*10465441SEvalZero 
get_helper_cmds()691*10465441SEvalZero struct cli_commandset * get_helper_cmds()
692*10465441SEvalZero {
693*10465441SEvalZero 	return &helper_cmdset;
694*10465441SEvalZero };
695