diff --git a/edit/Makefile.am b/edit/Makefile.am index 1d51095d9..cb19bec5e 100644 --- a/edit/Makefile.am +++ b/edit/Makefile.am @@ -33,7 +33,9 @@ SHARED_SOURCE_FILES = \ ../fish/options.h \ ../fish/options.c \ ../fish/uri.h \ - ../fish/uri.c + ../fish/uri.c \ + ../fish/windows.h \ + ../fish/windows.c virt_edit_SOURCES = \ $(SHARED_SOURCE_FILES) \ diff --git a/edit/edit.c b/edit/edit.c index 733c9119c..d4ce747b3 100644 --- a/edit/edit.c +++ b/edit/edit.c @@ -37,6 +37,7 @@ #include "guestfs.h" #include "options.h" +#include "windows.h" /* Currently open libguestfs handle. */ guestfs_h *g; @@ -56,8 +57,6 @@ static void edit_files (int argc, char *argv[]); static void edit (const char *filename, const char *root); static char *edit_interactively (const char *tmpfile); static char *edit_non_interactively (const char *tmpfile); -static int is_windows (guestfs_h *g, const char *root); -static char *windows_path (guestfs_h *g, const char *root, const char *filename); static char *generate_random_name (const char *filename); static char *generate_backup_name (const char *filename); @@ -527,107 +526,6 @@ edit_non_interactively (const char *tmpfile) return ret; /* caller will free */ } -static int -is_windows (guestfs_h *g, const char *root) -{ - int w; - CLEANUP_FREE char *type = guestfs_inspect_get_type (g, root); - if (!type) - return 0; - - w = STREQ (type, "windows"); - return w; -} - -static void mount_drive_letter (char drive_letter, const char *root); - -static char * -windows_path (guestfs_h *g, const char *root, const char *path) -{ - char *ret; - size_t i; - - /* If there is a drive letter, rewrite the path. */ - if (c_isalpha (path[0]) && path[1] == ':') { - char drive_letter = c_tolower (path[0]); - /* This returns the newly allocated string. */ - mount_drive_letter (drive_letter, root); - ret = strdup (path + 2); - if (ret == NULL) { - perror ("strdup"); - exit (EXIT_FAILURE); - } - } - else if (!*path) { - ret = strdup ("/"); - if (ret == NULL) { - perror ("strdup"); - exit (EXIT_FAILURE); - } - } - else { - ret = strdup (path); - if (ret == NULL) { - perror ("strdup"); - exit (EXIT_FAILURE); - } - } - - /* Blindly convert any backslashes into forward slashes. Is this good? */ - for (i = 0; i < strlen (ret); ++i) - if (ret[i] == '\\') - ret[i] = '/'; - - char *t = guestfs_case_sensitive_path (g, ret); - free (ret); - ret = t; - if (ret == NULL) - exit (EXIT_FAILURE); - - return ret; -} - -static void -mount_drive_letter (char drive_letter, const char *root) -{ - char *device; - size_t i; - - /* Resolve the drive letter using the drive mappings table. */ - CLEANUP_FREE_STRING_LIST char **drives = - guestfs_inspect_get_drive_mappings (g, root); - if (drives == NULL || drives[0] == NULL) { - fprintf (stderr, _("%s: to use Windows drive letters, this must be a Windows guest\n"), - program_name); - exit (EXIT_FAILURE); - } - - device = NULL; - for (i = 0; drives[i] != NULL; i += 2) { - if (c_tolower (drives[i][0]) == drive_letter && drives[i][1] == '\0') { - device = drives[i+1]; - break; - } - } - - if (device == NULL) { - fprintf (stderr, _("%s: drive '%c:' not found.\n"), - program_name, drive_letter); - exit (EXIT_FAILURE); - } - - /* Unmount current disk and remount device. */ - if (guestfs_umount_all (g) == -1) - exit (EXIT_FAILURE); - - if (guestfs_mount (g, device, "/") == -1) - exit (EXIT_FAILURE); - - /* Don't need to free (device) because that string was in the - * drives array. - */ -} - static char random_char (void) { diff --git a/fish/windows.c b/fish/windows.c new file mode 100644 index 000000000..ddf2af1b5 --- /dev/null +++ b/fish/windows.c @@ -0,0 +1,135 @@ +/* libguestfs - shared Windows path for tools + * Copyright (C) 2009-2014 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include + +#include "windows.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "guestfs-internal-frontend.h" + +#include "c-ctype.h" + +static void mount_drive_letter (guestfs_h *g, char drive_letter, + const char *root); + +int +is_windows (guestfs_h *g, const char *root) +{ + int w; + CLEANUP_FREE char *type = guestfs_inspect_get_type (g, root); + if (!type) + return 0; + + w = STREQ (type, "windows"); + return w; +} + +char * +windows_path (guestfs_h *g, const char *root, const char *path) +{ + char *ret; + size_t i; + + /* If there is a drive letter, rewrite the path. */ + if (c_isalpha (path[0]) && path[1] == ':') { + char drive_letter = c_tolower (path[0]); + /* This returns the newly allocated string. */ + mount_drive_letter (g, drive_letter, root); + ret = strdup (path + 2); + if (ret == NULL) { + perror ("strdup"); + exit (EXIT_FAILURE); + } + } + else if (!*path) { + ret = strdup ("/"); + if (ret == NULL) { + perror ("strdup"); + exit (EXIT_FAILURE); + } + } + else { + ret = strdup (path); + if (ret == NULL) { + perror ("strdup"); + exit (EXIT_FAILURE); + } + } + + /* Blindly convert any backslashes into forward slashes. Is this good? */ + for (i = 0; i < strlen (ret); ++i) + if (ret[i] == '\\') + ret[i] = '/'; + + char *t = guestfs_case_sensitive_path (g, ret); + free (ret); + ret = t; + if (ret == NULL) + exit (EXIT_FAILURE); + + return ret; +} + +static void +mount_drive_letter (guestfs_h *g, char drive_letter, const char *root) +{ + char *device; + size_t i; + + /* Resolve the drive letter using the drive mappings table. */ + CLEANUP_FREE_STRING_LIST char **drives = + guestfs_inspect_get_drive_mappings (g, root); + if (drives == NULL || drives[0] == NULL) { + fprintf (stderr, _("%s: to use Windows drive letters, this must be a Windows guest\n"), + program_name); + exit (EXIT_FAILURE); + } + + device = NULL; + for (i = 0; drives[i] != NULL; i += 2) { + if (c_tolower (drives[i][0]) == drive_letter && drives[i][1] == '\0') { + device = drives[i+1]; + break; + } + } + + if (device == NULL) { + fprintf (stderr, _("%s: drive '%c:' not found.\n"), + program_name, drive_letter); + exit (EXIT_FAILURE); + } + + /* Unmount current disk and remount device. */ + if (guestfs_umount_all (g) == -1) + exit (EXIT_FAILURE); + + if (guestfs_mount (g, device, "/") == -1) + exit (EXIT_FAILURE); + + /* Don't need to free (device) because that string was in the + * drives array. + */ +} diff --git a/fish/windows.h b/fish/windows.h new file mode 100644 index 000000000..bb6863456 --- /dev/null +++ b/fish/windows.h @@ -0,0 +1,44 @@ +/* libguestfs - shared Windows path for tools + * Copyright (C) 2009-2014 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef FISH_WINDOWS_H +#define FISH_WINDOWS_H + +#include + +/** + * Checks whether 'root' is a Windows installation. + * + * This relies on an already being done introspection. + */ +extern int is_windows (guestfs_h *g, const char *root); + +/** + * Resolves 'path' as possible Windows path according to 'root', + * giving a new path that can be used in libguestfs API calls. + * + * Notes: + * - 'root' must be a Windows installation + * - relies on an already being done introspection + * - will unmount all the existing mount points and mount the Windows root + * - will exit() on memory allocation failures, and if it is not possible + * to get the true path on case-insensitive filesystems + */ +extern char *windows_path (guestfs_h *g, const char *root, const char *path); + +#endif diff --git a/po/POTFILES b/po/POTFILES index 3d208d503..d40cf9be0 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -160,6 +160,7 @@ fish/supported.c fish/tilde.c fish/time.c fish/uri.c +fish/windows.c format/format.c fuse/guestmount.c fuse/guestunmount.c