From: Richard W.M. Jones Date: Tue, 5 Apr 2011 18:43:30 +0000 (+0100) Subject: fish: Enhance guestfish win:... parsing to understand drive letters. X-Git-Tag: 1.9.17~2 X-Git-Url: http://git.annexia.org/?p=libguestfs.git;a=commitdiff_plain;h=b8be128caa27fa5e1636e9e4caff3e23a6dc761f fish: Enhance guestfish win:... parsing to understand drive letters. --- diff --git a/fish/fish.c b/fish/fish.c index c4fdf79..1419c89 100644 --- a/fish/fish.c +++ b/fish/fish.c @@ -1375,16 +1375,18 @@ xwrite (int fd, const void *v_buf, size_t len) return 0; } -/* Resolve the special "win:..." form for Windows-specific paths. - * This always returns a newly allocated string which is freed by the - * caller function in "cmds.c". +/* Resolve the special "win:..." form for Windows-specific paths. The + * generated code calls this for all device or path arguments. The + * function must return a newly allocated string (caller frees) or + * display an error and return NULL. */ char * -resolve_win_path (const char *path) +win_prefix (const char *path) { char *ret; size_t i; + /* If there is not a "win:..." prefix on the path, return strdup'd string. */ if (STRCASENEQLEN (path, "win:", 4)) { ret = strdup (path); if (ret == NULL) @@ -1394,10 +1396,76 @@ resolve_win_path (const char *path) path += 4; - /* Drop drive letter, if it's "C:". */ - if (STRCASEEQLEN (path, "c:", 2)) + /* Is there a drive letter? */ + if (c_isalpha (path[0]) && path[1] == ':') { + char drive_letter; + char **roots, **drives, **mountpoints, *device; + size_t i; + + drive_letter = c_tolower (path[0]); path += 2; + /* Resolve the drive letter using the drive mappings table. */ + roots = guestfs_inspect_get_roots (g); + if (roots == NULL) + return NULL; + if (roots[0] == NULL) { + fprintf (stderr, _("%s: to use Windows drive letters, you must inspect the guest (\"-i\" option or run \"inspect-os\" command)\n"), + program_name); + free_strings (roots); + return NULL; + } + drives = guestfs_inspect_get_drive_mappings (g, roots[0]); + if (drives == NULL || drives[0] == NULL) { + fprintf (stderr, _("%s: to use Windows drive letters, this must be a Windows guest\n"), + program_name); + free_strings (roots); + free_strings (drives); + return NULL; + } + + 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. To list available drives do:\n inspect-get-drive-mappings %s\n"), + program_name, drive_letter, roots[0]); + free_strings (roots); + free_strings (drives); + return NULL; + } + + /* This drive letter must be mounted on / (we won't do it). */ + mountpoints = guestfs_mountpoints (g); + if (mountpoints == NULL) { + free_strings (roots); + free_strings (drives); + return NULL; + } + + for (i = 0; mountpoints[i] != NULL; i += 2) { + if (STREQ (mountpoints[i+1], "/")) { + if (STRNEQ (mountpoints[i], device)) { + fprintf (stderr, _("%s: to access '%c:', mount %s on / first. One way to do this is:\n umount-all\n mount %s /\n"), + program_name, drive_letter, device, device); + free_strings (roots); + free_strings (drives); + free_strings (mountpoints); + return NULL; + } + } + } + + free_strings (roots); + free_strings (drives); + free_strings (mountpoints); + } + if (!*path) { ret = strdup ("/"); if (ret == NULL) diff --git a/fish/fish.h b/fish/fish.h index 114e8a8..a885b89 100644 --- a/fish/fish.h +++ b/fish/fish.h @@ -73,7 +73,7 @@ extern void print_table (char *const *argv); extern int is_true (const char *str); extern char **parse_string_list (const char *str); extern int xwrite (int fd, const void *buf, size_t len); -extern char *resolve_win_path (const char *path); +extern char *win_prefix (const char *path); extern char *file_in (const char *arg); extern void free_file_in (char *s); extern char *file_out (const char *arg); diff --git a/generator/generator_fish.ml b/generator/generator_fish.ml index 61916a3..532639d 100644 --- a/generator/generator_fish.ml +++ b/generator/generator_fish.ml @@ -393,7 +393,7 @@ Guestfish will prompt for these separately." pr " %s = argv[i++];\n" name | Pathname name | Dev_or_Path name -> - pr " %s = resolve_win_path (argv[i++]);\n" name; + pr " %s = win_prefix (argv[i++]); /* process \"win:\" prefix */\n" name; pr " if (%s == NULL) return -1;\n" name | OptString name -> pr " %s = STRNEQ (argv[i], \"\") ? argv[i] : NULL;\n" name;