LCOV - code coverage report
Current view: top level - AP_Filesystem - AP_Filesystem_ROMFS.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 78 138 56.5 %
Date: 2026-09-09 11:02:08 Functions: 9 17 52.9 %

          Line data    Source code
       1             : /*
       2             :    This program is free software: you can redistribute it and/or modify
       3             :    it under the terms of the GNU General Public License as published by
       4             :    the Free Software Foundation, either version 3 of the License, or
       5             :    (at your option) any later version.
       6             : 
       7             :    This program is distributed in the hope that it will be useful,
       8             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
       9             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      10             :    GNU General Public License for more details.
      11             : 
      12             :    You should have received a copy of the GNU General Public License
      13             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      14             :  */
      15             : /*
      16             :   ArduPilot filesystem interface for ROMFS
      17             :  */
      18             : 
      19             : #include "AP_Filesystem_config.h"
      20             : 
      21             : #if AP_FILESYSTEM_ROMFS_ENABLED
      22             : 
      23             : #include "AP_Filesystem.h"
      24             : #include "AP_Filesystem_ROMFS.h"
      25             : #include <AP_HAL/AP_HAL.h>
      26             : #include <AP_Math/AP_Math.h>
      27             : #include <AP_ROMFS/AP_ROMFS.h>
      28             : 
      29       16592 : int AP_Filesystem_ROMFS::open(const char *fname, int flags, bool allow_absolute_paths)
      30             : {
      31       16592 :     if ((flags & O_ACCMODE) != O_RDONLY) {
      32           0 :         errno = EROFS;
      33           0 :         return -1;
      34             :     }
      35             : 
      36       16592 :     WITH_SEMAPHORE(record_sem); // search for free file record
      37             :     uint8_t idx;
      38       16592 :     for (idx=0; idx<max_open_file; idx++) {
      39       16592 :         if (file[idx].data == nullptr) {
      40       16592 :             break;
      41             :         }
      42             :     }
      43       16592 :     if (idx == max_open_file) {
      44           0 :         errno = ENFILE;
      45           0 :         return -1;
      46             :     }
      47       16592 :     file[idx].data = AP_ROMFS::find_decompress(fname, file[idx].size);
      48       16592 :     if (file[idx].data == nullptr) {
      49        2315 :         errno = ENOENT;
      50        2315 :         return -1;
      51             :     }
      52       14277 :     file[idx].ofs = 0;
      53       14277 :     return idx;
      54       16592 : }
      55             : 
      56       14277 : int AP_Filesystem_ROMFS::close(int fd)
      57             : {
      58       14277 :     if (fd < 0 || fd >= max_open_file || file[fd].data == nullptr) {
      59           0 :         errno = EBADF;
      60           0 :         return -1;
      61             :     }
      62             : 
      63       14277 :     WITH_SEMAPHORE(record_sem); // release file record
      64       14277 :     AP_ROMFS::free(file[fd].data);
      65       14277 :     file[fd].data = nullptr;
      66       14277 :     return 0;
      67       14277 : }
      68             : 
      69      690431 : int32_t AP_Filesystem_ROMFS::read(int fd, void *buf, uint32_t count)
      70             : {
      71      690431 :     if (fd < 0 || fd >= max_open_file || file[fd].data == nullptr) {
      72           0 :         errno = EBADF;
      73           0 :         return -1;
      74             :     }
      75      690431 :     count = MIN(file[fd].size - file[fd].ofs, count);
      76      690431 :     if (count == 0) {
      77       12154 :         return 0;
      78             :     }
      79      678277 :     memcpy(buf, &file[fd].data[file[fd].ofs], count);
      80      678277 :     file[fd].ofs += count;
      81      678277 :     return count;
      82             : }
      83             : 
      84           0 : int32_t AP_Filesystem_ROMFS::write(int fd, const void *buf, uint32_t count)
      85             : {
      86           0 :     errno = EROFS;
      87           0 :     return -1;
      88             : }
      89             : 
      90           0 : int AP_Filesystem_ROMFS::fsync(int fd)
      91             : {
      92           0 :     return 0;
      93             : }
      94             : 
      95     1364462 : int32_t AP_Filesystem_ROMFS::lseek(int fd, int32_t offset, int seek_from)
      96             : {
      97     1364462 :     if (fd < 0 || fd >= max_open_file || file[fd].data == nullptr) {
      98           0 :         errno = EBADF;
      99           0 :         return -1;
     100             :     }
     101     1364462 :     switch (seek_from) {
     102      676154 :     case SEEK_SET:
     103      676154 :         if (offset < 0) {
     104           0 :             errno = EINVAL;
     105           0 :             return -1;
     106             :         }
     107      676154 :         file[fd].ofs = MIN(file[fd].size, (uint32_t)offset);
     108      676154 :         break;
     109      688308 :     case SEEK_CUR:
     110      688308 :         file[fd].ofs = MIN(file[fd].size, offset+file[fd].ofs);
     111      688308 :         break;
     112           0 :     case SEEK_END:
     113           0 :         file[fd].ofs = file[fd].size;
     114           0 :         break;
     115             :     }
     116     1364462 :     return file[fd].ofs;
     117             : }
     118             : 
     119        8492 : int AP_Filesystem_ROMFS::stat(const char *name, struct stat *stbuf)
     120             : {
     121             :     uint32_t size;
     122        8492 :     if (!AP_ROMFS::find_size(name, size)) {
     123        6340 :         errno = ENOENT;
     124        6340 :         return -1;
     125             :     }
     126        2152 :     memset(stbuf, 0, sizeof(*stbuf));
     127        2152 :     stbuf->st_size = size;
     128        2152 :     return 0;
     129             : }
     130             : 
     131           0 : int AP_Filesystem_ROMFS::unlink(const char *pathname)
     132             : {
     133           0 :     errno = EROFS;
     134           0 :     return -1;
     135             : }
     136             : 
     137           0 : int AP_Filesystem_ROMFS::mkdir(const char *pathname)
     138             : {
     139           0 :     errno = EROFS;
     140           0 :     return -1;
     141             : }
     142             : 
     143           1 : void *AP_Filesystem_ROMFS::opendir(const char *pathname)
     144             : {
     145           1 :     WITH_SEMAPHORE(record_sem); // search for free directory record
     146             :     uint8_t idx;
     147           1 :     for (idx=0; idx<max_open_dir; idx++) {
     148           1 :         if (dir[idx].path == nullptr) {
     149           1 :             break;
     150             :         }
     151             :     }
     152           1 :     if (idx == max_open_dir) {
     153           0 :         errno = ENFILE;
     154           0 :         return nullptr;
     155             :     }
     156           1 :     dir[idx].ofs = 0;
     157           1 :     dir[idx].path = strdup(pathname);
     158           1 :     if (!dir[idx].path) {
     159           0 :         return nullptr;
     160             :     }
     161             : 
     162             :     // Take a sneak peek and reset
     163           1 :     const char *name = AP_ROMFS::dir_list(dir[idx].path, dir[idx].ofs);
     164           1 :     dir[idx].ofs = 0;
     165           1 :     if (!name) {
     166             :         // Directory does not exist
     167           0 :         return nullptr;
     168             :     }
     169             : 
     170           1 :     return (void*)&dir[idx];
     171           1 : }
     172             : 
     173           0 : struct dirent *AP_Filesystem_ROMFS::readdir(void *dirp)
     174             : {
     175           0 :     uint32_t idx = ((rdir*)dirp) - &dir[0];
     176           0 :     if (idx >= max_open_dir) {
     177           0 :         errno = EBADF;
     178           0 :         return nullptr;
     179             :     }
     180           0 :     const char *name = AP_ROMFS::dir_list(dir[idx].path, dir[idx].ofs);
     181           0 :     if (!name) {
     182           0 :         return nullptr;
     183             :     }
     184           0 :     const uint32_t plen = strlen(dir[idx].path);
     185           0 :     if (plen > 0) {
     186             :         // Offset to get just file/directory name
     187           0 :         name += plen + 1;
     188             :     }
     189             : 
     190             :     // Copy full name
     191           0 :     strncpy(dir[idx].de.d_name, name, sizeof(dir[idx].de.d_name));
     192             : 
     193           0 :     const char* slash = strchr(name, '/');
     194           0 :     if (slash == nullptr) {
     195             :         // File
     196             : #if AP_FILESYSTEM_HAVE_DIRENT_DTYPE
     197           0 :         dir[idx].de.d_type = DT_REG;
     198             : #endif
     199             :     } else {
     200             :         // Directory
     201             : #if AP_FILESYSTEM_HAVE_DIRENT_DTYPE
     202           0 :         dir[idx].de.d_type = DT_DIR;
     203             : #endif
     204             : 
     205             :         // Add null termination after directory name
     206           0 :         const size_t index = slash - name;
     207           0 :         dir[idx].de.d_name[index] = 0;
     208             :     }
     209             : 
     210           0 :     return &dir[idx].de;
     211             : }
     212             : 
     213           1 : int AP_Filesystem_ROMFS::closedir(void *dirp)
     214             : {
     215           1 :     uint32_t idx = ((rdir *)dirp) - &dir[0];
     216           1 :     if (idx >= max_open_dir) {
     217           0 :         errno = EBADF;
     218           0 :         return -1;
     219             :     }
     220             : 
     221           1 :     WITH_SEMAPHORE(record_sem); // release directory record
     222           1 :     free(dir[idx].path);
     223           1 :     dir[idx].path = nullptr;
     224           1 :     return 0;
     225           1 : }
     226             : 
     227             : // return free disk space in bytes
     228           0 : int64_t AP_Filesystem_ROMFS::disk_free(const char *path)
     229             : {
     230           0 :     return 0;
     231             : }
     232             : 
     233             : // return total disk space in bytes
     234           0 : int64_t AP_Filesystem_ROMFS::disk_space(const char *path)
     235             : {
     236           0 :     return 0;
     237             : }
     238             : 
     239             : /*
     240             :   set mtime on a file
     241             :  */
     242           0 : bool AP_Filesystem_ROMFS::set_mtime(const char *filename, const uint32_t mtime_sec)
     243             : {
     244           0 :     return false;
     245             : }
     246             : 
     247             : /*
     248             :   Load a file's contents into memory. Returned object must be `delete`d to free
     249             :   the data. The data is guaranteed to be null-terminated such that it can be
     250             :   treated as a string. Overridden in ROMFS to avoid taking twice the memory.
     251             : */
     252           8 : FileData *AP_Filesystem_ROMFS::load_file(const char *filename)
     253             : {
     254           8 :     FileData *fd = NEW_NOTHROW FileData(this);
     255           8 :     if (!fd) {
     256           0 :         return nullptr;
     257             :     }
     258             :     // AP_ROMFS adds the guaranteed termination so we don't have to.
     259           8 :     fd->data = AP_ROMFS::find_decompress(filename, fd->length);
     260           8 :     if (fd->data == nullptr) {
     261           0 :         delete fd;
     262           0 :         return nullptr;
     263             :     }
     264           8 :     return fd;
     265             : }
     266             : 
     267             : // unload data from load_file()
     268           8 : void AP_Filesystem_ROMFS::unload_file(FileData *fd)
     269             : {
     270           8 :     AP_ROMFS::free(fd->data);
     271           8 : }
     272             : 
     273             : #endif // AP_FILESYSTEM_ROMFS_ENABLED

Generated by: LCOV version 1.14