From 60aa4238c40519512cc4767f394201699042bf66 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 29 Sep 2015 12:10:02 +0100 Subject: [PATCH] lib: Move read_whole_file function into separate library. Allow this useful function to be called from elsewhere. This commit is almost, but not completely refactoring. I made a minor change to the function so that it \0-terminates the returned data, which is convenient for some callers. --- po/POTFILES | 1 + src/Makefile.am | 1 + src/guestfs-internal.h | 3 ++ src/inspect-icon.c | 72 +++------------------------------ src/whole-file.c | 91 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 101 insertions(+), 67 deletions(-) create mode 100644 src/whole-file.c diff --git a/po/POTFILES b/po/POTFILES index bb68183ec..9d9269056 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -349,6 +349,7 @@ src/structs-free.c src/test-utils.c src/tmpdirs.c src/utils.c +src/whole-file.c test-tool/test-tool.c v2v/domainxml-c.c v2v/kvmuid-c.c diff --git a/src/Makefile.am b/src/Makefile.am index 38a4f507a..f5ecaa6ed 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -126,6 +126,7 @@ libguestfs_la_SOURCES = \ structs-copy.c \ structs-free.c \ tmpdirs.c \ + whole-file.c \ libguestfs.syms libguestfs_la_CPPFLAGS = \ diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h index 22e8e06b6..75ca71c96 100644 --- a/src/guestfs-internal.h +++ b/src/guestfs-internal.h @@ -754,6 +754,9 @@ extern int guestfs_int_lazy_make_tmpdir (guestfs_h *g); extern void guestfs_int_remove_tmpdir (guestfs_h *g); extern void guestfs_int_recursive_remove_dir (guestfs_h *g, const char *dir); +/* whole-file.c */ +extern int guestfs_int_read_whole_file (guestfs_h *g, const char *filename, char **data_r, size_t *size_r); + /* drives.c */ extern size_t guestfs_int_checkpoint_drives (guestfs_h *g); extern void guestfs_int_rollback_drives (guestfs_h *g, size_t); diff --git a/src/inspect-icon.c b/src/inspect-icon.c index 33d0aa798..15c721b1a 100644 --- a/src/inspect-icon.c +++ b/src/inspect-icon.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include @@ -43,8 +42,6 @@ #define CAN_DO_WINDOWS 1 #endif -static int read_whole_file (guestfs_h *g, const char *filename, char **data_r, size_t *size_r); - /* All these icon_*() functions return the same way. One of: * * ret == NULL: @@ -272,7 +269,7 @@ get_png (guestfs_h *g, struct inspect_fs *fs, const char *filename, return NOT_FOUND; /* Successfully passed checks and downloaded. Read it into memory. */ - if (read_whole_file (g, local, &ret, size_r) == -1) + if (guestfs_int_read_whole_file (g, local, &ret, size_r) == -1) return NULL; return ret; @@ -419,7 +416,7 @@ icon_cirros (guestfs_h *g, struct inspect_fs *fs, size_t *size_r) return NOT_FOUND; /* Read it into memory. */ - if (read_whole_file (g, pngfile, &ret, size_r) == -1) + if (guestfs_int_read_whole_file (g, pngfile, &ret, size_r) == -1) return NULL; return ret; @@ -488,7 +485,7 @@ icon_windows_xp (guestfs_h *g, struct inspect_fs *fs, size_t *size_r) if (!WIFEXITED (r) || WEXITSTATUS (r) != 0) return NOT_FOUND; - if (read_whole_file (g, pngfile, &ret, size_r) == -1) + if (guestfs_int_read_whole_file (g, pngfile, &ret, size_r) == -1) return NULL; return ret; @@ -540,7 +537,7 @@ icon_windows_7 (guestfs_h *g, struct inspect_fs *fs, size_t *size_r) if (!WIFEXITED (r) || WEXITSTATUS (r) != 0) return NOT_FOUND; - if (read_whole_file (g, pngfile, &ret, size_r) == -1) + if (guestfs_int_read_whole_file (g, pngfile, &ret, size_r) == -1) return NULL; return ret; @@ -577,7 +574,7 @@ icon_windows_8 (guestfs_h *g, struct inspect_fs *fs, size_t *size_r) if (filename_downloaded == NULL) return NOT_FOUND; - if (read_whole_file (g, filename_downloaded, &ret, size_r) == -1) + if (guestfs_int_read_whole_file (g, filename_downloaded, &ret, size_r) == -1) return NULL; return ret; @@ -606,62 +603,3 @@ icon_windows (guestfs_h *g, struct inspect_fs *fs, size_t *size_r) } #endif /* CAN_DO_WINDOWS */ - -/* Read the whole file into a memory buffer and return it. The file - * should be a regular, local, trusted file. - */ -static int -read_whole_file (guestfs_h *g, const char *filename, - char **data_r, size_t *size_r) -{ - int fd; - char *data; - off_t size; - off_t n; - ssize_t r; - struct stat statbuf; - - fd = open (filename, O_RDONLY|O_CLOEXEC); - if (fd == -1) { - perrorf (g, "open: %s", filename); - return -1; - } - - if (fstat (fd, &statbuf) == -1) { - perrorf (g, "stat: %s", filename); - close (fd); - return -1; - } - - size = statbuf.st_size; - data = safe_malloc (g, size); - - n = 0; - while (n < size) { - r = read (fd, &data[n], size - n); - if (r == -1) { - perrorf (g, "read: %s", filename); - free (data); - close (fd); - return -1; - } - if (r == 0) { - error (g, _("read: %s: unexpected end of file"), filename); - free (data); - close (fd); - return -1; - } - n += r; - } - - if (close (fd) == -1) { - perrorf (g, "close: %s", filename); - free (data); - return -1; - } - - *data_r = data; - *size_r = size; - - return 0; -} diff --git a/src/whole-file.c b/src/whole-file.c new file mode 100644 index 000000000..38050d92f --- /dev/null +++ b/src/whole-file.c @@ -0,0 +1,91 @@ +/* libguestfs + * Copyright (C) 2011-2015 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include +#include +#include +#include +#include + +#include "guestfs.h" +#include "guestfs-internal.h" + +/* Read the whole file into a memory buffer and return it. The file + * should be a regular, local, trusted file. + */ +int +guestfs_int_read_whole_file (guestfs_h *g, const char *filename, + char **data_r, size_t *size_r) +{ + int fd; + char *data; + off_t size; + off_t n; + ssize_t r; + struct stat statbuf; + + fd = open (filename, O_RDONLY|O_CLOEXEC); + if (fd == -1) { + perrorf (g, "open: %s", filename); + return -1; + } + + if (fstat (fd, &statbuf) == -1) { + perrorf (g, "stat: %s", filename); + close (fd); + return -1; + } + + size = statbuf.st_size; + data = safe_malloc (g, size + 1); + + n = 0; + while (n < size) { + r = read (fd, &data[n], size - n); + if (r == -1) { + perrorf (g, "read: %s", filename); + free (data); + close (fd); + return -1; + } + if (r == 0) { + error (g, _("read: %s: unexpected end of file"), filename); + free (data); + close (fd); + return -1; + } + n += r; + } + + if (close (fd) == -1) { + perrorf (g, "close: %s", filename); + free (data); + return -1; + } + + /* For convenience of callers, \0-terminate the data. */ + data[size] = '\0'; + + *data_r = data; + if (size_r != NULL) + *size_r = size; + + return 0; +}