Skip to content

Commit a052fa3

Browse files
Merge pull request #4561 from geky/fat-fs-volume-prefixes
fatfs: Add full support for multiple fs volume prefixes
2 parents b38c85c + 1775e1f commit a052fa3

File tree

1 file changed

+77
-17
lines changed

1 file changed

+77
-17
lines changed

features/filesystem/fat/FATFileSystem.cpp

Lines changed: 77 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,61 @@ static int fat_error_remap(FRESULT res)
7171
}
7272
}
7373

74+
// Helper class for deferring operations when variable falls out of scope
75+
template <typename T>
76+
class Deferred {
77+
public:
78+
T _t;
79+
Callback<void(T)> _ondefer;
80+
81+
Deferred(const Deferred&);
82+
Deferred &operator=(const Deferred&);
83+
84+
public:
85+
Deferred(T t, Callback<void(T)> ondefer = NULL)
86+
: _t(t), _ondefer(ondefer)
87+
{
88+
}
89+
90+
operator T()
91+
{
92+
return _t;
93+
}
94+
95+
~Deferred()
96+
{
97+
if (_ondefer) {
98+
_ondefer(_t);
99+
}
100+
}
101+
};
102+
103+
static void dodelete(const char *data)
104+
{
105+
delete[] data;
106+
}
107+
108+
// Adds prefix needed internally by fatfs, this can be avoided for the first fatfs
109+
// (id 0) otherwise a prefix of "id:/" is inserted in front of the string.
110+
static Deferred<const char*> fat_path_prefix(int id, const char *path)
111+
{
112+
// We can avoid dynamic allocation when only on fatfs is in use
113+
if (id == 0) {
114+
return path;
115+
}
116+
117+
// Prefix path with id, will look something like 2:/hi/hello/filehere.txt
118+
char *buffer = new char[strlen("0:/") + strlen(path) + 1];
119+
if (!buffer) {
120+
return NULL;
121+
}
122+
123+
buffer[0] = '0' + id;
124+
buffer[1] = ':';
125+
buffer[2] = '/';
126+
strcpy(buffer + strlen("0:/"), path);
127+
return Deferred<const char*>(buffer, dodelete);
128+
}
74129

75130

76131
////// Disk operations //////
@@ -263,9 +318,11 @@ int FATFileSystem::format(BlockDevice *bd, int allocation_unit) {
263318
return 0;
264319
}
265320

266-
int FATFileSystem::remove(const char *filename) {
321+
int FATFileSystem::remove(const char *path) {
322+
Deferred<const char*> fpath = fat_path_prefix(_id, path);
323+
267324
lock();
268-
FRESULT res = f_unlink(filename);
325+
FRESULT res = f_unlink(fpath);
269326
unlock();
270327

271328
if (res != FR_OK) {
@@ -274,9 +331,12 @@ int FATFileSystem::remove(const char *filename) {
274331
return fat_error_remap(res);
275332
}
276333

277-
int FATFileSystem::rename(const char *oldname, const char *newname) {
334+
int FATFileSystem::rename(const char *oldpath, const char *newpath) {
335+
Deferred<const char*> oldfpath = fat_path_prefix(_id, oldpath);
336+
Deferred<const char*> newfpath = fat_path_prefix(_id, newpath);
337+
278338
lock();
279-
FRESULT res = f_rename(oldname, newname);
339+
FRESULT res = f_rename(oldfpath, newfpath);
280340
unlock();
281341

282342
if (res != FR_OK) {
@@ -285,9 +345,11 @@ int FATFileSystem::rename(const char *oldname, const char *newname) {
285345
return fat_error_remap(res);
286346
}
287347

288-
int FATFileSystem::mkdir(const char *name, mode_t mode) {
348+
int FATFileSystem::mkdir(const char *path, mode_t mode) {
349+
Deferred<const char*> fpath = fat_path_prefix(_id, path);
350+
289351
lock();
290-
FRESULT res = f_mkdir(name);
352+
FRESULT res = f_mkdir(fpath);
291353
unlock();
292354

293355
if (res != FR_OK) {
@@ -296,12 +358,14 @@ int FATFileSystem::mkdir(const char *name, mode_t mode) {
296358
return fat_error_remap(res);
297359
}
298360

299-
int FATFileSystem::stat(const char *name, struct stat *st) {
361+
int FATFileSystem::stat(const char *path, struct stat *st) {
362+
Deferred<const char*> fpath = fat_path_prefix(_id, path);
363+
300364
lock();
301365
FILINFO f;
302366
memset(&f, 0, sizeof(f));
303367

304-
FRESULT res = f_stat(name, &f);
368+
FRESULT res = f_stat(fpath, &f);
305369
if (res != FR_OK) {
306370
unlock();
307371
return fat_error_remap(res);
@@ -332,13 +396,10 @@ void FATFileSystem::unlock() {
332396

333397
////// File operations //////
334398
int FATFileSystem::file_open(fs_file_t *file, const char *path, int flags) {
335-
debug_if(FFS_DBG, "open(%s) on filesystem [%s], drv [%s]\n", path, getName(), _fsid);
399+
debug_if(FFS_DBG, "open(%s) on filesystem [%s], drv [%s]\n", path, getName(), _id);
336400

337401
FIL *fh = new FIL;
338-
char *buffer = new char[strlen(_fsid) + strlen(path) + 3];
339-
strcpy(buffer, _fsid);
340-
strcat(buffer, "/");
341-
strcat(buffer, path);
402+
Deferred<const char*> fpath = fat_path_prefix(_id, path);
342403

343404
/* POSIX flags -> FatFS open mode */
344405
BYTE openmode;
@@ -358,12 +419,11 @@ int FATFileSystem::file_open(fs_file_t *file, const char *path, int flags) {
358419
}
359420

360421
lock();
361-
FRESULT res = f_open(fh, buffer, openmode);
422+
FRESULT res = f_open(fh, fpath, openmode);
362423

363424
if (res != FR_OK) {
364425
unlock();
365426
debug_if(FFS_DBG, "f_open('w') failed: %d\n", res);
366-
delete[] buffer;
367427
delete fh;
368428
return fat_error_remap(res);
369429
}
@@ -373,7 +433,6 @@ int FATFileSystem::file_open(fs_file_t *file, const char *path, int flags) {
373433
}
374434
unlock();
375435

376-
delete[] buffer;
377436
*file = fh;
378437
return 0;
379438
}
@@ -480,9 +539,10 @@ off_t FATFileSystem::file_size(fs_file_t file) {
480539
////// Dir operations //////
481540
int FATFileSystem::dir_open(fs_dir_t *dir, const char *path) {
482541
FATFS_DIR *dh = new FATFS_DIR;
542+
Deferred<const char*> fpath = fat_path_prefix(_id, path);
483543

484544
lock();
485-
FRESULT res = f_opendir(dh, path);
545+
FRESULT res = f_opendir(dh, fpath);
486546
unlock();
487547

488548
if (res != FR_OK) {

0 commit comments

Comments
 (0)