Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compile-time APP_DATA_PATH() and APP_ASSETS_PATH() #3435

Draft
wants to merge 23 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 16 additions & 61 deletions applications/debug/unit_tests/tests/storage/storage_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -410,72 +410,28 @@ MU_TEST_SUITE(storage_rename) {
furi_record_close(RECORD_STORAGE);
}

#define APPSDATA_APP_PATH(path) APPS_DATA_PATH "/" path

static const char* storage_test_apps[] = {
"-_twilight_-",
"-_rainbow_-",
"-_pinkie_-",
"-_apple_-",
"-_flutter_-",
"-_rare_-",
};

static size_t storage_test_apps_count = COUNT_OF(storage_test_apps);
#define APPSDATA_APP_PATH(path) STORAGE_APPS_DATA_STEM "/" path

static int32_t storage_test_app(void* arg) {
UNUSED(arg);
Storage* storage = furi_record_open(RECORD_STORAGE);
storage_common_remove(storage, "/data/test");
int32_t ret = storage_file_create(storage, "/data/test", "test");
furi_record_close(RECORD_STORAGE);
return ret;
}

MU_TEST(test_storage_data_path_apps) {
for(size_t i = 0; i < storage_test_apps_count; i++) {
FuriThread* thread =
furi_thread_alloc_ex(storage_test_apps[i], 1024, storage_test_app, NULL);
furi_thread_set_appid(thread, storage_test_apps[i]);
furi_thread_start(thread);
furi_thread_join(thread);

mu_assert_int_eq(true, furi_thread_get_return_code(thread));

// Check if app data dir and file exists
Storage* storage = furi_record_open(RECORD_STORAGE);
FuriString* expected = furi_string_alloc();
furi_string_printf(expected, APPSDATA_APP_PATH("%s"), storage_test_apps[i]);

mu_check(storage_dir_exists(storage, furi_string_get_cstr(expected)));
furi_string_cat(expected, "/test");
mu_check(storage_file_exists(storage, furi_string_get_cstr(expected)));

furi_string_printf(expected, APPSDATA_APP_PATH("%s"), storage_test_apps[i]);
storage_simply_remove_recursive(storage, furi_string_get_cstr(expected));

furi_record_close(RECORD_STORAGE);

furi_string_free(expected);
furi_thread_free(thread);
}
}

