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

AP_Filesystem: add support for listing @SYS files #15493

Merged
merged 1 commit into from Oct 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
96 changes: 89 additions & 7 deletions libraries/AP_Filesystem/AP_Filesystem_Sys.cpp
Expand Up @@ -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) {
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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;
}
bugobliterator marked this conversation as resolved.
Show resolved Hide resolved
stbuf->st_size = sysfs_file_list[pos].filesize;
return 0;
}
9 changes: 9 additions & 0 deletions libraries/AP_Filesystem/AP_Filesystem_Sys.h
Expand Up @@ -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;
Expand Down