From f8143eea68c5a5af38b110497fd4e37189fec83f Mon Sep 17 00:00:00 2001 From: Peter Barker Date: Mon, 17 Oct 2022 10:25:30 +1100 Subject: [PATCH] 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 --- libraries/AP_Filesystem/AP_Filesystem.cpp | 52 ++++++++++++++++++++--- libraries/AP_Filesystem/AP_Filesystem.h | 8 ++++ 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/libraries/AP_Filesystem/AP_Filesystem.cpp b/libraries/AP_Filesystem/AP_Filesystem.cpp index e62ec5920827c3..3597bfda01c83e 100644 --- a/libraries/AP_Filesystem/AP_Filesystem.cpp +++ b/libraries/AP_Filesystem/AP_Filesystem.cpp @@ -63,17 +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 }; @@ -89,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 0 && path[0] == '/') { + path++; + } return backends[i]; } } @@ -187,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) { @@ -198,6 +218,7 @@ AP_Filesystem::DirHandle *AP_Filesystem::opendir(const char *pathname) return nullptr; } h->fs_index = BACKEND_IDX(backend); + return h; } @@ -207,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) diff --git a/libraries/AP_Filesystem/AP_Filesystem.h b/libraries/AP_Filesystem/AP_Filesystem.h index b139713a751f59..63dfb68fa64ec8 100644 --- a/libraries/AP_Filesystem/AP_Filesystem.h +++ b/libraries/AP_Filesystem/AP_Filesystem.h @@ -155,6 +155,14 @@ class AP_Filesystem { 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 {