]> cloudbase.mooo.com Git - z180-stamp.git/blame - avr/cmd_fat.c
Remove extern declarations from command_tbl.c, create .h files for that.
[z180-stamp.git] / avr / cmd_fat.c
CommitLineData
35edb766 1/*
2d914b45 2 * (C) Copyright 2014,2016 Leo C. <erbl259-lmu@yahoo.de>
35edb766 3 *
2d914b45 4 * SPDX-License-Identifier: GPL-2.0
35edb766
L
5 */
6
7/*
8 * FAT filesystem commands
9 */
10
b6c04275 11#include "cmd_fat.h"
2f53dd65 12
2f53dd65
L
13#include "ff.h"
14#include "z80-if.h"
2d914b45 15#include "eval_arg.h"
4565be9a 16#include "con-utils.h"
2f53dd65 17#include "print-utils.h"
19b9a7d8 18#include "time.h"
2f53dd65 19#include "timer.h"
4f881b02 20#include "debug.h"
b6c04275 21#include "env.h"
3d8c1907 22#include "getopt-min.h"
2f53dd65 23
5f7f3586
L
24/* TODO: use memory size test function (cmd_mem.c) */
25#define MAX_MEMORY (1ul << 19)
19b9a7d8
L
26#define BUFFER_SIZE 512
27
4565be9a 28
b6c04275
L
29FATFS FatFs0;
30FATFS FatFs1;
31
32char chur_drv[3];
33
2f53dd65
L
34DWORD get_fattime (void)
35{
19b9a7d8
L
36 time_t timer;
37 struct tm tm_timer;
38
39 time(&timer);
40 gmtime_r(&timer, &tm_timer);
41
42 return fatfs_time(&tm_timer);
2f53dd65
L
43}
44
45
b15d22a4
L
46static bool check_abort(void)
47{
48 bool ret = ctrlc();
49
50 if (ret)
51 printf_P(PSTR("Abort\n"));
52
53 return ret;
54}
55
56
2f53dd65
L
57static const FLASH char * const FLASH rc_names[] = {
58 FSTR("OK"),
59 FSTR("DISK_ERR"),
60 FSTR("INT_ERR"),
61 FSTR("NOT_READY"),
62 FSTR("NO_FILE"),
63 FSTR("NO_PATH"),
64 FSTR("INVALID_NAME"),
65 FSTR("DENIED"),
66 FSTR("EXIST"),
67 FSTR("INVALID_OBJECT"),
68 FSTR("WRITE_PROTECTED"),
69 FSTR("INVALID_DRIVE"),
70 FSTR("NOT_ENABLED"),
71 FSTR("NO_FILE_SYSTEM"),
72 FSTR("MKFS_ABORTED"),
73 FSTR("TIMEOUT"),
74 FSTR("LOCKED"),
75 FSTR("NOT_ENOUGH_CORE"),
7af9364e
L
76 FSTR("TOO_MANY_OPEN_FILES"),
77 FSTR("INVALID_PARAMETER")
2f53dd65
L
78 };
79
80static
81void put_rc (FRESULT rc)
82{
83#if GCC_BUG_61443
7af9364e
L
84 printf_P(PSTR("rc=%u FR_"), rc);
85 my_puts_P(rc < ARRAY_SIZE(rc_names) ? rc_names[rc] : PSTR(" Unknown Error"));
86 my_puts_P(PSTR("\n"));
2f53dd65 87#else
7af9364e
L
88 printf_P(PSTR("rc=%u FR_%S\n"), rc,
89 rc < ARRAY_SIZE(rc_names) ? rc_names[rc] : PSTR(" Unknown Error"));
2f53dd65
L
90#endif
91}
92
b15d22a4 93
b6c04275
L
94void setup_fatfs(void)
95{
96 f_mount(&FatFs0, "0:", 0);
97 f_mount(&FatFs1, "1:", 0);
98}
99
100
b15d22a4
L
101static void swirl(void)
102{
6204987c 103 static const FLASH char swirlchar[] = { '-','\\','|','/' };
b15d22a4
L
104 static uint_fast8_t cnt;
105 static uint32_t tstamp;
106
107 if (get_timer(0) > tstamp) {
108 printf_P(PSTR("\b%c"), swirlchar[cnt]);
109 cnt = (cnt+1) % ARRAY_SIZE(swirlchar);
6204987c 110 tstamp = get_timer(0) + 250;
b15d22a4
L
111 }
112}
113
6204987c
L
114/* Work register for fs command */
115struct stat_dat_s {
116 DWORD AccSize;
117 WORD AccFiles, AccDirs;
118 FILINFO Finfo;
119};
120
2f53dd65
L
121static
122FRESULT scan_files (
6204987c
L
123 char *path, /* Pointer to the working buffer with start path */
124 struct stat_dat_s *statp
2f53dd65
L
125)
126{
127 DIR dirs;
128 FRESULT res;
129 int i;
130 char *fn;
131
132 res = f_opendir(&dirs, path);
b15d22a4 133 swirl();
2f53dd65
L
134 if (res == FR_OK) {
135 i = strlen(path);
6204987c
L
136 while (((res = f_readdir(&dirs, &statp->Finfo)) == FR_OK) &&
137 statp->Finfo.fname[0]) {
138 if (_FS_RPATH && statp->Finfo.fname[0] == '.')
139 continue;
140 fn = statp->Finfo.fname;
141 if (statp->Finfo.fattrib & AM_DIR) {
142 statp->AccDirs++;
143 path[i] = '/';
144 strcpy(path+i+1, fn);
145 res = scan_files(path, statp);
2f53dd65 146 path[i] = '\0';
6204987c
L
147 if (res != FR_OK)
148 break;
2f53dd65 149 } else {
6204987c
L
150 //printf_P(PSTR("%s/%s\n"), path, fn);
151 statp->AccFiles++;
152 statp->AccSize += statp->Finfo.fsize;
2f53dd65 153 }
b15d22a4
L
154 if (check_abort()) {
155 res = 255;
156 break;
157 }
2f53dd65
L
158 }
159 }
160
161 return res;
162}
163
164
165/*
166 * fatstat path - Show logical drive status
167 *
168 */
93ea25f2 169command_ret_t do_stat(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
2f53dd65 170{
bbd45c46 171 FATFS *fs;
4565be9a 172 DWORD nfreeclst;
2f53dd65 173 FRESULT res;
3d8c1907
L
174 char *buf;
175 char *path = "";
6204987c 176 struct stat_dat_s statp;
2f53dd65
L
177
178 (void) cmdtp; (void) flag; (void) argc;
179
3d8c1907
L
180 buf = (char *) malloc(BUFFER_SIZE);
181 if (buf == NULL) {
182 printf_P(PSTR("fat stat: Out of Memory!\n"));
2f53dd65
L
183 return CMD_RET_FAILURE;
184 }
185
3d8c1907
L
186 if (argc > 1)
187 path = argv[1];
188 res = f_getfree(path, &nfreeclst, &fs);
4565be9a 189 if (!res) {
bbd45c46
L
190 printf_P(PSTR(
191 "FAT type: %u\n"
192 "Bytes/Cluster: %lu\n"
193 "Number of FATs: %u\n"
194 "Root DIR entries: %u\n"
195 "Sectors/FAT: %lu\n"
196 "Number of clusters: %lu\n"
197 "FAT start (lba): %lu\n"
198 "DIR start (lba,cluster): %lu\n"
199 "Data start (lba): %lu\n"),
200 fs->fs_type, (DWORD)fs->csize * 512, fs->n_fats,
201 fs->n_rootdir, fs->fsize, fs->n_fatent - 2,
202 fs->fatbase, fs->dirbase, fs->database);
2f53dd65
L
203
204#if _USE_LABEL
bbd45c46 205 DWORD serial;
3d8c1907 206 res = f_getlabel(path, buf, &serial);
bbd45c46
L
207 if (!res) {
208 printf_P(PSTR(
209 "Volume name: %s\n"
210 "Volume S/N: %04X-%04X\n"),
3d8c1907 211 buf, (WORD)(serial >> 16), (WORD)(serial & 0xFFFF));
bbd45c46 212 }
2f53dd65 213#endif
bbd45c46
L
214 if (!res) {
215 my_puts_P(PSTR("\nCounting... "));
216 statp.AccSize = statp.AccFiles = statp.AccDirs = 0;
3d8c1907 217 strcpy(buf, path);
2f53dd65 218
3d8c1907 219 res = scan_files(buf, &statp);
bbd45c46
L
220 }
221 if (!res) {
222 printf_P(PSTR("\r%u files, %lu bytes.\n%u folders.\n"
223 "%lu KB total disk space.\n%lu KB available.\n"),
224 statp.AccFiles, statp.AccSize, statp.AccDirs,
225 (fs->n_fatent - 2) * (fs->csize / 2), nfreeclst * (fs->csize / 2)
226 );
4565be9a 227 }
2f53dd65 228 }
2f53dd65 229
3d8c1907 230 free(buf);
2f53dd65
L
231 if (res) {
232 put_rc(res);
233 return CMD_RET_FAILURE;
234 }
235 return CMD_RET_SUCCESS;
236}
237
b6c04275
L
238/*
239 * pwd - Print current directory of the current drive.
240 *
241 */
93ea25f2 242command_ret_t do_pwd(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
b6c04275
L
243{
244 FRESULT res;
245 char *buf;
246
247 (void) cmdtp; (void) flag; (void) argc; (void) argv;
248
249 buf = (char *) malloc(BUFFER_SIZE);
250 if (buf == NULL) {
251 printf_P(PSTR("pwd: Out of Memory!\n"));
252 free(buf);
253 return CMD_RET_FAILURE;
254 }
255
256 res = f_getcwd(buf, BUFFER_SIZE); /* Get current directory path */
257
258 if (!res) {
259 puts(buf);
260 }
261 free(buf);
262 if (res) {
263 put_rc(res);
264 return CMD_RET_FAILURE;
265 }
266 return CMD_RET_SUCCESS;
267}
268
269
270/*
271 * cd - Change the current/working directory.
272 *
273 */
93ea25f2 274command_ret_t do_cd(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
b6c04275
L
275{
276 char *arg;
277 FRESULT res = 0;
278
279 (void) cmdtp; (void) flag; (void) argc;
280
281 if (argc < 2) {
ee5c86e9 282 arg = getenv_str(PSTR(ENV_HOME));
b6c04275 283 if (arg == NULL) {
ee5c86e9 284 printf_P(PSTR("%s: \"%S\" is not set\n"), argv[0], PSTR(ENV_HOME));
b6c04275
L
285 return CMD_RET_FAILURE;
286 }
287 } else
288 arg = argv[1];
289
290 if (arg[1] == ':') {
291 char drv[3];
292 drv[2] = '\0';
293 drv[1] = ':';
294 drv[0] = arg[0];
295 res = f_chdrive(drv);
296 }
297 if (!res) {
298 res = f_chdir(arg);
299 }
300
301 if (res) {
302 put_rc(res);
303 return CMD_RET_FAILURE;
304 }
305 return CMD_RET_SUCCESS;
306}
307
3d8c1907
L
308#define MAX_PATHLEN 255
309
310 /* Remove trailing slashes,
311 * but keep a leading slash (absolute path)
312 */
313void strip_trailing_slash_relpath(char *p)
314{
315 int n = strlen(p);
316
317 if (n >= 2 && (p[0] & 0x38) == '0' && p[1] == ':') {
318 p += 2;
319 n -= 2;
320 }
321 if (n >= 1 && p[0] == '/') {
322 p++;
323 n--;
324 }
325 while (n-- != 0 && p[n] == '/')
326 p[n] = '\0';
327}
328
329int print_dirent(FILINFO *f)
330{
331 return printf_P(PSTR("%c%c%c%c%c %u/%02u/%02u %02u:%02u %9lu %s\n"),
332 (f->fattrib & AM_DIR) ? 'D' : '-',
333 (f->fattrib & AM_RDO) ? 'R' : '-',
334 (f->fattrib & AM_HID) ? 'H' : '-',
335 (f->fattrib & AM_SYS) ? 'S' : '-',
336 (f->fattrib & AM_ARC) ? 'A' : '-',
337 (f->fdate >> 9) + 1980, (f->fdate >> 5) & 15, f->fdate & 31,
338 (f->ftime >> 11), (f->ftime >> 5) & 63,
339 f->fsize, f->fname);
340}
2f53dd65
L
341
342/*
343 * fatls path - Directory listing
344 *
345 */
93ea25f2 346command_ret_t do_ls(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
2f53dd65 347{
bbd45c46 348 FATFS *fs;
2f53dd65
L
349 DIR Dir; /* Directory object */
350 FILINFO Finfo;
351 unsigned long p1;
352 unsigned int s1, s2;
3d8c1907 353 FRESULT res;
2f53dd65
L
354 (void) cmdtp; (void) flag; (void) argc;
355
b6c04275 356
3d8c1907
L
357 char *path = "";
358 if (argc > 1)
359 path = argv[1];
360 strip_trailing_slash_relpath(path);
b6c04275 361
3d8c1907
L
362 char *p = strrchr(path, '/');
363 if (p)
364 p++;
365 else {
366 p = path;
367 char *q = p;
368 if ((*q++ & 0x38) == '0' && *q++ == ':')
369 p = q;
370 }
371
372 char *pattern = NULL;
373 if (strpbrk_P(p, PSTR("*?")) ||
374 (f_stat(path, &Finfo) == FR_OK && !(Finfo.fattrib & AM_DIR))) {
375 pattern = strdup(p);
376 *p = '\0';
2f53dd65 377 }
3d8c1907
L
378 strip_trailing_slash_relpath(path);
379
380printf_P(PSTR("*: |%s| |%s|\n"), path ? path : "<NULL>", pattern ? pattern : "<NULL>");
2f53dd65
L
381
382 p1 = s1 = s2 = 0;
3d8c1907
L
383 res = f_findfirst(&Dir, &Finfo, path, pattern ? pattern : "*"); /* Start to search for files */
384 while (res == FR_OK && Finfo.fname[0]) {
2f53dd65
L
385 if (Finfo.fattrib & AM_DIR) {
386 s2++;
387 } else {
388 s1++; p1 += Finfo.fsize;
389 }
3d8c1907 390 print_dirent(&Finfo);
b15d22a4
L
391 if (check_abort())
392 break;
3d8c1907 393 res = f_findnext(&Dir, &Finfo);
2f53dd65 394 }
3d8c1907
L
395 f_closedir(&Dir);
396 free(pattern);
2f53dd65
L
397
398 if (res == FR_OK) {
399 printf_P(PSTR("%4u File(s),%10lu bytes total\n%4u Dir(s)"), s1, p1, s2);
3d8c1907 400 if (f_getfree(path, (DWORD*)&p1, &fs) == FR_OK)
2f53dd65
L
401 printf_P(PSTR(", %10luK bytes free\n"), p1 * fs->csize / 2);
402 }
403
3d8c1907
L
404 if (res) {
405 put_rc(res);
406 return CMD_RET_FAILURE;
407 }
408
409 return CMD_RET_SUCCESS;
410}
411
93ea25f2 412command_ret_t do_tst(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
3d8c1907
L
413{
414 DIR Dir; /* Directory object */
415 FILINFO Finfo;
416 FRESULT res = FR_OK;
417 char *path;
418
419 (void) cmdtp; (void) flag;
420
421 printf_P(PSTR("sizeof DIR: %u, sizeof FIL: %u\n"), sizeof (DIR), sizeof (FILINFO));
422
423 char * buf = (char *) malloc(BUFFER_SIZE);
424 if (buf == NULL) {
425 printf_P(PSTR("pwd: Out of Memory!\n"));
426 free(buf);
427 return CMD_RET_FAILURE;
428 }
429 res = f_getcwd(buf, BUFFER_SIZE); /* Get current directory path */
430
431 if (!res) {
432 printf_P(PSTR("cwd: |%s|\n"), buf);
433 }
b6c04275 434 free(buf);
2f53dd65
L
435 if (res) {
436 put_rc(res);
437 return CMD_RET_FAILURE;
438 }
439
3d8c1907
L
440 if (argc > 1)
441 path = argv[1];
442 else
443 path = "";
444
445 printf_P(PSTR("arg: |%s|\n"), path);
446 printf_P(PSTR("==== f_stat: "));
447 res = f_stat(path, &Finfo);
448 put_rc(res);
449 if (res == FR_OK) {
450 print_dirent(&Finfo);
451 }
452
453 printf_P(PSTR("==== f_findfirst: "));
454 res = f_findfirst(&Dir, &Finfo, path, "*"); /* Start to search for files */
455 put_rc(res);
456 if (res == FR_OK) {
457 print_dirent(&Finfo);
458 }
459 f_closedir(&Dir);
460
461 printf_P(PSTR("==== f_opendir: "));
462 res = f_opendir(&Dir, path);
463 put_rc(res);
464 f_closedir(&Dir);
465
2f53dd65
L
466 return CMD_RET_SUCCESS;
467}
468
35edb766
L
469static
470FRESULT mkpath(TCHAR *path)
471{
472 /* TODO: */
473 (void) path;
474#if 0
475 FILINFO fd
476 TCHAR *p, *q;
477 FRESULT ret;
478
35edb766
L
479 res = f_stat (path, &fd)
480
481 p = strchr(path, ':');
482 if (p == NULL || *++p == '\0' || *p++ != '/')
483 return FR_OK;
484
485 while ((q = strchr(p, '/')) != NULL) {
486 *q = '\0';
487 ret = f_mkdir(path);
488 *q = '/';
489 if (ret != FR_OK && ret != FR_EXIST)
490 return ret;
491 p = q + 1;
492 }
493#endif
494
495 return FR_OK;
496}
2f53dd65 497
4565be9a
L
498/*
499 * fatread/write - load binary file to/from a dos filesystem
500 * read <d:/path/filename> <addr> [bytes [pos]]
501 * write <d:/path/filename> <addr> <bytes>
502 */
93ea25f2 503command_ret_t do_rw(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
4565be9a 504{
4565be9a
L
505 FIL File;
506 uint32_t addr;
507 unsigned long bytes;
508 unsigned long pos;
509 unsigned long bytes_rw;
510
3d8c1907 511 bool dowrite = (argv[0][0] == 'w');
3b841cea 512 FRESULT res = FR_OK;
4565be9a
L
513 bool buserr = 0;
514 uint32_t timer;
19b9a7d8 515 uint8_t *buffer;
4565be9a
L
516
517 (void) cmdtp; (void) flag;
518
519 if (argc < (dowrite ? 4 : 3))
520 return CMD_RET_USAGE;
521
2d914b45 522 addr = eval_arg(argv[2], NULL);
4565be9a
L
523 if (addr >= MAX_MEMORY) {
524 printf_P(PSTR("address too high: 0x%0lx\n"), addr);
525 return CMD_RET_FAILURE;
526 }
527 if (argc > 3)
2d914b45 528 bytes = eval_arg(argv[3], NULL);
4565be9a
L
529 else
530 bytes = MAX_MEMORY;
531 if (argc > 4)
2d914b45 532 pos = eval_arg(argv[4], NULL);
4565be9a
L
533 else
534 pos = 0;
535
536 if (addr + bytes > MAX_MEMORY)
537 bytes = MAX_MEMORY - addr;
538
19b9a7d8 539 buffer = (uint8_t *) malloc(BUFFER_SIZE);
bbd45c46 540 if (buffer == NULL) {
19b9a7d8 541 printf_P(PSTR("fatstat: Out of Memory!\n"));
19b9a7d8
L
542 free(buffer);
543 return CMD_RET_FAILURE;
544 }
545
bbd45c46
L
546 if (dowrite) {
547 res = mkpath(argv[1]);
35edb766 548 }
4565be9a
L
549 if (!res) {
550 res = f_open(&File, argv[1], dowrite ? FA_WRITE | FA_CREATE_ALWAYS
551 : FA_READ );
552
553 if (!res) {
554 res = f_lseek(&File, pos);
555 if (!res) {
556 bytes_rw = 0;
557 timer = get_timer(0);
558 while (bytes) {
559 unsigned int cnt, br;
560
19b9a7d8
L
561 if (bytes >= BUFFER_SIZE) {
562 cnt = BUFFER_SIZE;
563 bytes -= BUFFER_SIZE;
4565be9a
L
564 } else {
565 cnt = bytes; bytes = 0;
566 }
567 if (dowrite) {
568 if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
569 buserr = 1;
570 break;
571 }
572 z80_read_block(buffer, addr, cnt);
573 z80_bus_cmd(Release);
574 res = f_write(&File, buffer, cnt, &br);
575 if (res != FR_OK)
576 break;
577 } else {
578 res = f_read(&File, buffer, cnt, &br);
579 if (res != FR_OK)
580 break;
581 if (!(z80_bus_cmd(Request) & ZST_ACQUIRED)) {
582 buserr = 1;
583 break;
584 }
585 z80_write_block(buffer, addr, br);
586 z80_bus_cmd(Release);
587 }
588 addr += br;
589
590 bytes_rw += br;
591 if (cnt != br) {
592 if (dowrite)
593 printf_P(PSTR("Disk full?\n"));
594 break;
595 }
b15d22a4 596 if (check_abort())
4565be9a 597 break;
4565be9a
L
598 }
599
600 FRESULT fr = f_close(&File);
601 if (!res)
602 res = fr;
603 timer = get_timer(timer);
604 printf_P(PSTR("%lu (0x%lx) bytes read/written with %lu bytes/sec.\n"),
605 bytes_rw, bytes_rw, timer ? (bytes_rw * 1000 / timer) : 0);
606 }
607 }
4565be9a
L
608 }
609
19b9a7d8 610 free(buffer);
19b9a7d8 611
4565be9a
L
612 if (buserr)
613 my_puts_P(PSTR("Bus timeout\n"));
614 if (res)
615 put_rc(res);
616 if (buserr || res)
617 return CMD_RET_FAILURE;
618
619 return CMD_RET_SUCCESS;
620}
b6c04275 621
3d8c1907
L
622/* ========================================================================== */
623
624
625typedef struct {
626 char *p_end; /* pointer to NULL at end of path */
627 char p_path[MAX_PATHLEN + 1]; /* pointer to the start of a path */
628} PATH_T;
629
630static inline void strip_trailing_slash(PATH_T *p)
631{
632 while (p->p_end > p->p_path && p->p_end[-1] == '/')
633 *--p->p_end = 0;
634}
635
636/*
637 * Move specified string into path. Convert "" to "." to handle BSD
638 * semantics for a null path. Strip trailing slashes.
639 */
640int
641path_set(PATH_T *p, char *string)
642{
643 if (strlen(string) > MAX_PATHLEN) {
644 //err("%s: name too long", string);
645 return(0);
646 }
647
648 (void)strcpy(p->p_path, string);
649 p->p_end = p->p_path + strlen(p->p_path);
650
651 if (p->p_path == p->p_end) {
652 *p->p_end++ = '.';
653 *p->p_end = 0;
654 }
655
656 strip_trailing_slash(p);
657 return(1);
658}
659
660#define R_FLAG (1<<0)
661#define I_FLAG (1<<1)
662#define N_FLAG (1<<2)
663#define F_FLAG (1<<3)
664#define P_FLAG (1<<4)
665#define V_FLAG (1<<5)
666
93ea25f2 667command_ret_t do_cp(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int argc, char * const argv[])
3d8c1907
L
668{
669
670 FRESULT fr; /* Return value */
671 DIR dj; /* Directory search object */
672 FILINFO fno; /* File information */
673
674 uint8_t flags = 0;
675
676
677 /* reset getopt() */
678 optind = 0;
679
680 int opt;
681 while ((opt = getopt(argc, argv, PSTR("Rrfip"))) != -1) {
682 switch (opt) {
683 case 'f':
684 flags &= I_FLAG;
685 break;
686 case 'i':
687 flags |= I_FLAG;
688 flags &= F_FLAG;
689 break;
690 case 'p':
691 flags |= P_FLAG;
692 break;
693 case 'R':
694 case 'r':
695 flags |= R_FLAG;
696 break;
697 case 'v':
698 flags |= V_FLAG;
699 break;
700 default:
701 return CMD_RET_USAGE;
702 break;
703 }
704 }
705 argc -= optind;
706 argv += optind;
707
708 if (argc < 2)
709 return CMD_RET_USAGE;
710
711#if 0
712 /* consume last argument first. */
713 if (!path_set(&to, argv[--argc]))
714 exit(1);
715
716
717 if (flags & V_FLAG)
718 printf_P((PSTR("%s %s -> %s\n", badcp ? : "ERR:" : " ",
719 curr->fts_path, to.p_path);
720#endif
721
722/* Search a directory for objects and display it */
723
724
725 fr = f_findfirst(&dj, &fno, argv[1], argv[2]); /* Start to search for files */
726
727 while (fr == FR_OK && fno.fname[0]) { /* Repeat while an item is found */
728 printf_P(PSTR("%c%c%c%c%c %u/%02u/%02u %02u:%02u %9lu %s\n"),
729 (fno.fattrib & AM_DIR) ? 'D' : '-',
730 (fno.fattrib & AM_RDO) ? 'R' : '-',
731 (fno.fattrib & AM_HID) ? 'H' : '-',
732 (fno.fattrib & AM_SYS) ? 'S' : '-',
733 (fno.fattrib & AM_ARC) ? 'A' : '-',
734 (fno.fdate >> 9) + 1980, (fno.fdate >> 5) & 15, fno.fdate & 31,
735 (fno.ftime >> 11), (fno.ftime >> 5) & 63,
736 fno.fsize, fno.fname);
737 fr = f_findnext(&dj, &fno); /* Search for next item */
738 }
739
740 f_closedir(&dj);
741
742 return CMD_RET_SUCCESS;
743}
744
b6c04275 745
6c851813 746cmd_tbl_t cmd_tbl_fat[] = {
b6c04275 747CMD_TBL_ITEM(
93ea25f2 748 stat, 2, CTBL_REPEAT, do_stat,
b6c04275
L
749 "Show logical drive status",
750 "dev"
751),
752CMD_TBL_ITEM(
93ea25f2 753 pwd, 2, CTBL_REPEAT, do_pwd,
b6c04275
L
754 "Print name of current/working directory",
755 ""
756),
757CMD_TBL_ITEM(
93ea25f2 758 cd, 2, CTBL_REPEAT, do_cd,
b6c04275
L
759 "Change the current/working directory.",
760 "path"
761),
762CMD_TBL_ITEM(
93ea25f2 763 ls, 2, CTBL_REPEAT, do_ls,
b6c04275
L
764 "Directory listing",
765 "path"
766),
3d8c1907 767CMD_TBL_ITEM(
93ea25f2 768 tst, 2, CTBL_REPEAT, do_tst,
3d8c1907
L
769 "FatFS test function",
770 "path"
771),
b6c04275
L
772CMD_TBL_ITEM(
773 load, 5, 0, do_rw,
774 "load binary file from a dos filesystem",
775 "<d:/path/filename> <addr> [bytes [pos]]\n"
776 " - Load binary file 'path/filename' on logical drive 'd'\n"
777 " to address 'addr' from dos filesystem.\n"
778 " 'pos' gives the file position to start loading from.\n"
779 " If 'pos' is omitted, 0 is used. 'pos' requires 'bytes'.\n"
780 " 'bytes' gives the size to load. If 'bytes' is 0 or omitted,\n"
781 " the load stops on end of file."
782),
783CMD_TBL_ITEM(
784 write, 4, 0, do_rw,
785 "write file into a dos filesystem",
786 "<d:/path/filename> <addr> <bytes>\n"
787 " - Write file to 'path/filename' on logical drive 'd' from RAM\n"
788 " starting at address 'addr'.\n"
789),
790
3d8c1907
L
791CMD_TBL_ITEM(
792 cp, CONFIG_SYS_MAXARGS, 0, do_cp,
793 "copy files",
794 "cp [-R] [-f | -i | -n] [-aprv] source_file target_file\n"
795 " - \n"
796),
797
ee5c86e9 798CMD_TBL_ITEM(
93ea25f2 799 help, CONFIG_SYS_MAXARGS, CTBL_REPEAT, do_help,
ee5c86e9
L
800 "Print sub command description/usage",
801 "\n"
802 " - print brief description of all sub commands\n"
803 "fat help command ...\n"
804 " - print detailed usage of sub cmd 'command'"
805),
806
b6c04275
L
807/* This does not use the CMD_TBL_ITEM macro as ? can't be used in symbol names */
808 {FSTR("?"), CONFIG_SYS_MAXARGS, 1, do_help,
809 FSTR("Alias for 'help'"),
810#ifdef CONFIG_SYS_LONGHELP
811 FSTR(""),
812#endif /* CONFIG_SYS_LONGHELP */
6c851813 813 NULL,
b6c04275 814#ifdef CONFIG_AUTO_COMPLETE
6c851813 815 NULL,
b6c04275
L
816#endif
817},
6c851813 818/* Mark end of table */
6c7c9c2d 819CMD_TBL_END(cmd_tbl_fat)
b6c04275
L
820};
821
b6c04275 822
93ea25f2 823command_ret_t do_fat(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[])
b6c04275 824{
6c7c9c2d 825 puts_P(PSTR("Huch?"));
b6c04275
L
826
827 return CMD_RET_USAGE;
828}