"Das U-Boot" Source Tree
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge patch series "fs: ext4: implement opendir, readdir, closedir"

Heinrich Schuchardt <heinrich.schuchardt@canonical.com> says:

With this series opendir, readdir, closedir are implemented for ext4.
These functions are needed for the UEFI sub-system to interact with
the ext4 file system.

To reduce code growth the functions are reused to implement the ls
command for ext4.

A memory leak in ext4fs_exists is resolved.

ext4fs_iterate_dir is simplified by removing a redundant pointer copy.

Link: https://lore.kernel.org/r/20241026064048.370062-1-heinrich.schuchardt@canonical.com

Tom Rini 8e5e64d5 15a55dbf

+197 -75
+9 -39
fs/ext4/ext4_common.c
··· 2046 2046 unsigned int fpos = 0; 2047 2047 int status; 2048 2048 loff_t actread; 2049 - struct ext2fs_node *diro = (struct ext2fs_node *) dir; 2050 2049 2051 2050 #ifdef DEBUG 2052 2051 if (name != NULL) 2053 2052 printf("Iterate dir %s\n", name); 2054 2053 #endif /* of DEBUG */ 2055 - if (!diro->inode_read) { 2056 - status = ext4fs_read_inode(diro->data, diro->ino, &diro->inode); 2054 + if (!dir->inode_read) { 2055 + status = ext4fs_read_inode(dir->data, dir->ino, &dir->inode); 2057 2056 if (status == 0) 2058 2057 return 0; 2059 2058 } 2060 2059 /* Search the file. */ 2061 - while (fpos < le32_to_cpu(diro->inode.size)) { 2060 + while (fpos < le32_to_cpu(dir->inode.size)) { 2062 2061 struct ext2_dirent dirent; 2063 2062 2064 - status = ext4fs_read_file(diro, fpos, 2065 - sizeof(struct ext2_dirent), 2066 - (char *)&dirent, &actread); 2063 + status = ext4fs_read_file(dir, fpos, 2064 + sizeof(struct ext2_dirent), 2065 + (char *)&dirent, &actread); 2067 2066 if (status < 0) 2068 2067 return 0; 2069 2068 ··· 2077 2076 struct ext2fs_node *fdiro; 2078 2077 int type = FILETYPE_UNKNOWN; 2079 2078 2080 - status = ext4fs_read_file(diro, 2079 + status = ext4fs_read_file(dir, 2081 2080 fpos + 2082 2081 sizeof(struct ext2_dirent), 2083 2082 dirent.namelen, filename, ··· 2089 2088 if (!fdiro) 2090 2089 return 0; 2091 2090 2092 - fdiro->data = diro->data; 2091 + fdiro->data = dir->data; 2093 2092 fdiro->ino = le32_to_cpu(dirent.inode); 2094 2093 2095 2094 filename[dirent.namelen] = '\0'; ··· 2104 2103 else if (dirent.filetype == FILETYPE_REG) 2105 2104 type = FILETYPE_REG; 2106 2105 } else { 2107 - status = ext4fs_read_inode(diro->data, 2106 + status = ext4fs_read_inode(dir->data, 2108 2107 le32_to_cpu 2109 2108 (dirent.inode), 2110 2109 &fdiro->inode); ··· 2138 2137 *fnode = fdiro; 2139 2138 return 1; 2140 2139 } 2141 - } else { 2142 - if (fdiro->inode_read == 0) { 2143 - status = ext4fs_read_inode(diro->data, 2144 - le32_to_cpu( 2145 - dirent.inode), 2146 - &fdiro->inode); 2147 - if (status == 0) { 2148 - free(fdiro); 2149 - return 0; 2150 - } 2151 - fdiro->inode_read = 1; 2152 - } 2153 - switch (type) { 2154 - case FILETYPE_DIRECTORY: 2155 - printf("<DIR> "); 2156 - break; 2157 - case FILETYPE_SYMLINK: 2158 - printf("<SYM> "); 2159 - break; 2160 - case FILETYPE_REG: 2161 - printf(" "); 2162 - break; 2163 - default: 2164 - printf("< ? > "); 2165 - break; 2166 - } 2167 - printf("%10u %s\n", 2168 - le32_to_cpu(fdiro->inode.size), 2169 - filename); 2170 2140 } 2171 2141 free(fdiro); 2172 2142 }
+158 -19
fs/ext4/ext4fs.c
··· 21 21 */ 22 22 23 23 #include <blk.h> 24 + #include <div64.h> 25 + #include <errno.h> 24 26 #include <ext_common.h> 25 27 #include <ext4fs.h> 26 - #include "ext4_common.h" 27 - #include <div64.h> 28 28 #include <malloc.h> 29 29 #include <part.h> 30 30 #include <u-boot/uuid.h> 31 + #include "ext4_common.h" 31 32 32 33 int ext4fs_symlinknest; 33 34 struct ext_filesystem ext_fs; 35 + 36 + /** 37 + * struct ext4_dir_stream - ext4 directory stream 38 + * 39 + * @parent: partition data used by fs layer. 40 + * This field must be at the beginning of the structure. 41 + * All other fields are private to the ext4 driver. 42 + * @root: root directory node 43 + * @dir: directory node 44 + * @dirent: directory stream entry 45 + * @fpos: file position in directory 46 + */ 47 + struct ext4_dir_stream { 48 + struct fs_dir_stream parent; 49 + char *dirname; 50 + struct fs_dirent dirent; 51 + unsigned int fpos; 52 + }; 34 53 35 54 struct ext_filesystem *get_fs(void) 36 55 { ··· 182 201 return 0; 183 202 } 184 203 185 - int ext4fs_ls(const char *dirname) 204 + int ext4fs_opendir(const char *dirname, struct fs_dir_stream **dirsp) 186 205 { 187 - struct ext2fs_node *dirnode = NULL; 188 - int status; 206 + struct ext4_dir_stream *dirs; 207 + struct ext2fs_node *dir = NULL; 208 + int ret; 209 + 210 + *dirsp = NULL; 211 + 212 + dirs = calloc(1, sizeof(struct ext4_dir_stream)); 213 + if (!dirs) 214 + return -ENOMEM; 215 + dirs->dirname = strdup(dirname); 216 + if (!dirs) { 217 + free(dirs); 218 + return -ENOMEM; 219 + } 220 + 221 + ret = ext4fs_find_file(dirname, &ext4fs_root->diropen, &dir, 222 + FILETYPE_DIRECTORY); 223 + if (ret == 1) { 224 + ret = 0; 225 + *dirsp = (struct fs_dir_stream *)dirs; 226 + } else { 227 + ret = -ENOENT; 228 + } 229 + 230 + if (dir) 231 + ext4fs_free_node(dir, &ext4fs_root->diropen); 232 + 233 + return ret; 234 + } 235 + 236 + int ext4fs_readdir(struct fs_dir_stream *fs_dirs, struct fs_dirent **dentp) 237 + { 238 + struct ext4_dir_stream *dirs = (struct ext4_dir_stream *)fs_dirs; 239 + struct fs_dirent *dent = &dirs->dirent; 240 + struct ext2fs_node *dir = NULL; 241 + int ret; 242 + loff_t actread; 243 + struct ext2fs_node fdiro; 244 + int len; 245 + struct ext2_dirent dirent; 246 + 247 + *dentp = NULL; 248 + 249 + ret = ext4fs_find_file(dirs->dirname, &ext4fs_root->diropen, &dir, 250 + FILETYPE_DIRECTORY); 251 + if (ret != 1) { 252 + ret = -ENOENT; 253 + goto out; 254 + } 255 + if (!dir->inode_read) { 256 + ret = ext4fs_read_inode(dir->data, dir->ino, &dir->inode); 257 + if (!ret) { 258 + ret = -EIO; 259 + goto out; 260 + } 261 + } 262 + 263 + if (dirs->fpos >= le32_to_cpu(dir->inode.size)) 264 + return -ENOENT; 265 + 266 + memset(dent, 0, sizeof(struct fs_dirent)); 267 + 268 + while (dirs->fpos < le32_to_cpu(dir->inode.size)) { 269 + ret = ext4fs_read_file(dir, dirs->fpos, 270 + sizeof(struct ext2_dirent), 271 + (char *)&dirent, &actread); 272 + if (ret < 0) 273 + return -ret; 189 274 190 - if (dirname == NULL) 191 - return 0; 275 + if (!dirent.direntlen) 276 + return -EIO; 192 277 193 - status = ext4fs_find_file(dirname, &ext4fs_root->diropen, &dirnode, 194 - FILETYPE_DIRECTORY); 195 - if (status != 1) { 196 - printf("** Can not find directory. **\n"); 197 - if (dirnode) 198 - ext4fs_free_node(dirnode, &ext4fs_root->diropen); 199 - return 1; 278 + if (dirent.namelen) 279 + break; 280 + 281 + dirs->fpos += le16_to_cpu(dirent.direntlen); 200 282 } 201 283 202 - ext4fs_iterate_dir(dirnode, NULL, NULL, NULL); 203 - ext4fs_free_node(dirnode, &ext4fs_root->diropen); 284 + len = min(FS_DIRENT_NAME_LEN - 1, (int)dirent.namelen); 285 + 286 + ret = ext4fs_read_file(dir, dirs->fpos + sizeof(struct ext2_dirent), 287 + len, dent->name, &actread); 288 + if (ret < 0) 289 + goto out; 290 + dent->name[len] = '\0'; 204 291 205 - return 0; 292 + fdiro.data = dir->data; 293 + fdiro.ino = le32_to_cpu(dirent.inode); 294 + 295 + ret = ext4fs_read_inode(dir->data, fdiro.ino, &fdiro.inode); 296 + if (!ret) { 297 + ret = -EIO; 298 + goto out; 299 + } 300 + 301 + switch (le16_to_cpu(fdiro.inode.mode) & FILETYPE_INO_MASK) { 302 + case FILETYPE_INO_DIRECTORY: 303 + dent->type = FS_DT_DIR; 304 + break; 305 + case FILETYPE_INO_SYMLINK: 306 + dent->type = FS_DT_LNK; 307 + break; 308 + case FILETYPE_INO_REG: 309 + dent->type = FS_DT_REG; 310 + break; 311 + default: 312 + dent->type = FILETYPE_UNKNOWN; 313 + } 314 + 315 + rtc_to_tm(fdiro.inode.atime, &dent->access_time); 316 + rtc_to_tm(fdiro.inode.ctime, &dent->create_time); 317 + rtc_to_tm(fdiro.inode.mtime, &dent->change_time); 318 + 319 + dirs->fpos += le16_to_cpu(dirent.direntlen); 320 + dent->size = fdiro.inode.size; 321 + *dentp = dent; 322 + ret = 0; 323 + 324 + out: 325 + if (dir) 326 + ext4fs_free_node(dir, &ext4fs_root->diropen); 327 + 328 + return ret; 329 + } 330 + 331 + void ext4fs_closedir(struct fs_dir_stream *fs_dirs) 332 + { 333 + struct ext4_dir_stream *dirs = (struct ext4_dir_stream *)fs_dirs; 334 + 335 + if (!dirs) 336 + return; 337 + 338 + free(dirs->dirname); 339 + free(dirs); 206 340 } 207 341 208 342 int ext4fs_exists(const char *filename) 209 343 { 210 344 struct ext2fs_node *dirnode = NULL; 211 345 int filetype; 346 + int ret; 212 347 213 348 if (!filename) 214 349 return 0; 215 350 216 - return ext4fs_find_file1(filename, &ext4fs_root->diropen, &dirnode, 217 - &filetype); 351 + ret = ext4fs_find_file1(filename, &ext4fs_root->diropen, &dirnode, 352 + &filetype); 353 + if (dirnode) 354 + ext4fs_free_node(dirnode, &ext4fs_root->diropen); 355 + 356 + return ret; 218 357 } 219 358 220 359 int ext4fs_size(const char *filename, loff_t *size)
+4 -2
fs/fs.c
··· 220 220 .null_dev_desc_ok = false, 221 221 .probe = ext4fs_probe, 222 222 .close = ext4fs_close, 223 - .ls = ext4fs_ls, 223 + .ls = fs_ls_generic, 224 224 .exists = ext4fs_exists, 225 225 .size = ext4fs_size, 226 226 .read = ext4_read_file, ··· 232 232 .ln = fs_ln_unsupported, 233 233 #endif 234 234 .uuid = ext4fs_uuid, 235 - .opendir = fs_opendir_unsupported, 235 + .opendir = ext4fs_opendir, 236 + .readdir = ext4fs_readdir, 237 + .closedir = ext4fs_closedir, 236 238 .unlink = fs_unlink_unsupported, 237 239 .mkdir = fs_mkdir_unsupported, 238 240 },
+4
include/ext4fs.h
··· 27 27 #ifndef __EXT4__ 28 28 #define __EXT4__ 29 29 #include <ext_common.h> 30 + #include <fs.h> 30 31 31 32 struct disk_partition; 32 33 ··· 218 219 void ext_cache_init(struct ext_block_cache *cache); 219 220 void ext_cache_fini(struct ext_block_cache *cache); 220 221 int ext_cache_read(struct ext_block_cache *cache, lbaint_t block, int size); 222 + int ext4fs_opendir(const char *dirname, struct fs_dir_stream **dirsp); 223 + int ext4fs_readdir(struct fs_dir_stream *dirs, struct fs_dirent **dentp); 224 + void ext4fs_closedir(struct fs_dir_stream *dirs); 221 225 #endif
+20 -10
lib/efi_loader/efi_file.c
··· 864 864 } 865 865 866 866 ret = efi_get_file_size(fh, &file_size); 867 - if (ret != EFI_SUCCESS) 868 - goto error; 867 + if (ret != EFI_SUCCESS) { 868 + if (!fh->isdir) 869 + goto error; 870 + /* 871 + * Some file drivers don't implement fs_size() for 872 + * directories. Use a dummy non-zero value. 873 + */ 874 + file_size = 4096; 875 + ret = EFI_SUCCESS; 876 + } 869 877 870 878 memset(info, 0, required_size); 871 879 ··· 976 984 } 977 985 free(new_file_name); 978 986 /* Check for truncation */ 979 - ret = efi_get_file_size(fh, &file_size); 980 - if (ret != EFI_SUCCESS) 981 - goto out; 982 - if (file_size != info->file_size) { 983 - /* TODO: we do not support truncation */ 984 - EFI_PRINT("Truncation not supported\n"); 985 - ret = EFI_ACCESS_DENIED; 986 - goto out; 987 + if (!fh->isdir) { 988 + ret = efi_get_file_size(fh, &file_size); 989 + if (ret != EFI_SUCCESS) 990 + goto out; 991 + if (file_size != info->file_size) { 992 + /* TODO: we do not support truncation */ 993 + EFI_PRINT("Truncation not supported\n"); 994 + ret = EFI_ACCESS_DENIED; 995 + goto out; 996 + } 987 997 } 988 998 /* 989 999 * We do not care for the other attributes
+1 -1
test/py/tests/test_env.py
··· 488 488 assert 'Loading Environment from EXT4... OK' in response 489 489 490 490 response = c.run_command('ext4ls host 0:0') 491 - assert '8192 uboot.env' in response 491 + assert '8192 uboot.env' in response 492 492 493 493 response = c.run_command('env info') 494 494 assert 'env_valid = valid' in response
+1 -4
test/py/tests/test_fs/test_basic.py
··· 33 33 # In addition, test with a nonexistent directory to see if we crash. 34 34 output = u_boot_console.run_command( 35 35 '%sls host 0:0 invalid_d' % fs_type) 36 - if fs_type == 'ext4': 37 - assert('Can not find directory' in output) 38 - else: 39 - assert('' == output) 36 + assert('' == output) 40 37 41 38 def test_fs2(self, u_boot_console, fs_obj_basic): 42 39 """