/* libguestfs
- * Copyright (C) 2010 Red Hat Inc.
+ * Copyright (C) 2010-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
#if defined(HAVE_PCRE) && defined(HAVE_HIVEX)
+/* Some limits on what we will read, for safety. */
+
+/* Small text configuration files.
+ *
+ * The upper limit is for general files that we grep or download. The
+ * largest such file is probably "txtsetup.sif" from Windows CDs
+ * (~500K). This number has to be larger than any legitimate file and
+ * smaller than the protocol message size.
+ *
+ * The lower limit is for files parsed by Augeas on the daemon side,
+ * where Augeas is running in reduced memory and can potentially
+ * create a lot of metadata so we really need to be careful about
+ * those.
+ */
+#define MAX_SMALL_FILE_SIZE (2 * 1000 * 1000)
+#define MAX_AUGEAS_FILE_SIZE (100 * 1000)
+
+/* Maximum Windows Registry hive that we will download to /tmp. Some
+ * registries can be legitimately very large.
+ */
+#define MAX_REGISTRY_SIZE (100 * 1000 * 1000)
+
+/* Maximum RPM or dpkg database we will download to /tmp. */
+#define MAX_PKG_DB_SIZE (10 * 1000 * 1000)
+
/* Compile all the regular expressions once when the shared library is
* loaded. PCRE is thread safe so we're supposedly OK here if
* multiple threads call into the libguestfs API functions below
COMPILE (re_fedora, "Fedora release (\\d+)", 0);
COMPILE (re_rhel_old,
- "(?:Red Hat Enterprise Linux|CentOS|Scientific Linux).*release (\\d+).*Update (\\d+)", 0);
+ "(?:Red Hat|CentOS|Scientific Linux).*release (\\d+).*Update (\\d+)", 0);
COMPILE (re_rhel,
- "(?:Red Hat Enterprise Linux|CentOS|Scientific Linux).*release (\\d+)\\.(\\d+)", 0);
+ "(?:Red Hat|CentOS|Scientific Linux).*release (\\d+)\\.(\\d+)", 0);
COMPILE (re_rhel_no_minor,
- "(?:Red Hat Enterprise Linux|CentOS|Scientific Linux).*release (\\d+)", 0);
+ "(?:Red Hat|CentOS|Scientific Linux).*release (\\d+)", 0);
COMPILE (re_major_minor, "(\\d+)\\.(\\d+)", 0);
COMPILE (re_aug_seq, "/\\d+$", 0);
COMPILE (re_xdev, "^/dev/(?:h|s|v|xv)d([a-z]\\d*)$", 0);
static int check_windows_arch (guestfs_h *g, struct inspect_fs *fs);
static int check_windows_software_registry (guestfs_h *g, struct inspect_fs *fs);
static int check_windows_system_registry (guestfs_h *g, struct inspect_fs *fs);
-static char *resolve_windows_path_silently (guestfs_h *g, const char *);
+static char *case_sensitive_path_silently (guestfs_h *g, const char *);
+static int is_file_nocase (guestfs_h *g, const char *);
+static int is_dir_nocase (guestfs_h *g, const char *);
static int extend_fses (guestfs_h *g);
static int parse_unsigned_int (guestfs_h *g, const char *str);
static int add_fstab_entry (guestfs_h *g, struct inspect_fs *fs,
guestfs_is_dir (g, "/run") > 0 &&
guestfs_is_dir (g, "/spool") > 0)
fs->content = FS_CONTENT_LINUX_VAR;
- /* Windows root? */
- else if (guestfs_is_file (g, "/AUTOEXEC.BAT") > 0 ||
- guestfs_is_file (g, "/autoexec.bat") > 0 ||
- guestfs_is_dir (g, "/Program Files") > 0 ||
- guestfs_is_dir (g, "/WINDOWS") > 0 ||
- guestfs_is_dir (g, "/Windows") > 0 ||
- guestfs_is_dir (g, "/windows") > 0 ||
- guestfs_is_dir (g, "/WIN32") > 0 ||
- guestfs_is_dir (g, "/Win32") > 0 ||
- guestfs_is_dir (g, "/WINNT") > 0 ||
- guestfs_is_file (g, "/boot.ini") > 0 ||
- guestfs_is_file (g, "/ntldr") > 0) {
+ /* Windows root?
+ * Note that if a Windows guest has multiple disks and applications
+ * are installed on those other disks, then those other disks will
+ * contain "/Program Files" and "/System Volume Information". Those
+ * would *not* be Windows root disks. (RHBZ#674130)
+ */
+ else if (is_file_nocase (g, "/AUTOEXEC.BAT") > 0 ||
+ is_dir_nocase (g, "/WINDOWS/SYSTEM32") > 0 ||
+ is_dir_nocase (g, "/WIN32/SYSTEM32") > 0 ||
+ is_dir_nocase (g, "/WINNT/SYSTEM32") > 0 ||
+ is_file_nocase (g, "/boot.ini") > 0 ||
+ is_file_nocase (g, "/ntldr") > 0) {
fs->is_root = 1;
fs->content = FS_CONTENT_WINDOWS_ROOT;
if (check_windows_root (g, fs) == -1)
return -1;
}
+ /* Windows volume with installed applications (but not root)? */
+ else if (is_dir_nocase (g, "/System Volume Information") > 0 &&
+ is_dir_nocase (g, "/Program Files") > 0)
+ fs->content = FS_CONTENT_WINDOWS_VOLUME_WITH_APPS;
+ /* Windows volume (but not root)? */
+ else if (is_dir_nocase (g, "/System Volume Information") > 0)
+ fs->content = FS_CONTENT_WINDOWS_VOLUME;
return 0;
}
if (size == -1)
/* guestfs_filesize failed and has already set error in handle */
return -1;
- if (size > 1000000) {
+ if (size > MAX_SMALL_FILE_SIZE) {
error (g, _("size of %s is unreasonably large (%" PRIi64 " bytes)"),
filename, size);
return -1;
static int
check_freebsd_root (guestfs_h *g, struct inspect_fs *fs)
{
- int r;
-
fs->type = OS_TYPE_FREEBSD;
/* FreeBSD has no authoritative version file. The version number is
static int
check_hostname_unix (guestfs_h *g, struct inspect_fs *fs)
{
- char **lines;
-
switch (fs->type) {
case OS_TYPE_LINUX:
/* Red Hat-derived would be in /etc/sysconfig/network, and
if (size == -1)
/* guestfs_filesize failed and has already set error in handle */
return -1;
- if (size > 1000000) {
+ if (size > MAX_SMALL_FILE_SIZE) {
error (g, _("size of %s is unreasonably large (%" PRIi64 " bytes)"),
filename, size);
return -1;
for (i = 0;
systemroot == NULL && i < sizeof systemroots / sizeof systemroots[0];
++i) {
- systemroot = resolve_windows_path_silently (g, systemroots[i]);
+ systemroot = case_sensitive_path_silently (g, systemroots[i]);
}
if (!systemroot) {
char cmd_exe[len];
snprintf (cmd_exe, len, "%s/system32/cmd.exe", fs->windows_systemroot);
- char *cmd_exe_path = resolve_windows_path_silently (g, cmd_exe);
+ char *cmd_exe_path = case_sensitive_path_silently (g, cmd_exe);
if (!cmd_exe_path)
return 0;
snprintf (software, len, "%s/system32/config/software",
fs->windows_systemroot);
- char *software_path = resolve_windows_path_silently (g, software);
+ char *software_path = case_sensitive_path_silently (g, software);
if (!software_path)
/* If the software hive doesn't exist, just accept that we cannot
* find product_name etc.
hive_h *h = NULL;
hive_value_h *values = NULL;
- if (download_to_tmp (g, software_path, software_local, 100000000) == -1)
+ if (download_to_tmp (g, software_path, software_local,
+ MAX_REGISTRY_SIZE) == -1)
goto out;
h = hivex_open (software_local, g->verbose ? HIVEX_OPEN_VERBOSE : 0);
snprintf (system, len, "%s/system32/config/system",
fs->windows_systemroot);
- char *system_path = resolve_windows_path_silently (g, system);
+ char *system_path = case_sensitive_path_silently (g, system);
if (!system_path)
/* If the system hive doesn't exist, just accept that we cannot
* find hostname etc.
hive_h *h = NULL;
hive_value_h *values = NULL;
- if (download_to_tmp (g, system_path, system_local, 100000000) == -1)
+ if (download_to_tmp (g, system_path, system_local, MAX_REGISTRY_SIZE) == -1)
goto out;
h = hivex_open (system_local, g->verbose ? HIVEX_OPEN_VERBOSE : 0);
}
static char *
-resolve_windows_path_silently (guestfs_h *g, const char *path)
+case_sensitive_path_silently (guestfs_h *g, const char *path)
{
guestfs_error_handler_cb old_error_cb = g->error_cb;
g->error_cb = NULL;
}
static int
+is_file_nocase (guestfs_h *g, const char *path)
+{
+ char *p;
+ int r;
+
+ p = case_sensitive_path_silently (g, path);
+ if (!p)
+ return 0;
+ r = guestfs_is_file (g, p);
+ free (p);
+ return r > 0;
+}
+
+static int
+is_dir_nocase (guestfs_h *g, const char *path)
+{
+ char *p;
+ int r;
+
+ p = case_sensitive_path_silently (g, path);
+ if (!p)
+ return 0;
+ r = guestfs_is_dir (g, p);
+ free (p);
+ return r > 0;
+}
+
+static int
extend_fses (guestfs_h *g)
{
size_t n = g->nr_fses + 1;
{
TMP_TEMPLATE_ON_STACK (tmpfile);
- if (download_to_tmp (g, "/var/lib/rpm/Name", tmpfile, 10000000) == -1)
+ if (download_to_tmp (g, "/var/lib/rpm/Name", tmpfile, MAX_PKG_DB_SIZE) == -1)
return NULL;
struct guestfs_application_list *apps = NULL, *ret = NULL;
{
TMP_TEMPLATE_ON_STACK (tmpfile);
- if (download_to_tmp (g, "/var/lib/dpkg/status", tmpfile, 10000000) == -1)
+ if (download_to_tmp (g, "/var/lib/dpkg/status", tmpfile,
+ MAX_PKG_DB_SIZE) == -1)
return NULL;
struct guestfs_application_list *apps = NULL, *ret = NULL;
snprintf (software, len, "%s/system32/config/software",
fs->windows_systemroot);
- char *software_path = resolve_windows_path_silently (g, software);
- if (!software_path)
- /* If the software hive doesn't exist, just accept that we cannot
- * find product_name etc.
- */
- return 0;
+ char *software_path = case_sensitive_path_silently (g, software);
+ if (!software_path) {
+ /* Missing software hive is a problem. */
+ error (g, "no HKLM\\SOFTWARE hive found in the guest");
+ return NULL;
+ }
struct guestfs_application_list *apps = NULL, *ret = NULL;
hive_h *h = NULL;
hive_node_h *children = NULL;
- if (download_to_tmp (g, software_path, software_local, 100000000) == -1)
+ if (download_to_tmp (g, software_path, software_local,
+ MAX_REGISTRY_SIZE) == -1)
goto out;
h = hivex_open (software_local, g->verbose ? HIVEX_OPEN_VERBOSE : 0);
if (size == -1)
/* guestfs_filesize failed and has already set error in handle */
return -1;
- if (size > 100000) {
+ if (size > MAX_AUGEAS_FILE_SIZE) {
error (g, _("size of %s is unreasonably large (%" PRIi64 " bytes)"),
filename, size);
return -1;
if (size == -1)
/* guestfs_filesize failed and has already set error in handle */
return NULL;
- if (size > 1000000) {
+ if (size > MAX_SMALL_FILE_SIZE) {
error (g, _("size of %s is unreasonably large (%" PRIi64 " bytes)"),
filename, size);
return NULL;
NOT_IMPL(NULL);
}
+char *
+guestfs__inspect_get_format (guestfs_h *g, const char *root)
+{
+ NOT_IMPL(NULL);
+}
+
+int
+guestfs__inspect_is_live (guestfs_h *g, const char *root)
+{
+ NOT_IMPL(-1);
+}
+
+int
+guestfs__inspect_is_netinst (guestfs_h *g, const char *root)
+{
+ NOT_IMPL(-1);
+}
+
+int
+guestfs__inspect_is_multipart (guestfs_h *g, const char *root)
+{
+ NOT_IMPL(-1);
+}
+
#endif /* no PCRE or hivex at compile time */
void