Compare commits

...

22 Commits

Author SHA1 Message Date
Richard Jones
0a6b935294 Version 1.2.2 2010-04-12 19:56:02 +01:00
Richard Jones
901b775e6b Fix time and timezone to be correct within the appliance.
(cherry picked from commit 508f1ee87e)
2010-04-12 19:12:50 +01:00
Richard Jones
79089f73d0 virt-resize: Mention alternate tools like gparted in the documentation.
Note for stable-1.2:
Cherry picked from development commit c53e64a and rebased
against stable-1.2 tree.
2010-04-12 19:11:56 +01:00
Richard Jones
9ac3cfd1a7 Documentation updates.
Fix copyright years.
Fix URLs to point to new PRC site.
Make sure guestfish(1) and guestfs(3) manpages reference the
current list of tools.

(cherry picked from commit 9a608a1516)
2010-04-12 19:09:57 +01:00
Richard Jones
73ae773ca2 Bugfixes for virt-resize.
- copy more than 64 boot loader sectors across, since real boot
   loaders (eg. for Windows) can be much larger than this
 - copy bootable flag and ID byte to new partitions
 - start the first partition on the new disk at the same sector
   offset as on the old disk
 - sync the disks before existing
(cherry picked from commit add5e22563)
2010-04-12 19:08:21 +01:00
Richard Jones
e84ab94975 New partition APIs: part_del, part_get_bootable, part_get/set_mbr_id
These APIs flesh out further the partitioning API.

