mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-22 07:03:38 +00:00
New API: inspect-get-icon returns the guest icon.
This API returns the guest's favicon if found, else an icon representing the guest operating system. Currently supported by this patch: Fedora, RHEL and derivatives, Debian (but not Ubuntu), Windows XP, Windows 7. This also updates virt-inspector to include an <icon> element containing the icon in base64 encoding.
This commit is contained in:
7
TODO
7
TODO
@@ -441,13 +441,6 @@ More inspection features
|
||||
- last user who logged in
|
||||
- lastlog, last, who
|
||||
|
||||
Get the guest icon
|
||||
------------------
|
||||
|
||||
- For Linux guests, use /etc/favicon.png if available, else get it in
|
||||
a distro-specific manner.
|
||||
- For Windows guests, parse it out of c:\windows\explorer.exe
|
||||
|
||||
Integrate virt-inspector with CMDBs
|
||||
-----------------------------------
|
||||
|
||||
|
||||
@@ -1462,6 +1462,70 @@ Please read L<guestfs(3)/INSPECTION> for more details.
|
||||
See also C<guestfs_inspect_get_mountpoints>,
|
||||
C<guestfs_inspect_get_filesystems>.");
|
||||
|
||||
("inspect_get_icon", (RBufferOut "icon", [Device "root"], [Bool "favicon"; Bool "highquality"]), -1, [],
|
||||
[],
|
||||
"get the icon corresponding to this operating system",
|
||||
"\
|
||||
This function returns an icon corresponding to the inspected
|
||||
operating system. The icon is returned as a buffer containing a
|
||||
PNG image (re-encoded to PNG if necessary).
|
||||
|
||||
If it was not possible to get an icon this function returns a
|
||||
zero-length (non-NULL) buffer. I<Callers must check for this case>.
|
||||
|
||||
Libguestfs will start by looking for a file called
|
||||
C</etc/favicon.png> or C<C:\\etc\\favicon.png>
|
||||
and if it has the correct format, the contents of this file will
|
||||
be returned. You can disable favicons by passing the
|
||||
optional C<favicon> boolean as false (default is true).
|
||||
|
||||
If finding the favicon fails, then we look in other places in the
|
||||
guest for a suitable icon.
|
||||
|
||||
If the optional C<highquality> boolean is true then
|
||||
only high quality icons are returned, which means only icons of
|
||||
high resolution with an alpha channel. The default (false) is
|
||||
to return any icon we can, even if it is of substandard quality.
|
||||
|
||||
Notes:
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
Unlike most other inspection API calls, the guest's disks must be
|
||||
mounted up before you call this, since it needs to read information
|
||||
from the guest filesystem during the call.
|
||||
|
||||
=item *
|
||||
|
||||
B<Security:> The icon data comes from the untrusted guest,
|
||||
and should be treated with caution. PNG files have been
|
||||
known to contain exploits. Ensure that libpng (or other relevant
|
||||
libraries) are fully up to date before trying to process or
|
||||
display the icon.
|
||||
|
||||
=item *
|
||||
|
||||
The PNG image returned can be any size. It might not be square.
|
||||
Libguestfs tries to return the largest, highest quality
|
||||
icon available. The application must scale the icon to the
|
||||
required size.
|
||||
|
||||
=item *
|
||||
|
||||
Extracting icons from Windows guests requires the external
|
||||
C<wrestool> program from the C<icoutils> package, and
|
||||
several programs (C<bmptopnm>, C<pnmtopng>, C<pamcut>)
|
||||
from the C<netpbm> package. These must be installed separately.
|
||||
|
||||
=item *
|
||||
|
||||
Operating system icons are usually trademarks. Seek legal
|
||||
advice before using trademarks in applications.
|
||||
|
||||
=back");
|
||||
|
||||
]
|
||||
|
||||
(* daemon_functions are any functions which cause some action
|
||||
|
||||
@@ -340,6 +340,7 @@ output_root (xmlTextWriterPtr xo, char *root)
|
||||
int i, r;
|
||||
char buf[32];
|
||||
char canonical_root[strlen (root) + 1];
|
||||
size_t size;
|
||||
|
||||
XMLERROR (-1, xmlTextWriterStartElement (xo, BAD_CAST "operatingsystem"));
|
||||
|
||||
@@ -471,8 +472,32 @@ output_root (xmlTextWriterPtr xo, char *root)
|
||||
|
||||
output_drive_mappings (xo, root);
|
||||
|
||||
/* We need to mount everything up in order to read out the list of
|
||||
* applications and the icon, ie. everything below this point.
|
||||
*/
|
||||
inspect_mount_root (root);
|
||||
|
||||
output_applications (xo, root);
|
||||
|
||||
/* Don't return favicon. XXX Should we? */
|
||||
str = guestfs_inspect_get_icon (g, root, &size,
|
||||
GUESTFS_INSPECT_GET_ICON_FAVICON, 0,
|
||||
-1);
|
||||
if (!str) exit (EXIT_FAILURE);
|
||||
if (size > 0) {
|
||||
XMLERROR (-1, xmlTextWriterStartElement (xo, BAD_CAST "icon"));
|
||||
XMLERROR (-1, xmlTextWriterWriteBase64 (xo, str, 0, size));
|
||||
XMLERROR (-1, xmlTextWriterEndElement (xo));
|
||||
}
|
||||
/* Note we must free (str) even if size == 0, because that indicates
|
||||
* there was no icon.
|
||||
*/
|
||||
free (str);
|
||||
|
||||
/* Unmount (see inspect_mount_root above). */
|
||||
if (guestfs_umount_all (g) == -1)
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
XMLERROR (-1, xmlTextWriterEndElement (xo));
|
||||
}
|
||||
|
||||
@@ -652,19 +677,12 @@ output_applications (xmlTextWriterPtr xo, char *root)
|
||||
struct guestfs_application_list *apps;
|
||||
size_t i;
|
||||
|
||||
/* We need to mount everything up in order to read out the list of
|
||||
* applications.
|
||||
*/
|
||||
inspect_mount_root (root);
|
||||
|
||||
/* This returns an empty list if we simply couldn't determine the
|
||||
* applications, so if it returns NULL then it's a real error.
|
||||
*/
|
||||
apps = guestfs_inspect_list_applications (g, root);
|
||||
if (apps == NULL)
|
||||
exit (EXIT_FAILURE);
|
||||
if (guestfs_umount_all (g) == -1)
|
||||
exit (EXIT_FAILURE);
|
||||
|
||||
XMLERROR (-1, xmlTextWriterStartElement (xo, BAD_CAST "applications"));
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<grammar xmlns="http://relaxng.org/ns/structure/1.0">
|
||||
<grammar
|
||||
xmlns="http://relaxng.org/ns/structure/1.0"
|
||||
datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
|
||||
<!-- -*- xml -*-
|
||||
This is a RELAX NG schema for the output of 'virt-inspector'.
|
||||
|
||||
@@ -51,6 +53,8 @@
|
||||
<optional><ref name="drive_mappings"/></optional>
|
||||
<optional><ref name="applications"/></optional>
|
||||
|
||||
<optional><element name="icon"><data type="base64Binary"/></element></optional>
|
||||
|
||||
</interleave>
|
||||
</element>
|
||||
</oneOrMore>
|
||||
|
||||
@@ -147,6 +147,7 @@ src/inspect_fs.c
|
||||
src/inspect_fs_cd.c
|
||||
src/inspect_fs_unix.c
|
||||
src/inspect_fs_windows.c
|
||||
src/inspect_icon.c
|
||||
src/launch.c
|
||||
src/listfs.c
|
||||
src/match.c
|
||||
|
||||
@@ -133,6 +133,7 @@ libguestfs_la_SOURCES = \
|
||||
inspect_fs_cd.c \
|
||||
inspect_fs_unix.c \
|
||||
inspect_fs_windows.c \
|
||||
inspect_icon.c \
|
||||
launch.c \
|
||||
listfs.c \
|
||||
match.c \
|
||||
|
||||
@@ -89,6 +89,9 @@
|
||||
*/
|
||||
#define MAX_PKG_DB_SIZE (300 * 1000 * 1000)
|
||||
|
||||
/* Maximum size of Windows explorer.exe. 2.6MB on Windows 7. */
|
||||
#define MAX_WINDOWS_EXPLORER_SIZE (4 * 1000 * 1000)
|
||||
|
||||
/* Network configuration of the appliance. Note these addresses are
|
||||
* only meaningful within the context of the running appliance. QEMU
|
||||
* translates network connections to these magic addresses into
|
||||
|
||||
470
src/inspect_icon.c
Normal file
470
src/inspect_icon.c
Normal file
@@ -0,0 +1,470 @@
|
||||
/* libguestfs
|
||||
* Copyright (C) 2011 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 <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "guestfs.h"
|
||||
#include "guestfs-internal.h"
|
||||
#include "guestfs-internal-actions.h"
|
||||
#include "guestfs_protocol.h"
|
||||
|
||||
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:
|
||||
* An error occurred. Error has been set in the handle. The caller
|
||||
* should return NULL immediately.
|
||||
*
|
||||
* ret == NOT_FOUND:
|
||||
* Not an error, but no icon was found. 'ret' is just a dummy value
|
||||
* which should be ignored (do not free it!)
|
||||
*
|
||||
* ret == ordinary pointer:
|
||||
* An icon was found. 'ret' points to the icon buffer, and *size_r
|
||||
* is the size.
|
||||
*/
|
||||
static char *icon_favicon (guestfs_h *g, struct inspect_fs *fs, size_t *size_r);
|
||||
static char *icon_fedora (guestfs_h *g, struct inspect_fs *fs, size_t *size_r);
|
||||
static char *icon_rhel (guestfs_h *g, struct inspect_fs *fs, size_t *size_r);
|
||||
static char *icon_debian (guestfs_h *g, struct inspect_fs *fs, size_t *size_r);
|
||||
static char *icon_windows (guestfs_h *g, struct inspect_fs *fs, size_t *size_r);
|
||||
|
||||
/* Dummy static object. */
|
||||
static char *NOT_FOUND = (char *) "not_found";
|
||||
|
||||
/* For the unexpected legal consequences of this function, see:
|
||||
* http://lists.fedoraproject.org/pipermail/legal/2011-April/001615.html
|
||||
*
|
||||
* Returns an RBufferOut, so the length of the returned buffer is
|
||||
* returned in *size_r.
|
||||
*
|
||||
* Check optargs for the optional argument.
|
||||
*/
|
||||
char *
|
||||
guestfs__inspect_get_icon (guestfs_h *g, const char *root, size_t *size_r,
|
||||
const struct guestfs_inspect_get_icon_argv *optargs)
|
||||
{
|
||||
struct inspect_fs *fs;
|
||||
char *r = NOT_FOUND;
|
||||
int favicon, highquality;
|
||||
size_t size;
|
||||
|
||||
fs = guestfs___search_for_root (g, root);
|
||||
if (!fs)
|
||||
return NULL;
|
||||
|
||||
/* Get optargs, or defaults. */
|
||||
favicon =
|
||||
optargs->bitmask & GUESTFS_INSPECT_GET_ICON_FAVICON_BITMASK ?
|
||||
optargs->favicon : 1;
|
||||
|
||||
highquality =
|
||||
optargs->bitmask & GUESTFS_INSPECT_GET_ICON_HIGHQUALITY_BITMASK ?
|
||||
optargs->highquality : 0;
|
||||
|
||||
/* Favicons are never high quality, so ... */
|
||||
if (highquality)
|
||||
favicon = 0;
|
||||
|
||||
/* Try looking for a favicon first. */
|
||||
if (favicon) {
|
||||
r = icon_favicon (g, fs, &size);
|
||||
if (!r)
|
||||
return NULL;
|
||||
|
||||
if (r != NOT_FOUND) {
|
||||
/* try_favicon succeeded in finding a favicon. */
|
||||
*size_r = size;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
/* Favicon failed, so let's try a method based on the detected operating
|
||||
* system.
|
||||
*/
|
||||
switch (fs->type) {
|
||||
case OS_TYPE_LINUX:
|
||||
switch (fs->distro) {
|
||||
case OS_DISTRO_FEDORA:
|
||||
r = icon_fedora (g, fs, &size);
|
||||
break;
|
||||
|
||||
case OS_DISTRO_RHEL:
|
||||
case OS_DISTRO_REDHAT_BASED:
|
||||
case OS_DISTRO_CENTOS:
|
||||
case OS_DISTRO_SCIENTIFIC_LINUX:
|
||||
r = icon_rhel (g, fs, &size);
|
||||
break;
|
||||
|
||||
case OS_DISTRO_DEBIAN:
|
||||
r = icon_debian (g, fs, &size);
|
||||
break;
|
||||
|
||||
/* These are just to keep gcc warnings happy. */
|
||||
case OS_DISTRO_ARCHLINUX:
|
||||
case OS_DISTRO_GENTOO:
|
||||
case OS_DISTRO_LINUX_MINT:
|
||||
case OS_DISTRO_MANDRIVA:
|
||||
case OS_DISTRO_MEEGO:
|
||||
case OS_DISTRO_PARDUS:
|
||||
case OS_DISTRO_SLACKWARE:
|
||||
case OS_DISTRO_UBUNTU:
|
||||
case OS_DISTRO_WINDOWS:
|
||||
case OS_DISTRO_UNKNOWN:
|
||||
default: ;
|
||||
}
|
||||
break;
|
||||
|
||||
case OS_TYPE_WINDOWS:
|
||||
/* We don't know how to get high quality icons from a Windows guest,
|
||||
* so disable this if high quality was specified.
|
||||
*/
|
||||
if (!highquality)
|
||||
r = icon_windows (g, fs, &size);
|
||||
break;
|
||||
|
||||
case OS_TYPE_FREEBSD:
|
||||
case OS_TYPE_UNKNOWN:
|
||||
default: ;
|
||||
}
|
||||
|
||||
if (r == NOT_FOUND) {
|
||||
/* Not found, but not an error. So return the special zero-length
|
||||
* buffer. Use malloc(1) here to ensure that malloc won't return
|
||||
* NULL.
|
||||
*/
|
||||
r = safe_malloc (g, 1);
|
||||
size = 0;
|
||||
}
|
||||
|
||||
*size_r = size;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Check that the named file 'filename' is a PNG file and is reasonable.
|
||||
* If it is, download and return it.
|
||||
*/
|
||||
static char *
|
||||
get_png (guestfs_h *g, struct inspect_fs *fs, const char *filename,
|
||||
size_t *size_r, size_t max_size)
|
||||
{
|
||||
char *ret = NOT_FOUND;
|
||||
char *type = NULL;
|
||||
char *local = NULL;
|
||||
int r, w, h;
|
||||
|
||||
r = guestfs_exists (g, filename);
|
||||
if (r == -1) {
|
||||
ret = NULL; /* a real error */
|
||||
goto out;
|
||||
}
|
||||
if (r == 0) goto out;
|
||||
|
||||
/* Check the file type and geometry. */
|
||||
type = guestfs_file (g, filename);
|
||||
if (!type) goto out;
|
||||
|
||||
if (!STRPREFIX (type, "PNG image data, ")) goto out;
|
||||
if (sscanf (&type[16], "%d x %d", &w, &h) != 2) goto out;
|
||||
if (w < 16 || h < 16 || w > 1024 || h > 1024) goto out;
|
||||
|
||||
/* Define a maximum reasonable size based on the geometry. This
|
||||
* also limits the maximum we allocate below to around 4 MB.
|
||||
*/
|
||||
if (max_size == 0)
|
||||
max_size = 4 * w * h;
|
||||
|
||||
local = guestfs___download_to_tmp (g, fs, filename, "icon", max_size);
|
||||
if (!local) goto out;
|
||||
|
||||
/* Successfully passed checks and downloaded. Read it into memory. */
|
||||
if (read_whole_file (g, local, &ret, size_r) == -1) {
|
||||
ret = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
free (local);
|
||||
free (type);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Return /etc/favicon.png (or \etc\favicon.png) if it exists and if
|
||||
* it has a reasonable size and format.
|
||||
*/
|
||||
static char *
|
||||
icon_favicon (guestfs_h *g, struct inspect_fs *fs, size_t *size_r)
|
||||
{
|
||||
char *ret;
|
||||
char *filename = safe_strdup (g, "/etc/favicon.png");
|
||||
|
||||
if (fs->type == OS_TYPE_WINDOWS) {
|
||||
char *f = guestfs___case_sensitive_path_silently (g, filename);
|
||||
if (f) {
|
||||
free (filename);
|
||||
filename = f;
|
||||
}
|
||||
}
|
||||
|
||||
ret = get_png (g, fs, filename, size_r, 0);
|
||||
free (filename);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Return FEDORA_ICON. I checked that this exists on at least Fedora 6
|
||||
* through 16.
|
||||
*/
|
||||
#define FEDORA_ICON "/usr/share/icons/hicolor/96x96/apps/fedora-logo-icon.png"
|
||||
|
||||
static char *
|
||||
icon_fedora (guestfs_h *g, struct inspect_fs *fs, size_t *size_r)
|
||||
{
|
||||
return get_png (g, fs, FEDORA_ICON, size_r, 0);
|
||||
}
|
||||
|
||||
/* RHEL 3, 4:
|
||||
* /usr/share/pixmaps/redhat/shadowman-transparent.png is a 517x515
|
||||
* PNG with alpha channel, around 64K in size.
|
||||
*
|
||||
* RHEL 5, 6:
|
||||
* As above, but the file has been optimized to about 16K.
|
||||
*
|
||||
* Conveniently the RHEL clones also have the same file with the
|
||||
* same name, but containing their own logos. Sense prevails!
|
||||
*/
|
||||
#define SHADOWMAN_ICON "/usr/share/pixmaps/redhat/shadowman-transparent.png"
|
||||
|
||||
static char *
|
||||
icon_rhel (guestfs_h *g, struct inspect_fs *fs, size_t *size_r)
|
||||
{
|
||||
size_t max_size = 0;
|
||||
|
||||
if (fs->distro == OS_DISTRO_RHEL) {
|
||||
if (fs->major_version <= 4)
|
||||
max_size = 66000;
|
||||
else
|
||||
max_size = 17000;
|
||||
}
|
||||
|
||||
return get_png (g, fs, SHADOWMAN_ICON, size_r, max_size);
|
||||
}
|
||||
|
||||
/* NB: I've not located an Ubuntu logo yet. */
|
||||
#define DEBIAN_ICON "/usr/share/pixmaps/debian-logo.png"
|
||||
|
||||
static char *
|
||||
icon_debian (guestfs_h *g, struct inspect_fs *fs, size_t *size_r)
|
||||
{
|
||||
return get_png (g, fs, DEBIAN_ICON, size_r, 2048);
|
||||
}
|
||||
|
||||
/* Windows, as usual, has to be much more complicated and stupid than
|
||||
* anything else.
|
||||
*
|
||||
* We have to download %systemroot%\explorer.exe and use a special
|
||||
* program called 'wrestool' to extract the icons from this file. For
|
||||
* each version of Windows, the icon we want is in a different place.
|
||||
* The icon is in a stupid format (BMP), and in some cases multiple
|
||||
* icons are in a single BMP file so we have to do some manipulation
|
||||
* on the file.
|
||||
*
|
||||
* XXX I've only bothered with this nonsense for a few versions of
|
||||
* Windows that I have handy. Please send patches to support other
|
||||
* versions.
|
||||
*/
|
||||
|
||||
static char *
|
||||
icon_windows_xp (guestfs_h *g, struct inspect_fs *fs, const char *explorer,
|
||||
size_t *size_r)
|
||||
{
|
||||
char *ret;
|
||||
char *pngfile;
|
||||
char *cmd;
|
||||
int r;
|
||||
|
||||
pngfile = safe_asprintf (g, "%s/windows-xp-icon.png", g->tmpdir);
|
||||
|
||||
cmd = safe_asprintf (g,
|
||||
"wrestool -x --type=2 --name=143 %s | "
|
||||
"bmptopnm | pnmtopng > %s",
|
||||
explorer, pngfile);
|
||||
r = system (cmd);
|
||||
if (r == -1 || WEXITSTATUS (r) != 0) {
|
||||
debug (g, "external command failed: %s", cmd);
|
||||
free (cmd);
|
||||
free (pngfile);
|
||||
return NOT_FOUND;
|
||||
}
|
||||
|
||||
free (cmd);
|
||||
|
||||
if (read_whole_file (g, pngfile, &ret, size_r) == -1) {
|
||||
free (pngfile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
free (pngfile);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *
|
||||
icon_windows_7 (guestfs_h *g, struct inspect_fs *fs, const char *explorer,
|
||||
size_t *size_r)
|
||||
{
|
||||
char *ret;
|
||||
char *pngfile;
|
||||
char *cmd;
|
||||
int r;
|
||||
|
||||
pngfile = safe_asprintf (g, "%s/windows-7-icon.png", g->tmpdir);
|
||||
|
||||
cmd = safe_asprintf (g,
|
||||
"wrestool -x --type=2 --name=6801 %s | "
|
||||
"bmptopnm | pamcut -bottom 54 | pnmtopng > %s",
|
||||
explorer, pngfile);
|
||||
r = system (cmd);
|
||||
if (r == -1 || WEXITSTATUS (r) != 0) {
|
||||
debug (g, "external command failed: %s", cmd);
|
||||
free (cmd);
|
||||
free (pngfile);
|
||||
return NOT_FOUND;
|
||||
}
|
||||
|
||||
free (cmd);
|
||||
|
||||
if (read_whole_file (g, pngfile, &ret, size_r) == -1) {
|
||||
free (pngfile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
free (pngfile);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *
|
||||
icon_windows (guestfs_h *g, struct inspect_fs *fs, size_t *size_r)
|
||||
{
|
||||
char *(*fn) (guestfs_h *g, struct inspect_fs *fs, const char *explorer,
|
||||
size_t *size_r);
|
||||
char *filename1, *filename2, *filename3;
|
||||
char *ret;
|
||||
|
||||
/* Windows XP. */
|
||||
if (fs->major_version == 5 && fs->minor_version == 1)
|
||||
fn = icon_windows_xp;
|
||||
|
||||
/* Windows 7 */
|
||||
else if (fs->major_version == 6 && fs->minor_version == 1)
|
||||
fn = icon_windows_7;
|
||||
|
||||
/* Not (yet) a supported version of Windows. */
|
||||
else return NOT_FOUND;
|
||||
|
||||
if (fs->windows_systemroot == NULL)
|
||||
return NOT_FOUND;
|
||||
|
||||
/* Download %systemroot%\explorer.exe */
|
||||
filename1 = safe_asprintf (g, "%s/explorer.exe", fs->windows_systemroot);
|
||||
filename2 = guestfs___case_sensitive_path_silently (g, filename1);
|
||||
free (filename1);
|
||||
if (filename2 == NULL)
|
||||
return NOT_FOUND;
|
||||
|
||||
filename3 = guestfs___download_to_tmp (g, fs, filename2, "explorer",
|
||||
MAX_WINDOWS_EXPLORER_SIZE);
|
||||
free (filename2);
|
||||
if (filename3 == NULL)
|
||||
return NOT_FOUND;
|
||||
|
||||
ret = fn (g, fs, filename3, size_r);
|
||||
free (filename3);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user