mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 16:14:16 +01:00 
			
		
		
		
	Added support for full seek operations
A rather involved upgrade for both files and directories, seek and related functions are now completely supported: - lfs_file_seek - lfs_file_tell - lfs_file_rewind - lfs_file_size - lfs_dir_seek - lfs_dir_tell - lfs_dir_rewind This change also highlighted the concern that lfs_off_t is unsigned, whereas off_t is traditionally signed. Unfortunately, lfs_off_t is already used intensively through the codebase, so in focusing on moving forward and avoiding getting bogged down by details, I'm going to keep it as is and use the signed type lfs_soff_t where necessary.
This commit is contained in:
		
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							| @@ -31,7 +31,7 @@ size: $(OBJ) | |||||||
| 	$(SIZE) -t $^ | 	$(SIZE) -t $^ | ||||||
|  |  | ||||||
| .SUFFIXES: | .SUFFIXES: | ||||||
| test: test_format test_dirs test_files test_alloc test_paths test_orphan | test: test_format test_dirs test_files test_seek test_alloc test_paths test_orphan | ||||||
| test_%: tests/test_%.sh | test_%: tests/test_%.sh | ||||||
| 	./$< | 	./$< | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										161
									
								
								lfs.c
									
									
									
									
									
								
							
							
						
						
									
										161
									
								
								lfs.c
									
									
									
									
									
								
							| @@ -545,8 +545,8 @@ static int lfs_dir_remove(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) { | |||||||
|  |  | ||||||
| static int lfs_dir_next(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) { | static int lfs_dir_next(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) { | ||||||
|     while (true) { |     while (true) { | ||||||
|         if ((0x7fffffff & dir->d.size) - dir->off < sizeof(entry->d)) { |         if (dir->off + sizeof(entry->d) > (0x7fffffff & dir->d.size)) { | ||||||
|             if (!(dir->d.size >> 31)) { |             if (!(0x80000000 & dir->d.size)) { | ||||||
|                 entry->pair[0] = dir->pair[0]; |                 entry->pair[0] = dir->pair[0]; | ||||||
|                 entry->pair[1] = dir->pair[1]; |                 entry->pair[1] = dir->pair[1]; | ||||||
|                 entry->off = dir->off; |                 entry->off = dir->off; | ||||||
| @@ -559,6 +559,7 @@ static int lfs_dir_next(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) { | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             dir->off = sizeof(dir->d); |             dir->off = sizeof(dir->d); | ||||||
|  |             dir->pos += sizeof(dir->d); | ||||||
|             continue; |             continue; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -569,6 +570,7 @@ static int lfs_dir_next(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         dir->off += entry->d.len; |         dir->off += entry->d.len; | ||||||
|  |         dir->pos += entry->d.len; | ||||||
|         if ((0xff & entry->d.type) == LFS_TYPE_REG || |         if ((0xff & entry->d.type) == LFS_TYPE_REG || | ||||||
|             (0xff & entry->d.type) == LFS_TYPE_DIR) { |             (0xff & entry->d.type) == LFS_TYPE_DIR) { | ||||||
|             entry->pair[0] = dir->pair[0]; |             entry->pair[0] = dir->pair[0]; | ||||||
| @@ -714,9 +716,14 @@ int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) { | |||||||
|     int err = lfs_dir_fetch(lfs, dir, dir->pair); |     int err = lfs_dir_fetch(lfs, dir, dir->pair); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
|     } else if (strcmp(path, "/") == 0) { |     } | ||||||
|         // special offset for '.' and '..' |  | ||||||
|         dir->off = sizeof(dir->d) - 2; |     if (strspn(path, "/.") == strlen(path)) { | ||||||
|  |         // can only be something like '/././../.' | ||||||
|  |         dir->head[0] = dir->pair[0]; | ||||||
|  |         dir->head[1] = dir->pair[1]; | ||||||
|  |         dir->pos = sizeof(dir->d) - 2; | ||||||
|  |         dir->off = sizeof(dir->d); | ||||||
|         return 0; |         return 0; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -733,8 +740,12 @@ int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) { | |||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // setup head dir | ||||||
|     // special offset for '.' and '..' |     // special offset for '.' and '..' | ||||||
|     dir->off = sizeof(dir->d) - 2; |     dir->head[0] = dir->pair[0]; | ||||||
|  |     dir->head[1] = dir->pair[1]; | ||||||
|  |     dir->pos = sizeof(dir->d) - 2; | ||||||
|  |     dir->off = sizeof(dir->d); | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -746,15 +757,16 @@ int lfs_dir_close(lfs_t *lfs, lfs_dir_t *dir) { | |||||||
| int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info) { | int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info) { | ||||||
|     memset(info, 0, sizeof(*info)); |     memset(info, 0, sizeof(*info)); | ||||||
|  |  | ||||||
|     if (dir->off == sizeof(dir->d) - 2) { |     // special offset for '.' and '..' | ||||||
|  |     if (dir->pos == sizeof(dir->d) - 2) { | ||||||
|         info->type = LFS_TYPE_DIR; |         info->type = LFS_TYPE_DIR; | ||||||
|         strcpy(info->name, "."); |         strcpy(info->name, "."); | ||||||
|         dir->off += 1; |         dir->pos += 1; | ||||||
|         return 1; |         return 1; | ||||||
|     } else if (dir->off == sizeof(dir->d) - 1) { |     } else if (dir->pos == sizeof(dir->d) - 1) { | ||||||
|         info->type = LFS_TYPE_DIR; |         info->type = LFS_TYPE_DIR; | ||||||
|         strcpy(info->name, ".."); |         strcpy(info->name, ".."); | ||||||
|         dir->off += 1; |         dir->pos += 1; | ||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -778,6 +790,48 @@ int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info) { | |||||||
|     return 1; |     return 1; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | int lfs_dir_seek(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off) { | ||||||
|  |     // simply walk from head dir | ||||||
|  |     int err = lfs_dir_rewind(lfs, dir); | ||||||
|  |     if (err) { | ||||||
|  |         return err; | ||||||
|  |     } | ||||||
|  |     dir->pos = off; | ||||||
|  |  | ||||||
|  |     while (off > (0x7fffffff & dir->d.size)) { | ||||||
|  |         off -= 0x7fffffff & dir->d.size; | ||||||
|  |         if (!(0x80000000 & dir->d.size)) { | ||||||
|  |             return LFS_ERROR_INVALID; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         int err = lfs_dir_fetch(lfs, dir, dir->d.tail); | ||||||
|  |         if (err) { | ||||||
|  |             return err; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     dir->off = off; | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | lfs_soff_t lfs_dir_tell(lfs_t *lfs, lfs_dir_t *dir) { | ||||||
|  |     return dir->pos; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir) { | ||||||
|  |     // reload the head dir | ||||||
|  |     int err = lfs_dir_fetch(lfs, dir, dir->head); | ||||||
|  |     if (err) { | ||||||
|  |         return err; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     dir->pair[0] = dir->head[0]; | ||||||
|  |     dir->pair[1] = dir->head[1]; | ||||||
|  |     dir->pos = sizeof(dir->d) - 2; | ||||||
|  |     dir->off = sizeof(dir->d); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| /// Index list operations /// | /// Index list operations /// | ||||||
| static int lfs_index(lfs_t *lfs, lfs_off_t *off) { | static int lfs_index(lfs_t *lfs, lfs_off_t *off) { | ||||||
| @@ -975,7 +1029,7 @@ int lfs_file_close(lfs_t *lfs, lfs_file_t *file) { | |||||||
|     return lfs_file_sync(lfs, file); |     return lfs_file_sync(lfs, file); | ||||||
| } | } | ||||||
|  |  | ||||||
| int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) { | static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) { | ||||||
|     if (file->wblock == 0) { |     if (file->wblock == 0) { | ||||||
|         // already in sync, may be rdonly |         // already in sync, may be rdonly | ||||||
|         return 0; |         return 0; | ||||||
| @@ -1008,10 +1062,23 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) { | |||||||
|     file->rblock = 0; |     file->rblock = 0; | ||||||
|     file->wpos = oldwpos; |     file->wpos = oldwpos; | ||||||
|     file->wblock = 0; |     file->wblock = 0; | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) { | ||||||
|  |     if (file->wblock == 0) { | ||||||
|  |         // already in sync, may be rdonly | ||||||
|  |         return 0; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     int err = lfs_file_flush(lfs, file); | ||||||
|  |     if (err) { | ||||||
|  |         return err; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     // update dir entry |     // update dir entry | ||||||
|     lfs_dir_t cwd; |     lfs_dir_t cwd; | ||||||
|     int err = lfs_dir_fetch(lfs, &cwd, file->entry.pair); |     err = lfs_dir_fetch(lfs, &cwd, file->entry.pair); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
| @@ -1024,9 +1091,24 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file, | |||||||
|     const uint8_t *data = buffer; |     const uint8_t *data = buffer; | ||||||
|     lfs_size_t nsize = size; |     lfs_size_t nsize = size; | ||||||
|  |  | ||||||
|  |     if ((file->flags & 3) == LFS_O_RDONLY) { | ||||||
|  |         return LFS_ERROR_INVALID; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     while (nsize > 0) { |     while (nsize > 0) { | ||||||
|         // check if we need a new block |         // check if we need a new block | ||||||
|         if (!file->wblock || file->woff == lfs->cfg->block_size) { |         if (!file->wblock || file->woff == lfs->cfg->block_size) { | ||||||
|  |             if (!file->wblock) { | ||||||
|  |                 // find out which block we're extending from | ||||||
|  |                 int err = lfs_index_find(lfs, | ||||||
|  |                         file->entry.d.u.file.head, file->entry.d.u.file.size, | ||||||
|  |                         file->wpos, &file->wblock, &file->woff); | ||||||
|  |                 if (err) { | ||||||
|  |                     return err; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // extend file with new blocks | ||||||
|             int err = lfs_index_extend(lfs, file->wblock, file->wpos, |             int err = lfs_index_extend(lfs, file->wblock, file->wpos, | ||||||
|                     &file->wblock, &file->woff); |                     &file->wblock, &file->woff); | ||||||
|             if (err) { |             if (err) { | ||||||
| @@ -1068,6 +1150,10 @@ lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file, | |||||||
|     size = lfs_min(size, file->entry.d.u.file.size - file->rpos); |     size = lfs_min(size, file->entry.d.u.file.size - file->rpos); | ||||||
|     lfs_size_t nsize = size; |     lfs_size_t nsize = size; | ||||||
|  |  | ||||||
|  |     if ((file->flags & 3) == LFS_O_WRONLY) { | ||||||
|  |         return LFS_ERROR_INVALID; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     while (nsize > 0) { |     while (nsize > 0) { | ||||||
|         // check if we need a new block |         // check if we need a new block | ||||||
|         if (!file->rblock || file->roff == lfs->cfg->block_size) { |         if (!file->rblock || file->roff == lfs->cfg->block_size) { | ||||||
| @@ -1095,6 +1181,57 @@ lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file, | |||||||
|     return size; |     return size; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file, | ||||||
|  |         lfs_soff_t off, int whence) { | ||||||
|  |     // write out everything beforehand, may be noop if rdonly | ||||||
|  |     int err = lfs_file_flush(lfs, file); | ||||||
|  |     if (err) { | ||||||
|  |         return err; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // rpos is always correct pos, even in append mode | ||||||
|  |     // TODO keep rpos and wpos together? | ||||||
|  |     lfs_off_t prev = file->rpos; | ||||||
|  |     file->rblock = 0; | ||||||
|  |     switch (whence) { | ||||||
|  |         case LFS_SEEK_SET: | ||||||
|  |             file->rpos = off; | ||||||
|  |             break; | ||||||
|  |  | ||||||
|  |         case LFS_SEEK_CUR: | ||||||
|  |             file->rpos = file->rpos + off; | ||||||
|  |             break; | ||||||
|  |  | ||||||
|  |         case LFS_SEEK_END: | ||||||
|  |             file->rpos = file->entry.d.u.file.size + off; | ||||||
|  |             break; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (!(file->flags & LFS_O_APPEND)) { | ||||||
|  |         file->wpos = file->rpos; | ||||||
|  |         file->wblock = 0; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return prev; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file) { | ||||||
|  |     return lfs_max(file->wpos, file->entry.d.u.file.size); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | lfs_soff_t lfs_file_tell(lfs_t *lfs, lfs_file_t *file) { | ||||||
|  |     return file->rpos; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int lfs_file_rewind(lfs_t *lfs, lfs_file_t *file) { | ||||||
|  |     lfs_soff_t res = lfs_file_seek(lfs, file, 0, LFS_SEEK_SET); | ||||||
|  |     if (res < 0) { | ||||||
|  |         return res; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| /// Generic filesystem operations /// | /// Generic filesystem operations /// | ||||||
| static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) { | static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) { | ||||||
|   | |||||||
							
								
								
									
										19
									
								
								lfs.h
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								lfs.h
									
									
									
									
									
								
							| @@ -40,6 +40,12 @@ enum lfs_open_flags { | |||||||
|     LFS_O_SYNC   = 0x200, |     LFS_O_SYNC   = 0x200, | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | enum lfs_whence_flags { | ||||||
|  |     LFS_SEEK_SET = 0, | ||||||
|  |     LFS_SEEK_CUR = 1, | ||||||
|  |     LFS_SEEK_END = 2, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
| // Configuration provided during initialization of the littlefs | // Configuration provided during initialization of the littlefs | ||||||
| struct lfs_config { | struct lfs_config { | ||||||
| @@ -138,6 +144,9 @@ typedef struct lfs_dir { | |||||||
|     lfs_block_t pair[2]; |     lfs_block_t pair[2]; | ||||||
|     lfs_off_t off; |     lfs_off_t off; | ||||||
|  |  | ||||||
|  |     lfs_block_t head[2]; | ||||||
|  |     lfs_off_t pos; | ||||||
|  |  | ||||||
|     struct lfs_disk_dir { |     struct lfs_disk_dir { | ||||||
|         uint32_t rev; |         uint32_t rev; | ||||||
|         lfs_size_t size; |         lfs_size_t size; | ||||||
| @@ -146,7 +155,7 @@ typedef struct lfs_dir { | |||||||
| } lfs_dir_t; | } lfs_dir_t; | ||||||
|  |  | ||||||
| typedef struct lfs_superblock { | typedef struct lfs_superblock { | ||||||
|     lfs_block_t dir[2]; //TODO rm me? |     lfs_block_t pair[2]; | ||||||
|     lfs_off_t off; |     lfs_off_t off; | ||||||
|  |  | ||||||
|     struct lfs_disk_superblock { |     struct lfs_disk_superblock { | ||||||
| @@ -195,6 +204,9 @@ int lfs_mkdir(lfs_t *lfs, const char *path); | |||||||
| int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path); | int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path); | ||||||
| int lfs_dir_close(lfs_t *lfs, lfs_dir_t *dir); | int lfs_dir_close(lfs_t *lfs, lfs_dir_t *dir); | ||||||
| int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info); | int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info); | ||||||
|  | int lfs_dir_seek(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off); | ||||||
|  | lfs_soff_t lfs_dir_tell(lfs_t *lfs, lfs_dir_t *dir); | ||||||
|  | int lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir); | ||||||
|  |  | ||||||
| int lfs_file_open(lfs_t *lfs, lfs_file_t *file, | int lfs_file_open(lfs_t *lfs, lfs_file_t *file, | ||||||
|         const char *path, int flags); |         const char *path, int flags); | ||||||
| @@ -204,6 +216,11 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file, | |||||||
|         const void *buffer, lfs_size_t size); |         const void *buffer, lfs_size_t size); | ||||||
| lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file, | lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file, | ||||||
|         void *buffer, lfs_size_t size); |         void *buffer, lfs_size_t size); | ||||||
|  | lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file, | ||||||
|  |         lfs_soff_t off, int whence); | ||||||
|  | lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file); | ||||||
|  | lfs_soff_t lfs_file_tell(lfs_t *lfs, lfs_file_t *file); | ||||||
|  | int lfs_file_rewind(lfs_t *lfs, lfs_file_t *file); | ||||||
|  |  | ||||||
| int lfs_deorphan(lfs_t *lfs); | int lfs_deorphan(lfs_t *lfs); | ||||||
| int lfs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data); | int lfs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data); | ||||||
|   | |||||||
							
								
								
									
										281
									
								
								tests/test_seek.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										281
									
								
								tests/test_seek.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,281 @@ | |||||||
|  | #!/bin/bash | ||||||
|  | set -eu | ||||||
|  |  | ||||||
|  | SMALLSIZE=4 | ||||||
|  | MEDIUMSIZE=128 | ||||||
|  | LARGESIZE=132 | ||||||
|  |  | ||||||
|  | echo "=== Seek tests ===" | ||||||
|  | rm -rf blocks | ||||||
|  | tests/test.py << TEST | ||||||
|  |     lfs_format(&lfs, &cfg) => 0; | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_mkdir(&lfs, "hello") => 0; | ||||||
|  |     for (int i = 0; i < $LARGESIZE; i++) { | ||||||
|  |         sprintf((char*)buffer, "hello/kitty%d", i); | ||||||
|  |         lfs_file_open(&lfs, &file[0], (char*)buffer, | ||||||
|  |                 LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0; | ||||||
|  |  | ||||||
|  |         size = strlen("kittycatcat"); | ||||||
|  |         memcpy(buffer, "kittycatcat", size); | ||||||
|  |         for (int j = 0; j < $LARGESIZE; j++) { | ||||||
|  |             lfs_file_write(&lfs, &file[0], buffer, size); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         lfs_file_close(&lfs, &file[0]) => 0; | ||||||
|  |     } | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  | TEST | ||||||
|  |  | ||||||
|  | echo "--- Simple dir seek ---" | ||||||
|  | tests/test.py << TEST | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir[0], "hello") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir[0], &info) => 1; | ||||||
|  |     strcmp(info.name, ".") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir[0], &info) => 1; | ||||||
|  |     strcmp(info.name, "..") => 0; | ||||||
|  |  | ||||||
|  |     lfs_soff_t pos; | ||||||
|  |     int i; | ||||||
|  |     for (i = 0; i < $SMALLSIZE; i++) { | ||||||
|  |         sprintf((char*)buffer, "kitty%d", i); | ||||||
|  |         lfs_dir_read(&lfs, &dir[0], &info) => 1; | ||||||
|  |         strcmp(info.name, (char*)buffer) => 0; | ||||||
|  |         pos = lfs_dir_tell(&lfs, &dir[0]); | ||||||
|  |     } | ||||||
|  |     pos >= 0 => 1; | ||||||
|  |  | ||||||
|  |     lfs_dir_seek(&lfs, &dir[0], pos) => 0; | ||||||
|  |     sprintf((char*)buffer, "kitty%d", i); | ||||||
|  |     lfs_dir_read(&lfs, &dir[0], &info) => 1; | ||||||
|  |     strcmp(info.name, (char*)buffer) => 0; | ||||||
|  |  | ||||||
|  |     lfs_dir_rewind(&lfs, &dir[0]) => 0; | ||||||
|  |     sprintf((char*)buffer, "kitty%d", 0); | ||||||
|  |     lfs_dir_read(&lfs, &dir[0], &info) => 1; | ||||||
|  |     strcmp(info.name, ".") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir[0], &info) => 1; | ||||||
|  |     strcmp(info.name, "..") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir[0], &info) => 1; | ||||||
|  |     strcmp(info.name, (char*)buffer) => 0; | ||||||
|  |  | ||||||
|  |     lfs_dir_seek(&lfs, &dir[0], pos) => 0; | ||||||
|  |     sprintf((char*)buffer, "kitty%d", i); | ||||||
|  |     lfs_dir_read(&lfs, &dir[0], &info) => 1; | ||||||
|  |     strcmp(info.name, (char*)buffer) => 0; | ||||||
|  |  | ||||||
|  |     lfs_dir_close(&lfs, &dir[0]) => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  | TEST | ||||||
|  |  | ||||||
|  | echo "--- Large dir seek ---" | ||||||
|  | tests/test.py << TEST | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_dir_open(&lfs, &dir[0], "hello") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir[0], &info) => 1; | ||||||
|  |     strcmp(info.name, ".") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir[0], &info) => 1; | ||||||
|  |     strcmp(info.name, "..") => 0; | ||||||
|  |  | ||||||
|  |     lfs_soff_t pos; | ||||||
|  |     int i; | ||||||
|  |     for (i = 0; i < $MEDIUMSIZE; i++) { | ||||||
|  |         sprintf((char*)buffer, "kitty%d", i); | ||||||
|  |         lfs_dir_read(&lfs, &dir[0], &info) => 1; | ||||||
|  |         strcmp(info.name, (char*)buffer) => 0; | ||||||
|  |         pos = lfs_dir_tell(&lfs, &dir[0]); | ||||||
|  |     } | ||||||
|  |     pos >= 0 => 1; | ||||||
|  |  | ||||||
|  |     lfs_dir_seek(&lfs, &dir[0], pos) => 0; | ||||||
|  |     sprintf((char*)buffer, "kitty%d", i); | ||||||
|  |     lfs_dir_read(&lfs, &dir[0], &info) => 1; | ||||||
|  |     strcmp(info.name, (char*)buffer) => 0; | ||||||
|  |  | ||||||
|  |     lfs_dir_rewind(&lfs, &dir[0]) => 0; | ||||||
|  |     sprintf((char*)buffer, "kitty%d", 0); | ||||||
|  |     lfs_dir_read(&lfs, &dir[0], &info) => 1; | ||||||
|  |     strcmp(info.name, ".") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir[0], &info) => 1; | ||||||
|  |     strcmp(info.name, "..") => 0; | ||||||
|  |     lfs_dir_read(&lfs, &dir[0], &info) => 1; | ||||||
|  |     strcmp(info.name, (char*)buffer) => 0; | ||||||
|  |  | ||||||
|  |     lfs_dir_seek(&lfs, &dir[0], pos) => 0; | ||||||
|  |     sprintf((char*)buffer, "kitty%d", i); | ||||||
|  |     lfs_dir_read(&lfs, &dir[0], &info) => 1; | ||||||
|  |     strcmp(info.name, (char*)buffer) => 0; | ||||||
|  |  | ||||||
|  |     lfs_dir_close(&lfs, &dir[0]) => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  | TEST | ||||||
|  |  | ||||||
|  | echo "--- Simple file seek ---" | ||||||
|  | tests/test.py << TEST | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_file_open(&lfs, &file[0], "hello/kitty42", LFS_O_RDONLY) => 0; | ||||||
|  |  | ||||||
|  |     lfs_soff_t pos; | ||||||
|  |     size = strlen("kittycatcat"); | ||||||
|  |     for (int i = 0; i < $SMALLSIZE; i++) { | ||||||
|  |         lfs_file_read(&lfs, &file[0], buffer, size) => size; | ||||||
|  |         memcmp(buffer, "kittycatcat", size) => 0; | ||||||
|  |         pos = lfs_file_tell(&lfs, &file[0]); | ||||||
|  |     } | ||||||
|  |     pos >= 0 => 1; | ||||||
|  |  | ||||||
|  |     lfs_file_seek(&lfs, &file[0], pos, LFS_SEEK_SET) => pos; | ||||||
|  |     lfs_file_read(&lfs, &file[0], buffer, size) => size; | ||||||
|  |     memcmp(buffer, "kittycatcat", size) => 0; | ||||||
|  |  | ||||||
|  |     lfs_file_rewind(&lfs, &file[0]) => 0; | ||||||
|  |     lfs_file_read(&lfs, &file[0], buffer, size) => size; | ||||||
|  |     memcmp(buffer, "kittycatcat", size) => 0; | ||||||
|  |  | ||||||
|  |     lfs_file_seek(&lfs, &file[0], pos, LFS_SEEK_SET) => size; | ||||||
|  |     lfs_file_read(&lfs, &file[0], buffer, size) => size; | ||||||
|  |     memcmp(buffer, "kittycatcat", size) => 0; | ||||||
|  |  | ||||||
|  |     lfs_file_seek(&lfs, &file[0], -size, LFS_SEEK_CUR) => pos+size; | ||||||
|  |     lfs_file_read(&lfs, &file[0], buffer, size) => size; | ||||||
|  |     memcmp(buffer, "kittycatcat", size) => 0; | ||||||
|  |  | ||||||
|  |     lfs_file_seek(&lfs, &file[0], -size, LFS_SEEK_END) => pos+size; | ||||||
|  |     lfs_file_read(&lfs, &file[0], buffer, size) => size; | ||||||
|  |     memcmp(buffer, "kittycatcat", size) => 0; | ||||||
|  |  | ||||||
|  |     lfs_size_t size = lfs_file_size(&lfs, &file[0]); | ||||||
|  |     lfs_file_seek(&lfs, &file[0], 0, LFS_SEEK_CUR) => size; | ||||||
|  |  | ||||||
|  |     lfs_file_close(&lfs, &file[0]) => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  | TEST | ||||||
|  |  | ||||||
|  | echo "--- Large file seek ---" | ||||||
|  | tests/test.py << TEST | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_file_open(&lfs, &file[0], "hello/kitty42", LFS_O_RDONLY) => 0; | ||||||
|  |  | ||||||
|  |     lfs_soff_t pos; | ||||||
|  |     size = strlen("kittycatcat"); | ||||||
|  |     for (int i = 0; i < $MEDIUMSIZE; i++) { | ||||||
|  |         lfs_file_read(&lfs, &file[0], buffer, size) => size; | ||||||
|  |         memcmp(buffer, "kittycatcat", size) => 0; | ||||||
|  |         pos = lfs_file_tell(&lfs, &file[0]); | ||||||
|  |     } | ||||||
|  |     pos >= 0 => 1; | ||||||
|  |  | ||||||
|  |     lfs_file_seek(&lfs, &file[0], pos, LFS_SEEK_SET) => pos; | ||||||
|  |     lfs_file_read(&lfs, &file[0], buffer, size) => size; | ||||||
|  |     memcmp(buffer, "kittycatcat", size) => 0; | ||||||
|  |  | ||||||
|  |     lfs_file_rewind(&lfs, &file[0]) => 0; | ||||||
|  |     lfs_file_read(&lfs, &file[0], buffer, size) => size; | ||||||
|  |     memcmp(buffer, "kittycatcat", size) => 0; | ||||||
|  |  | ||||||
|  |     lfs_file_seek(&lfs, &file[0], pos, LFS_SEEK_SET) => size; | ||||||
|  |     lfs_file_read(&lfs, &file[0], buffer, size) => size; | ||||||
|  |     memcmp(buffer, "kittycatcat", size) => 0; | ||||||
|  |  | ||||||
|  |     lfs_file_seek(&lfs, &file[0], -size, LFS_SEEK_CUR) => pos+size; | ||||||
|  |     lfs_file_read(&lfs, &file[0], buffer, size) => size; | ||||||
|  |     memcmp(buffer, "kittycatcat", size) => 0; | ||||||
|  |  | ||||||
|  |     lfs_file_seek(&lfs, &file[0], -size, LFS_SEEK_END) => pos+size; | ||||||
|  |     lfs_file_read(&lfs, &file[0], buffer, size) => size; | ||||||
|  |     memcmp(buffer, "kittycatcat", size) => 0; | ||||||
|  |  | ||||||
|  |     lfs_size_t size = lfs_file_size(&lfs, &file[0]); | ||||||
|  |     lfs_file_seek(&lfs, &file[0], 0, LFS_SEEK_CUR) => size; | ||||||
|  |  | ||||||
|  |     lfs_file_close(&lfs, &file[0]) => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  | TEST | ||||||
|  |  | ||||||
|  | echo "--- Simple file seek and write ---" | ||||||
|  | tests/test.py << TEST | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_file_open(&lfs, &file[0], "hello/kitty42", LFS_O_RDWR) => 0; | ||||||
|  |  | ||||||
|  |     lfs_soff_t pos; | ||||||
|  |     size = strlen("kittycatcat"); | ||||||
|  |     for (int i = 0; i < $SMALLSIZE; i++) { | ||||||
|  |         lfs_file_read(&lfs, &file[0], buffer, size) => size; | ||||||
|  |         memcmp(buffer, "kittycatcat", size) => 0; | ||||||
|  |         pos = lfs_file_tell(&lfs, &file[0]); | ||||||
|  |     } | ||||||
|  |     pos >= 0 => 1; | ||||||
|  |  | ||||||
|  |     memcpy(buffer, "doggodogdog", size); | ||||||
|  |     lfs_file_seek(&lfs, &file[0], pos, LFS_SEEK_SET) => pos; | ||||||
|  |     lfs_file_write(&lfs, &file[0], buffer, size) => size; | ||||||
|  |  | ||||||
|  |     lfs_file_seek(&lfs, &file[0], pos, LFS_SEEK_SET) => pos; | ||||||
|  |     lfs_file_read(&lfs, &file[0], buffer, size) => size; | ||||||
|  |     memcmp(buffer, "doggodogdog", size) => 0; | ||||||
|  |  | ||||||
|  |     lfs_file_rewind(&lfs, &file[0]) => 0; | ||||||
|  |     lfs_file_read(&lfs, &file[0], buffer, size) => size; | ||||||
|  |     memcmp(buffer, "kittycatcat", size) => 0; | ||||||
|  |  | ||||||
|  |     lfs_file_seek(&lfs, &file[0], pos, LFS_SEEK_SET) => size; | ||||||
|  |     lfs_file_read(&lfs, &file[0], buffer, size) => size; | ||||||
|  |     memcmp(buffer, "doggodogdog", size) => 0; | ||||||
|  |  | ||||||
|  |     lfs_file_seek(&lfs, &file[0], -size, LFS_SEEK_END) => pos+size; | ||||||
|  |     lfs_file_read(&lfs, &file[0], buffer, size) => size; | ||||||
|  |     memcmp(buffer, "kittycatcat", size) => 0; | ||||||
|  |  | ||||||
|  |     lfs_size_t size = lfs_file_size(&lfs, &file[0]); | ||||||
|  |     lfs_file_seek(&lfs, &file[0], 0, LFS_SEEK_CUR) => size; | ||||||
|  |  | ||||||
|  |     lfs_file_close(&lfs, &file[0]) => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  | TEST | ||||||
|  |  | ||||||
|  | echo "--- Large file seek and write ---" | ||||||
|  | tests/test.py << TEST | ||||||
|  |     lfs_mount(&lfs, &cfg) => 0; | ||||||
|  |     lfs_file_open(&lfs, &file[0], "hello/kitty42", LFS_O_RDWR) => 0; | ||||||
|  |  | ||||||
|  |     lfs_soff_t pos; | ||||||
|  |     size = strlen("kittycatcat"); | ||||||
|  |     for (int i = 0; i < $MEDIUMSIZE; i++) { | ||||||
|  |         lfs_file_read(&lfs, &file[0], buffer, size) => size; | ||||||
|  |         if (i != $SMALLSIZE) { | ||||||
|  |             memcmp(buffer, "kittycatcat", size) => 0; | ||||||
|  |         } | ||||||
|  |         pos = lfs_file_tell(&lfs, &file[0]); | ||||||
|  |     } | ||||||
|  |     pos >= 0 => 1; | ||||||
|  |  | ||||||
|  |     memcpy(buffer, "doggodogdog", size); | ||||||
|  |     lfs_file_seek(&lfs, &file[0], pos, LFS_SEEK_SET) => pos; | ||||||
|  |     lfs_file_write(&lfs, &file[0], buffer, size) => size; | ||||||
|  |  | ||||||
|  |     lfs_file_seek(&lfs, &file[0], pos, LFS_SEEK_SET) => pos; | ||||||
|  |     lfs_file_read(&lfs, &file[0], buffer, size) => size; | ||||||
|  |     memcmp(buffer, "doggodogdog", size) => 0; | ||||||
|  |  | ||||||
|  |     lfs_file_rewind(&lfs, &file[0]) => 0; | ||||||
|  |     lfs_file_read(&lfs, &file[0], buffer, size) => size; | ||||||
|  |     memcmp(buffer, "kittycatcat", size) => 0; | ||||||
|  |  | ||||||
|  |     lfs_file_seek(&lfs, &file[0], pos, LFS_SEEK_SET) => size; | ||||||
|  |     lfs_file_read(&lfs, &file[0], buffer, size) => size; | ||||||
|  |     memcmp(buffer, "doggodogdog", size) => 0; | ||||||
|  |  | ||||||
|  |     lfs_file_seek(&lfs, &file[0], -size, LFS_SEEK_END) => pos+size; | ||||||
|  |     lfs_file_read(&lfs, &file[0], buffer, size) => size; | ||||||
|  |     memcmp(buffer, "kittycatcat", size) => 0; | ||||||
|  |  | ||||||
|  |     lfs_size_t size = lfs_file_size(&lfs, &file[0]); | ||||||
|  |     lfs_file_seek(&lfs, &file[0], 0, LFS_SEEK_CUR) => size; | ||||||
|  |  | ||||||
|  |     lfs_file_close(&lfs, &file[0]) => 0; | ||||||
|  |     lfs_unmount(&lfs) => 0; | ||||||
|  | TEST | ||||||
|  |  | ||||||
|  | echo "--- Results ---" | ||||||
|  | tests/stats.py | ||||||
		Reference in New Issue
	
	Block a user