Note for stable-1.2 branch:
Cherry picked from b68c030adf and modified
to apply against stable-1.2.  We need these new APIs
in order to support bugfixes in virt-resize.
2010-04-12 19:07:12 +01:00
Richard Jones
7095bab611 daemon: More reliable parsing of the output from 'parted print'.
Previously we used strtok.  However this has the problem that
strtok considers multiple delimiter characters to be like a single
delimiter, eg. "1:::2" would be parsed the same as "1:2".  In
other words, the previous code would skip over or fail if there
are empty fields.
(cherry picked from commit cb9350019c)
2010-04-12 19:04:13 +01:00
Richard Jones
b15faa4319 daemon: Make the RUN_PARTED macro take an error statement.
This allows us to make the RUN_PARTED macro do something else
along the error path, other than just returning -1.
(cherry picked from commit 440ad646cd)
2010-04-12 19:04:01 +01:00
Richard Jones
1dfa17eb37 Documentation: Clarify documentation on the bootable flag.
(cherry picked from commit 30752ac7ca)
2010-04-12 19:03:52 +01:00
Richard Jones
837b66e30e Allow aug-ls to take Augeas variable as argument (RHBZ#580016).
(cherry picked from commit d1dd00606d)
2010-04-12 19:03:41 +01:00
Richard Jones
6fe09ad1af Update PO files. 2010-04-08 22:56:29 +01:00
Richard Jones
f9c45f2b74 Prepare for stable version 1.2.1. 2010-04-08 22:26:01 +01:00
Richard Jones
a62a1aecb1 Remove warning "No grub default" (RHBZ#580650).
(cherry picked from commit 3765f97898)
2010-04-08 22:23:48 +01:00
Richard Jones
cd7a5b8ddf If qemu dies during launch in "null vmchannel" mode, don't hang (RHBZ#579155).
Detect if qemu dies during launch by wait(2)-ing for it, and
then getting EOF on the qemu pipe.  This was broken in null
vmchannel mode, causing a hang.
(cherry picked from commit e35debd642)
2010-04-08 22:23:37 +01:00
Richard Jones
772a830961 Don't kill self accidentally.
Always check that pid > 0 before calling kill (pid, 9).  The
issue was that sometimes pid == 0, and this ends up killing
ourselves.
(cherry picked from commit dc5df3bfec)
2010-04-08 22:23:27 +01:00
Richard Jones
08ddf6b1d9 Fix for "warning: unexpected connection from UID ..."
This warning is currently a fatal error.  The code attempts
to retry the accept call, but because we don't reset sock = -1
the retry doesn't happen and it dies anyway.

Set sock = -1 so the retry attempt can happen.
(cherry picked from commit fb4ec82d97)
2010-04-08 22:23:18 +01:00
Richard Jones
b5fc0f478f configure: Default to using Fedora 12 repo (was Fedora 11).
Fedora 11 is almost EOL at this point.
(cherry picked from commit 0ce9b2bb9b)
2010-04-08 22:23:07 +01:00
Richard Jones
86fb1e3440 Code cleanups related to RHBZ#580246.
This includes various code cleanups:

 (a) A regression test for RHBZ#580246.

 (b) Use write instead of fwrite to write out the tar file.  This is
     just because the error handling of write seems to be better
     specified and easier to use.

 (c) Use size_t instead of int for length.

 (d) Clearer debug messages when in verbose mode.
(cherry picked from commit de7ef2a0fd)
2010-04-08 22:22:58 +01:00
Richard Jones
dfd7f552bb Fix tar-in command hangs when running out of disk space (RHBZ#580246).
The problem was this sequence of events:

 (1) File transfer goes through OK.

 (2) pclose returns failure (because 'tar' subprocess failed)

 (3) We try to cancel the transfer by calling cancel_receive.

Step (3) fails because the transfer (as far as the library is
concerned) has succeeded, so causing a hang.

The more fundamental reason why we see steps (1) and (2) is that
'tar' does NOT fail immediately if there is a write error.  Instead
it continues reading and discarding the input until the end of the
input before giving "Error exit delayed from previous errors".
IMHO this is a bug with tar, since an ENOSPC write error should
be fatal for tar.
(cherry picked from commit 07f4b20ae9)
2010-04-08 22:22:48 +01:00
Richard Jones
3f785126cf fish: Print extended help when the user types an unknown command first.
$ guestfish /tmp/disk.img
/tmp/disk.img: unknown command
Did you mean to open a disk image?  guestfish -a disk.img
For a list of commands:             guestfish -h
For complete documentation:         man guestfish
(cherry picked from commit 4c50f4c38d)
2010-04-08 22:21:44 +01:00
Richard Jones
d5f98968a4 Check error returns from posix_fallocate (RHBZ#579664).
posix_fallocate has a non-standard way to return error indications.
Thus all our calls to posix_fallocate were effectively unchecked.  For
example:

  $ guestfish alloc test.img 1P
  $ echo $?
  0
  $ ll test.img
  -rw-rw-r--. 1 rjones rjones 0 2010-04-06 11:02 test.img
  $ rm test.img

With this change, errors are detected and reported properly:

  $ ./fish/guestfish alloc test.img 1P
  fallocate: File too large

This is a fix for:
https://bugzilla.redhat.com/show_bug.cgi?id=579664
(cherry picked from commit 2ade61d1f8)
2010-04-08 22:21:20 +01:00
Richard W.M. Jones
d7bb354026 Prettier POD CSS.
(cherry picked from commit fb0375a098)
2010-04-08 22:20:24 +01:00
47 changed files with 6642 additions and 5851 deletions

4
README
View File

@@ -315,13 +315,13 @@ first:
- python
- rpm-python http://www.rpm.org/
- yum http://yum.baseurl.org/
- febootstrap http://et.redhat.com/~rjones/febootstrap/
- febootstrap http://people.redhat.com/~rjones/febootstrap/
Copyright and license information
----------------------------------------------------------------------
Copyright (C) 2009 Red Hat Inc.
Copyright (C) 2009-2010 Red Hat Inc.
The library is distributed under the LGPLv2+. The programs are
distributed under the GPLv2+. Please see the files COPYING and

View File

@@ -47,12 +47,17 @@ if grep -sq selinux=1 /proc/cmdline; then
mount -t selinuxfs none /selinux
fi
modprobe dm_mod ||:
# Update the system clock.
hwclock -u -s
# Set up the network.
ifconfig lo 127.0.0.1
ifconfig eth0 10.0.2.10
route add default gw 10.0.2.2
# Scan for LVM.
modprobe dm_mod ||:
lvm vgscan --ignorelockingfailure
lvm vgchange -ay --ignorelockingfailure
@@ -68,6 +73,8 @@ lvm lvs
ifconfig
netstat -rn
lsmod
#hwclock -r
date
#ping -n -v -c 5 10.0.2.2
#ping -n -v -c 5 10.0.2.4

View File

@@ -73,6 +73,10 @@ for path in $(find -not -name fakeroot.log); do
if [ "$path" = "./init" -o "$file" = "guestfsd" ]; then
echo "$path" >&5
# Get timezone configuration from local system.
elif [ "$path" = "./etc/localtime" ]; then
echo "$path" >&6
elif [[ "$path" =~ $p_etc || "$path" =~ $p_dev || "$path" =~ $p_var ]]
then
echo "$path" >&5

View File

@@ -17,8 +17,8 @@
# major/minor/release must be numbers
m4_define([libguestfs_major], [1])
m4_define([libguestfs_minor], [0])
m4_define([libguestfs_release], [89])
m4_define([libguestfs_minor], [2])
m4_define([libguestfs_release], [2])
# extra can be any string
m4_define([libguestfs_extra], [])
@@ -345,9 +345,9 @@ if test "x$enable_appliance" = "xyes"; then
dnl --with-updates to specify a Fedora updates repository.
AC_ARG_WITH([updates],
[AS_HELP_STRING([--with-updates],
[set name of Fedora updates repository @<:@default=updates-released-f11@:>@])],
[set name of Fedora updates repository @<:@default=updates-released-f12@:>@])],
[],
[with_updates=updates-released-f11])
[with_updates=updates-released-f12])
UPDATES="$with_updates"
AC_SUBST(UPDATES)
@@ -364,9 +364,9 @@ fi
dnl --with-repo to specify a Fedora repository.
AC_ARG_WITH([repo],
[AS_HELP_STRING([--with-repo],
[set name of Fedora repository @<:@default=fedora-11@:>@])],
[set name of Fedora repository @<:@default=fedora-12@:>@])],
[],
[with_repo=fedora-11])
[with_repo=fedora-12])
REPO="$with_repo"
AC_SUBST(REPO)
AC_DEFINE_UNQUOTED([REPO],["$REPO"],[Name of Fedora repository.])

View File

