[PATCH] ext2: Don't load whole files into memory when copying to the appliance (RHBZ#1113065).
by Richard W.M. Jones
Obviously for very large files this is going to be a problem, as well
as not being very cache efficient.
libext2fs can handle writes to parts of files just fine so copy files
in blocks.
Also demote the "Permission denied" error to a warning, and add some
explanatory text telling people not to use sudo.
---
src/ext2fs-c.c | 127 +++++++++++++++++++++++++++++++++++----------------------
1 file changed, 78 insertions(+), 49 deletions(-)
diff --git a/src/ext2fs-c.c b/src/ext2fs-c.c
index cb9282b..96a3de0 100644
--- a/src/ext2fs-c.c
+++ b/src/ext2fs-c.c
@@ -185,6 +185,7 @@ supermin_ext2fs_read_bitmaps (value fsv)
static void ext2_mkdir (ext2_filsys fs, ext2_ino_t dir_ino, const char *dirname, const char *basename, mode_t mode, uid_t uid, gid_t gid, time_t ctime, time_t atime, time_t mtime);
static void ext2_empty_inode (ext2_filsys fs, ext2_ino_t dir_ino, const char *dirname, const char *basename, mode_t mode, uid_t uid, gid_t gid, time_t ctime, time_t atime, time_t mtime, int major, int minor, int dir_ft, ext2_ino_t *ino_ret);
static void ext2_write_file (ext2_filsys fs, ext2_ino_t ino, const char *buf, size_t size, const char *filename);
+static void ext2_write_host_file (ext2_filsys fs, ext2_ino_t ino, const char *src, const char *filename);
static void ext2_link (ext2_filsys fs, ext2_ino_t dir_ino, const char *basename, ext2_ino_t ino, int dir_ft);
static void ext2_clean_path (ext2_filsys fs, ext2_ino_t dir_ino, const char *dirname, const char *basename, int isdir);
static void ext2_copy_file (struct ext2_data *data, const char *src, const char *dest);
@@ -500,6 +501,81 @@ ext2_write_file (ext2_filsys fs,
ext2_error_to_exception ("ext2fs_write_inode", err, filename);
}
+/* Same as ext2_write_file, but it copies the file contents from the
+ * host. You must create the file first with ext2_empty_inode, and
+ * the host file must be a regular file.
+ */
+static void
+ext2_write_host_file (ext2_filsys fs,
+ ext2_ino_t ino,
+ const char *src, /* source (host) file */
+ const char *filename)
+{
+ int fd;
+ char buf[BUFSIZ];
+ ssize_t r;
+ size_t size = 0;
+ errcode_t err;
+ ext2_file_t file;
+ unsigned int written;
+
+ fd = open (src, O_RDONLY);
+ if (fd == -1) {
+ static int warned = 0;
+
+ /* We skip unreadable files. However if the error is -EACCES then
+ * modify the message so as not to frighten the horses.
+ */
+ fprintf (stderr, "supermin: warning: %s: %m (ignored)\n", filename);
+ if (errno == EACCES && !warned) {
+ fprintf (stderr,
+ "Some distro files are not public readable, so supermin cannot copy them\n"
+ "into the appliance. This is a problem with your Linux distro. Please ask\n"
+ "your distro to stop doing pointless security by obscurity.\n"
+ "You can ignore these warnings. You *do not* need to use sudo.\n");
+ warned = 1;
+ }
+ return;
+ }
+
+ err = ext2fs_file_open2 (fs, ino, NULL, EXT2_FILE_WRITE, &file);
+ if (err != 0)
+ ext2_error_to_exception ("ext2fs_file_open2", err, filename);
+
+ while ((r = read (fd, buf, sizeof buf)) > 0) {
+ err = ext2fs_file_write (file, buf, r, &written);
+ if (err != 0)
+ ext2_error_to_exception ("ext2fs_file_open2", err, filename);
+ if ((ssize_t) written != r)
+ caml_failwith ("ext2fs_file_write: requested write size != bytes written");
+ size += written;
+ }
+
+ if (r == -1)
+ unix_error (errno, (char *) "read", caml_copy_string (filename));
+
+ if (close (fd) == -1)
+ unix_error (errno, (char *) "close", caml_copy_string (filename));
+
+ /* Flush out the ext2 file. */
+ err = ext2fs_file_flush (file);
+ if (err != 0)
+ ext2_error_to_exception ("ext2fs_file_flush", err, filename);
+ err = ext2fs_file_close (file);
+ if (err != 0)
+ ext2_error_to_exception ("ext2fs_file_close", err, filename);
+
+ /* Update the true size in the inode. */
+ struct ext2_inode inode;
+ err = ext2fs_read_inode (fs, ino, &inode);
+ if (err != 0)
+ ext2_error_to_exception ("ext2fs_read_inode", err, filename);
+ inode.i_size = size;
+ err = ext2fs_write_inode (fs, ino, &inode);
+ if (err != 0)
+ ext2_error_to_exception ("ext2fs_write_inode", err, filename);
+}
+
/* This is just a wrapper around ext2fs_link which calls
* ext2fs_expand_dir as necessary if the directory fills up. See
* definition of expand_dir in the sources of debugfs.
@@ -589,43 +665,6 @@ ext2_clean_path (ext2_filsys fs, ext2_ino_t dir_ino,
/* else it's a directory, what to do? XXX */
}
-/* Read in the whole file into memory. Check the size is still 'size'. */
-static char *
-read_whole_file (const char *filename, size_t size)
-{
- char *buf = malloc (size);
- if (buf == NULL)
- caml_raise_out_of_memory ();
-
- int fd = open (filename, O_RDONLY);
- if (fd == -1) {
- /* Skip unreadable files. */
- fprintf (stderr, "supermin: open: %s: %m\n", filename);
- free (buf);
- return NULL;
- }
-
- size_t n = 0;
- char *p = buf;
-
- while (n < size) {
- ssize_t r = read (fd, p, size - n);
- if (r == -1)
- unix_error (errno, (char *) "read", caml_copy_string (filename));
- if (r == 0) {
- fprintf (stderr, "supermin: end of file reading '%s'\n", filename);
- caml_invalid_argument ("ext2fs: file has changed size unexpectedly");
- }
- n += r;
- p += r;
- }
-
- if (close (fd) == -1)
- unix_error (errno, (char *) "close", caml_copy_string (filename));
-
- return buf;
-}
-
/* Copy a file (or directory etc) from the host. */
static void
ext2_copy_file (struct ext2_data *data, const char *src, const char *dest)
@@ -766,24 +805,14 @@ ext2_copy_file (struct ext2_data *data, const char *src, const char *dest)
if (S_ISREG (statbuf.st_mode)) {
/* XXX Hard links get duplicated here. */
ext2_ino_t ino;
- char *buf = NULL;
-
- if (statbuf.st_size > 0) {
- buf = read_whole_file (src, statbuf.st_size);
- if (buf == NULL)
- goto skip_unreadable_file;
- }
ext2_empty_inode (data->fs, dir_ino, dirname, basename,
statbuf.st_mode, statbuf.st_uid, statbuf.st_gid,
statbuf.st_ctime, statbuf.st_atime, statbuf.st_mtime,
0, 0, EXT2_FT_REG_FILE, &ino);
- if (statbuf.st_size > 0) {
- ext2_write_file (data->fs, ino, buf, statbuf.st_size, dest);
- free (buf);
- }
- skip_unreadable_file: ;
+ if (statbuf.st_size > 0)
+ ext2_write_host_file (data->fs, ino, src, dest);
}
/* Create a symlink. */
else if (S_ISLNK (statbuf.st_mode)) {
--
2.7.4
8 years, 5 months
[PATCH 1/2] inspection: Find Ubuntu logo from an alternate location (RHBZ#1352761).
by Richard W.M. Jones
The current location doesn't exist unless you've installed GNOME,
which is not so common on Ubuntu. Unfortunately I couldn't find any
other location containing a clean, high quality logo.
This adds another low quality icon source, and also prevents any icon
being returned if the highquality flag was set (note this prevents
virt-manager from displaying an icon, but there's nothing we can do
about that, and it's no worse than the current situation).
Updates commit 1d0683964f996b24b8fcf5bce7611a98443344f3.
Thanks: Xiaoyun Hu
---
src/inspect-icon.c | 26 ++++++++++++++++++++++----
1 file changed, 22 insertions(+), 4 deletions(-)
diff --git a/src/inspect-icon.c b/src/inspect-icon.c
index c298dd7..3893fba 100644
--- a/src/inspect-icon.c
+++ b/src/inspect-icon.c
@@ -141,7 +141,8 @@ guestfs_impl_inspect_get_icon (guestfs_h *g, const char *root, size_t *size_r,
break;
case OS_DISTRO_UBUNTU:
- r = icon_ubuntu (g, fs, &size);
+ if (!highquality)
+ r = icon_ubuntu (g, fs, &size);
break;
case OS_DISTRO_MAGEIA:
@@ -349,12 +350,29 @@ icon_debian (guestfs_h *g, struct inspect_fs *fs, size_t *size_r)
return get_png (g, fs, DEBIAN_ICON, size_r, 2048);
}
-#define UBUNTU_ICON "/usr/share/icons/gnome/24x24/places/ubuntu-logo.png"
-
static char *
icon_ubuntu (guestfs_h *g, struct inspect_fs *fs, size_t *size_r)
{
- return get_png (g, fs, UBUNTU_ICON, size_r, 2048);
+ const char *icons[] = {
+ "/usr/share/icons/gnome/24x24/places/ubuntu-logo.png",
+
+ /* Very low quality and only present when ubuntu-desktop packages
+ * have been installed.
+ */
+ "/usr/share/help/C/ubuntu-help/figures/ubuntu-logo.png",
+ NULL
+ };
+ size_t i;
+ char *ret;
+
+ for (i = 0; icons[i] != NULL; ++i) {
+ ret = get_png (g, fs, icons[i], size_r, 2048);
+ if (ret == NULL)
+ return NULL;
+ if (ret != NOT_FOUND)
+ return ret;
+ }
+ return NOT_FOUND;
}
#define MAGEIA_ICON "/usr/share/icons/mageia.png"
--
2.7.4
8 years, 5 months
[PATCH 0/2] More information reported by filesystem_walk
by Matteo Cafasso
Report access, modification, status update and creation time in Unix format.
Report number of links pointing to a given entry.
If the entry is a symbolic link, report the path of its target.
If the filesystem supports native/transparent compression, report compressed
files with dedicated flag (DIRENT_COMPRESSED 0x04).
Matteo Cafasso (2):
filesystem_walk: more information into tsk_dirent
filesystem_walk: update tests
daemon/tsk.c | 39 +++++++++++++++++++++++++++-------
generator/actions.ml | 34 ++++++++++++++++++++++++++++++
generator/structs.ml | 20 +++++++++---------
tests/tsk/test-filesystem-walk.sh | 44 +++++++++++++++++++--------------------
4 files changed, 97 insertions(+), 40 deletions(-)
--
2.8.1
8 years, 5 months
[PATCH 0/2] v2v: fix setting custom modprobe options
by Pino Toscano
Hi,
due to a broken discover_modpath function, and to a wrong block for a
match statement, the modprobe options for virtio/SCSI blocks where not
written at all.
This series provides a small refactor, and the fixes.
Thanks,
--
Pino Toscano (2):
v2v: fix and implify the internal Convert_linux:discover_modpath
v2v: fix priority of match in configure_kernel_modules
v2v/convert_linux.ml | 34 ++++++++++++----------------------
1 file changed, 12 insertions(+), 22 deletions(-)
--
2.5.5
8 years, 6 months