Add a size argument to copy_fd() to allow copying a specified number of bytes. While at it add some function documentation.
Signed-off-by: Sascha Hauer <[email protected]> --- common/firmware.c | 2 +- include/libfile.h | 2 +- lib/libfile.c | 37 +++++++++++++++++++++++++++++++++---- 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/common/firmware.c b/common/firmware.c index 264fc9d66d..cdc55467cd 100644 --- a/common/firmware.c +++ b/common/firmware.c @@ -292,7 +292,7 @@ int firmwaremgr_load_file(struct firmware_mgr *mgr, const char *firmware) ret = uncompress_fd_to_fd(firmwarefd, devicefd, uncompress_err_stdout); else - ret = copy_fd(firmwarefd, devicefd); + ret = copy_fd(firmwarefd, devicefd, 0); out: free(dst); diff --git a/include/libfile.h b/include/libfile.h index dc292e422e..370f8b9725 100644 --- a/include/libfile.h +++ b/include/libfile.h @@ -11,7 +11,7 @@ int pread_full(int fd, void *buf, size_t size, loff_t offset); int pwrite_full(int fd, const void *buf, size_t size, loff_t offset); int write_full(int fd, const void *buf, size_t size); int read_full(int fd, void *buf, size_t size); -int copy_fd(int in, int out); +int copy_fd(int in, int out, size_t size); ssize_t read_file_into_buf(const char *filename, void *buf, size_t size); diff --git a/lib/libfile.c b/lib/libfile.c index 01189773b7..32b0c27eba 100644 --- a/lib/libfile.c +++ b/lib/libfile.c @@ -124,25 +124,54 @@ int read_full(int fd, void *buf, size_t size) } EXPORT_SYMBOL(read_full); -int copy_fd(int in, int out) +/* + * copy_fd - copy one file descriptor to another + * @in: input file descriptor + * @out: output file descriptor + * @size: size to copy + * + * This copies at @size bytes from @in file descriptor to @out + * file descriptor. If @size is zero then all data is copied until + * EOF is reached. + * + * @return: 0 for success and negatibe error code otherwise. If @size + * is non zero and not all data could be read from @in then -ENODATA + * is returned. + */ +int copy_fd(int in, int out, size_t size) { - int bs = 4096, ret; + size_t copied = 0, bs = 4096; void *buf = malloc(bs); + int ret; if (!buf) return -ENOMEM; while (1) { - ret = read(in, buf, bs); + size_t now = min(bs, size - copied); + + if (!now) { + ret = 0; + break; + } + + ret = read(in, buf, now); if (ret <= 0) break; + now = ret; + ret = write_full(out, buf, ret); if (ret < 0) break; + + copied += now; } - free(buf); + free(buf); + + if (size && copied < size) + ret = -ENODATA; return ret; } -- 2.47.3
