AP_Filesystem: list virtual @SYS, @MISSION etc directories in /

Adds virtual directory entries for these virtual filesystems in /

RTL> ftp list
RTL> Listing /
 D @MISSION
 D @PARAM
 D @ROMFS
 D @SYS
 D APM
 D log
   V5_BT.dfu	10541
   bootlog.txt	297
   dataman	350216
   message-intervals-chan0.txt	7
Total size 352.60 kByte
ftp list @MISSION
RTL> Listing @MISSION
LIST: OP seq:7 sess:2 opcode:129 req_opcode:3 size:2 bc:0 ofs:0 plen=2 [2]
ftp list @ROMFS
RTL> Listing @ROMFS
   bootloader.bin	16448
   hwdef.dat	5743
   io_firmware.bin	40880
Total size 61.59 kByte

This PR also makes us *much* more lenient in what we accept for looking at virtual filesystems, so

ftp list @SYS
ftp list /@SYS
ftp list @SYS/
ftp list /@SYS/

should all work
This commit is contained in:
Peter Barker 2022-10-17 10:25:30 +11:00 committed by Peter Barker
parent e9d065c1cc
commit ac769014c4
2 changed files with 53 additions and 6 deletions

View File

@ -63,18 +63,16 @@ static AP_Filesystem_Mission fs_mission;
const AP_Filesystem::Backend AP_Filesystem::backends[] = {
{ nullptr, fs_local },
#if AP_FILESYSTEM_ROMFS_ENABLED
{ "@ROMFS/", fs_romfs },
{ "@ROMFS", fs_romfs },
#endif
#if AP_FILESYSTEM_PARAM_ENABLED
{ "@PARAM/", fs_param },
{ "@PARAM", fs_param },
#endif
#if AP_FILESYSTEM_SYS_ENABLED
{ "@SYS/", fs_sys },
{ "@SYS", fs_sys },
#endif
#if AP_FILESYSTEM_MISSION_ENABLED
{ "@MISSION/", fs_mission },
{ "@MISSION", fs_mission },
#endif
};
@ -90,10 +88,19 @@ extern const AP_HAL::HAL& hal;
*/
const AP_Filesystem::Backend &AP_Filesystem::backend_by_path(const char *&path) const
{
// ignore leading slashes:
const char *path_with_no_leading_slash = path;
if (path_with_no_leading_slash[0] == '/') {
path_with_no_leading_slash = &path_with_no_leading_slash[1];
}
for (uint8_t i=1; i<NUM_BACKENDS; i++) {
const uint8_t plen = strlen(backends[i].prefix);
if (strncmp(path, backends[i].prefix, plen) == 0) {
if (strncmp(path_with_no_leading_slash, backends[i].prefix, plen) == 0) {
path = path_with_no_leading_slash;
path += plen;
if (strlen(path) > 0 && path[0] == '/') {
path++;
}
return backends[i];
}
}
@ -188,6 +195,18 @@ int AP_Filesystem::rename(const char *oldpath, const char *newpath)
AP_Filesystem::DirHandle *AP_Filesystem::opendir(const char *pathname)
{
// support reading a list of "@" filesystems (e.g. @SYS) in
// listing of root directory. Note that backend_by_path modifies
// its parameter.
if (strlen(pathname) == 0 ||
(strlen(pathname) == 1 && pathname[0] == '/')) {
virtual_dirent.backend_ofs = 0;
virtual_dirent.d_off = 0;
virtual_dirent.de.d_type = DT_DIR;
} else {
virtual_dirent.backend_ofs = 255;
}
const Backend &backend = backend_by_path(pathname);
DirHandle *h = new DirHandle;
if (!h) {
@ -199,6 +218,7 @@ AP_Filesystem::DirHandle *AP_Filesystem::opendir(const char *pathname)
return nullptr;
}
h->fs_index = BACKEND_IDX(backend);
return h;
}
@ -208,7 +228,26 @@ struct dirent *AP_Filesystem::readdir(DirHandle *dirp)
return nullptr;
}
const Backend &backend = backends[dirp->fs_index];
return backend.fs.readdir(dirp->dir);
struct dirent * ret = backend.fs.readdir(dirp->dir);
if (ret != nullptr) {
return ret;
}
// virtual directory entries in the root directory (e.g. @SYS, @MISSION)
for (; ret == nullptr && virtual_dirent.backend_ofs < ARRAY_SIZE(AP_Filesystem::backends); virtual_dirent.backend_ofs++) {
const char *prefix = backends[virtual_dirent.backend_ofs].prefix;
if (prefix == nullptr) {
continue;
}
if (prefix[0] != '@') {
continue;
}
// found a virtual directory we haven't returned yet
strncpy_noterm(virtual_dirent.de.d_name, prefix, sizeof(virtual_dirent.de.d_name));
virtual_dirent.d_off++;
ret = &virtual_dirent.de;
}
return ret;
}
int AP_Filesystem::closedir(DirHandle *dirp)

View File

@ -155,6 +155,14 @@ private:
find backend by open fd
*/
const Backend &backend_by_fd(int &fd) const;
// support for listing out virtual directory entries (e.g. @SYS
// then @MISSION)
struct {
uint8_t backend_ofs;
struct dirent de;
uint8_t d_off;
} virtual_dirent;
};
namespace AP {