@@ -348,7 +348,9 @@ do_aug_ls (const char *path)
NEED_AUG (NULL);
ABS_PATH (path, return NULL);
/* Note that path might also be a previously defined variable
* (defined with aug_defvar). See RHBZ#580016.
*/
len = strlen (path);
@@ -358,9 +360,8 @@ do_aug_ls (const char *path)
return NULL;
}
if (len == 1)
/* we know path must be "/" because of ABS_PATH above */
matches = do_aug_match ("/");
if (STREQ (path, "/"))
matches = do_aug_match ("/*");
else {
len += 3; /* / * + terminating \0 */
buf = malloc (len);

View File

@@ -133,7 +133,7 @@ extern void reply_with_perror_errno (int err, const char *fs, ...)
/* daemon functions that receive files (FileIn) should call
* receive_file for each FileIn parameter.
*/
typedef int (*receive_cb) (void *opaque, const void *buf, int len);
typedef int (*receive_cb) (void *opaque, const void *buf, size_t len);
extern int receive_file (receive_cb cb, void *opaque);
/* daemon functions that receive files (FileIn) can call this

View File

@@ -23,6 +23,7 @@
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include "daemon.h"
#include "actions.h"
@@ -41,10 +42,9 @@ do_fallocate (const char *path, int len)
}
#ifdef HAVE_POSIX_FALLOCATE
int r;
r = posix_fallocate (fd, 0, len);
if (r == -1) {
int err = posix_fallocate (fd, 0, len);
if (err != 0) {
errno = err;
reply_with_perror ("%s", path);
close (fd);
return -1;

View File

@@ -55,7 +55,7 @@ recover_blkrrpart (const char *device, const char *err)
return 0;
}
#define RUN_PARTED(device,...) \
#define RUN_PARTED(error,device,...) \
do { \
int r; \
char *err; \
@@ -66,7 +66,7 @@ recover_blkrrpart (const char *device, const char *err)
if (recover_blkrrpart ((device), err) == -1) { \
reply_with_error ("%s: parted: %s: %s", __func__, (device), err); \
free (err); \
return -1; \
error; \
} \
} \
\
@@ -107,7 +107,7 @@ do_part_init (const char *device, const char *parttype)
return -1;
}
RUN_PARTED (device, "mklabel", parttype, NULL);
RUN_PARTED (return -1, device, "mklabel", parttype, NULL);
udev_settle ();
@@ -151,13 +151,25 @@ do_part_add (const char *device, const char *prlogex,
* name_ to prlogex, eg. "primary". I would essentially describe
* this as a bug in the parted mkpart command.
*/
RUN_PARTED (device, "mkpart", prlogex, startstr, endstr, NULL);
RUN_PARTED (return -1, device, "mkpart", prlogex, startstr, endstr, NULL);
udev_settle ();
return 0;
}
int
do_part_del (const char *device, int partnum)
{
char partnum_str[16];
snprintf (partnum_str, sizeof partnum_str, "%d", partnum);
RUN_PARTED (return -1, device, "rm", partnum_str, NULL);
udev_settle ();
return 0;
}
int
do_part_disk (const char *device, const char *parttype)
{
@@ -183,7 +195,8 @@ do_part_disk (const char *device, const char *parttype)
endstr = "-1s";
}
RUN_PARTED (device,
RUN_PARTED (return -1,
device,
"mklabel", parttype,
/* See comment about about the parted mkpart command. */
"mkpart", STREQ (parttype, "gpt") ? "p1" : "primary",
@@ -201,7 +214,8 @@ do_part_set_bootable (const char *device, int partnum, int bootable)
snprintf (partstr, sizeof partstr, "%d", partnum);
RUN_PARTED (device, "set", partstr, "boot", bootable ? "on" : "off", NULL);
RUN_PARTED (return -1,
device, "set", partstr, "boot", bootable ? "on" : "off", NULL);
udev_settle ();
@@ -215,13 +229,43 @@ do_part_set_name (const char *device, int partnum, const char *name)
snprintf (partstr, sizeof partstr, "%d", partnum);
RUN_PARTED (device, "name", partstr, name, NULL);
RUN_PARTED (return -1, device, "name", partstr, name, NULL);
udev_settle ();
return 0;
}
/* Return the nth field from a string of ':'/';'-delimited strings.
* Useful for parsing the return value from print_partition_table
* function below.
*/
static char *
get_table_field (const char *line, int n)
{
const char *p = line;
while (*p && n > 0) {
p += strcspn (p, ":;") + 1;
n--;
}
if (n > 0) {
reply_with_error ("not enough fields in output of parted print command: %s",
line);
return NULL;
}
size_t len = strcspn (p, ":;");
char *q = strndup (p, len);
if (q == NULL) {
reply_with_perror ("strndup");
return NULL;
}
return q;
}
static char **
print_partition_table (const char *device)
{
@@ -267,31 +311,15 @@ print_partition_table (const char *device)
char *
do_part_get_parttype (const char *device)
{
char **lines;
char *r;
lines = print_partition_table (device);
char **lines = print_partition_table (device);
if (!lines)
return NULL;
/* lines[1] is something like:
* "/dev/sda:1953525168s:scsi:512:512:msdos:ATA Hitachi HDT72101;"
*/
if (strtok (lines[1], ":") == NULL /* device */
|| strtok (NULL, ":") == NULL /* size */
|| strtok (NULL, ":") == NULL /* transport */
|| strtok (NULL, ":") == NULL /* sector size */
|| strtok (NULL, ":") == NULL /* physical sector size */
|| (r = strtok (NULL, ":")) == NULL /* return value */
) {
reply_with_error ("too few fields in output from parted print command: %s", lines[1]);
free_strings (lines);
return NULL;
}
r = strdup (r);
if (!r) {
reply_with_perror ("strdup");
char *r = get_table_field (lines[1], 5);
if (r == NULL) {
free_strings (lines);
return NULL;
}
@@ -355,3 +383,92 @@ do_part_list (const char *device)
free_strings (lines);
return NULL;
}
int
do_part_get_bootable (const char *device, int partnum)
{
char **lines = print_partition_table (device);
if (!lines)
return -1;
/* We want lines[1+partnum]. */
if (count_strings (lines) < 1+partnum) {
reply_with_error ("partition number out of range: %d", partnum);
free_strings (lines);
return -1;
}
char *boot = get_table_field (lines[1+partnum], 6);
if (boot == NULL) {
free_strings (lines);
return -1;
}
int r = STREQ (boot, "boot");
free (boot);
free_strings (lines);
return r;
}
/* Currently we use sfdisk for getting and setting the ID byte. In
* future, extend parted to provide this functionality. As a result
* of using sfdisk, this won't work for non-MBR-style partitions, but
* that limitation is noted in the documentation and we can extend it
* later without breaking the ABI.
*/
int
do_part_get_mbr_id (const char *device, int partnum)
{
char partnum_str[16];
snprintf (partnum_str, sizeof partnum_str, "%d", partnum);
char *out, *err;
int r;
r = command (&out, &err, "sfdisk", "--print-id", device, partnum_str, NULL);
if (r == -1) {
reply_with_error ("sfdisk --print-id: %s", err);
free (out);
free (err);
return -1;
}
free (err);
/* It's printed in hex ... */
int id;
if (sscanf (out, "%x", &id) != 1) {
reply_with_error ("sfdisk --print-id: cannot parse output: %s", out);
free (out);
return -1;
}
free (out);
return id;
}
int
do_part_set_mbr_id (const char *device, int partnum, int idbyte)
{
char partnum_str[16];
snprintf (partnum_str, sizeof partnum_str, "%d", partnum);
char idbyte_str[16];
snprintf (idbyte_str, sizeof partnum_str, "%x", idbyte); /* NB: hex */
char *err;
int r;
r = command (NULL, &err, "sfdisk",
"--change-id", device, partnum_str, idbyte_str, NULL);
if (r == -1) {
reply_with_error ("sfdisk --change-id: %s", err);
free (err);
return -1;
}
free (err);
return 0;
}

View File

@@ -324,6 +324,9 @@ receive_file (receive_cb cb, void *opaque)
uint32_t len;
for (;;) {
if (verbose)
fprintf (stderr, "receive_file: reading length word\n");
/* Read the length word. */
if (xread (sock, lenbuf, 4) == -1)
exit (EXIT_FAILURE);
@@ -361,15 +364,18 @@ receive_file (receive_cb cb, void *opaque)
free (buf);
if (verbose)
printf ("receive_file: got chunk: cancel = %d, len = %d, buf = %p\n",
chunk.cancel, chunk.data.data_len, chunk.data.data_val);
fprintf (stderr, "receive_file: got chunk: cancel = %d, len = %d, buf = %p\n",
chunk.cancel, chunk.data.data_len, chunk.data.data_val);
if (chunk.cancel) {
fprintf (stderr, "receive_file: received cancellation from library\n");
if (verbose)
fprintf (stderr, "receive_file: received cancellation from library\n");
xdr_free ((xdrproc_t) xdr_guestfs_chunk, (char *) &chunk);
return -2;
}
if (chunk.data.data_len == 0) {
if (verbose)
fprintf (stderr, "receive_file: end of file, leaving function\n");
xdr_free ((xdrproc_t) xdr_guestfs_chunk, (char *) &chunk);
return 0; /* end of file */
}
@@ -380,8 +386,11 @@ receive_file (receive_cb cb, void *opaque)
r = 0;
xdr_free ((xdrproc_t) xdr_guestfs_chunk, (char *) &chunk);
if (r == -1) /* write error */
if (r == -1) { /* write error */
if (verbose)
fprintf (stderr, "receive_file: write error\n");
return -1;
}
}
}

View File

@@ -28,10 +28,10 @@
#include "actions.h"
static int
fwrite_cb (void *fp_ptr, const void *buf, int len)
write_cb (void *fd_ptr, const void *buf, size_t len)
{
FILE *fp = *(FILE **)fp_ptr;
return fwrite (buf, len, 1, fp) == 1 ? 0 : -1;
int fd = *(int *)fd_ptr;
return xwrite (fd, buf, len);
}
/* Has one FileIn parameter. */
@@ -71,12 +71,15 @@ do_tar_in (const char *dir)
}
free (cmd);
r = receive_file (fwrite_cb, &fp);
/* The semantics of fwrite are too undefined, so write to the
* file descriptor directly instead.
*/
int fd = fileno (fp);
r = receive_file (write_cb, &fd);
if (r == -1) { /* write error */
err = errno;
cancel_receive ();
errno = err;
reply_with_perror ("write: %s", dir);
reply_with_error ("write error on directory: %s", dir);
pclose (fp);
return -1;
}
@@ -87,10 +90,9 @@ do_tar_in (const char *dir)
}
if (pclose (fp) != 0) {
err = errno;
cancel_receive ();
errno = err;
reply_with_perror ("pclose: %s", dir);
if (r == -1) /* if r == 0, file transfer ended already */
cancel_receive ();
reply_with_error ("tar subcommand failed on directory: %s", dir);
return -1;
}
@@ -192,12 +194,12 @@ do_tgz_in (const char *dir)
}
free (cmd);
r = receive_file (fwrite_cb, &fp);
int fd = fileno (fp);
r = receive_file (write_cb, &fd);
if (r == -1) { /* write error */
err = errno;
cancel_receive ();
errno = err;
reply_with_perror ("write: %s", dir);
reply_with_error ("write error on directory: %s", dir);
pclose (fp);
return -1;
}
@@ -208,10 +210,9 @@ do_tgz_in (const char *dir)
}
if (pclose (fp) != 0) {
err = errno;
cancel_receive ();
errno = err;
reply_with_perror ("pclose: %s", dir);
if (r == -1) /* if r == 0, file transfer ended already */
cancel_receive ();
reply_with_error ("tar subcommand failed on directory: %s", dir);
return -1;
}

