156 lines
5.3 KiB
C
156 lines
5.3 KiB
C
/* f_util.c
|
|
Copyright 2021 Carl John Kugler III
|
|
|
|
Licensed under the Apache License, Version 2.0 (the License); you may not use
|
|
this file except in compliance with the License. You may obtain a copy of the
|
|
License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
Unless required by applicable law or agreed to in writing, software distributed
|
|
under the License is distributed on an AS IS BASIS, WITHOUT WARRANTIES OR
|
|
CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
|
specific language governing permissions and limitations under the License.
|
|
*/
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
//
|
|
#include "ff.h"
|
|
|
|
const char *FRESULT_str(FRESULT i) {
|
|
switch (i) {
|
|
case FR_OK:
|
|
return "Succeeded";
|
|
case FR_DISK_ERR:
|
|
return "A hard error occurred in the low level disk I/O layer";
|
|
case FR_INT_ERR:
|
|
return "Assertion failed";
|
|
case FR_NOT_READY:
|
|
return "The physical drive cannot work";
|
|
case FR_NO_FILE:
|
|
return "Could not find the file";
|
|
case FR_NO_PATH:
|
|
return "Could not find the path";
|
|
case FR_INVALID_NAME:
|
|
return "The path name format is invalid";
|
|
case FR_DENIED:
|
|
return "Access denied due to prohibited access or directory full";
|
|
case FR_EXIST:
|
|
return "Access denied due to prohibited access (exists)";
|
|
case FR_INVALID_OBJECT:
|
|
return "The file/directory object is invalid";
|
|
case FR_WRITE_PROTECTED:
|
|
return "The physical drive is write protected";
|
|
case FR_INVALID_DRIVE:
|
|
return "The logical drive number is invalid";
|
|
case FR_NOT_ENABLED:
|
|
return "The volume has no work area (mount)";
|
|
case FR_NO_FILESYSTEM:
|
|
return "There is no valid FAT volume";
|
|
case FR_MKFS_ABORTED:
|
|
return "The f_mkfs() aborted due to any problem";
|
|
case FR_TIMEOUT:
|
|
return "Could not get a grant to access the volume within defined "
|
|
"period";
|
|
case FR_LOCKED:
|
|
return "The operation is rejected according to the file sharing "
|
|
"policy";
|
|
case FR_NOT_ENOUGH_CORE:
|
|
return "LFN working buffer could not be allocated";
|
|
case FR_TOO_MANY_OPEN_FILES:
|
|
return "Number of open files > FF_FS_LOCK";
|
|
case FR_INVALID_PARAMETER:
|
|
return "Given parameter is invalid";
|
|
default:
|
|
return "Unknown";
|
|
}
|
|
}
|
|
|
|
FRESULT delete_node (
|
|
TCHAR* path, /* Path name buffer with the sub-directory to delete */
|
|
UINT sz_buff, /* Size of path name buffer (items) */
|
|
FILINFO* fno /* Name read buffer */
|
|
)
|
|
{
|
|
UINT i, j;
|
|
FRESULT fr;
|
|
DIR dir;
|
|
|
|
|
|
fr = f_opendir(&dir, path); /* Open the sub-directory to make it empty */
|
|
if (fr != FR_OK) return fr;
|
|
|
|
for (i = 0; path[i]; i++) ; /* Get current path length */
|
|
path[i++] = '/';
|
|
|
|
for (;;) {
|
|
fr = f_readdir(&dir, fno); /* Get a directory item */
|
|
if (fr != FR_OK || !fno->fname[0]) break; /* End of directory? */
|
|
j = 0;
|
|
do { /* Make a path name */
|
|
if (i + j >= sz_buff) { /* Buffer over flow? */
|
|
fr = 100; break; /* Fails with 100 when buffer overflow */
|
|
}
|
|
path[i + j] = fno->fname[j];
|
|
} while (fno->fname[j++]);
|
|
if (fno->fattrib & AM_DIR) { /* Item is a sub-directory */
|
|
fr = delete_node(path, sz_buff, fno);
|
|
} else { /* Item is a file */
|
|
fr = f_unlink(path);
|
|
}
|
|
if (fr != FR_OK) break;
|
|
}
|
|
|
|
path[--i] = 0; /* Restore the path name */
|
|
f_closedir(&dir);
|
|
|
|
if (fr == FR_OK) fr = f_unlink(path); /* Delete the empty sub-directory */
|
|
return fr;
|
|
}
|
|
|
|
void ls(const char *dir) {
|
|
char cwdbuf[FF_LFN_BUF] = {0};
|
|
FRESULT fr; /* Return value */
|
|
char const *p_dir;
|
|
if (dir[0]) {
|
|
p_dir = dir;
|
|
} else {
|
|
fr = f_getcwd(cwdbuf, sizeof cwdbuf);
|
|
if (FR_OK != fr) {
|
|
printf("f_getcwd error: %s (%d)\n", FRESULT_str(fr), fr);
|
|
return;
|
|
}
|
|
p_dir = cwdbuf;
|
|
}
|
|
printf("Directory Listing: %s\n", p_dir);
|
|
DIR dj = {}; /* Directory object */
|
|
FILINFO fno = {}; /* File information */
|
|
assert(p_dir);
|
|
fr = f_findfirst(&dj, &fno, p_dir, "*");
|
|
if (FR_OK != fr) {
|
|
printf("f_findfirst error: %s (%d)\n", FRESULT_str(fr), fr);
|
|
return;
|
|
}
|
|
while (fr == FR_OK && fno.fname[0]) { /* Repeat while an item is found */
|
|
/* Create a string that includes the file name, the file size and the
|
|
attributes string. */
|
|
const char *pcWritableFile = "writable file",
|
|
*pcReadOnlyFile = "read only file",
|
|
*pcDirectory = "directory";
|
|
const char *pcAttrib;
|
|
/* Point pcAttrib to a string that describes the file. */
|
|
if (fno.fattrib & AM_DIR) {
|
|
pcAttrib = pcDirectory;
|
|
} else if (fno.fattrib & AM_RDO) {
|
|
pcAttrib = pcReadOnlyFile;
|
|
} else {
|
|
pcAttrib = pcWritableFile;
|
|
}
|
|
/* Create a string that includes the file name, the file size and the
|
|
attributes string. */
|
|
printf("%s [%s] [size=%llu]\n", fno.fname, pcAttrib, fno.fsize);
|
|
|
|
fr = f_findnext(&dj, &fno); /* Search for next item */
|
|
}
|
|
f_closedir(&dj);
|
|
}
|