[FL-1191][FL-1524] Filesystem rework (#568)

* FS-Api: removed datetime manipulation functions and most of the file flags
* Filesystem: common proxy api
* Filesystem: renamed to Storage. Work has begun on a glue layer. Added functions for reentrance.
* Storage: sd mount and sd file open
* Storage: sd file close
* Storage: temporary test app
* Storage: free filedata on close
* Storage: sd file read and write
* Storage: added internal storage (LittleFS)
* Storage: renamed internal commands
* Storage: seek, tell, truncate, size, sync, eof
* Storage: error descriptions
* Storage: directory management api (open, close, read, rewind)
* Storage: common management api (stat, fs_stat, remove, rename, mkdir)
* Dolphin app and Notifications app now use raw storage.
* Storage: storage statuses renamed. Implemented sd card icon.
* Storage: added raw sd-card api.
* Storage settings: work started
* Assets: use new icons approach
* Storage settings: working storage settings
* Storage: completely redesigned api, no longer sticking out FS_Api
* Storage: more simplified api, getting error_id from file is hidden from user, pointer to api is hidden inside file
* Storage: cli info and format commands
* Storage-cli: file list
* Storage: a simpler and more reliable api
* FatFS: slightly lighter and faster config. Also disabled reentrancy and file locking functions. They moved to a storage service.
* Storage-cli: accommodate to the new cli api.
* Storage: filesystem api is separated into internal and common api.
* Cli: added the ability to print the list of free heap blocks
* Storage: uses a list instead of an array to store the StorageFile. Rewrote api calls to use semaphores instead of thread flags.
* Storage settings: added the ability to benchmark the SD card.
* Gui module file select: uses new storage api
* Apps: removed deprecated sd_card_test application
* Args lib: support for enquoted arguments
* Dialogs: a new gui app for simple non-asynchronous apps
* Dialogs: view holder for easy single view work
* File worker: use new storage api
* IButton and lfrrfid apps: save keys to any storage
* Apps: fix ibutton and lfrfid stack, remove sd_card_test.
* SD filesystem: app removed
* File worker: fixed api pointer type
* Subghz: loading assets using the new storage api
* NFC: use the new storage api
* Dialogs: the better api for the message element
* Archive: use new storage api
* Irda: changed assest path, changed app path
* FileWorker: removed unused file_buf_cnt
* Storage: copying and renaming files now works between storages
* Storage cli: read, copy, remove, rename commands
* Archive: removed commented code
* Storage cli: write command
* Applications: add SRV_STORAGE and SRV_DIALOGS
* Internal-storage: removed
* Storage: improved api
* Storage app: changed api pointer from StorageApp to Storage
* Storage: better file_id handling
* Storage: more consistent errors
* Loader: support for NULL icons
* Storage: do nothing with the lfs file or directory if it is not open
* Storage: fix typo
* Storage: minor float usage cleanup, rename some symbols.
* Storage: compact doxygen comments.

Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
SG
2021-07-23 22:20:19 +10:00
committed by GitHub
parent a81203941b
commit ad421a81bc
95 changed files with 6451 additions and 4349 deletions

View File

@@ -3,18 +3,17 @@
static bool archive_get_filenames(ArchiveApp* archive);
static bool is_favorite(ArchiveApp* archive, ArchiveFile_t* file) {
FS_Common_Api* common_api = &archive->fs_api->common;
FileInfo file_info;
FS_Error fr;
string_t path;
string_init_printf(path, "favorites/%s", string_get_cstr(file->name));
string_init_printf(path, "%s/%s", get_favorites_path(), string_get_cstr(file->name));
fr = common_api->info(string_get_cstr(path), &file_info, NULL, 0);
fr = storage_common_stat(archive->api, string_get_cstr(path), &file_info);
FURI_LOG_I("FAV", "%d", fr);
string_clear(path);
return fr == 0 || fr == 2;
return (fr == FSE_OK || fr == FSE_EXIST);
}
static void update_offset(ArchiveApp* archive) {
@@ -147,14 +146,11 @@ static void set_file_type(ArchiveFile_t* file, FileInfo* file_info) {
static bool archive_get_filenames(ArchiveApp* archive) {
furi_assert(archive);
FS_Dir_Api* dir_api = &archive->fs_api->dir;
ArchiveFile_t item;
FileInfo file_info;
File directory;
File* directory = storage_file_alloc(archive->api);
char name[MAX_NAME_LEN];
bool result;
result = dir_api->open(&directory, string_get_cstr(archive->browser.path));
with_view_model(
archive->view_archive_main, (ArchiveViewModel * model) {
@@ -162,51 +158,50 @@ static bool archive_get_filenames(ArchiveApp* archive) {
return true;
});
if(!result) {
dir_api->close(&directory);
if(!storage_dir_open(directory, string_get_cstr(archive->browser.path))) {
storage_dir_close(directory);
storage_file_free(directory);
return false;
}
while(1) {
result = dir_api->read(&directory, &file_info, name, MAX_NAME_LEN);
if(directory.error_id == FSE_NOT_EXIST || name[0] == 0) {
if(!storage_dir_read(directory, &file_info, name, MAX_NAME_LEN)) {
break;
}
if(result) {
uint16_t files_cnt;
with_view_model(
archive->view_archive_main, (ArchiveViewModel * model) {
files_cnt = files_array_size(model->files);
uint16_t files_cnt;
with_view_model(
archive->view_archive_main, (ArchiveViewModel * model) {
files_cnt = files_array_size(model->files);
return true;
});
return true;
});
if(files_cnt > MAX_FILES) {
break;
} else if(directory.error_id == FSE_OK) {
if(filter_by_extension(archive, &file_info, name)) {
ArchiveFile_t_init(&item);
string_init_set(item.name, name);
set_file_type(&item, &file_info);
if(files_cnt > MAX_FILES) {
break;
} else if(storage_file_get_error(directory) == FSE_OK) {
if(filter_by_extension(archive, &file_info, name)) {
ArchiveFile_t_init(&item);
string_init_set(item.name, name);
set_file_type(&item, &file_info);
with_view_model(
archive->view_archive_main, (ArchiveViewModel * model) {
files_array_push_back(model->files, item);
return true;
});
with_view_model(
archive->view_archive_main, (ArchiveViewModel * model) {
files_array_push_back(model->files, item);
return true;
});
ArchiveFile_t_clear(&item);
}
} else {
dir_api->close(&directory);
return false;
ArchiveFile_t_clear(&item);
}
} else {
storage_dir_close(directory);
storage_file_free(directory);
return false;
}
}
dir_api->close(&directory);
storage_dir_close(directory);
storage_file_free(directory);
return true;
}
@@ -226,17 +221,7 @@ static uint32_t archive_previous_callback(void* context) {
static void archive_add_to_favorites(ArchiveApp* archive) {
furi_assert(archive);
FS_Common_Api* common_api = &archive->fs_api->common;
common_api->mkdir("favorites");
FS_File_Api* file_api = &archive->fs_api->file;
File src;
File dst;
bool fr;
uint16_t buffer[MAX_FILE_SIZE];
uint16_t bw = 0;
uint16_t br = 0;
storage_common_mkdir(archive->api, get_favorites_path());
string_t buffer_src;
string_t buffer_dst;
@@ -246,22 +231,10 @@ static void archive_add_to_favorites(ArchiveApp* archive) {
"%s/%s",
string_get_cstr(archive->browser.path),
string_get_cstr(archive->browser.name));
string_init_printf(buffer_dst, "/favorites/%s", string_get_cstr(archive->browser.name));
string_init_printf(
buffer_dst, "%s/%s", get_favorites_path(), string_get_cstr(archive->browser.name));
fr = file_api->open(&src, string_get_cstr(buffer_src), FSAM_READ, FSOM_OPEN_EXISTING);
FURI_LOG_I("FATFS", "OPEN: %d", fr);
fr = file_api->open(&dst, string_get_cstr(buffer_dst), FSAM_WRITE, FSOM_CREATE_ALWAYS);
FURI_LOG_I("FATFS", "CREATE: %d", fr);
for(;;) {
br = file_api->read(&src, &buffer, sizeof(buffer));
if(br == 0) break;
bw = file_api->write(&dst, &buffer, sizeof(buffer));
if(bw < br) break;
}
file_api->close(&src);
file_api->close(&dst);
storage_common_copy(archive->api, string_get_cstr(buffer_src), string_get_cstr(buffer_dst));
string_clear(buffer_src);
string_clear(buffer_dst);
@@ -271,7 +244,6 @@ static void archive_text_input_callback(void* context) {
furi_assert(context);
ArchiveApp* archive = (ArchiveApp*)context;
FS_Common_Api* common_api = &archive->fs_api->common;
string_t buffer_src;
string_t buffer_dst;
@@ -299,7 +271,7 @@ static void archive_text_input_callback(void* context) {
});
string_cat(buffer_dst, known_ext[file->type]);
common_api->rename(string_get_cstr(buffer_src), string_get_cstr(buffer_dst));
storage_common_rename(archive->api, string_get_cstr(buffer_src), string_get_cstr(buffer_dst));
view_dispatcher_switch_to_view(archive->view_dispatcher, ArchiveViewMain);
@@ -371,23 +343,22 @@ static void archive_delete_file(ArchiveApp* archive, ArchiveFile_t* file, bool f
furi_assert(archive);
furi_assert(file);
FS_Common_Api* common_api = &archive->fs_api->common;
string_t path;
string_init(path);
if(!fav && !orig) {
string_printf(
path, "%s/%s", string_get_cstr(archive->browser.path), string_get_cstr(file->name));
common_api->remove(string_get_cstr(path));
storage_common_remove(archive->api, string_get_cstr(path));
} else { // remove from favorites
string_printf(path, "favorites/%s", string_get_cstr(file->name));
common_api->remove(string_get_cstr(path));
string_printf(path, "%s/%s", get_favorites_path(), string_get_cstr(file->name));
storage_common_remove(archive->api, string_get_cstr(path));
if(orig) { // remove original file
string_printf(
path, "%s/%s", get_default_path(file->type), string_get_cstr(file->name));
common_api->remove(string_get_cstr(path));
storage_common_remove(archive->api, string_get_cstr(path));
}
}
@@ -604,8 +575,8 @@ void archive_free(ArchiveApp* archive) {
text_input_free(archive->text_input);
furi_record_close("sdcard");
archive->fs_api = NULL;
furi_record_close("storage");
archive->api = NULL;
furi_record_close("gui");
archive->gui = NULL;
furi_record_close("loader");
@@ -623,7 +594,7 @@ ArchiveApp* archive_alloc() {
archive->app_thread = furi_thread_alloc();
archive->gui = furi_record_open("gui");
archive->loader = furi_record_open("loader");
archive->fs_api = furi_record_open("sdcard");
archive->api = furi_record_open("storage");
archive->text_input = text_input_alloc();
archive->view_archive_main = view_alloc();

View File

@@ -10,7 +10,7 @@
#include <m-string.h>
#include <m-array.h>
#include <filesystem-api.h>
#include <storage/storage.h>
#include "archive_views.h"
#include "applications.h"
@@ -41,13 +41,13 @@ static const char* known_ext[] = {
};
static const char* tab_default_paths[] = {
[ArchiveTabFavorites] = "favorites",
[ArchiveTabIButton] = "ibutton",
[ArchiveTabNFC] = "nfc",
[ArchiveTabSubOne] = "subone",
[ArchiveTabLFRFID] = "lfrfid",
[ArchiveTabIrda] = "irda",
[ArchiveTabBrowser] = "/",
[ArchiveTabFavorites] = "/any/favorites",
[ArchiveTabIButton] = "/any/ibutton",
[ArchiveTabNFC] = "/any/nfc",
[ArchiveTabSubOne] = "/any/subone",
[ArchiveTabLFRFID] = "/any/lfrfid",
[ArchiveTabIrda] = "/any/irda",
[ArchiveTabBrowser] = "/any",
};
static inline const char* get_tab_ext(ArchiveTabEnum tab) {
@@ -84,6 +84,10 @@ static inline const char* get_default_path(ArchiveFileTypeEnum type) {
}
}
static inline const char* get_favorites_path() {
return tab_default_paths[ArchiveTabFavorites];
}
typedef enum {
EventTypeTick,
EventTypeKey,
@@ -118,6 +122,6 @@ struct ArchiveApp {
View* view_archive_main;
TextInput* text_input;
FS_Api* fs_api;
Storage* api;
ArchiveBrowser browser;
};

View File

@@ -4,7 +4,7 @@
#include <gui/canvas.h>
#include <gui/elements.h>
#include <furi.h>
#include <filesystem-api.h>
#include <storage/storage.h>
#define MAX_LEN_PX 100
#define MAX_NAME_LEN 255