View File

@@ -28,7 +28,7 @@
#include "actions.h"
static int
write_cb (void *fd_ptr, const void *buf, int len)
write_cb (void *fd_ptr, const void *buf, size_t len)
{
int fd = *(int *)fd_ptr;
return xwrite (fd, buf, len);
@@ -65,7 +65,7 @@ do_upload (const char *filename)
err = errno;
cancel_receive ();
errno = err;
reply_with_perror ("write: %s", filename);
reply_with_error ("write error: %s", filename);
close (fd);
return -1;
}
@@ -77,7 +77,8 @@ do_upload (const char *filename)
if (close (fd) == -1) {
err = errno;
cancel_receive ();
if (r == -1) /* if r == 0, file transfer ended already */
cancel_receive ();
errno = err;
reply_with_perror ("close: %s", filename);
return -1;

View File

@@ -24,6 +24,7 @@
#include <unistd.h>
#include <fcntl.h>
#include <inttypes.h>
#include <errno.h>
#include "fish.h"
@@ -55,7 +56,9 @@ do_alloc (const char *cmd, int argc, char *argv[])
}
#ifdef HAVE_POSIX_FALLOCATE
if (posix_fallocate (fd, 0, size) == -1) {
int err = posix_fallocate (fd, 0, size);
if (err != 0) {
errno = err;
perror ("fallocate");
close (fd);
unlink (argv[0]);

View File

@@ -73,6 +73,7 @@ int echo_commands = 0;
int remote_control_listen = 0;
int remote_control = 0;
int exit_on_error = 1;
int command_num = 0;
int
launch (guestfs_h *_g)
@@ -790,6 +791,9 @@ issue_command (const char *cmd, char *argv[], const char *pipecmd)
int pid = 0;
int i, r;
/* This counts the commands issued, starting at 1. */
command_num++;
if (echo_commands) {
printf ("%s", cmd);
for (i = 0; argv[i] != NULL; ++i)
@@ -1073,6 +1077,21 @@ display_builtin_command (const char *cmd)
cmd);
}
/* This is printed when the user types in an unknown command for the
* first command issued. A common case is the user doing:
* guestfish disk.img
* expecting guestfish to open 'disk.img' (in fact, this tried to
* run a command 'disk.img').
*/
void
extended_help_message (void)
{
fprintf (stderr,
_("Did you mean to open a disk image? guestfish -a disk.img\n"
"For a list of commands: guestfish -h\n"
"For complete documentation: man guestfish\n"));
}
void
free_strings (char **argv)
{

View File

@@ -51,6 +51,7 @@
extern guestfs_h *g;
extern int quit;
extern int verbose;
extern int command_num;
extern int issue_command (const char *cmd, char *argv[], const char *pipe);
extern void pod2text (const char *name, const char *shortdesc, const char *body);
extern void list_builtin_commands (void);
@@ -64,6 +65,7 @@ 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 void extended_help_message (void);
/* in cmds.c (auto-generated) */
extern void list_commands (void);

View File

@@ -98,7 +98,7 @@ the functionality of the guestfs API, see L<guestfs(3)>.
Guestfish gives you structured access to the libguestfs API, from
shell scripts or the command line or interactively. If you want to
rescue a broken virtual machine image, you might want to look at the
rescue a broken virtual machine image, you should look at the
L<virt-rescue(1)> command.
Using guestfish in read/write mode on live virtual machines can be
@@ -738,11 +738,15 @@ I<1> if there was an error.
L<guestfs(3)>,
L<http://libguestfs.org/>,
L<virt-cat(1)>,
L<virt-df(1)>,
L<virt-edit(1)>,
L<virt-list-filesystems(1)>,
L<virt-list-partitions(1)>,
L<virt-ls(1)>,
L<virt-make-fs(1)>,
L<virt-rescue(1)>,
L<virt-tar(1)>.
L<virt-tar(1)>,
L<virt-win-reg(1)>.
=head1 AUTHORS

View File

@@ -1,24 +1,87 @@
/* CSS to make pod2html files look a little bit better. */
@import url("http://et.redhat.com/~rjones/css/standard.css");
@import url("http://people.redhat.com/~rjones/css/standard.css");
/* Put the index on the right hand side in a floating box. */
div[name="index"] {
float: right;
width: 24em;
background-color: white;
margin-right: 2em;
width: 18em;
border-left: 1px solid #f0f0f0;
background-color: #fcfcfc;
margin-top: 0px;
padding-top: 0px;
margin-left: 1em;
padding-left: 1em;
padding-right: 1em;
font-size: 90%;
}
div[name="index"] a[href] {
text-decoration: none;
}
div[name="index"] a[href]:hover {
text-decoration: underline;
}
div[name="index"] a[href]:before {
content: '#\00a0';
color: #e00;
font-size: x-small;
}
div[name="index"] > ul {
width: 17em;
list-style: none;
margin-left: 0px;
margin-right: 0px;
padding-left: 0px;
padding-right: 0px;
}
div[name="index"] > ul > li {
margin-bottom: 0.5em;
}
div[name="index"] > ul ul {
width: 16em;
list-style: none;
margin-left: 0px;
margin-right: 0px;
padding-left: 0px;
padding-right: 0px;
margin-bottom: 0.5em;
}
div[name="index"] > ul > ul li {
display: inline;
margin-right: 1em;
}
/*
div[name="index"] > ul > ul li:after {
color: #ccc;
content: '\2014';
}
*/
/* Get rid of those horrible <hr>'s :-( */
hr { display: none; }
/* Demote <h1>'s. */
/* Demote <h1>'s and set rest of headers relative. */
h1 {
font-size: 100%;
border-bottom: none;
border-bottom: solid 1px black;
}
h2 {
font-size: 120%;
font-size: 95%;
border-bottom: none;
}
h3 {
font-size: 90%;
}
h4 {
font-size: 85%;
}

View File

@@ -1,5 +1,5 @@
/* CSS to make pod2html files look a little bit better. */
@import url("http://et.redhat.com/~rjones/css/standard.css");
@import url("http://people.redhat.com/~rjones/css/standard.css");
pre.example {
font-weight: bold;

View File

@@ -847,9 +847,9 @@ L<Sys::Guestfs::Lib(3)>,
L<Sys::Virt(3)>,
L<http://libguestfs.org/>.
=head1 AUTHOR
=head1 AUTHORS
Richard W.M. Jones L<http://et.redhat.com/~rjones/>
Richard W.M. Jones L<http://people.redhat.com/~rjones/>
Matthew Booth L<mbooth@redhat.com>

View File

@@ -1672,9 +1672,6 @@ sub _check_for_kernels
eval {
$boot{default} = $g->aug_get("/files/$grub_conf/default");
};
if($@) {
warn __"No grub default specified";
}
$os->{boot} = \%boot;
}

985
po/es.po

File diff suppressed because it is too large Load Diff

985
po/gu.po

File diff suppressed because it is too large Load Diff

985
po/hi.po

File diff suppressed because it is too large Load Diff

985
po/kn.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

985
po/ml.po

File diff suppressed because it is too large Load Diff

985
po/mr.po

File diff suppressed because it is too large Load Diff

985
po/or.po

File diff suppressed because it is too large Load Diff

985
po/pa.po

File diff suppressed because it is too large Load Diff

985
po/pl.po

File diff suppressed because it is too large Load Diff

985
po/ta.po

File diff suppressed because it is too large Load Diff

985
po/te.po

File diff suppressed because it is too large Load Diff

View File

@@ -27,6 +27,7 @@ TESTS = \
rhbz503169c10.sh \
rhbz503169c13.sh \
rhbz557655.sh \
rhbz580246.sh \
test-cancellation-download-librarycancels.sh \
test-cancellation-upload-daemoncancels.sh \
test-find0.sh \

47
regressions/rhbz580246.sh Executable file
View File

@@ -0,0 +1,47 @@
#!/bin/bash -
# libguestfs
# Copyright (C) 2010 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., 675 Mass Ave, Cambridge, MA 02139, USA.
# Test tar_in call when we upload something which is larger than
# available space.
# https://bugzilla.redhat.com/show_bug.cgi?id=580246
set -e
export LANG=C
rm -f test.img test.tar
dd if=/dev/zero of=test.img bs=1M count=2
tar cf test.tar test.img
output=$(
../fish/guestfish 2>&1 <<'EOF'
add test.img
run
mkfs ext2 /dev/sda
mount /dev/sda /
-tar-in test.tar /
EOF
)
rm -f test.img test.tar
# Check for error message in the output.
if [[ ! $output =~ libguestfs:.error:.tar_in ]]; then
echo "Missing error message from tar-in (expecting an error message)"
exit 1
fi

View File

@@ -1 +1 @@
227
236

View File

@@ -4093,10 +4093,9 @@ but other possible values are described in C<guestfs_part_init>.");
This sets the bootable flag on partition numbered C<partnum> on
device C<device>. Note that partitions are numbered from 1.
The bootable flag is used by some PC BIOSes to determine which
partition to boot from. It is by no means universally recognized,
and in any case if your operating system installed a boot
sector on the device itself, then that takes precedence.");
The bootable flag is used by some operating systems (notably
Windows) to determine which partition to boot from. It is by
no means universally recognized.");
("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
[InitEmpty, Always, TestRun (
@@ -4346,6 +4345,61 @@ or file C<src> to another destination device or file C<dest>.
Note this will fail if the source is too short or if the destination
is not large enough.");
("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
[InitEmpty, Always, TestRun (
[["part_init"; "/dev/sda"; "mbr"];
["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
["part_del"; "/dev/sda"; "1"]])],
"delete a partition",
"\
This command deletes the partition numbered C<partnum> on C<device>.
Note that in the case of MBR partitioning, deleting an
extended partition also deletes any logical partitions
it contains.");
("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
[InitEmpty, Always, TestOutputTrue (
[["part_init"; "/dev/sda"; "mbr"];
["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
["part_set_bootable"; "/dev/sda"; "1"; "true"];
["part_get_bootable"; "/dev/sda"; "1"]])],
"return true if a partition is bootable",
"\
This command returns true if the partition C<partnum> on
C<device> has the bootable flag set.
See also C<guestfs_part_set_bootable>.");
("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [],
[InitEmpty, Always, TestOutputInt (
[["part_init"; "/dev/sda"; "mbr"];
["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
"get the MBR type byte (ID byte) from a partition",
"\
Returns the MBR type byte (also known as the ID byte) from
the numbered partition C<partnum>.
Note that only MBR (old DOS-style) partitions have type bytes.
You will get undefined results for other partition table
types (see C<guestfs_part_get_parttype>).");
("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
[], (* tested by part_get_mbr_id *)
"set the MBR type byte (ID byte) of a partition",
"\
Sets the MBR type byte (also known as the ID byte) of
the numbered partition C<partnum> to C<idbyte>. Note
that the type bytes quoted in most documentation are
in fact hexadecimal numbers, but usually documented
without any leading \"0x\" which might be confusing.
Note that only MBR (old DOS-style) partitions have type bytes.
You will get undefined results for other partition table
types (see C<guestfs_part_get_parttype>).");
]
let all_functions = non_daemon_functions @ daemon_functions
@@ -7394,6 +7448,8 @@ and generate_fish_cmds () =
) all_functions;
pr " {\n";
pr " fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
pr " if (command_num == 1)\n";
pr " extended_help_message ();\n";
pr " return -1;\n";
pr " }\n";
pr " return 0;\n";

View File

@@ -1405,6 +1405,7 @@ guestfs__launch (guestfs_h *g)
"libguestfs: warning: unexpected connection from UID %d to port %d\n",
uid, null_vmchannel_sock);
close (sock);
sock = -1;
continue;
}
}
@@ -1499,7 +1500,7 @@ guestfs__launch (guestfs_h *g)
close (wfd[1]);
close (rfd[0]);
}
kill (g->pid, 9);
if (g->pid > 0) kill (g->pid, 9);
if (g->recoverypid > 0) kill (g->recoverypid, 9);
waitpid (g->pid, NULL, 0);
if (g->recoverypid > 0) waitpid (g->recoverypid, NULL, 0);
@@ -1847,7 +1848,7 @@ guestfs__kill_subprocess (guestfs_h *g)
if (g->verbose)
fprintf (stderr, "sending SIGTERM to process %d\n", g->pid);
kill (g->pid, SIGTERM);
if (g->pid > 0) kill (g->pid, SIGTERM);
if (g->recoverypid > 0) kill (g->recoverypid, 9);
return 0;
@@ -1998,7 +1999,7 @@ child_cleanup (guestfs_h *g)
if (g->verbose)
fprintf (stderr, "child_cleanup: %p: child process died\n", g);
/*kill (g->pid, SIGTERM);*/
/*if (g->pid > 0) kill (g->pid, SIGTERM);*/
if (g->recoverypid > 0) kill (g->recoverypid, 9);
waitpid (g->pid, NULL, 0);
if (g->recoverypid > 0) waitpid (g->recoverypid, NULL, 0);
@@ -2365,8 +2366,16 @@ accept_from_daemon (guestfs_h *g)
int sock = -1;
while (sock == -1) {
/* If the qemu process has died, clean up the zombie (RHBZ#579155).
* By partially polling in the select below we ensure that this
* function will be called eventually.
*/
waitpid (g->pid, NULL, WNOHANG);
rset2 = rset;
int r = select (max_fd+1, &rset2, NULL, NULL, NULL);
struct timeval tv = { .tv_sec = 1, .tv_usec = 0 };
int r = select (max_fd+1, &rset2, NULL, NULL, &tv);
if (r == -1) {
if (errno == EINTR || errno == EAGAIN)
continue;

View File

@@ -1326,8 +1326,21 @@ enough.
=head1 SEE ALSO
L<guestfish(1)>,
L<guestmount(1)>,
L<virt-cat(1)>,
L<virt-df(1)>,
L<virt-edit(1)>,
L<virt-inspector(1)>,
L<virt-list-filesystems(1)>,
L<virt-list-partitions(1)>,
L<virt-ls(1)>,
L<virt-make-fs(1)>,
L<virt-rescue(1)>,
L<virt-tar(1)>,
L<virt-win-reg(1)>,
L<qemu(1)>,
L<febootstrap(1)>,
L<hivex(3)>,
L<http://libguestfs.org/>.
Tools with a similar purpose:

View File

@@ -173,7 +173,7 @@ L<http://libguestfs.org/>.
=head1 AUTHOR
Richard W.M. Jones L<http://et.redhat.com/~rjones/>
Richard W.M. Jones L<http://people.redhat.com/~rjones/>
=head1 COPYRIGHT

View File

@@ -350,11 +350,11 @@ L<http://libguestfs.org/>.
=head1 AUTHOR
Richard W.M. Jones L<http://et.redhat.com/~rjones/>
Richard W.M. Jones L<http://people.redhat.com/~rjones/>
=head1 COPYRIGHT
Copyright (C) 2009 Red Hat Inc.
Copyright (C) 2009-2010 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

View File

@@ -192,7 +192,7 @@ L<http://libguestfs.org/>.
=head1 AUTHOR
Richard W.M. Jones L<http://et.redhat.com/~rjones/>
Richard W.M. Jones L<http://people.redhat.com/~rjones/>
=head1 COPYRIGHT

View File

@@ -202,7 +202,7 @@ L<http://libguestfs.org/>.
=head1 AUTHOR
Richard W.M. Jones L<http://et.redhat.com/~rjones/>
Richard W.M. Jones L<http://people.redhat.com/~rjones/>
=head1 COPYRIGHT

View File

@@ -203,11 +203,11 @@ L<http://libguestfs.org/>.
=head1 AUTHOR
Richard W.M. Jones L<http://et.redhat.com/~rjones/>
Richard W.M. Jones L<http://people.redhat.com/~rjones/>
=head1 COPYRIGHT
Copyright (C) 2009 Red Hat Inc.
Copyright (C) 2009-2010 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

View File

@@ -221,7 +221,7 @@ L<http://libguestfs.org/>.
=head1 AUTHOR
Richard W.M. Jones L<http://et.redhat.com/~rjones/>
Richard W.M. Jones L<http://people.redhat.com/~rjones/>
=head1 COPYRIGHT

View File

@@ -159,7 +159,7 @@ L<http://libguestfs.org/>.
=head1 AUTHOR
Richard W.M. Jones L<http://et.redhat.com/~rjones/>
Richard W.M. Jones L<http://people.redhat.com/~rjones/>
=head1 COPYRIGHT

View File

@@ -411,12 +411,23 @@ if ($debug) {
print "$outfile size $outsize bytes\n";
}
# In reality the number of sectors containing boot loader data will be
# less than this (although Windows 7 defaults to putting the first
# partition on sector 2048, and has quite a large boot loader).
#
# However make this large enough to be sure that we have copied over
# the boot loader. We could also do this by looking for the sector
# offset of the first partition.
#
# It doesn't matter if we copy too much.
my $boot_sectors = 4096;
die __x("virt-resize: {file}: file is too small to be a disk image ({sz} bytes)\n",
file => $infile, sz => $insize)
if $insize < 64 * 512;
if $insize < $boot_sectors * 512;
die __x("virt-resize: {file}: file is too small to be a disk image ({sz} bytes)\n",
file => $outfile, sz => $outsize)
if $outsize < 64 * 512;
if $outsize < $boot_sectors * 512;
# Copy the boot loader across.
do_copy_boot_loader () if $copy_boot_loader;
@@ -426,12 +437,12 @@ sub do_copy_boot_loader
print "copying boot loader ...\n" if $debug;
open IFILE, $infile or die "$infile: $!";
my $s;
my $r = sysread (IFILE, $s, 64 * 512) or die "$infile: $!";
die "$infile: short read" if $r < 64 * 512;
my $r = sysread (IFILE, $s, $boot_sectors * 512) or die "$infile: $!";
die "$infile: short read" if $r < $boot_sectors * 512;
open OFILE, "+<$outfile" or die "$outfile: $!";
sysseek OFILE, 0, SEEK_SET or die "$outfile: seek: $!";
$r = syswrite (OFILE, $s, 64 * 512) or die "$outfile: $!";
die "$outfile: short write" if $r < 64 * 512;
$r = syswrite (OFILE, $s, $boot_sectors * 512) or die "$outfile: $!";
die "$outfile: short write" if $r < $boot_sectors * 512;
}
# Add them to the handle and launch the appliance.
@@ -466,6 +477,8 @@ sub check_source_disk
my %h = %$_;
$h{name} = $name;
$h{bootable} = $g->part_get_bootable ("/dev/sda", $h{part_num});
eval { $h{mbr_id} = $g->part_get_mbr_id ("/dev/sda", $h{part_num}); };
$partitions{$name} = \%h;
}
}
@@ -676,7 +689,11 @@ sub calculate_surplus
# We need some overhead for partitioning. Worst case would be for
# EFI partitioning + massive per-partition alignment.
my $overhead = $sectsize * (2 * 64 + (64 * (@partitions + 1)) + 128);
my $overhead = $sectsize * (
2 * 64 + # GPT start and end
(64 * (@partitions + 1)) + # Maximum alignment
($boot_sectors - 64) # Boot loader
);
my $required = 0;
foreach (@partitions) {
@@ -777,17 +794,36 @@ sub repartition
if ($copy_boot_loader) {
$parttype = $g->part_get_parttype ("/dev/sdb");
print "partition table type: $parttype\n" if $debug;
} else {
# Didn't copy over the initial boot loader, so we need
# to make a new partition type here.
$parttype = "efi";
}
print "partition table type: $parttype\n" if $debug;
# Delete any existing partitions on the destination disk.
$g->part_init ("/dev/sdb", $parttype);
# Delete any existing partitions on the destination disk,
# but leave the bootloader that we copied over intact.
if ($copy_boot_loader) {
# Delete in reverse as an easy way to deal with extended
# partitions.
foreach (sort { $b cmp $a } $g->list_partitions ()) {
if (m{^/dev/.db(\d+)$}) {
$g->part_del ("/dev/sdb", $1);
}
}
} else {
# Didn't copy over the initial boot loader, so we need
# to make a new partition table here.
$g->part_init ("/dev/sdb", $parttype);
}
my $start = 64;
# Work out where to start the first partition.
die __"virt-resize: source disk does not have a first partition\n"
unless exists ($partitions{"/dev/sda1"});
my $start = $partitions{"/dev/sda1"}->{part_start} / $sectsize;
# Align to 64.
$start = ($start + 63) & ~63;
print "starting to partition from $start\n" if $debug;
# Create the new partitions.
foreach my $part (@partitions) {
@@ -803,9 +839,18 @@ sub repartition
}
# Create it.
my ($target, $end) = add_partition ($start, $size);
my ($target, $end, $part_num) = add_partition ($start, $size);
$partitions{$part}->{target} = $target;
if ($partitions{$part}->{bootable}) {
$g->part_set_bootable ("/dev/sdb", $part_num, 1);
}
if ($partitions{$part}->{mbr_id}) {
$g->part_set_mbr_id ("/dev/sdb", $part_num,
$partitions{$part}->{mbr_id});
}
# Start of next partition + alignment.
$start = $end + 1;
$start = ($start + 63) & ~63;
@@ -825,26 +870,26 @@ sub add_partition
my $start = shift;
my $size = shift;
my ($target, $end);
my ($target, $end, $part_num);
if ($nextpart <= 3 || $parttype ne "msdos") {
$target = "/dev/sdb$nextpart";
$end = $start + $size - 1;
$g->part_add ("/dev/sdb", "primary", $start, $end);
$nextpart++;
$part_num = $nextpart++;
} else {
if ($nextpart == 4) {
$g->part_add ("/dev/sdb", "extended", $start, -1);
$nextpart++;
$part_num = $nextpart++;
$start += 64;
}
$target = "/dev/sdb$nextpart";
$end = $start + $size - 1;
$g->part_add ("/dev/sdb", "logical", $start, $end);
$nextpart++;
$part_num = $nextpart++;
}
return ($target, $end);
return ($target, $end, $part_num);
}
# Copy over the data.
@@ -881,6 +926,11 @@ sub copy_data
}
}
# Sync disk and exit.
$g->umount_all ();
$g->sync ();
undef $g;
exit 0;
sub sizebytes
@@ -945,6 +995,22 @@ sub canonicalize
$_;
}
=head1 ALTERNATIVE TOOLS
There are several proprietary tools for resizing partitions. We
won't mention any here.
L<parted(8)> and its graphical shell gparted can do some types of
resizing operations on disk images. They can resize and move
partitions, but I don't think they can do anything with the contents,
and they certainly don't understand LVM.
L<guestfish(1)> can do everything that virt-resize can do and a lot
more, but at a much lower level. You will probably end up
hand-calculating sector offsets, which is something that virt-resize
was designed to avoid. If you want to see the guestfish-equivalent
commands that virt-resize runs, use the C<--debug> flag.
=head1 SEE ALSO
L<virt-list-partitions(1)>,
@@ -957,12 +1023,13 @@ L<pvresize(8)>,
L<lvresize(8)>,
L<resize2fs(8)>,
L<virsh(1)>,
L<parted(8)>,
L<Sys::Guestfs(3)>,
L<http://libguestfs.org/>.
=head1 AUTHOR
Richard W.M. Jones L<http://et.redhat.com/~rjones/>
Richard W.M. Jones L<http://people.redhat.com/~rjones/>
=head1 COPYRIGHT

View File

@@ -267,7 +267,7 @@ L<http://libguestfs.org/>.
=head1 AUTHOR
Richard W.M. Jones L<http://et.redhat.com/~rjones/>
Richard W.M. Jones L<http://people.redhat.com/~rjones/>
=head1 COPYRIGHT

View File

@@ -472,7 +472,7 @@ L<https://bugzilla.redhat.com/>
=head1 AUTHOR
Richard W.M. Jones L<http://et.redhat.com/~rjones/>
Richard W.M. Jones L<http://people.redhat.com/~rjones/>
=head1 COPYRIGHT