diff --git a/libraries/AP_Filesystem/AP_Filesystem_Sys.cpp b/libraries/AP_Filesystem/AP_Filesystem_Sys.cpp index 25511bcf12517..5d97e45d316f9 100644 --- a/libraries/AP_Filesystem/AP_Filesystem_Sys.cpp +++ b/libraries/AP_Filesystem/AP_Filesystem_Sys.cpp @@ -25,6 +25,30 @@ extern const AP_HAL::HAL& hal; +struct SysFileList { + const char* name; + uint32_t filesize; +}; + +static const SysFileList sysfs_file_list[] = { + {"threads.txt", 1024}, + {"tasks.txt", 6500}, +#if HAL_MAX_CAN_PROTOCOL_DRIVERS + {"can_log.txt", 1024}, + {"can0_stats.txt", 1024}, + {"can1_stats.txt", 1024}, +#endif +}; + +int8_t AP_Filesystem_Sys::file_in_sysfs(const char *fname) { + for (uint8_t i = 0; i < ARRAY_SIZE(sysfs_file_list); i++) { + if (strcmp(fname, sysfs_file_list[i].name) == 0) { + return i; + } + } + return -1; +} + int AP_Filesystem_Sys::open(const char *fname, int flags) { if ((flags & O_ACCMODE) != O_RDONLY) { @@ -47,15 +71,24 @@ int AP_Filesystem_Sys::open(const char *fname, int flags) errno = ENOMEM; return -1; } + + // This ensure that whenever new sys file is added its also added to list above + int8_t pos = file_in_sysfs(fname); + uint32_t max_size = 0; + if (pos >= 0) { + max_size = sysfs_file_list[pos].filesize; + } else { + errno = ENOENT; + return -1; + } + if (strcmp(fname, "threads.txt") == 0) { - const uint32_t max_size = 1024; r.data->data = (char *)malloc(max_size); if (r.data->data) { r.data->length = hal.util->thread_info(r.data->data, max_size); } } if (strcmp(fname, "tasks.txt") == 0) { - const uint32_t max_size = 6500; r.data->data = (char *)malloc(max_size); if (r.data->data) { r.data->length = AP::scheduler().task_info(r.data->data, max_size); @@ -68,7 +101,6 @@ int AP_Filesystem_Sys::open(const char *fname, int flags) #if HAL_MAX_CAN_PROTOCOL_DRIVERS int8_t can_stats_num = -1; if (strcmp(fname, "can_log.txt") == 0) { - const uint32_t max_size = 1024; r.data->data = (char *)malloc(max_size); if (r.data->data) { r.data->length = AP::can().log_retrieve(r.data->data, max_size); @@ -80,7 +112,6 @@ int AP_Filesystem_Sys::open(const char *fname, int flags) } if (can_stats_num != -1 && can_stats_num < HAL_NUM_CAN_IFACES) { if (hal.can[can_stats_num] != nullptr) { - const uint32_t max_size = 1024; r.data->data = (char *)malloc(max_size); if (r.data->data) { r.data->length = hal.can[can_stats_num]->get_stats(r.data->data, max_size); @@ -145,10 +176,61 @@ int32_t AP_Filesystem_Sys::lseek(int fd, int32_t offset, int seek_from) return r.file_ofs; } -int AP_Filesystem_Sys::stat(const char *name, struct stat *stbuf) +void *AP_Filesystem_Sys::opendir(const char *pathname) +{ + if (strlen(pathname) > 0) { + // no sub directories + errno = ENOENT; + return nullptr; + } + DirReadTracker *dtracker = new DirReadTracker; + if (dtracker == nullptr) { + errno = ENOMEM; + return nullptr; + } + return dtracker; +} + +struct dirent *AP_Filesystem_Sys::readdir(void *dirp) +{ + DirReadTracker* dtracker = ((DirReadTracker*)dirp); + if (dtracker->file_offset >= ARRAY_SIZE(sysfs_file_list)) { + // we have reached end of list + return nullptr; + } + dtracker->curr_file.d_type = DT_REG; + size_t max_length = ARRAY_SIZE(dtracker->curr_file.d_name); + strncpy(dtracker->curr_file.d_name, sysfs_file_list[dtracker->file_offset].name, max_length); + dtracker->file_offset++; + return &dtracker->curr_file; +} + +int AP_Filesystem_Sys::closedir(void *dirp) { + if (dirp == nullptr) { + errno = EINVAL; + return -1; + } + delete (DirReadTracker*)dirp; + return 0; +} + +int AP_Filesystem_Sys::stat(const char *pathname, struct stat *stbuf) +{ + if (pathname == nullptr || stbuf == nullptr || (strlen(pathname) == 0)) { + errno = EINVAL; + return -1; + } memset(stbuf, 0, sizeof(*stbuf)); - // give fixed size, EOF on read gives real size - stbuf->st_size = 1024*1024; + if (strlen(pathname) == 1 && pathname[0] == '/') { + stbuf->st_size = 0; // just a placeholder value + return 0; + } + int8_t pos = file_in_sysfs(&pathname[1]); + if (pos < 0) { + errno = ENOENT; + return -1; + } + stbuf->st_size = sysfs_file_list[pos].filesize; return 0; } diff --git a/libraries/AP_Filesystem/AP_Filesystem_Sys.h b/libraries/AP_Filesystem/AP_Filesystem_Sys.h index 870c956a9f8f6..9907527ee3be4 100644 --- a/libraries/AP_Filesystem/AP_Filesystem_Sys.h +++ b/libraries/AP_Filesystem/AP_Filesystem_Sys.h @@ -26,16 +26,25 @@ class AP_Filesystem_Sys : public AP_Filesystem_Backend int32_t read(int fd, void *buf, uint32_t count) override; int32_t lseek(int fd, int32_t offset, int whence) override; int stat(const char *pathname, struct stat *stbuf) override; + void *opendir(const char *pathname) override; + struct dirent *readdir(void *dirp) override; + int closedir(void *dirp) override; private: // only allow up to 4 files at a time static constexpr uint8_t max_open_file = 4; + int8_t file_in_sysfs(const char *fname); struct file_data { char *data; size_t length; }; + struct DirReadTracker { + size_t file_offset; + struct dirent curr_file; + }; + struct rfile { bool open; uint32_t file_ofs;