fs_write() with an offset trims the file at the end of the written range. Add fs_overwrite() for callers that need to update a part of a file and keep the rest.
Add an optional overwrite() operation to struct fstype_info and set it for FAT. A filesystem without it falls back to write(), so nothing changes for them. fs_write() and fs_overwrite() share the same code. Signed-off-by: Cedric Hombourger <[email protected]> --- fs/fs.c | 25 ++++++++++++++++++++++--- include/fs.h | 16 ++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/fs/fs.c b/fs/fs.c index b18ccec8cb43d8e575d2c22f7df3a01308f47751..b0bb8d58d2a458f983b9b98a47eefa05416689a1 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -169,6 +169,9 @@ struct fstype_info { loff_t len, loff_t *actread); int (*write)(const char *filename, void *buf, loff_t offset, loff_t len, loff_t *actwrite); + /* Optional: like write, but keeps data after the written range */ + int (*overwrite)(const char *filename, void *buf, loff_t offset, + loff_t len, loff_t *actwrite); void (*close)(void); int (*uuid)(char *uuid_str); /* @@ -205,6 +208,7 @@ static struct fstype_info fstypes[] = { .read = fat_read_file, #if CONFIG_IS_ENABLED(FAT_WRITE) .write = file_fat_write, + .overwrite = file_fat_overwrite, .unlink = fat_unlink, .mkdir = fat_mkdir, #else @@ -709,15 +713,18 @@ int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len, return _fs_read(filename, addr, offset, len, 0, actread); } -int fs_write(const char *filename, ulong addr, loff_t offset, loff_t len, - loff_t *actwrite) +static int fs_write_with(bool keep_tail, const char *filename, ulong addr, + loff_t offset, loff_t len, loff_t *actwrite) { struct fstype_info *info = fs_get_info(fs_type); void *buf; int ret; buf = map_sysmem(addr, len); - ret = info->write(filename, buf, offset, len, actwrite); + if (keep_tail && info->overwrite) + ret = info->overwrite(filename, buf, offset, len, actwrite); + else + ret = info->write(filename, buf, offset, len, actwrite); unmap_sysmem(buf); if (ret < 0 && len != *actwrite) { @@ -729,6 +736,18 @@ int fs_write(const char *filename, ulong addr, loff_t offset, loff_t len, return ret; } +int fs_write(const char *filename, ulong addr, loff_t offset, loff_t len, + loff_t *actwrite) +{ + return fs_write_with(false, filename, addr, offset, len, actwrite); +} + +int fs_overwrite(const char *filename, ulong addr, loff_t offset, loff_t len, + loff_t *actwrite) +{ + return fs_write_with(true, filename, addr, offset, len, actwrite); +} + struct fs_dir_stream *fs_opendir(const char *filename) { struct fstype_info *info = fs_get_info(fs_type); diff --git a/include/fs.h b/include/fs.h index 8afc81c0017da1d7fbc2c3a5c63fb00d2fc1c262..02d357cd62849cc19e15ad3fad08964d9ec66c94 100644 --- a/include/fs.h +++ b/include/fs.h @@ -167,6 +167,22 @@ int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len, int fs_write(const char *filename, ulong addr, loff_t offset, loff_t len, loff_t *actwrite); +/** + * fs_overwrite() - write into a file without cutting off its tail + * + * Like fs_write(), but data after the written range stays and the file + * size only grows. Filesystem drivers without support fall back to fs_write(). + * + * @filename: full path of the file to write to + * @addr: address of the buffer to read from + * @offset: offset in the file from where to start writing + * @len: the number of bytes to write + * @actwrite: returns the actual number of bytes written + * Return: 0 if OK with valid @actwrite, -1 on error conditions + */ +int fs_overwrite(const char *filename, ulong addr, loff_t offset, loff_t len, + loff_t *actwrite); + /* * Directory entry types, matches the subset of DT_x in posix readdir() * which apply to u-boot. -- 2.47.3
