+/*
+ * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/*
+ * FAT filesystem commands
+ */
+
#include "common.h"
#include <stdlib.h>
#include <string.h>
#include "timer.h"
#include "debug.h"
-
-#define MAX_MEMORY (1ul << 20)
+/* TODO: use memory size test function (cmd_mem.c) */
+#define MAX_MEMORY (1ul << 19)
#define BUFFER_SIZE 512
}
+static bool check_abort(void)
+{
+ bool ret = ctrlc();
+
+ if (ret)
+ printf_P(PSTR("Abort\n"));
+
+ return ret;
+}
+
+
static const FLASH char * const FLASH rc_names[] = {
FSTR("OK"),
FSTR("DISK_ERR"),
static
void put_rc (FRESULT rc)
{
+ if (rc < ARRAY_SIZE(rc_names)) {
#if GCC_BUG_61443
- printf_P(PSTR("rc=%u FR_"), rc);
- my_puts_P(rc_names[rc]);
- my_puts_P(PSTR("\n"));
+ printf_P(PSTR("rc=%u FR_"), rc);
+ my_puts_P(rc_names[rc]);
+ my_puts_P(PSTR("\n"));
#else
- printf_P(PSTR("rc=%u FR_%S\n"), rc, rc_names[rc]);
+ printf_P(PSTR("rc=%u FR_%S\n"), rc, rc_names[rc]);
#endif
+ }
+}
+
+
+static void swirl(void)
+{
+ static const FLASH char swirlchar[] = { '-','\\','|','/' };
+ static uint_fast8_t cnt;
+ static uint32_t tstamp;
+
+ if (get_timer(0) > tstamp) {
+ printf_P(PSTR("\b%c"), swirlchar[cnt]);
+ cnt = (cnt+1) % ARRAY_SIZE(swirlchar);
+ tstamp = get_timer(0) + 250;
+ }
}
/* Work register for fs command */
-static DWORD AccSize;
-static WORD AccFiles, AccDirs;
-#if _USE_LFN
-char Lfname[_MAX_LFN+1];
-FILINFO Finfo = {
- .lfname = Lfname,
- .lfsize = sizeof Lfname
- };
-#else
-FILINFO Finfo;
-#endif
+struct stat_dat_s {
+ DWORD AccSize;
+ WORD AccFiles, AccDirs;
+ FILINFO Finfo;
+};
static
FRESULT scan_files (
- char* path /* Pointer to the working buffer with start path */
+ char *path, /* Pointer to the working buffer with start path */
+ struct stat_dat_s *statp
)
{
DIR dirs;
char *fn;
res = f_opendir(&dirs, path);
-
+ swirl();
if (res == FR_OK) {
i = strlen(path);
- while (((res = f_readdir(&dirs, &Finfo)) == FR_OK) && Finfo.fname[0]) {
- if (_FS_RPATH && Finfo.fname[0] == '.') continue;
-#if _USE_LFN
- fn = *Finfo.lfname ? Finfo.lfname : Finfo.fname;
-#else
- fn = Finfo.fname;
-#endif
- if (Finfo.fattrib & AM_DIR) {
- AccDirs++;
- path[i] = '/'; strcpy(path+i+1, fn);
- res = scan_files(path);
+ while (((res = f_readdir(&dirs, &statp->Finfo)) == FR_OK) &&
+ statp->Finfo.fname[0]) {
+ if (_FS_RPATH && statp->Finfo.fname[0] == '.')
+ continue;
+ fn = statp->Finfo.fname;
+ if (statp->Finfo.fattrib & AM_DIR) {
+ statp->AccDirs++;
+ path[i] = '/';
+ strcpy(path+i+1, fn);
+ res = scan_files(path, statp);
path[i] = '\0';
- if (res != FR_OK) break;
+ if (res != FR_OK)
+ break;
} else {
-// printf_P(PSTR("%s/%s\n"), path, fn);
- AccFiles++;
- AccSize += Finfo.fsize;
+ //printf_P(PSTR("%s/%s\n"), path, fn);
+ statp->AccFiles++;
+ statp->AccSize += statp->Finfo.fsize;
+ }
+ if (check_abort()) {
+ res = 255;
+ break;
}
}
}
*/
command_ret_t do_fat_stat(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
- FATFS *FatFs, *fs;
+ FATFS *fs;
DWORD nfreeclst;
FRESULT res;
- char *buffer;
+ char *path;
+ struct stat_dat_s statp;
(void) cmdtp; (void) flag; (void) argc;
- FatFs = (FATFS *) malloc(sizeof (FATFS));
- buffer = (char *) malloc(BUFFER_SIZE);
- if (FatFs == NULL || buffer == NULL) {
+ path = (char *) malloc(BUFFER_SIZE);
+ if (path == NULL) {
printf_P(PSTR("fatstat: Out of Memory!\n"));
- free(buffer);
- free(FatFs);
+ free(path);
return CMD_RET_FAILURE;
}
- res = f_mount(FatFs, argv[1], 0);
+ res = f_getfree(argv[1], &nfreeclst, &fs);
if (!res) {
- res = f_getfree(argv[1], &nfreeclst, &fs);
- if (!res) {
- printf_P(PSTR(
- "FAT type: %u\n"
- "Bytes/Cluster: %lu\n"
- "Number of FATs: %u\n"
- "Root DIR entries: %u\n"
- "Sectors/FAT: %lu\n"
- "Number of clusters: %lu\n"
- "FAT start (lba): %lu\n"
- "DIR start (lba,cluster): %lu\n"
- "Data start (lba): %lu\n"),
- fs->fs_type, (DWORD)fs->csize * 512, fs->n_fats,
- fs->n_rootdir, fs->fsize, fs->n_fatent - 2,
- fs->fatbase, fs->dirbase, fs->database);
+ printf_P(PSTR(
+ "FAT type: %u\n"
+ "Bytes/Cluster: %lu\n"
+ "Number of FATs: %u\n"
+ "Root DIR entries: %u\n"
+ "Sectors/FAT: %lu\n"
+ "Number of clusters: %lu\n"
+ "FAT start (lba): %lu\n"
+ "DIR start (lba,cluster): %lu\n"
+ "Data start (lba): %lu\n"),
+ fs->fs_type, (DWORD)fs->csize * 512, fs->n_fats,
+ fs->n_rootdir, fs->fsize, fs->n_fatent - 2,
+ fs->fatbase, fs->dirbase, fs->database);
#if _USE_LABEL
- TCHAR label[12];
- DWORD serial;
- res = f_getlabel(argv[1], label, &serial);
- if (!res) {
- printf_P(PSTR(
- "Volume name: %s\n"
- "Volume S/N: %04X-%04X\n"),
- label, (WORD)(serial >> 16), (WORD)(serial & 0xFFFF));
- }
+ TCHAR label[12];
+ DWORD serial;
+ res = f_getlabel(argv[1], label, &serial);
+ if (!res) {
+ printf_P(PSTR(
+ "Volume name: %s\n"
+ "Volume S/N: %04X-%04X\n"),
+ label, (WORD)(serial >> 16), (WORD)(serial & 0xFFFF));
+ }
#endif
- if (!res) {
- my_puts_P(PSTR("\n..."));
- AccSize = AccFiles = AccDirs = 0;
-
- strcpy(buffer, argv[1]);
+ if (!res) {
+ my_puts_P(PSTR("\nCounting... "));
+ statp.AccSize = statp.AccFiles = statp.AccDirs = 0;
+ strcpy(path, argv[1]);
- res = scan_files(buffer);
- }
- if (!res) {
- printf_P(PSTR("\r%u files, %lu bytes.\n%u folders.\n"
- "%lu KB total disk space.\n%lu KB available.\n"),
- AccFiles, AccSize, AccDirs,
- (fs->n_fatent - 2) * (fs->csize / 2), nfreeclst * (fs->csize / 2)
- );
- }
+ res = scan_files(path, &statp);
+ }
+ if (!res) {
+ printf_P(PSTR("\r%u files, %lu bytes.\n%u folders.\n"
+ "%lu KB total disk space.\n%lu KB available.\n"),
+ statp.AccFiles, statp.AccSize, statp.AccDirs,
+ (fs->n_fatent - 2) * (fs->csize / 2), nfreeclst * (fs->csize / 2)
+ );
}
}
- f_mount(NULL, argv[1], 0);
- free(buffer);
- free(FatFs);
+ free(path);
if (res) {
put_rc(res);
return CMD_RET_FAILURE;
*/
command_ret_t do_fat_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
- FATFS FatFs, *fs;
+ FATFS *fs;
DIR Dir; /* Directory object */
FILINFO Finfo;
unsigned long p1;
(void) cmdtp; (void) flag; (void) argc;
- res = f_mount(&FatFs, argv[1], 0);
- if (!res)
- res = f_opendir(&Dir, argv[1]);
+ res = f_opendir(&Dir, argv[1]);
if (res) {
put_rc(res);
return CMD_RET_FAILURE;
#else
printf_P(PSTR("%s\n"), Finfo.fname);
#endif
+ if (check_abort())
+ break;
}
if (res == FR_OK) {
return CMD_RET_SUCCESS;
}
+static
+FRESULT mkpath(TCHAR *path)
+{
+ /* TODO: */
+ (void) path;
+#if 0
+ FILINFO fd
+ TCHAR *p, *q;
+ FRESULT ret;
+
+#if _USE_LFN
+ fd.lfname = 0;
+#endif
+
+
+ res = f_stat (path, &fd)
+
+ p = strchr(path, ':');
+ if (p == NULL || *++p == '\0' || *p++ != '/')
+ return FR_OK;
+
+ while ((q = strchr(p, '/')) != NULL) {
+ *q = '\0';
+ ret = f_mkdir(path);
+ *q = '/';
+ if (ret != FR_OK && ret != FR_EXIST)
+ return ret;
+ p = q + 1;
+ }
+#endif
+
+ return FR_OK;
+}
/*
* fatread/write - load binary file to/from a dos filesystem
*/
command_ret_t do_fat_rw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
- FATFS *FatFs;
FIL File;
uint32_t addr;
unsigned long bytes;
if (addr + bytes > MAX_MEMORY)
bytes = MAX_MEMORY - addr;
- FatFs = (FATFS *) malloc(sizeof (FATFS));
buffer = (uint8_t *) malloc(BUFFER_SIZE);
- if (FatFs == NULL || buffer == NULL) {
+ if (buffer == NULL) {
printf_P(PSTR("fatstat: Out of Memory!\n"));
- free(FatFs);
free(buffer);
return CMD_RET_FAILURE;
}
- res = f_mount(FatFs, argv[1], 0);
+ if (dowrite) {
+ res = mkpath(argv[1]);
+ }
if (!res) {
res = f_open(&File, argv[1], dowrite ? FA_WRITE | FA_CREATE_ALWAYS
: FA_READ );
printf_P(PSTR("Disk full?\n"));
break;
}
- if (ctrlc()) {
- printf_P(PSTR("Abort\n"));
+ if (check_abort())
break;
- }
}
FRESULT fr = f_close(&File);
bytes_rw, bytes_rw, timer ? (bytes_rw * 1000 / timer) : 0);
}
}
- f_mount(NULL, argv[1], 0);
}
free(buffer);
- free(FatFs);
if (buserr)
my_puts_P(PSTR("Bus timeout\n"));