diff options
Diffstat (limited to 'lib/libfile.c')
-rw-r--r-- | lib/libfile.c | 145 |
1 files changed, 103 insertions, 42 deletions
diff --git a/lib/libfile.c b/lib/libfile.c index 3b7985fbca..67fc9cc7f3 100644 --- a/lib/libfile.c +++ b/lib/libfile.c @@ -33,10 +33,8 @@ int pwrite_full(int fd, const void *buf, size_t size, loff_t offset) while (size) { now = pwrite(fd, buf, size, offset); - if (now == 0) { - errno = ENOSPC; - return -errno; - } + if (now == 0) + return errno_set(-ENOSPC); if (now < 0) return now; size -= now; @@ -61,10 +59,8 @@ int write_full(int fd, const void *buf, size_t size) while (size) { now = write(fd, buf, size); - if (now == 0) { - errno = ENOSPC; - return -errno; - } + if (now == 0) + return errno_set(-ENOSPC); if (now < 0) return now; size -= now; @@ -191,6 +187,33 @@ out: EXPORT_SYMBOL_GPL(read_file_line); /** + * read_file_into_buf - read a file to an external buffer + * @filename: The filename to read + * @buf: The buffer to read into + * @size: The buffer size + * + * This function reads a file to an external buffer. At maximum @size + * bytes are read. + * + * Return: number of bytes read, or negative error code. + */ +ssize_t read_file_into_buf(const char *filename, void *buf, size_t size) +{ + int fd; + ssize_t ret; + + fd = open(filename, O_RDONLY); + if (fd < 0) + return fd; + + ret = read_full(fd, buf, size); + + close(fd); + + return ret; +} + +/** * read_file_2 - read a file to an allocated buffer * @filename: The filename to read * @size: After successful return contains the size of the file @@ -212,11 +235,10 @@ EXPORT_SYMBOL_GPL(read_file_line); int read_file_2(const char *filename, size_t *size, void **outbuf, loff_t max_size) { - int fd; struct stat s; void *buf = NULL; const char *tmpfile = "/.read_file_tmp"; - int ret; + ssize_t ret; loff_t read_size; again: @@ -240,22 +262,13 @@ again: /* ensure wchar_t nul termination */ buf = calloc(ALIGN(read_size, 2) + 2, 1); if (!buf) { - ret = -ENOMEM; - errno = ENOMEM; - goto err_out; - } - - fd = open(filename, O_RDONLY); - if (fd < 0) { - ret = fd; + ret = errno_set(-ENOMEM); goto err_out; } - ret = read_full(fd, buf, read_size); + ret = read_file_into_buf(filename, buf, read_size); if (ret < 0) - goto err_out1; - - close(fd); + goto err_out; if (size) *size = ret; @@ -270,8 +283,6 @@ again: return 0; -err_out1: - close(fd); err_out: free(buf); @@ -307,6 +318,56 @@ void *read_file(const char *filename, size_t *size) EXPORT_SYMBOL(read_file); /** + * 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; + + if (st.st_size == FILE_SIZE_STREAM) { + errno = EINVAL; + 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; +} +EXPORT_SYMBOL(read_fd); + +/** * write_file - write a buffer to a file * @filename: The filename to write * @size: The size of the buffer @@ -387,7 +448,7 @@ int copy_file(const char *src, const char *dst, int verbose) srcfd = open(src, O_RDONLY); if (srcfd < 0) { - printf("could not open %s: %s\n", src, errno_str()); + printf("could not open %s: %m\n", src); ret = srcfd; goto out; } @@ -396,7 +457,7 @@ int copy_file(const char *src, const char *dst, int verbose) s = stat(dst, &dststat); if (s && s != -ENOENT) { - printf("could not stat %s: %s\n", dst, errno_str()); + printf("could not stat %s: %m\n", dst); ret = s; goto out; } @@ -407,7 +468,7 @@ int copy_file(const char *src, const char *dst, int verbose) dstfd = open(dst, mode); if (dstfd < 0) { - printf("could not open %s: %s\n", dst, errno_str()); + printf("could not open %s: %m\n", dst); ret = dstfd; goto out; } @@ -542,8 +603,10 @@ int compare_file(const char *f1, const char *f2) if (ret) goto err_out2; - if (s1.st_size != s2.st_size) - return 1; + if (s1.st_size != s2.st_size) { + ret = 1; + goto err_out2; + } buf1 = xmalloc(RW_BUF_SIZE); buf2 = xmalloc(RW_BUF_SIZE); @@ -587,17 +650,15 @@ err_out1: * @pos: The position to lseek to * * Return: If successful this function returns a positive - * filedescriptor number, otherwise -1 is returned + * filedescriptor number, otherwise a negative error code is returned */ int open_and_lseek(const char *filename, int mode, loff_t pos) { - int fd; + int fd, ret; fd = open(filename, mode); - if (fd < 0) { - perror("open"); + if (fd < 0) return fd; - } if (!pos) return fd; @@ -605,26 +666,26 @@ int open_and_lseek(const char *filename, int mode, loff_t pos) if (mode & (O_WRONLY | O_RDWR)) { struct stat s; - if (fstat(fd, &s)) { - perror("fstat"); + ret = fstat(fd, &s); + if (ret < 0) goto out; - } - if (s.st_size < pos && ftruncate(fd, pos)) { - perror("ftruncate"); - goto out; + if (s.st_size < pos) { + ret = ftruncate(fd, pos); + if (ret) + goto out; } } if (lseek(fd, pos, SEEK_SET) != pos) { - perror("lseek"); + ret = -errno; goto out; } return fd; out: close(fd); - return -1; + return ret; } /** |