This will be useful for host/target tools that use stdin as a fall back to read from when no file name is supplied. Code is taken from the barebox version in lib/libfile.c. Signed-off-by: Ahmad Fatoum <a.fatoum@xxxxxxxxxxxxxx> --- scripts/common.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++ scripts/common.h | 2 ++ 2 files changed, 70 insertions(+) diff --git a/scripts/common.c b/scripts/common.c index 49c468a1ea35..a6eee968b79d 100644 --- a/scripts/common.c +++ b/scripts/common.c @@ -97,6 +97,50 @@ void *read_file(const char *filename, size_t *size) return NULL; } +/** + * read_fd - read from a file descriptor to an allocated buffer + * @filename: The file descriptor to read + * @size: After successful return contains the size of the file + * + * This function reads a file descriptor from offset 0 until EOF to an + * allocated buffer. + * + * Return: On success, returns a nul-terminated buffer with the file's + * contents that should be deallocated with free(). + * On error, NULL is returned and errno is set to an error code. + */ +void *read_fd(int fd, size_t *out_size) +{ + struct stat st; + ssize_t ret; + void *buf; + + ret = fstat(fd, &st); + if (ret < 0) + return NULL; + + /* For user convenience, we always nul-terminate the buffer in + * case it contains a string. As we don't want to assume the string + * to be either an array of char or wchar_t, we just unconditionally + * add 2 bytes as terminator. As the two byte terminator needs to be + * aligned, we just make it three bytes + */ + buf = malloc(st.st_size + 3); + if (!buf) + return NULL; + + ret = pread_full(fd, buf, st.st_size, 0); + if (ret < 0) { + free(buf); + return NULL; + } + + memset(buf + st.st_size, '\0', 3); + *out_size = st.st_size; + + return buf; +} + int write_file(const char *filename, const void *buf, size_t size) { int fd, ret = 0; @@ -147,6 +191,30 @@ int read_full(int fd, void *buf, size_t size) return insize; } +/* + * pread_full - read to filedescriptor at offset + * + * Like pread, but this function only returns less bytes than + * requested when the end of file is reached. + */ +int pread_full(int fd, void *buf, size_t size, loff_t offset) +{ + size_t insize = size; + int now; + + while (size) { + now = pread(fd, buf, size, offset); + if (now == 0) + break; + if (now < 0) + return now; + size -= now; + buf += now; + } + + return insize - size; +} + int write_full(int fd, const void *buf, size_t size) { size_t insize = size; diff --git a/scripts/common.h b/scripts/common.h index 399729c338f3..a0d16606b5d9 100644 --- a/scripts/common.h +++ b/scripts/common.h @@ -3,8 +3,10 @@ int read_file_2(const char *filename, size_t *size, void **outbuf, size_t max_size); void *read_file(const char *filename, size_t *size); +void *read_fd(int fd, size_t *out_size); int write_file(const char *filename, const void *buf, size_t size); int read_full(int fd, void *buf, size_t size); +int pread_full(int fd, void *buf, size_t size, loff_t offset); int write_full(int fd, const void *buf, size_t size); #endif /* __COMMON_H */ -- 2.39.5