MU_TEST(test_storage_data_path) {
MU_TEST(test_storage_apps_data_path) {
Storage* storage = furi_record_open(RECORD_STORAGE);

File* file = storage_file_alloc(storage);
mu_check(storage_dir_open(file, "/data"));
mu_check(storage_dir_close(file));
mu_check(storage_file_open(
file, APPSDATA_APP_PATH("test/file.txt"), FSAM_WRITE, FSOM_CREATE_ALWAYS));
mu_check(storage_file_close(file));
storage_file_free(file);

// check that appsdata folder exists
mu_check(storage_dir_exists(storage, APPS_DATA_PATH));
mu_check(storage_dir_exists(storage, STORAGE_APPS_DATA_STEM));

// check that test folder exists
mu_check(storage_dir_exists(storage, APPSDATA_APP_PATH("test")));

// check that cli folder exists
mu_check(storage_dir_exists(storage, APPSDATA_APP_PATH("cli")));
// check that file exists
mu_check(storage_file_exists(storage, APPSDATA_APP_PATH("test/file.txt")));

storage_simply_remove(storage, APPSDATA_APP_PATH("cli"));
storage_simply_remove(storage, APPSDATA_APP_PATH("test/file.txt"));
storage_simply_remove(storage, APPSDATA_APP_PATH("test"));

furi_record_close(RECORD_STORAGE);
}
Expand Down Expand Up @@ -689,9 +645,8 @@ MU_TEST(test_md5_calc) {
furi_record_close(RECORD_STORAGE);
}

MU_TEST_SUITE(test_data_path) {
MU_RUN_TEST(test_storage_data_path);
MU_RUN_TEST(test_storage_data_path_apps);
MU_TEST_SUITE(test_apps_data_path) {
MU_RUN_TEST(test_storage_apps_data_path);
}

MU_TEST_SUITE(test_storage_common) {
Expand All @@ -707,7 +662,7 @@ int run_minunit_test_storage(void) {
MU_RUN_SUITE(storage_file_64k);
MU_RUN_SUITE(storage_dir);
MU_RUN_SUITE(storage_rename);
MU_RUN_SUITE(test_data_path);
MU_RUN_SUITE(test_apps_data_path);
MU_RUN_SUITE(test_storage_common);
MU_RUN_SUITE(test_md5_calc_suite);
return MU_EXIT_CODE;
Expand Down
10 changes: 6 additions & 4 deletions applications/examples/example_apps_assets/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,18 @@ Source code for this example can be found [here](https://github.com/flipperdevic

The **Apps Assets** folder is a folder where external applications unpack their assets.

The path to the current application folder is related to the `appid` of the app. The `appid` is used to identify the app in the app store and is stored in the `application.fam` file.
The path to the current application assets folder is related to the `appid` of the app. The `appid` is used to identify the app in the app store and is stored in the `application.fam` file.
The Apps Assets folder is located only on the external storage, the SD card.

For example, if the `appid` of the app is `snake_game`, the path to the Apps Assets folder will be `/ext/apps_assets/snake_game`. But using raw paths is not recommended, because the path to the Apps Assets folder can change in the future. Use the `/assets` alias instead.
For example, if the `appid` of the app is `snake_game`, the path to the Apps Assets folder will be `/ext/apps_assets/snake_game`. But using raw paths is not recommended, because the path to the Apps Assets folder can change in the future. Use the `APP_ASSETS_PATH()` and/or `STORAGE_APP_ASSETS_PATH_PREFIX` macros instead.

## How to get the path to the Apps Assets folder?

You can use `/assets` alias to get the path to the current application data folder. For example, if you want to open a file `database.txt` in the Apps Assets folder, you can use the next path: `/data/database.txt`. But this way is not recommended, because even the `/assets` alias can change in the future.
You can use `/ext/apps_assets/appid` directly (replacing `appid`) to access your application assets folder. For example, if you want to open a file `database.txt` in the Apps Assets folder, you can use this path: `/ext/apps_assets/appid/database.txt`. But this way is not recommended, because the path can change in the future.

We recommend to use the `APP_ASSETS_PATH` macro to get the path to the Apps Assets folder. For example, if you want to open a file `database.txt` in the Apps Assets folder, you can use the next path: `APP_ASSETS_PATH("database.txt")`.
We recommend to use the `APP_ASSETS_PATH()` macro to get the path to the Apps Assets folder. For example, if you want to open a file `database.txt` in the Apps Assets folder, you can use this path: `APP_ASSETS_PATH("database.txt")`.

If you want to construct paths at run-time, you can use the `STORAGE_APP_ASSETS_PATH_PREFIX` macro, which evaluates to `/ext/apps_assets/appid` at compile-time.

## What is the difference between the Apps Assets folder and the Apps Data folder?

Expand Down
10 changes: 7 additions & 3 deletions applications/examples/example_apps_data/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,17 @@ The **Apps Data** folder is a folder used to store data for external apps that a
The path to the current application folder is related to the `appid` of the app. The `appid` is used to identify the app in the app store and is stored in the `application.fam` file.
The Apps Data folder is located only on the external storage, the SD card.

For example, if the `appid` of the app is `snake_game`, the path to the Apps Data folder will be `/ext/apps_data/snake_game`. But using raw paths is not recommended, because the path to the Apps Data folder can change in the future. Use the `/data` alias instead.
For example, if the `appid` of the app is `snake_game`, the path to the Apps Data folder will be `/ext/apps_data/snake_game`. But using raw paths is not recommended, because the path to the Apps Data folder can change in the future. Use the `APP_DATA_PATH()` and/or `STORAGE_APP_DATA_PATH_PREFIX` macros instead.

Accessing a path like this will also ensure the directory exists (just the root `/ext/apps_data/snake_game` for example, not subdirectories), so you won't need to create it.

## How to get the path to the Apps Data folder?

You can use `/data` alias to get the path to the current application data folder. For example, if you want to open a file `config.txt` in the Apps Data folder, you can use the next path: `/data/config.txt`. But this way is not recommended, because even the `/data` alias can change in the future.
You can use `/ext/apps_data/appid` directly (replacing `appid`) to access your application data folder. For example, if you want to open a file `config.txt` in the Apps Data folder, you can use this path: `/ext/apps_data/appid/config.txt`. But this way is not recommended, because the path can change in the future.

We recommend to use the `APP_DATA_PATH()` macro to get the path to the Apps Data folder. For example, if you want to open a file `config.txt` in the Apps Data folder, you can use this path: `APP_DATA_PATH("config.txt")`.

We recommend to use the `APP_DATA_PATH` macro to get the path to the Apps Data folder. For example, if you want to open a file `config.txt` in the Apps Data folder, you can use the next path: `APP_DATA_PATH("config.txt")`.
If you want to construct paths at run-time, you can use the `STORAGE_APP_DATA_PATH_PREFIX` macro, which evaluates to `/ext/apps_data/appid` at compile-time.

## What is the difference between the Apps Assets folder and the Apps Data folder?

Expand Down
26 changes: 15 additions & 11 deletions applications/services/storage/storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,21 @@
extern "C" {
#endif

#define STORAGE_INT_PATH_PREFIX "/int"
#define STORAGE_EXT_PATH_PREFIX "/ext"
#define STORAGE_ANY_PATH_PREFIX "/any"
#define STORAGE_APP_DATA_PATH_PREFIX "/data"
#define STORAGE_APP_ASSETS_PATH_PREFIX "/assets"

#define INT_PATH(path) STORAGE_INT_PATH_PREFIX "/" path
#define EXT_PATH(path) STORAGE_EXT_PATH_PREFIX "/" path
#define ANY_PATH(path) STORAGE_ANY_PATH_PREFIX "/" path
#define APP_DATA_PATH(path) STORAGE_APP_DATA_PATH_PREFIX "/" path
#define APP_ASSETS_PATH(path) STORAGE_APP_ASSETS_PATH_PREFIX "/" path
#define STORAGE_INT_PATH_PREFIX "/int"
#define STORAGE_EXT_PATH_PREFIX "/ext"
#define STORAGE_ANY_PATH_PREFIX "/any"

#define INT_PATH(path) STORAGE_INT_PATH_PREFIX "/" path
#define EXT_PATH(path) STORAGE_EXT_PATH_PREFIX "/" path
#define ANY_PATH(path) STORAGE_ANY_PATH_PREFIX "/" path

#define STORAGE_APPS_DATA_STEM EXT_PATH("apps_data")
#define STORAGE_APPS_ASSETS_STEM EXT_PATH("apps_assets")

#define STORAGE_APP_DATA_PATH_PREFIX STORAGE_APPS_DATA_STEM "/" FAP_APPID
#define STORAGE_APP_ASSETS_PATH_PREFIX STORAGE_APPS_ASSETS_STEM "/" FAP_APPID
#define APP_DATA_PATH(path) STORAGE_APP_DATA_PATH_PREFIX "/" path
#define APP_ASSETS_PATH(path) STORAGE_APP_ASSETS_PATH_PREFIX "/" path

#define RECORD_STORAGE "storage"

Expand Down
9 changes: 0 additions & 9 deletions applications/services/storage/storage_external_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ static bool storage_file_open_internal(
.path = path,
.access_mode = access_mode,
.open_mode = open_mode,
.thread_id = furi_thread_get_current_id(),
}};

file->type = FileTypeOpenFile;
Expand Down Expand Up @@ -327,7 +326,6 @@ static bool storage_dir_open_internal(File* file, const char* path) {
.dopen = {
.file = file,
.path = path,
.thread_id = furi_thread_get_current_id(),
}};

file->type = FileTypeOpenDir;
Expand Down Expand Up @@ -436,7 +434,6 @@ FS_Error storage_common_timestamp(Storage* storage, const char* path, uint32_t*
.ctimestamp = {
.path = path,
.timestamp = timestamp,
.thread_id = furi_thread_get_current_id(),
}};

S_API_MESSAGE(StorageCommandCommonTimestamp);
Expand All @@ -452,7 +449,6 @@ FS_Error storage_common_stat(Storage* storage, const char* path, FileInfo* filei
.cstat = {
.path = path,
.fileinfo = fileinfo,
.thread_id = furi_thread_get_current_id(),
}};

S_API_MESSAGE(StorageCommandCommonStat);
Expand All @@ -467,7 +463,6 @@ FS_Error storage_common_remove(Storage* storage, const char* path) {
SAData data = {
.path = {
.path = path,
.thread_id = furi_thread_get_current_id(),
}};

S_API_MESSAGE(StorageCommandCommonRemove);
Expand Down Expand Up @@ -748,7 +743,6 @@ FS_Error storage_common_mkdir(Storage* storage, const char* path) {
SAData data = {
.path = {
.path = path,
.thread_id = furi_thread_get_current_id(),
}};

S_API_MESSAGE(StorageCommandCommonMkDir);
Expand All @@ -770,7 +764,6 @@ FS_Error storage_common_fs_info(
.fs_path = fs_path,
.total_space = total_space,
.free_space = free_space,
.thread_id = furi_thread_get_current_id(),
}};

S_API_MESSAGE(StorageCommandCommonFSInfo);
Expand All @@ -786,7 +779,6 @@ void storage_common_resolve_path_and_ensure_app_directory(Storage* storage, Furi
SAData data = {
.cresolvepath = {
.path = path,
.thread_id = furi_thread_get_current_id(),
}};

S_API_MESSAGE(StorageCommandCommonResolvePath);
Expand Down Expand Up @@ -830,7 +822,6 @@ bool storage_common_equivalent_path(
.path1 = path1,
.path2 = path2,
.truncate = truncate,
.thread_id = furi_thread_get_current_id(),
}};

S_API_MESSAGE(StorageCommandCommonEquivalentPath);
Expand Down
3 changes: 0 additions & 3 deletions applications/services/storage/storage_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ extern "C" {

#define STORAGE_COUNT (ST_INT + 1)

#define APPS_DATA_PATH EXT_PATH("apps_data")
#define APPS_ASSETS_PATH EXT_PATH("apps_assets")

typedef struct {
ViewPort* view_port;
bool enabled;
Expand Down
8 changes: 0 additions & 8 deletions applications/services/storage/storage_message.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ typedef struct {
const char* path;
FS_AccessMode access_mode;
FS_OpenMode open_mode;
FuriThreadId thread_id;
} SADataFOpen;

typedef struct {
Expand All @@ -35,7 +34,6 @@ typedef struct {
typedef struct {
File* file;
const char* path;
FuriThreadId thread_id;
} SADataDOpen;

typedef struct {
Expand All @@ -48,32 +46,27 @@ typedef struct {
typedef struct {
const char* path;
uint32_t* timestamp;
FuriThreadId thread_id;
} SADataCTimestamp;

typedef struct {
const char* path;
FileInfo* fileinfo;
FuriThreadId thread_id;
} SADataCStat;

typedef struct {
const char* fs_path;
uint64_t* total_space;
uint64_t* free_space;
FuriThreadId thread_id;
} SADataCFSInfo;

typedef struct {
FuriString* path;
FuriThreadId thread_id;
} SADataCResolvePath;

typedef struct {
const char* path1;
const char* path2;
bool truncate;
FuriThreadId thread_id;
} SADataCEquivPath;

typedef struct {
Expand All @@ -82,7 +75,6 @@ typedef struct {

typedef struct {
const char* path;
FuriThreadId thread_id;
} SADataPath;

typedef struct {
Expand Down
Loading