mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-22 07:03:38 +00:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0a6b935294 | ||
|
|
901b775e6b | ||
|
|
79089f73d0 | ||
|
|
9ac3cfd1a7 | ||
|
|
73ae773ca2 | ||
|
|
e84ab94975 | ||
|
|
7095bab611 | ||
|
|
b15faa4319 | ||
|
|
1dfa17eb37 | ||
|
|
837b66e30e | ||
|
|
6fe09ad1af | ||
|
|
f9c45f2b74 | ||
|
|
a62a1aecb1 | ||
|
|
cd7a5b8ddf | ||
|
|
772a830961 | ||
|
|
08ddf6b1d9 | ||
|
|
b5fc0f478f | ||
|
|
86fb1e3440 | ||
|
|
dfd7f552bb | ||
|
|
3f785126cf | ||
|
|
d5f98968a4 | ||
|
|
d7bb354026 |
4
README
4
README
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
12
configure.ac
12
configure.ac
@@ -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.])
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
169
daemon/parted.c
169
daemon/parted.c
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
39
daemon/tar.c
39
daemon/tar.c
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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]);
|
||||
|
||||
19
fish/fish.c
19
fish/fish.c
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
77
html/pod.css
77
html/pod.css
@@ -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%;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
47
regressions/rhbz580246.sh
Executable 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
|
||||
@@ -1 +1 @@
|
||||
227
|
||||
236
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user