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