summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard W.M. Jones <rjones@redhat.com>2009-06-29 11:47:07 +0100
committerRichard W.M. Jones <rjones@redhat.com>2009-06-29 11:47:07 +0100
commit826020fe18bf2eee43f8afea392874bb88c0650a (patch)
tree7c6c40758611605be29b3528da647a78a071ea1b
parent3854bbdecd1c089959fb812a739b84a96c05fbbf (diff)
downloadlibguestfs-826020fe18bf2eee43f8afea392874bb88c0650a.tar.gz
libguestfs-826020fe18bf2eee43f8afea392874bb88c0650a.tar.xz
libguestfs-826020fe18bf2eee43f8afea392874bb88c0650a.zip
Generated code for head/tail commands.
-rw-r--r--capitests/tests.c1290
-rw-r--r--daemon/actions.h6
-rw-r--r--daemon/stubs.c134
-rw-r--r--fish/cmds.c108
-rw-r--r--fish/completion.c4
-rw-r--r--guestfish-actions.pod56
-rw-r--r--guestfs-actions.pod78
-rw-r--r--haskell/Guestfs.hs4
-rw-r--r--images/Makefile.am2
-rw-r--r--java/com/redhat/et/libguestfs/GuestFS.java108
-rw-r--r--java/com_redhat_et_libguestfs_GuestFS.c144
-rw-r--r--ocaml/guestfs.ml4
-rw-r--r--ocaml/guestfs.mli12
-rw-r--r--ocaml/guestfs_c_actions.c114
-rw-r--r--perl/Guestfs.xs84
-rw-r--r--perl/lib/Sys/Guestfs.pm48
-rw-r--r--python/guestfs-py.c112
-rw-r--r--python/guestfs.py66
-rw-r--r--ruby/ext/guestfs/_guestfs.c136
-rw-r--r--src/MAX_PROC_NR2
-rw-r--r--src/guestfs-actions.c396
-rw-r--r--src/guestfs-actions.h6
-rw-r--r--src/guestfs_protocol.c98
-rw-r--r--src/guestfs_protocol.h78
-rw-r--r--src/guestfs_protocol.x40
25 files changed, 3081 insertions, 49 deletions
diff --git a/capitests/tests.c b/capitests/tests.c
index 02544372..7a30498b 100644
--- a/capitests/tests.c
+++ b/capitests/tests.c
@@ -153,6 +153,1246 @@ static void no_test_warnings (void)
fprintf (stderr, "warning: \"guestfs_scrub_freespace\" has no tests\n");
}
+static int test_tail_n_0_skip (void)
+{
+ const char *str;
+
+ str = getenv ("TEST_ONLY");
+ if (str)
+ return strstr (str, "tail_n") == NULL;
+ str = getenv ("SKIP_TEST_TAIL_N_0");
+ if (str && strcmp (str, "1") == 0) return 1;
+ str = getenv ("SKIP_TEST_TAIL_N");
+ if (str && strcmp (str, "1") == 0) return 1;
+ return 0;
+}
+
+static int test_tail_n_0 (void)
+{
+ if (test_tail_n_0_skip ()) {
+ printf ("%s skipped (reason: environment variable set)\n", "test_tail_n_0");
+ return 0;
+ }
+
+ /* InitBasicFS for test_tail_n_0: create ext2 on /dev/sda1 */
+ {
+ char device[] = "/dev/sda";
+ int r;
+ suppress_error = 0;
+ r = guestfs_blockdev_setrw (g, device);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char device[] = "/dev/sda";
+ char lines_0[] = ",";
+ char *lines[] = {
+ lines_0,
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, device, 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char fstype[] = "ext2";
+ char device[] = "/dev/sda1";
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, fstype, device);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char device[] = "/dev/sda1";
+ char mountpoint[] = "/";
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, device, mountpoint);
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputList for tail_n (0) */
+ {
+ char options[] = "ro";
+ char vfstype[] = "squashfs";
+ char device[] = "/dev/sdd";
+ char mountpoint[] = "/";
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount_vfs (g, options, vfstype, device, mountpoint);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char path[] = "/10klines";
+ char **r;
+ int i;
+ suppress_error = 0;
+ r = guestfs_tail_n (g, 3, path);
+ if (r == NULL)
+ return -1;
+ if (!r[0]) {
+ fprintf (stderr, "test_tail_n_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ {
+ char expected[] = "9997abcdefghijklmnopqrstuvwxyz";
+ if (strcmp (r[0], expected) != 0) {
+ fprintf (stderr, "test_tail_n_0: expected \"%s\" but got \"%s\"\n", expected, r[0]);
+ return -1;
+ }
+ }
+ if (!r[1]) {
+ fprintf (stderr, "test_tail_n_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ {
+ char expected[] = "9998abcdefghijklmnopqrstuvwxyz";
+ if (strcmp (r[1], expected) != 0) {
+ fprintf (stderr, "test_tail_n_0: expected \"%s\" but got \"%s\"\n", expected, r[1]);
+ return -1;
+ }
+ }
+ if (!r[2]) {
+ fprintf (stderr, "test_tail_n_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ {
+ char expected[] = "9999abcdefghijklmnopqrstuvwxyz";
+ if (strcmp (r[2], expected) != 0) {
+ fprintf (stderr, "test_tail_n_0: expected \"%s\" but got \"%s\"\n", expected, r[2]);
+ return -1;
+ }
+ }
+ if (r[3] != NULL) {
+ fprintf (stderr, "test_tail_n_0: extra elements returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ for (i = 0; r[i] != NULL; ++i)
+ free (r[i]);
+ free (r);
+ }
+ return 0;
+}
+
+static int test_tail_n_1_skip (void)
+{
+ const char *str;
+
+ str = getenv ("TEST_ONLY");
+ if (str)
+ return strstr (str, "tail_n") == NULL;
+ str = getenv ("SKIP_TEST_TAIL_N_1");
+ if (str && strcmp (str, "1") == 0) return 1;
+ str = getenv ("SKIP_TEST_TAIL_N");
+ if (str && strcmp (str, "1") == 0) return 1;
+ return 0;
+}
+
+static int test_tail_n_1 (void)
+{
+ if (test_tail_n_1_skip ()) {
+ printf ("%s skipped (reason: environment variable set)\n", "test_tail_n_1");
+ return 0;
+ }
+
+ /* InitBasicFS for test_tail_n_1: create ext2 on /dev/sda1 */
+ {
+ char device[] = "/dev/sda";
+ int r;
+ suppress_error = 0;
+ r = guestfs_blockdev_setrw (g, device);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char device[] = "/dev/sda";
+ char lines_0[] = ",";
+ char *lines[] = {
+ lines_0,
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, device, 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char fstype[] = "ext2";
+ char device[] = "/dev/sda1";
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, fstype, device);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char device[] = "/dev/sda1";
+ char mountpoint[] = "/";
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, device, mountpoint);
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputList for tail_n (1) */
+ {
+ char options[] = "ro";
+ char vfstype[] = "squashfs";
+ char device[] = "/dev/sdd";
+ char mountpoint[] = "/";
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount_vfs (g, options, vfstype, device, mountpoint);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char path[] = "/10klines";
+ char **r;
+ int i;
+ suppress_error = 0;
+ r = guestfs_tail_n (g, -9998, path);
+ if (r == NULL)
+ return -1;
+ if (!r[0]) {
+ fprintf (stderr, "test_tail_n_1: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ {
+ char expected[] = "9997abcdefghijklmnopqrstuvwxyz";
+ if (strcmp (r[0], expected) != 0) {
+ fprintf (stderr, "test_tail_n_1: expected \"%s\" but got \"%s\"\n", expected, r[0]);
+ return -1;
+ }
+ }
+ if (!r[1]) {
+ fprintf (stderr, "test_tail_n_1: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ {
+ char expected[] = "9998abcdefghijklmnopqrstuvwxyz";
+ if (strcmp (r[1], expected) != 0) {
+ fprintf (stderr, "test_tail_n_1: expected \"%s\" but got \"%s\"\n", expected, r[1]);
+ return -1;
+ }
+ }
+ if (!r[2]) {
+ fprintf (stderr, "test_tail_n_1: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ {
+ char expected[] = "9999abcdefghijklmnopqrstuvwxyz";
+ if (strcmp (r[2], expected) != 0) {
+ fprintf (stderr, "test_tail_n_1: expected \"%s\" but got \"%s\"\n", expected, r[2]);
+ return -1;
+ }
+ }
+ if (r[3] != NULL) {
+ fprintf (stderr, "test_tail_n_1: extra elements returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ for (i = 0; r[i] != NULL; ++i)
+ free (r[i]);
+ free (r);
+ }
+ return 0;
+}
+
+static int test_tail_n_2_skip (void)
+{
+ const char *str;
+
+ str = getenv ("TEST_ONLY");
+ if (str)
+ return strstr (str, "tail_n") == NULL;
+ str = getenv ("SKIP_TEST_TAIL_N_2");
+ if (str && strcmp (str, "1") == 0) return 1;
+ str = getenv ("SKIP_TEST_TAIL_N");
+ if (str && strcmp (str, "1") == 0) return 1;
+ return 0;
+}
+
+static int test_tail_n_2 (void)
+{
+ if (test_tail_n_2_skip ()) {
+ printf ("%s skipped (reason: environment variable set)\n", "test_tail_n_2");
+ return 0;
+ }
+
+ /* InitBasicFS for test_tail_n_2: create ext2 on /dev/sda1 */
+ {
+ char device[] = "/dev/sda";
+ int r;
+ suppress_error = 0;
+ r = guestfs_blockdev_setrw (g, device);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char device[] = "/dev/sda";
+ char lines_0[] = ",";
+ char *lines[] = {
+ lines_0,
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, device, 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char fstype[] = "ext2";
+ char device[] = "/dev/sda1";
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, fstype, device);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char device[] = "/dev/sda1";
+ char mountpoint[] = "/";
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, device, mountpoint);
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputList for tail_n (2) */
+ {
+ char options[] = "ro";
+ char vfstype[] = "squashfs";
+ char device[] = "/dev/sdd";
+ char mountpoint[] = "/";
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount_vfs (g, options, vfstype, device, mountpoint);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char path[] = "/10klines";
+ char **r;
+ int i;
+ suppress_error = 0;
+ r = guestfs_tail_n (g, 0, path);
+ if (r == NULL)
+ return -1;
+ if (r[0] != NULL) {
+ fprintf (stderr, "test_tail_n_2: extra elements returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ for (i = 0; r[i] != NULL; ++i)
+ free (r[i]);
+ free (r);
+ }
+ return 0;
+}
+
+static int test_tail_0_skip (void)
+{
+ const char *str;
+
+ str = getenv ("TEST_ONLY");
+ if (str)
+ return strstr (str, "tail") == NULL;
+ str = getenv ("SKIP_TEST_TAIL_0");
+ if (str && strcmp (str, "1") == 0) return 1;
+ str = getenv ("SKIP_TEST_TAIL");
+ if (str && strcmp (str, "1") == 0) return 1;
+ return 0;
+}
+
+static int test_tail_0 (void)
+{
+ if (test_tail_0_skip ()) {
+ printf ("%s skipped (reason: environment variable set)\n", "test_tail_0");
+ return 0;
+ }
+
+ /* InitBasicFS for test_tail_0: create ext2 on /dev/sda1 */
+ {
+ char device[] = "/dev/sda";
+ int r;
+ suppress_error = 0;
+ r = guestfs_blockdev_setrw (g, device);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char device[] = "/dev/sda";
+ char lines_0[] = ",";
+ char *lines[] = {
+ lines_0,
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, device, 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char fstype[] = "ext2";
+ char device[] = "/dev/sda1";
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, fstype, device);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char device[] = "/dev/sda1";
+ char mountpoint[] = "/";
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, device, mountpoint);
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputList for tail (0) */
+ {
+ char options[] = "ro";
+ char vfstype[] = "squashfs";
+ char device[] = "/dev/sdd";
+ char mountpoint[] = "/";
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount_vfs (g, options, vfstype, device, mountpoint);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char path[] = "/10klines";
+ char **r;
+ int i;
+ suppress_error = 0;
+ r = guestfs_tail (g, path);
+ if (r == NULL)
+ return -1;
+ if (!r[0]) {
+ fprintf (stderr, "test_tail_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ {
+ char expected[] = "9990abcdefghijklmnopqrstuvwxyz";
+ if (strcmp (r[0], expected) != 0) {
+ fprintf (stderr, "test_tail_0: expected \"%s\" but got \"%s\"\n", expected, r[0]);
+ return -1;
+ }
+ }
+ if (!r[1]) {
+ fprintf (stderr, "test_tail_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ {
+ char expected[] = "9991abcdefghijklmnopqrstuvwxyz";
+ if (strcmp (r[1], expected) != 0) {
+ fprintf (stderr, "test_tail_0: expected \"%s\" but got \"%s\"\n", expected, r[1]);
+ return -1;
+ }
+ }
+ if (!r[2]) {
+ fprintf (stderr, "test_tail_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ {
+ char expected[] = "9992abcdefghijklmnopqrstuvwxyz";
+ if (strcmp (r[2], expected) != 0) {
+ fprintf (stderr, "test_tail_0: expected \"%s\" but got \"%s\"\n", expected, r[2]);
+ return -1;
+ }
+ }
+ if (!r[3]) {
+ fprintf (stderr, "test_tail_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ {
+ char expected[] = "9993abcdefghijklmnopqrstuvwxyz";
+ if (strcmp (r[3], expected) != 0) {
+ fprintf (stderr, "test_tail_0: expected \"%s\" but got \"%s\"\n", expected, r[3]);
+ return -1;
+ }
+ }
+ if (!r[4]) {
+ fprintf (stderr, "test_tail_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ {
+ char expected[] = "9994abcdefghijklmnopqrstuvwxyz";
+ if (strcmp (r[4], expected) != 0) {
+ fprintf (stderr, "test_tail_0: expected \"%s\" but got \"%s\"\n", expected, r[4]);
+ return -1;
+ }
+ }
+ if (!r[5]) {
+ fprintf (stderr, "test_tail_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ {
+ char expected[] = "9995abcdefghijklmnopqrstuvwxyz";
+ if (strcmp (r[5], expected) != 0) {
+ fprintf (stderr, "test_tail_0: expected \"%s\" but got \"%s\"\n", expected, r[5]);
+ return -1;
+ }
+ }
+ if (!r[6]) {
+ fprintf (stderr, "test_tail_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ {
+ char expected[] = "9996abcdefghijklmnopqrstuvwxyz";
+ if (strcmp (r[6], expected) != 0) {
+ fprintf (stderr, "test_tail_0: expected \"%s\" but got \"%s\"\n", expected, r[6]);
+ return -1;
+ }
+ }
+ if (!r[7]) {
+ fprintf (stderr, "test_tail_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ {
+ char expected[] = "9997abcdefghijklmnopqrstuvwxyz";
+ if (strcmp (r[7], expected) != 0) {
+ fprintf (stderr, "test_tail_0: expected \"%s\" but got \"%s\"\n", expected, r[7]);
+ return -1;
+ }
+ }
+ if (!r[8]) {
+ fprintf (stderr, "test_tail_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ {
+ char expected[] = "9998abcdefghijklmnopqrstuvwxyz";
+ if (strcmp (r[8], expected) != 0) {
+ fprintf (stderr, "test_tail_0: expected \"%s\" but got \"%s\"\n", expected, r[8]);
+ return -1;
+ }
+ }
+ if (!r[9]) {
+ fprintf (stderr, "test_tail_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ {
+ char expected[] = "9999abcdefghijklmnopqrstuvwxyz";
+ if (strcmp (r[9], expected) != 0) {
+ fprintf (stderr, "test_tail_0: expected \"%s\" but got \"%s\"\n", expected, r[9]);
+ return -1;
+ }
+ }
+ if (r[10] != NULL) {
+ fprintf (stderr, "test_tail_0: extra elements returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ for (i = 0; r[i] != NULL; ++i)
+ free (r[i]);
+ free (r);
+ }
+ return 0;
+}
+
+static int test_head_n_0_skip (void)
+{
+ const char *str;
+
+ str = getenv ("TEST_ONLY");
+ if (str)
+ return strstr (str, "head_n") == NULL;
+ str = getenv ("SKIP_TEST_HEAD_N_0");
+ if (str && strcmp (str, "1") == 0) return 1;
+ str = getenv ("SKIP_TEST_HEAD_N");
+ if (str && strcmp (str, "1") == 0) return 1;
+ return 0;
+}
+
+static int test_head_n_0 (void)
+{
+ if (test_head_n_0_skip ()) {
+ printf ("%s skipped (reason: environment variable set)\n", "test_head_n_0");
+ return 0;
+ }
+
+ /* InitBasicFS for test_head_n_0: create ext2 on /dev/sda1 */
+ {
+ char device[] = "/dev/sda";
+ int r;
+ suppress_error = 0;
+ r = guestfs_blockdev_setrw (g, device);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char device[] = "/dev/sda";
+ char lines_0[] = ",";
+ char *lines[] = {
+ lines_0,
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, device, 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char fstype[] = "ext2";
+ char device[] = "/dev/sda1";
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, fstype, device);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char device[] = "/dev/sda1";
+ char mountpoint[] = "/";
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, device, mountpoint);
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputList for head_n (0) */
+ {
+ char options[] = "ro";
+ char vfstype[] = "squashfs";
+ char device[] = "/dev/sdd";
+ char mountpoint[] = "/";
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount_vfs (g, options, vfstype, device, mountpoint);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char path[] = "/10klines";
+ char **r;
+ int i;
+ suppress_error = 0;
+ r = guestfs_head_n (g, 3, path);
+ if (r == NULL)
+ return -1;
+ if (!r[0]) {
+ fprintf (stderr, "test_head_n_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ {
+ char expected[] = "0abcdefghijklmnopqrstuvwxyz";
+ if (strcmp (r[0], expected) != 0) {
+ fprintf (stderr, "test_head_n_0: expected \"%s\" but got \"%s\"\n", expected, r[0]);
+ return -1;
+ }
+ }
+ if (!r[1]) {
+ fprintf (stderr, "test_head_n_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ {
+ char expected[] = "1abcdefghijklmnopqrstuvwxyz";
+ if (strcmp (r[1], expected) != 0) {
+ fprintf (stderr, "test_head_n_0: expected \"%s\" but got \"%s\"\n", expected, r[1]);
+ return -1;
+ }
+ }
+ if (!r[2]) {
+ fprintf (stderr, "test_head_n_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ {
+ char expected[] = "2abcdefghijklmnopqrstuvwxyz";
+ if (strcmp (r[2], expected) != 0) {
+ fprintf (stderr, "test_head_n_0: expected \"%s\" but got \"%s\"\n", expected, r[2]);
+ return -1;
+ }
+ }
+ if (r[3] != NULL) {
+ fprintf (stderr, "test_head_n_0: extra elements returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ for (i = 0; r[i] != NULL; ++i)
+ free (r[i]);
+ free (r);
+ }
+ return 0;
+}
+
+static int test_head_n_1_skip (void)
+{
+ const char *str;
+
+ str = getenv ("TEST_ONLY");
+ if (str)
+ return strstr (str, "head_n") == NULL;
+ str = getenv ("SKIP_TEST_HEAD_N_1");
+ if (str && strcmp (str, "1") == 0) return 1;
+ str = getenv ("SKIP_TEST_HEAD_N");
+ if (str && strcmp (str, "1") == 0) return 1;
+ return 0;
+}
+
+static int test_head_n_1 (void)
+{
+ if (test_head_n_1_skip ()) {
+ printf ("%s skipped (reason: environment variable set)\n", "test_head_n_1");
+ return 0;
+ }
+
+ /* InitBasicFS for test_head_n_1: create ext2 on /dev/sda1 */
+ {
+ char device[] = "/dev/sda";
+ int r;
+ suppress_error = 0;
+ r = guestfs_blockdev_setrw (g, device);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char device[] = "/dev/sda";
+ char lines_0[] = ",";
+ char *lines[] = {
+ lines_0,
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, device, 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char fstype[] = "ext2";
+ char device[] = "/dev/sda1";
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, fstype, device);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char device[] = "/dev/sda1";
+ char mountpoint[] = "/";
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, device, mountpoint);
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputList for head_n (1) */
+ {
+ char options[] = "ro";
+ char vfstype[] = "squashfs";
+ char device[] = "/dev/sdd";
+ char mountpoint[] = "/";
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount_vfs (g, options, vfstype, device, mountpoint);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char path[] = "/10klines";
+ char **r;
+ int i;
+ suppress_error = 0;
+ r = guestfs_head_n (g, -9997, path);
+ if (r == NULL)
+ return -1;
+ if (!r[0]) {
+ fprintf (stderr, "test_head_n_1: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ {
+ char expected[] = "0abcdefghijklmnopqrstuvwxyz";
+ if (strcmp (r[0], expected) != 0) {
+ fprintf (stderr, "test_head_n_1: expected \"%s\" but got \"%s\"\n", expected, r[0]);
+ return -1;
+ }
+ }
+ if (!r[1]) {
+ fprintf (stderr, "test_head_n_1: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ {
+ char expected[] = "1abcdefghijklmnopqrstuvwxyz";
+ if (strcmp (r[1], expected) != 0) {
+ fprintf (stderr, "test_head_n_1: expected \"%s\" but got \"%s\"\n", expected, r[1]);
+ return -1;
+ }
+ }
+ if (!r[2]) {
+ fprintf (stderr, "test_head_n_1: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ {
+ char expected[] = "2abcdefghijklmnopqrstuvwxyz";
+ if (strcmp (r[2], expected) != 0) {
+ fprintf (stderr, "test_head_n_1: expected \"%s\" but got \"%s\"\n", expected, r[2]);
+ return -1;
+ }
+ }
+ if (r[3] != NULL) {
+ fprintf (stderr, "test_head_n_1: extra elements returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ for (i = 0; r[i] != NULL; ++i)
+ free (r[i]);
+ free (r);
+ }
+ return 0;
+}
+
+static int test_head_n_2_skip (void)
+{
+ const char *str;
+
+ str = getenv ("TEST_ONLY");
+ if (str)
+ return strstr (str, "head_n") == NULL;
+ str = getenv ("SKIP_TEST_HEAD_N_2");
+ if (str && strcmp (str, "1") == 0) return 1;
+ str = getenv ("SKIP_TEST_HEAD_N");
+ if (str && strcmp (str, "1") == 0) return 1;
+ return 0;
+}
+
+static int test_head_n_2 (void)
+{
+ if (test_head_n_2_skip ()) {
+ printf ("%s skipped (reason: environment variable set)\n", "test_head_n_2");
+ return 0;
+ }
+
+ /* InitBasicFS for test_head_n_2: create ext2 on /dev/sda1 */
+ {
+ char device[] = "/dev/sda";
+ int r;
+ suppress_error = 0;
+ r = guestfs_blockdev_setrw (g, device);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char device[] = "/dev/sda";
+ char lines_0[] = ",";
+ char *lines[] = {
+ lines_0,
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, device, 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char fstype[] = "ext2";
+ char device[] = "/dev/sda1";
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, fstype, device);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char device[] = "/dev/sda1";
+ char mountpoint[] = "/";
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, device, mountpoint);
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputList for head_n (2) */
+ {
+ char options[] = "ro";
+ char vfstype[] = "squashfs";
+ char device[] = "/dev/sdd";
+ char mountpoint[] = "/";
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount_vfs (g, options, vfstype, device, mountpoint);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char path[] = "/10klines";
+ char **r;
+ int i;
+ suppress_error = 0;
+ r = guestfs_head_n (g, 0, path);
+ if (r == NULL)
+ return -1;
+ if (r[0] != NULL) {
+ fprintf (stderr, "test_head_n_2: extra elements returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ for (i = 0; r[i] != NULL; ++i)
+ free (r[i]);
+ free (r);
+ }
+ return 0;
+}
+
+static int test_head_0_skip (void)
+{
+ const char *str;
+
+ str = getenv ("TEST_ONLY");
+ if (str)
+ return strstr (str, "head") == NULL;
+ str = getenv ("SKIP_TEST_HEAD_0");
+ if (str && strcmp (str, "1") == 0) return 1;
+ str = getenv ("SKIP_TEST_HEAD");
+ if (str && strcmp (str, "1") == 0) return 1;
+ return 0;
+}
+
+static int test_head_0 (void)
+{
+ if (test_head_0_skip ()) {
+ printf ("%s skipped (reason: environment variable set)\n", "test_head_0");
+ return 0;
+ }
+
+ /* InitBasicFS for test_head_0: create ext2 on /dev/sda1 */
+ {
+ char device[] = "/dev/sda";
+ int r;
+ suppress_error = 0;
+ r = guestfs_blockdev_setrw (g, device);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_umount_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ int r;
+ suppress_error = 0;
+ r = guestfs_lvm_remove_all (g);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char device[] = "/dev/sda";
+ char lines_0[] = ",";
+ char *lines[] = {
+ lines_0,
+ NULL
+ };
+ int r;
+ suppress_error = 0;
+ r = guestfs_sfdisk (g, device, 0, 0, 0, lines);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char fstype[] = "ext2";
+ char device[] = "/dev/sda1";
+ int r;
+ suppress_error = 0;
+ r = guestfs_mkfs (g, fstype, device);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char device[] = "/dev/sda1";
+ char mountpoint[] = "/";
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount (g, device, mountpoint);
+ if (r == -1)
+ return -1;
+ }
+ /* TestOutputList for head (0) */
+ {
+ char options[] = "ro";
+ char vfstype[] = "squashfs";
+ char device[] = "/dev/sdd";
+ char mountpoint[] = "/";
+ int r;
+ suppress_error = 0;
+ r = guestfs_mount_vfs (g, options, vfstype, device, mountpoint);
+ if (r == -1)
+ return -1;
+ }
+ {
+ char path[] = "/10klines";
+ char **r;
+ int i;
+ suppress_error = 0;
+ r = guestfs_head (g, path);
+ if (r == NULL)
+ return -1;
+ if (!r[0]) {
+ fprintf (stderr, "test_head_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ {
+ char expected[] = "0abcdefghijklmnopqrstuvwxyz";
+ if (strcmp (r[0], expected) != 0) {
+ fprintf (stderr, "test_head_0: expected \"%s\" but got \"%s\"\n", expected, r[0]);
+ return -1;
+ }
+ }
+ if (!r[1]) {
+ fprintf (stderr, "test_head_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ {
+ char expected[] = "1abcdefghijklmnopqrstuvwxyz";
+ if (strcmp (r[1], expected) != 0) {
+ fprintf (stderr, "test_head_0: expected \"%s\" but got \"%s\"\n", expected, r[1]);
+ return -1;
+ }
+ }
+ if (!r[2]) {
+ fprintf (stderr, "test_head_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ {
+ char expected[] = "2abcdefghijklmnopqrstuvwxyz";
+ if (strcmp (r[2], expected) != 0) {
+ fprintf (stderr, "test_head_0: expected \"%s\" but got \"%s\"\n", expected, r[2]);
+ return -1;
+ }
+ }
+ if (!r[3]) {
+ fprintf (stderr, "test_head_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ {
+ char expected[] = "3abcdefghijklmnopqrstuvwxyz";
+ if (strcmp (r[3], expected) != 0) {
+ fprintf (stderr, "test_head_0: expected \"%s\" but got \"%s\"\n", expected, r[3]);
+ return -1;
+ }
+ }
+ if (!r[4]) {
+ fprintf (stderr, "test_head_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ {
+ char expected[] = "4abcdefghijklmnopqrstuvwxyz";
+ if (strcmp (r[4], expected) != 0) {
+ fprintf (stderr, "test_head_0: expected \"%s\" but got \"%s\"\n", expected, r[4]);
+ return -1;
+ }
+ }
+ if (!r[5]) {
+ fprintf (stderr, "test_head_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ {
+ char expected[] = "5abcdefghijklmnopqrstuvwxyz";
+ if (strcmp (r[5], expected) != 0) {
+ fprintf (stderr, "test_head_0: expected \"%s\" but got \"%s\"\n", expected, r[5]);
+ return -1;
+ }
+ }
+ if (!r[6]) {
+ fprintf (stderr, "test_head_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ {
+ char expected[] = "6abcdefghijklmnopqrstuvwxyz";
+ if (strcmp (r[6], expected) != 0) {
+ fprintf (stderr, "test_head_0: expected \"%s\" but got \"%s\"\n", expected, r[6]);
+ return -1;
+ }
+ }
+ if (!r[7]) {
+ fprintf (stderr, "test_head_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ {
+ char expected[] = "7abcdefghijklmnopqrstuvwxyz";
+ if (strcmp (r[7], expected) != 0) {
+ fprintf (stderr, "test_head_0: expected \"%s\" but got \"%s\"\n", expected, r[7]);
+ return -1;
+ }
+ }
+ if (!r[8]) {
+ fprintf (stderr, "test_head_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ {
+ char expected[] = "8abcdefghijklmnopqrstuvwxyz";
+ if (strcmp (r[8], expected) != 0) {
+ fprintf (stderr, "test_head_0: expected \"%s\" but got \"%s\"\n", expected, r[8]);
+ return -1;
+ }
+ }
+ if (!r[9]) {
+ fprintf (stderr, "test_head_0: short list returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ {
+ char expected[] = "9abcdefghijklmnopqrstuvwxyz";
+ if (strcmp (r[9], expected) != 0) {
+ fprintf (stderr, "test_head_0: expected \"%s\" but got \"%s\"\n", expected, r[9]);
+ return -1;
+ }
+ }
+ if (r[10] != NULL) {
+ fprintf (stderr, "test_head_0: extra elements returned from command\n");
+ print_strings (r);
+ return -1;
+ }
+ for (i = 0; r[i] != NULL; ++i)
+ free (r[i]);
+ free (r);
+ }
+ return 0;
+}
+
static int test_wc_c_0_skip (void)
{
const char *str;
@@ -17267,9 +18507,57 @@ int main (int argc, char *argv[])
/* Cancel previous alarm. */
alarm (0);
- nr_tests = 156;
+ nr_tests = 164;
test_num++;
+ printf ("%3d/%3d test_tail_n_0\n", test_num, nr_tests);
+ if (test_tail_n_0 () == -1) {
+ printf ("test_tail_n_0 FAILED\n");
+ failed++;
+ }
+ test_num++;
+ printf ("%3d/%3d test_tail_n_1\n", test_num, nr_tests);
+ if (test_tail_n_1 () == -1) {
+ printf ("test_tail_n_1 FAILED\n");
+ failed++;
+ }
+ test_num++;
+ printf ("%3d/%3d test_tail_n_2\n", test_num, nr_tests);
+ if (test_tail_n_2 () == -1) {
+ printf ("test_tail_n_2 FAILED\n");
+ failed++;
+ }
+ test_num++;
+ printf ("%3d/%3d test_tail_0\n", test_num, nr_tests);
+ if (test_tail_0 () == -1) {
+ printf ("test_tail_0 FAILED\n");
+ failed++;
+ }
+ test_num++;
+ printf ("%3d/%3d test_head_n_0\n", test_num, nr_tests);
+ if (test_head_n_0 () == -1) {
+ printf ("test_head_n_0 FAILED\n");
+ failed++;
+ }
+ test_num++;
+ printf ("%3d/%3d test_head_n_1\n", test_num, nr_tests);
+ if (test_head_n_1 () == -1) {
+ printf ("test_head_n_1 FAILED\n");
+ failed++;
+ }
+ test_num++;
+ printf ("%3d/%3d test_head_n_2\n", test_num, nr_tests);
+ if (test_head_n_2 () == -1) {
+ printf ("test_head_n_2 FAILED\n");
+ failed++;
+ }
+ test_num++;
+ printf ("%3d/%3d test_head_0\n", test_num, nr_tests);
+ if (test_head_0 () == -1) {
+ printf ("test_head_0 FAILED\n");
+ failed++;
+ }
+ test_num++;
printf ("%3d/%3d test_wc_c_0\n", test_num, nr_tests);
if (test_wc_c_0 () == -1) {
printf ("test_wc_c_0 FAILED\n");
diff --git a/daemon/actions.h b/daemon/actions.h
index 2de9aa22..8beeed6e 100644
--- a/daemon/actions.h
+++ b/daemon/actions.h
@@ -119,7 +119,7 @@ extern char **do_strings_e (char *encoding, char *path);
extern char *do_hexdump (char *path);
extern int do_zerofree (char *device);
extern int do_pvresize (char *device);
-extern int do_sfdisk_N (char *device, int n, int cyls, int heads, int sectors, char *line);
+extern int do_sfdisk_N (char *device, int partnum, int cyls, int heads, int sectors, char *line);
extern char *do_sfdisk_l (char *device);
extern char *do_sfdisk_kernel_geometry (char *device);
extern char *do_sfdisk_disk_geometry (char *device);
@@ -141,3 +141,7 @@ extern char *do_mkdtemp (char *template);
extern int do_wc_l (char *path);
extern int do_wc_w (char *path);
extern int do_wc_c (char *path);
+extern char **do_head (char *path);
+extern char **do_head_n (int nrlines, char *path);
+extern char **do_tail (char *path);
+extern char **do_tail_n (int nrlines, char *path);
diff --git a/daemon/stubs.c b/daemon/stubs.c
index ab58473e..170726c1 100644
--- a/daemon/stubs.c
+++ b/daemon/stubs.c
@@ -2450,7 +2450,7 @@ static void sfdisk_N_stub (XDR *xdr_in)
int r;
struct guestfs_sfdisk_N_args args;
char *device;
- int n;
+ int partnum;
int cyls;
int heads;
int sectors;
@@ -2463,13 +2463,13 @@ static void sfdisk_N_stub (XDR *xdr_in)
return;
}
device = args.device;
- n = args.n;
+ partnum = args.partnum;
cyls = args.cyls;
heads = args.heads;
sectors = args.sectors;
line = args.line;
- r = do_sfdisk_N (device, n, cyls, heads, sectors, line);
+ r = do_sfdisk_N (device, partnum, cyls, heads, sectors, line);
if (r == -1)
/* do_sfdisk_N has already called reply_with_error */
goto done;
@@ -3031,6 +3031,122 @@ done:
xdr_free ((xdrproc_t) xdr_guestfs_wc_c_args, (char *) &args);
}
+static void head_stub (XDR *xdr_in)
+{
+ char **r;
+ struct guestfs_head_args args;
+ char *path;
+
+ memset (&args, 0, sizeof args);
+
+ if (!xdr_guestfs_head_args (xdr_in, &args)) {
+ reply_with_error ("%s: daemon failed to decode procedure arguments", "head");
+ return;
+ }
+ path = args.path;
+
+ r = do_head (path);
+ if (r == NULL)
+ /* do_head has already called reply_with_error */
+ goto done;
+
+ struct guestfs_head_ret ret;
+ ret.lines.lines_len = count_strings (r);
+ ret.lines.lines_val = r;
+ reply ((xdrproc_t) &xdr_guestfs_head_ret, (char *) &ret);
+ free_strings (r);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_head_args, (char *) &args);
+}
+
+static void head_n_stub (XDR *xdr_in)
+{
+ char **r;
+ struct guestfs_head_n_args args;
+ int nrlines;
+ char *path;
+
+ memset (&args, 0, sizeof args);
+
+ if (!xdr_guestfs_head_n_args (xdr_in, &args)) {
+ reply_with_error ("%s: daemon failed to decode procedure arguments", "head_n");
+ return;
+ }
+ nrlines = args.nrlines;
+ path = args.path;
+
+ r = do_head_n (nrlines, path);
+ if (r == NULL)
+ /* do_head_n has already called reply_with_error */
+ goto done;
+
+ struct guestfs_head_n_ret ret;
+ ret.lines.lines_len = count_strings (r);
+ ret.lines.lines_val = r;
+ reply ((xdrproc_t) &xdr_guestfs_head_n_ret, (char *) &ret);
+ free_strings (r);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_head_n_args, (char *) &args);
+}
+
+static void tail_stub (XDR *xdr_in)
+{
+ char **r;
+ struct guestfs_tail_args args;
+ char *path;
+
+ memset (&args, 0, sizeof args);
+
+ if (!xdr_guestfs_tail_args (xdr_in, &args)) {
+ reply_with_error ("%s: daemon failed to decode procedure arguments", "tail");
+ return;
+ }
+ path = args.path;
+
+ r = do_tail (path);
+ if (r == NULL)
+ /* do_tail has already called reply_with_error */
+ goto done;
+
+ struct guestfs_tail_ret ret;
+ ret.lines.lines_len = count_strings (r);
+ ret.lines.lines_val = r;
+ reply ((xdrproc_t) &xdr_guestfs_tail_ret, (char *) &ret);
+ free_strings (r);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_tail_args, (char *) &args);
+}
+
+static void tail_n_stub (XDR *xdr_in)
+{
+ char **r;
+ struct guestfs_tail_n_args args;
+ int nrlines;
+ char *path;
+
+ memset (&args, 0, sizeof args);
+
+ if (!xdr_guestfs_tail_n_args (xdr_in, &args)) {
+ reply_with_error ("%s: daemon failed to decode procedure arguments", "tail_n");
+ return;
+ }
+ nrlines = args.nrlines;
+ path = args.path;
+
+ r = do_tail_n (nrlines, path);
+ if (r == NULL)
+ /* do_tail_n has already called reply_with_error */
+ goto done;
+
+ struct guestfs_tail_n_ret ret;
+ ret.lines.lines_len = count_strings (r);
+ ret.lines.lines_val = r;
+ reply ((xdrproc_t) &xdr_guestfs_tail_n_ret, (char *) &ret);
+ free_strings (r);
+done:
+ xdr_free ((xdrproc_t) xdr_guestfs_tail_n_args, (char *) &args);
+}
+
void dispatch_incoming_message (XDR *xdr_in)
{
switch (proc_nr) {
@@ -3394,6 +3510,18 @@ void dispatch_incoming_message (XDR *xdr_in)
case GUESTFS_PROC_WC_C:
wc_c_stub (xdr_in);
break;
+ case GUESTFS_PROC_HEAD:
+ head_stub (xdr_in);
+ break;
+ case GUESTFS_PROC_HEAD_N:
+ head_n_stub (xdr_in);
+ break;
+ case GUESTFS_PROC_TAIL:
+ tail_stub (xdr_in);
+ break;
+ case GUESTFS_PROC_TAIL_N:
+ tail_n_stub (xdr_in);
+ break;
default:
reply_with_error ("dispatch_incoming_message: unknown procedure number %d, set LIBGUESTFS_PATH to point to the matching libguestfs appliance directory", proc_nr);
}
diff --git a/fish/cmds.c b/fish/cmds.c
index 89fa1fb3..9bd53eca 100644
--- a/fish/cmds.c
+++ b/fish/cmds.c
@@ -86,6 +86,8 @@ void list_commands (void)
printf ("%-20s %s\n", "get-verbose", "get verbose mode");
printf ("%-20s %s\n", "glob-expand", "expand a wildcard path");
printf ("%-20s %s\n", "grub-install", "install GRUB");
+ printf ("%-20s %s\n", "head", "return first 10 lines of a file");
+ printf ("%-20s %s\n", "head-n", "return first N lines of a file");
printf ("%-20s %s\n", "hexdump", "dump a file in hexadecimal");
printf ("%-20s %s\n", "is-busy", "is busy processing a command");
printf ("%-20s %s\n", "is-config", "is in configuration state");
@@ -151,6 +153,8 @@ void list_commands (void)
printf ("%-20s %s\n", "strings", "print the printable strings in a file");
printf ("%-20s %s\n", "strings-e", "print the printable strings in a file");
printf ("%-20s %s\n", "sync", "sync disks, writes are flushed through to the disk image");
+ printf ("%-20s %s\n", "tail", "return last 10 lines of a file");
+ printf ("%-20s %s\n", "tail-n", "return last N lines of a file");
printf ("%-20s %s\n", "tar-in", "unpack tarfile to directory");
printf ("%-20s %s\n", "tar-out", "pack directory into tarfile");
printf ("%-20s %s\n", "tgz-in", "unpack compressed tarball to directory");
@@ -535,7 +539,7 @@ void display_command (const char *cmd)
pod2text ("pvresize - resize an LVM physical volume", " pvresize <device>\n\nThis resizes (expands or shrinks) an existing LVM physical\nvolume to match the new size of the underlying device.");
else
if (strcasecmp (cmd, "sfdisk_N") == 0 || strcasecmp (cmd, "sfdisk-N") == 0)
- pod2text ("sfdisk-N - modify a single partition on a block device", " sfdisk-N <device> <n> <cyls> <heads> <sectors> <line>\n\nThis runs L<sfdisk(8)> option to modify just the single\npartition C<n> (note: C<n> counts from 1).\n\nFor other parameters, see C<sfdisk>. You should usually\npass C<0> for the cyls/heads/sectors parameters.\n\nB<This command is dangerous. Without careful use you\ncan easily destroy all your data>.");
+ pod2text ("sfdisk-N - modify a single partition on a block device", " sfdisk-N <device> <partnum> <cyls> <heads> <sectors> <line>\n\nThis runs L<sfdisk(8)> option to modify just the single\npartition C<n> (note: C<n> counts from 1).\n\nFor other parameters, see C<sfdisk>. You should usually\npass C<0> for the cyls/heads/sectors parameters.\n\nB<This command is dangerous. Without careful use you\ncan easily destroy all your data>.");
else
if (strcasecmp (cmd, "sfdisk_l") == 0 || strcasecmp (cmd, "sfdisk-l") == 0)
pod2text ("sfdisk-l - display the partition table", " sfdisk-l <device>\n\nThis displays the partition table on C<device>, in the\nhuman-readable output of the L<sfdisk(8)> command. It is\nnot intended to be parsed.");
@@ -600,6 +604,18 @@ void display_command (const char *cmd)
if (strcasecmp (cmd, "wc_c") == 0 || strcasecmp (cmd, "wc-c") == 0)
pod2text ("wc-c - count characters in a file", " wc-c <path>\n\nThis command counts the characters in a file, using the\nC<wc -c> external command.");
else
+ if (strcasecmp (cmd, "head") == 0)
+ pod2text ("head - return first 10 lines of a file", " head <path>\n\nThis command returns up to the first 10 lines of a file as\na list of strings.\n\nBecause of the message protocol, there is a transfer limit \nof somewhere between 2MB and 4MB. To transfer large files you should use\nFTP.");
+ else
+ if (strcasecmp (cmd, "head_n") == 0 || strcasecmp (cmd, "head-n") == 0)
+ pod2text ("head-n - return first N lines of a file", " head-n <nrlines> <path>\n\nIf the parameter C<nrlines> is a positive number, this returns the first\nC<nrlines> lines of the file C<path>.\n\nIf the parameter C<nrlines> is a negative number, this returns lines\nfrom the file C<path>, excluding the last C<nrlines> lines.\n\nIf the parameter C<nrlines> is zero, this returns an empty list.\n\nBecause of the message protocol, there is a transfer limit \nof somewhere between 2MB and 4MB. To transfer large files you should use\nFTP.");
+ else
+ if (strcasecmp (cmd, "tail") == 0)
+ pod2text ("tail - return last 10 lines of a file", " tail <path>\n\nThis command returns up to the last 10 lines of a file as\na list of strings.\n\nBecause of the message protocol, there is a transfer limit \nof somewhere between 2MB and 4MB. To transfer large files you should use\nFTP.");
+ else
+ if (strcasecmp (cmd, "tail_n") == 0 || strcasecmp (cmd, "tail-n") == 0)
+ pod2text ("tail-n - return last N lines of a file", " tail-n <nrlines> <path>\n\nIf the parameter C<nrlines> is a positive number, this returns the last\nC<nrlines> lines of the file C<path>.\n\nIf the parameter C<nrlines> is a negative number, this returns lines\nfrom the file C<path>, starting with the C<-nrlines>th line.\n\nIf the parameter C<nrlines> is zero, this returns an empty list.\n\nBecause of the message protocol, there is a transfer limit \nof somewhere between 2MB and 4MB. To transfer large files you should use\nFTP.");
+ else
display_builtin_command (cmd);
}
@@ -2584,7 +2600,7 @@ static int run_sfdisk_N (const char *cmd, int argc, char *argv[])
{
int r;
const char *device;
- int n;
+ int partnum;
int cyls;
int heads;
int sectors;
@@ -2595,12 +2611,12 @@ static int run_sfdisk_N (const char *cmd, int argc, char *argv[])
return -1;
}
device = argv[0];
- n = atoi (argv[1]);
+ partnum = atoi (argv[1]);
cyls = atoi (argv[2]);
heads = atoi (argv[3]);
sectors = atoi (argv[4]);
line = argv[5];
- r = guestfs_sfdisk_N (g, device, n, cyls, heads, sectors, line);
+ r = guestfs_sfdisk_N (g, device, partnum, cyls, heads, sectors, line);
return r;
}
@@ -2936,6 +2952,78 @@ static int run_wc_c (const char *cmd, int argc, char *argv[])
return 0;
}
+static int run_head (const char *cmd, int argc, char *argv[])
+{
+ char **r;
+ const char *path;
+ if (argc != 1) {
+ fprintf (stderr, "%s should have 1 parameter(s)\n", cmd);
+ fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+ return -1;
+ }
+ path = argv[0];
+ r = guestfs_head (g, path);
+ if (r == NULL) return -1;
+ print_strings (r);
+ free_strings (r);
+ return 0;
+}
+
+static int run_head_n (const char *cmd, int argc, char *argv[])
+{
+ char **r;
+ int nrlines;
+ const char *path;
+ if (argc != 2) {
+ fprintf (stderr, "%s should have 2 parameter(s)\n", cmd);
+ fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+ return -1;
+ }
+ nrlines = atoi (argv[0]);
+ path = argv[1];
+ r = guestfs_head_n (g, nrlines, path);
+ if (r == NULL) return -1;
+ print_strings (r);
+ free_strings (r);
+ return 0;
+}
+
+static int run_tail (const char *cmd, int argc, char *argv[])
+{
+ char **r;
+ const char *path;
+ if (argc != 1) {
+ fprintf (stderr, "%s should have 1 parameter(s)\n", cmd);
+ fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+ return -1;
+ }
+ path = argv[0];
+ r = guestfs_tail (g, path);
+ if (r == NULL) return -1;
+ print_strings (r);
+ free_strings (r);
+ return 0;
+}
+
+static int run_tail_n (const char *cmd, int argc, char *argv[])
+{
+ char **r;
+ int nrlines;
+ const char *path;
+ if (argc != 2) {
+ fprintf (stderr, "%s should have 2 parameter(s)\n", cmd);
+ fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd);
+ return -1;
+ }
+ nrlines = atoi (argv[0]);
+ path = argv[1];
+ r = guestfs_tail_n (g, nrlines, path);
+ if (r == NULL) return -1;
+ print_strings (r);
+ free_strings (r);
+ return 0;
+}
+
int run_action (const char *cmd, int argc, char *argv[])
{
if (strcasecmp (cmd, "launch") == 0 || strcasecmp (cmd, "run") == 0)
@@ -3361,6 +3449,18 @@ int run_action (const char *cmd, int argc, char *argv[])
if (strcasecmp (cmd, "wc_c") == 0 || strcasecmp (cmd, "wc-c") == 0)
return run_wc_c (cmd, argc, argv);
else
+ if (strcasecmp (cmd, "head") == 0)
+ return run_head (cmd, argc, argv);
+ else
+ if (strcasecmp (cmd, "head_n") == 0 || strcasecmp (cmd, "head-n") == 0)
+ return run_head_n (cmd, argc, argv);
+ else
+ if (strcasecmp (cmd, "tail") == 0)
+ return run_tail (cmd, argc, argv);
+ else
+ if (strcasecmp (cmd, "tail_n") == 0 || strcasecmp (cmd, "tail-n") == 0)
+ return run_tail_n (cmd, argc, argv);
+ else
{
fprintf (stderr, "%s: unknown command\n", cmd);
return -1;
diff --git a/fish/completion.c b/fish/completion.c
index f81e0479..a2febb78 100644
--- a/fish/completion.c
+++ b/fish/completion.c
@@ -187,6 +187,10 @@ static const char *const commands[] = {
"wc-l",
"wc-w",
"wc-c",
+ "head",
+ "head-n",
+ "tail",
+ "tail-n",
NULL
};
diff --git a/guestfish-actions.pod b/guestfish-actions.pod
index ee0b14d9..d45c0015 100644
--- a/guestfish-actions.pod
+++ b/guestfish-actions.pod
@@ -705,6 +705,33 @@ See that manual page for more details.
This command installs GRUB (the Grand Unified Bootloader) on
C<device>, with the root directory being C<root>.
+=head2 head
+
+ head path
+
+This command returns up to the first 10 lines of a file as
+a list of strings.
+
+Because of the message protocol, there is a transfer limit
+of somewhere between 2MB and 4MB. To transfer large files you should use
+FTP.
+
+=head2 head-n
+
+ head-n nrlines path
+
+If the parameter C<nrlines> is a positive number, this returns the first
+C<nrlines> lines of the file C<path>.
+
+If the parameter C<nrlines> is a negative number, this returns lines
+from the file C<path>, excluding the last C<nrlines> lines.
+
+If the parameter C<nrlines> is zero, this returns an empty list.
+
+Because of the message protocol, there is a transfer limit
+of somewhere between 2MB and 4MB. To transfer large files you should use
+FTP.
+
=head2 hexdump
hexdump path
@@ -1266,7 +1293,7 @@ can easily destroy all your data>.
=head2 sfdisk-N
- sfdisk-N device n cyls heads sectors line
+ sfdisk-N device partnum cyls heads sectors line
This runs L<sfdisk(8)> option to modify just the single
partition C<n> (note: C<n> counts from 1).
@@ -1395,6 +1422,33 @@ underlying disk image.
You should always call this if you have modified a disk image, before
closing the handle.
+=head2 tail
+
+ tail path
+
+This command returns up to the last 10 lines of a file as
+a list of strings.
+
+Because of the message protocol, there is a transfer limit
+of somewhere between 2MB and 4MB. To transfer large files you should use
+FTP.
+
+=head2 tail-n
+
+ tail-n nrlines path
+
+If the parameter C<nrlines> is a positive number, this returns the last
+C<nrlines> lines of the file C<path>.
+
+If the parameter C<nrlines> is a negative number, this returns lines
+from the file C<path>, starting with the C<-nrlines>th line.
+
+If the parameter C<nrlines> is zero, this returns an empty list.
+
+Because of the message protocol, there is a transfer limit
+of somewhere between 2MB and 4MB. To transfer large files you should use
+FTP.
+
=head2 tar-in
tar-in (tarfile|-) directory
diff --git a/guestfs-actions.pod b/guestfs-actions.pod
index 530a4130..68357d62 100644
--- a/guestfs-actions.pod
+++ b/guestfs-actions.pod
@@ -915,6 +915,44 @@ C<device>, with the root directory being C<root>.
This function returns 0 on success or -1 on error.
+=head2 guestfs_head
+
+ char **guestfs_head (guestfs_h *handle,
+ const char *path);
+
+This command returns up to the first 10 lines of a file as
+a list of strings.
+
+This function returns a NULL-terminated array of strings
+(like L<environ(3)>), or NULL if there was an error.
+I<The caller must free the strings and the array after use>.
+
+Because of the message protocol, there is a transfer limit
+of somewhere between 2MB and 4MB. To transfer large files you should use
+FTP.
+
+=head2 guestfs_head_n
+
+ char **guestfs_head_n (guestfs_h *handle,
+ int nrlines,
+ const char *path);
+
+If the parameter C<nrlines> is a positive number, this returns the first
+C<nrlines> lines of the file C<path>.
+
+If the parameter C<nrlines> is a negative number, this returns lines
+from the file C<path>, excluding the last C<nrlines> lines.
+
+If the parameter C<nrlines> is zero, this returns an empty list.
+
+This function returns a NULL-terminated array of strings
+(like L<environ(3)>), or NULL if there was an error.
+I<The caller must free the strings and the array after use>.
+
+Because of the message protocol, there is a transfer limit
+of somewhere between 2MB and 4MB. To transfer large files you should use
+FTP.
+
=head2 guestfs_hexdump
char *guestfs_hexdump (guestfs_h *handle,
@@ -1689,7 +1727,7 @@ can easily destroy all your data>.
int guestfs_sfdisk_N (guestfs_h *handle,
const char *device,
- int n,
+ int partnum,
int cyls,
int heads,
int sectors,
@@ -1873,6 +1911,44 @@ closing the handle.
This function returns 0 on success or -1 on error.
+=head2 guestfs_tail
+
+ char **guestfs_tail (guestfs_h *handle,
+ const char *path);
+
+This command returns up to the last 10 lines of a file as
+a list of strings.
+
+This function returns a NULL-terminated array of strings
+(like L<environ(3)>), or NULL if there was an error.
+I<The caller must free the strings and the array after use>.
+
+Because of the message protocol, there is a transfer limit
+of somewhere between 2MB and 4MB. To transfer large files you should use
+FTP.
+
+=head2 guestfs_tail_n
+
+ char **guestfs_tail_n (guestfs_h *handle,
+ int nrlines,
+ const char *path);
+
+If the parameter C<nrlines> is a positive number, this returns the last
+C<nrlines> lines of the file C<path>.
+
+If the parameter C<nrlines> is a negative number, this returns lines
+from the file C<path>, starting with the C<-nrlines>th line.
+
+If the parameter C<nrlines> is zero, this returns an empty list.
+
+This function returns a NULL-terminated array of strings
+(like L<environ(3)>), or NULL if there was an error.
+I<The caller must free the strings and the array after use>.
+
+Because of the message protocol, there is a transfer limit
+of somewhere between 2MB and 4MB. To transfer large files you should use
+FTP.
+
=head2 guestfs_tar_in
int guestfs_tar_in (guestfs_h *handle,
diff --git a/haskell/Guestfs.hs b/haskell/Guestfs.hs
index 8101b526..dfa385ac 100644
--- a/haskell/Guestfs.hs
+++ b/haskell/Guestfs.hs
@@ -1158,8 +1158,8 @@ foreign import ccall unsafe "guestfs_sfdisk_N" c_sfdisk_N
:: GuestfsP -> CString -> CInt -> CInt -> CInt -> CInt -> CString -> IO (CInt)
sfdisk_N :: GuestfsH -> String -> Int -> Int -> Int -> Int -> String -> IO ()
-sfdisk_N h device n cyls heads sectors line = do
- r <- withCString device $ \device -> withCString line $ \line -> withForeignPtr h (\p -> c_sfdisk_N p device (fromIntegral n) (fromIntegral cyls) (fromIntegral heads) (fromIntegral sectors) line)
+sfdisk_N h device partnum cyls heads sectors line = do
+ r <- withCString device $ \device -> withCString line $ \line -> withForeignPtr h (\p -> c_sfdisk_N p device (fromIntegral partnum) (fromIntegral cyls) (fromIntegral heads) (fromIntegral sectors) line)
if (r == -1)
then do
err <- last_error h
diff --git a/images/Makefile.am b/images/Makefile.am
index 46488ebe..71d63a83 100644
--- a/images/Makefile.am
+++ b/images/Makefile.am
@@ -56,7 +56,7 @@ test.sqsh: $(squash_files)
rm -f $@ $@-t
i=0; \
while [ $$i -lt 10000 ]; do \
- echo "abcdefghijklmnopqrstuvwxyz"; \
+ echo "$${i}abcdefghijklmnopqrstuvwxyz"; \
i=$$(($$i+1)); \
done > $@-t
mv $@-t $@
diff --git a/java/com/redhat/et/libguestfs/GuestFS.java b/java/com/redhat/et/libguestfs/GuestFS.java
index 64b0802b..30913327 100644
--- a/java/com/redhat/et/libguestfs/GuestFS.java
+++ b/java/com/redhat/et/libguestfs/GuestFS.java
@@ -3112,14 +3112,14 @@ public HashMap<String,String> test0rhashtableerr ()
* <p>
* @throws LibGuestFSException
*/
- public void sfdisk_N (String device, int n, int cyls, int heads, int sectors, String line)
+ public void sfdisk_N (String device, int partnum, int cyls, int heads, int sectors, String line)
throws LibGuestFSException
{
if (g == 0)
throw new LibGuestFSException ("sfdisk_N: handle is closed");
- _sfdisk_N (g, device, n, cyls, heads, sectors, line);
+ _sfdisk_N (g, device, partnum, cyls, heads, sectors, line);
}
- private native void _sfdisk_N (long g, String device, int n, int cyls, int heads, int sectors, String line)
+ private native void _sfdisk_N (long g, String device, int partnum, int cyls, int heads, int sectors, String line)
throws LibGuestFSException;
/**
@@ -3623,4 +3623,106 @@ public HashMap<String,String> test0rhashtableerr ()
private native int _wc_c (long g, String path)
throws LibGuestFSException;
+ /**
+ * return first 10 lines of a file
+ * <p>
+ * This command returns up to the first 10 lines of a file
+ * as a list of strings.
+ * <p>
+ * Because of the message protocol, there is a transfer
+ * limit of somewhere between 2MB and 4MB. To transfer
+ * large files you should use FTP.
+ * <p>
+ * @throws LibGuestFSException
+ */
+ public String[] head (String path)
+ throws LibGuestFSException
+ {
+ if (g == 0)
+ throw new LibGuestFSException ("head: handle is closed");
+ return _head (g, path);
+ }
+ private native String[] _head (long g, String path)
+ throws LibGuestFSException;
+
+ /**
+ * return first N lines of a file
+ * <p>
+ * If the parameter "nrlines" is a positive number, this
+ * returns the first "nrlines" lines of the file "path".
+ * <p>
+ * If the parameter "nrlines" is a negative number, this
+ * returns lines from the file "path", excluding the last
+ * "nrlines" lines.
+ * <p>
+ * If the parameter "nrlines" is zero, this returns an
+ * empty list.
+ * <p>
+ * Because of the message protocol, there is a transfer
+ * limit of somewhere between 2MB and 4MB. To transfer
+ * large files you should use FTP.
+ * <p>
+ * @throws LibGuestFSException
+ */
+ public String[] head_n (int nrlines, String path)
+ throws LibGuestFSException
+ {
+ if (g == 0)
+ throw new LibGuestFSException ("head_n: handle is closed");
+ return _head_n (g, nrlines, path);
+ }
+ private native String[] _head_n (long g, int nrlines, String path)
+ throws LibGuestFSException;
+
+ /**
+ * return last 10 lines of a file
+ * <p>
+ * This command returns up to the last 10 lines of a file
+ * as a list of strings.
+ * <p>
+ * Because of the message protocol, there is a transfer
+ * limit of somewhere between 2MB and 4MB. To transfer
+ * large files you should use FTP.
+ * <p>
+ * @throws LibGuestFSException
+ */
+ public String[] tail (String path)
+ throws LibGuestFSException
+ {
+ if (g == 0)
+ throw new LibGuestFSException ("tail: handle is closed");
+ return _tail (g, path);
+ }
+ private native String[] _tail (long g, String path)
+ throws LibGuestFSException;
+
+ /**
+ * return last N lines of a file
+ * <p>
+ * If the parameter "nrlines" is a positive number, this
+ * returns the last "nrlines" lines of the file "path".
+ * <p>
+ * If the parameter "nrlines" is a negative number, this
+ * returns lines from the file "path", starting with the
+ * "-nrlines"th line.
+ * <p>
+ * If the parameter "nrlines" is zero, this returns an
+ * empty list.
+ * <p>
+ * Because of the message protocol, there is a transfer
+ * limit of somewhere between 2MB and 4MB. To transfer
+ * large files you should use FTP.
+ * <p>
+ * @throws LibGuestFSException
+ */
+ public String[] tail_n (int nrlines, String path)
+ throws LibGuestFSException
+ {
+ if (g == 0)
+ throw new LibGuestFSException ("tail_n: handle is closed");
+ return _tail_n (g, nrlines, path);
+ }
+ private native String[] _tail_n (long g, int nrlines, String path)
+ throws LibGuestFSException;
+
}
diff --git a/java/com_redhat_et_libguestfs_GuestFS.c b/java/com_redhat_et_libguestfs_GuestFS.c
index 3a162597..501e8d12 100644
--- a/java/com_redhat_et_libguestfs_GuestFS.c
+++ b/java/com_redhat_et_libguestfs_GuestFS.c
@@ -3728,24 +3728,24 @@ Java_com_redhat_et_libguestfs_GuestFS__1pvresize
JNIEXPORT void JNICALL
Java_com_redhat_et_libguestfs_GuestFS__1sfdisk_1N
- (JNIEnv *env, jobject obj, jlong jg, jstring jdevice, jint jn, jint jcyls, jint jheads, jint jsectors, jstring jline)
+ (JNIEnv *env, jobject obj, jlong jg, jstring jdevice, jint jpartnum, jint jcyls, jint jheads, jint jsectors, jstring jline)
{
guestfs_h *g = (guestfs_h *) (long) jg;
int r;
const char *device;
- int n;
+ int partnum;
int cyls;
int heads;
int sectors;
const char *line;
device = (*env)->GetStringUTFChars (env, jdevice, NULL);
- n = jn;
+ partnum = jpartnum;
cyls = jcyls;
heads = jheads;
sectors = jsectors;
line = (*env)->GetStringUTFChars (env, jline, NULL);
- r = guestfs_sfdisk_N (g, device, n, cyls, heads, sectors, line);
+ r = guestfs_sfdisk_N (g, device, partnum, cyls, heads, sectors, line);
(*env)->ReleaseStringUTFChars (env, jdevice, device);
(*env)->ReleaseStringUTFChars (env, jline, line);
if (r == -1) {
@@ -4199,3 +4199,139 @@ Java_com_redhat_et_libguestfs_GuestFS__1wc_1c
return (jint) r;
}
+JNIEXPORT jobjectArray JNICALL
+Java_com_redhat_et_libguestfs_GuestFS__1head
+ (JNIEnv *env, jobject obj, jlong jg, jstring jpath)
+{
+ guestfs_h *g = (guestfs_h *) (long) jg;
+ jobjectArray jr;
+ int r_len;
+ jclass cl;
+ jstring jstr;
+ char **r;
+ const char *path;
+ int i;
+
+ path = (*env)->GetStringUTFChars (env, jpath, NULL);
+ r = guestfs_head (g, path);
+ (*env)->ReleaseStringUTFChars (env, jpath, path);
+ if (r == NULL) {
+ throw_exception (env, guestfs_last_error (g));
+ return NULL;
+ }
+ for (r_len = 0; r[r_len] != NULL; ++r_len) ;
+ cl = (*env)->FindClass (env, "java/lang/String");
+ jstr = (*env)->NewStringUTF (env, "");
+ jr = (*env)->NewObjectArray (env, r_len, cl, jstr);
+ for (i = 0; i < r_len; ++i) {
+ jstr = (*env)->NewStringUTF (env, r[i]);
+ (*env)->SetObjectArrayElement (env, jr, i, jstr);
+ free (r[i]);
+ }
+ free (r);
+ return jr;
+}
+
+JNIEXPORT jobjectArray JNICALL
+Java_com_redhat_et_libguestfs_GuestFS__1head_1n
+ (JNIEnv *env, jobject obj, jlong jg, jint jnrlines, jstring jpath)
+{
+ guestfs_h *g = (guestfs_h *) (long) jg;
+ jobjectArray jr;
+ int r_len;
+ jclass cl;
+ jstring jstr;
+ char **r;
+ int nrlines;
+ const char *path;
+ int i;
+
+ nrlines = jnrlines;
+ path = (*env)->GetStringUTFChars (env, jpath, NULL);
+ r = guestfs_head_n (g, nrlines, path);
+ (*env)->ReleaseStringUTFChars (env, jpath, path);
+ if (r == NULL) {
+ throw_exception (env, guestfs_last_error (g));
+ return NULL;
+ }
+ for (r_len = 0; r[r_len] != NULL; ++r_len) ;
+ cl = (*env)->FindClass (env, "java/lang/String");
+ jstr = (*env)->NewStringUTF (env, "");
+ jr = (*env)->NewObjectArray (env, r_len, cl, jstr);
+ for (i = 0; i < r_len; ++i) {
+ jstr = (*env)->NewStringUTF (env, r[i]);
+ (*env)->SetObjectArrayElement (env, jr, i, jstr);
+ free (r[i]);
+ }
+ free (r);
+ return jr;
+}
+
+JNIEXPORT jobjectArray JNICALL
+Java_com_redhat_et_libguestfs_GuestFS__1tail
+ (JNIEnv *env, jobject obj, jlong jg, jstring jpath)
+{
+ guestfs_h *g = (guestfs_h *) (long) jg;
+ jobjectArray jr;
+ int r_len;
+ jclass cl;
+ jstring jstr;
+ char **r;
+ const char *path;
+ int i;
+
+ path = (*env)->GetStringUTFChars (env, jpath, NULL);
+ r = guestfs_tail (g, path);
+ (*env)->ReleaseStringUTFChars (env, jpath, path);
+ if (r == NULL) {
+ throw_exception (env, guestfs_last_error (g));
+ return NULL;
+ }
+ for (r_len = 0; r[r_len] != NULL; ++r_len) ;
+ cl = (*env)->FindClass (env, "java/lang/String");
+ jstr = (*env)->NewStringUTF (env, "");
+ jr = (*env)->NewObjectArray (env, r_len, cl, jstr);
+ for (i = 0; i < r_len; ++i) {
+ jstr = (*env)->NewStringUTF (env, r[i]);
+ (*env)->SetObjectArrayElement (env, jr, i, jstr);
+ free (r[i]);
+ }
+ free (r);
+ return jr;
+}
+
+JNIEXPORT jobjectArray JNICALL
+Java_com_redhat_et_libguestfs_GuestFS__1tail_1n
+ (JNIEnv *env, jobject obj, jlong jg, jint jnrlines, jstring jpath)
+{
+ guestfs_h *g = (guestfs_h *) (long) jg;
+ jobjectArray jr;
+ int r_len;
+ jclass cl;
+ jstring jstr;
+ char **r;
+ int nrlines;
+ const char *path;
+ int i;
+
+ nrlines = jnrlines;
+ path = (*env)->GetStringUTFChars (env, jpath, NULL);
+ r = guestfs_tail_n (g, nrlines, path);
+ (*env)->ReleaseStringUTFChars (env, jpath, path);
+ if (r == NULL) {
+ throw_exception (env, guestfs_last_error (g));
+ return NULL;
+ }
+ for (r_len = 0; r[r_len] != NULL; ++r_len) ;
+ cl = (*env)->FindClass (env, "java/lang/String");
+ jstr = (*env)->NewStringUTF (env, "");
+ jr = (*env)->NewObjectArray (env, r_len, cl, jstr);
+ for (i = 0; i < r_len; ++i) {
+ jstr = (*env)->NewStringUTF (env, r[i]);
+ (*env)->SetObjectArrayElement (env, jr, i, jstr);
+ free (r[i]);
+ }
+ free (r);
+ return jr;
+}
+
diff --git a/ocaml/guestfs.ml b/ocaml/guestfs.ml
index b84504e7..c631024b 100644
--- a/ocaml/guestfs.ml
+++ b/ocaml/guestfs.ml
@@ -287,3 +287,7 @@ external mkdtemp : t -> string -> string = "ocaml_guestfs_mkdtemp"
external wc_l : t -> string -> int = "ocaml_guestfs_wc_l"
external wc_w : t -> string -> int = "ocaml_guestfs_wc_w"
external wc_c : t -> string -> int = "ocaml_guestfs_wc_c"
+external head : t -> string -> string array = "ocaml_guestfs_head"
+external head_n : t -> int -> string -> string array = "ocaml_guestfs_head_n"
+external tail : t -> string -> string array = "ocaml_guestfs_tail"
+external tail_n : t -> int -> string -> string array = "ocaml_guestfs_tail_n"
diff --git a/ocaml/guestfs.mli b/ocaml/guestfs.mli
index 4c1ef721..97180b0d 100644
--- a/ocaml/guestfs.mli
+++ b/ocaml/guestfs.mli
@@ -640,3 +640,15 @@ val wc_w : t -> string -> int
val wc_c : t -> string -> int
(** count characters in a file *)
+val head : t -> string -> string array
+(** return first 10 lines of a file *)
+
+val head_n : t -> int -> string -> string array
+(** return first N lines of a file *)
+
+val tail : t -> string -> string array
+(** return last 10 lines of a file *)
+
+val tail_n : t -> int -> string -> string array
+(** return last N lines of a file *)
+
diff --git a/ocaml/guestfs_c_actions.c b/ocaml/guestfs_c_actions.c
index beb41d77..d8b05677 100644
--- a/ocaml/guestfs_c_actions.c
+++ b/ocaml/guestfs_c_actions.c
@@ -3901,9 +3901,9 @@ ocaml_guestfs_pvresize (value gv, value devicev)
}
CAMLprim value
-ocaml_guestfs_sfdisk_N (value gv, value devicev, value nv, value cylsv, value headsv, value sectorsv, value linev)
+ocaml_guestfs_sfdisk_N (value gv, value devicev, value partnumv, value cylsv, value headsv, value sectorsv, value linev)
{
- CAMLparam5 (gv, devicev, nv, cylsv, headsv);
+ CAMLparam5 (gv, devicev, partnumv, cylsv, headsv);
CAMLxparam2 (sectorsv, linev);
CAMLlocal1 (rv);
@@ -3912,7 +3912,7 @@ ocaml_guestfs_sfdisk_N (value gv, value devicev, value nv, value cylsv, value he
caml_failwith ("sfdisk_N: used handle after closing it");
const char *device = String_val (devicev);
- int n = Int_val (nv);
+ int partnum = Int_val (partnumv);
int cyls = Int_val (cylsv);
int heads = Int_val (headsv);
int sectors = Int_val (sectorsv);
@@ -3920,7 +3920,7 @@ ocaml_guestfs_sfdisk_N (value gv, value devicev, value nv, value cylsv, value he
int r;
caml_enter_blocking_section ();
- r = guestfs_sfdisk_N (g, device, n, cyls, heads, sectors, line);
+ r = guestfs_sfdisk_N (g, device, partnum, cyls, heads, sectors, line);
caml_leave_blocking_section ();
if (r == -1)
ocaml_guestfs_raise_error (g, "sfdisk_N");
@@ -4436,3 +4436,109 @@ ocaml_guestfs_wc_c (value gv, value pathv)
CAMLreturn (rv);
}
+CAMLprim value
+ocaml_guestfs_head (value gv, value pathv)
+{
+ CAMLparam2 (gv, pathv);
+ CAMLlocal1 (rv);
+
+ guestfs_h *g = Guestfs_val (gv);
+ if (g == NULL)
+ caml_failwith ("head: used handle after closing it");
+
+ const char *path = String_val (pathv);
+ int i;
+ char **r;
+
+ caml_enter_blocking_section ();
+ r = guestfs_head (g, path);
+ caml_leave_blocking_section ();
+ if (r == NULL)
+ ocaml_guestfs_raise_error (g, "head");
+
+ rv = caml_copy_string_array ((const char **) r);
+ for (i = 0; r[i] != NULL; ++i) free (r[i]);
+ free (r);
+ CAMLreturn (rv);
+}
+
+CAMLprim value
+ocaml_guestfs_head_n (value gv, value nrlinesv, value pathv)
+{
+ CAMLparam3 (gv, nrlinesv, pathv);
+ CAMLlocal1 (rv);
+
+ guestfs_h *g = Guestfs_val (gv);
+ if (g == NULL)
+ caml_failwith ("head_n: used handle after closing it");
+
+ int nrlines = Int_val (nrlinesv);
+ const char *path = String_val (pathv);
+ int i;
+ char **r;
+
+ caml_enter_blocking_section ();
+ r = guestfs_head_n (g, nrlines, path);
+ caml_leave_blocking_section ();
+ if (r == NULL)
+ ocaml_guestfs_raise_error (g, "head_n");
+
+ rv = caml_copy_string_array ((const char **) r);
+ for (i = 0; r[i] != NULL; ++i) free (r[i]);
+ free (r);
+ CAMLreturn (rv);
+}
+
+CAMLprim value
+ocaml_guestfs_tail (value gv, value pathv)
+{
+ CAMLparam2 (gv, pathv);
+ CAMLlocal1 (rv);
+
+ guestfs_h *g = Guestfs_val (gv);
+ if (g == NULL)
+ caml_failwith ("tail: used handle after closing it");
+
+ const char *path = String_val (pathv);
+ int i;
+ char **r;
+
+ caml_enter_blocking_section ();
+ r = guestfs_tail (g, path);
+ caml_leave_blocking_section ();
+ if (r == NULL)
+ ocaml_guestfs_raise_error (g, "tail");
+
+ rv = caml_copy_string_array ((const char **) r);
+ for (i = 0; r[i] != NULL; ++i) free (r[i]);
+ free (r);
+ CAMLreturn (rv);
+}
+
+CAMLprim value
+ocaml_guestfs_tail_n (value gv, value nrlinesv, value pathv)
+{
+ CAMLparam3 (gv, nrlinesv, pathv);
+ CAMLlocal1 (rv);
+
+ guestfs_h *g = Guestfs_val (gv);
+ if (g == NULL)
+ caml_failwith ("tail_n: used handle after closing it");
+
+ int nrlines = Int_val (nrlinesv);
+ const char *path = String_val (pathv);
+ int i;
+ char **r;
+
+ caml_enter_blocking_section ();
+ r = guestfs_tail_n (g, nrlines, path);
+ caml_leave_blocking_section ();
+ if (r == NULL)
+ ocaml_guestfs_raise_error (g, "tail_n");
+
+ rv = caml_copy_string_array ((const char **) r);
+ for (i = 0; r[i] != NULL; ++i) free (r[i]);
+ free (r);
+ CAMLreturn (rv);
+}
+
diff --git a/perl/Guestfs.xs b/perl/Guestfs.xs
index 1dc634f5..bcd7304f 100644
--- a/perl/Guestfs.xs
+++ b/perl/Guestfs.xs
@@ -2386,10 +2386,10 @@ PREINIT:
croak ("pvresize: %s", guestfs_last_error (g));
void
-sfdisk_N (g, device, n, cyls, heads, sectors, line)
+sfdisk_N (g, device, partnum, cyls, heads, sectors, line)
guestfs_h *g;
char *device;
- int n;
+ int partnum;
int cyls;
int heads;
int sectors;
@@ -2397,7 +2397,7 @@ sfdisk_N (g, device, n, cyls, heads, sectors, line)
PREINIT:
int r;
PPCODE:
- r = guestfs_sfdisk_N (g, device, n, cyls, heads, sectors, line);
+ r = guestfs_sfdisk_N (g, device, partnum, cyls, heads, sectors, line);
if (r == -1)
croak ("sfdisk_N: %s", guestfs_last_error (g));
@@ -2692,3 +2692,81 @@ PREINIT:
OUTPUT:
RETVAL
+void
+head (g, path)
+ guestfs_h *g;
+ char *path;
+PREINIT:
+ char **lines;
+ int i, n;
+ PPCODE:
+ lines = guestfs_head (g, path);
+ if (lines == NULL)
+ croak ("head: %s", guestfs_last_error (g));
+ for (n = 0; lines[n] != NULL; ++n) /**/;
+ EXTEND (SP, n);
+ for (i = 0; i < n; ++i) {
+ PUSHs (sv_2mortal (newSVpv (lines[i], 0)));
+ free (lines[i]);
+ }
+ free (lines);
+
+void
+head_n (g, nrlines, path)
+ guestfs_h *g;
+ int nrlines;
+ char *path;
+PREINIT:
+ char **lines;
+ int i, n;
+ PPCODE:
+ lines = guestfs_head_n (g, nrlines, path);
+ if (lines == NULL)
+ croak ("head_n: %s", guestfs_last_error (g));
+ for (n = 0; lines[n] != NULL; ++n) /**/;
+ EXTEND (SP, n);
+ for (i = 0; i < n; ++i) {
+ PUSHs (sv_2mortal (newSVpv (lines[i], 0)));
+ free (lines[i]);
+ }
+ free (lines);
+
+void
+tail (g, path)
+ guestfs_h *g;
+ char *path;
+PREINIT:
+ char **lines;
+ int i, n;
+ PPCODE:
+ lines = guestfs_tail (g, path);
+ if (lines == NULL)
+ croak ("tail: %s", guestfs_last_error (g));
+ for (n = 0; lines[n] != NULL; ++n) /**/;
+ EXTEND (SP, n);
+ for (i = 0; i < n; ++i) {
+ PUSHs (sv_2mortal (newSVpv (lines[i], 0)));
+ free (lines[i]);
+ }
+ free (lines);
+
+void
+tail_n (g, nrlines, path)
+ guestfs_h *g;
+ int nrlines;
+ char *path;
+PREINIT:
+ char **lines;
+ int i, n;
+ PPCODE:
+ lines = guestfs_tail_n (g, nrlines, path);
+ if (lines == NULL)
+ croak ("tail_n: %s", guestfs_last_error (g));
+ for (n = 0; lines[n] != NULL; ++n) /**/;
+ EXTEND (SP, n);
+ for (i = 0; i < n; ++i) {
+ PUSHs (sv_2mortal (newSVpv (lines[i], 0)));
+ free (lines[i]);
+ }
+ free (lines);
+
diff --git a/perl/lib/Sys/Guestfs.pm b/perl/lib/Sys/Guestfs.pm
index 8871b68e..3d15738a 100644
--- a/perl/lib/Sys/Guestfs.pm
+++ b/perl/lib/Sys/Guestfs.pm
@@ -694,6 +694,29 @@ See that manual page for more details.
This command installs GRUB (the Grand Unified Bootloader) on
C<device>, with the root directory being C<root>.
+=item @lines = $h->head ($path);
+
+This command returns up to the first 10 lines of a file as
+a list of strings.
+
+Because of the message protocol, there is a transfer limit
+of somewhere between 2MB and 4MB. To transfer large files you should use
+FTP.
+
+=item @lines = $h->head_n ($nrlines, $path);
+
+If the parameter C<nrlines> is a positive number, this returns the first
+C<nrlines> lines of the file C<path>.
+
+If the parameter C<nrlines> is a negative number, this returns lines
+from the file C<path>, excluding the last C<nrlines> lines.
+
+If the parameter C<nrlines> is zero, this returns an empty list.
+
+Because of the message protocol, there is a transfer limit
+of somewhere between 2MB and 4MB. To transfer large files you should use
+FTP.
+
=item $dump = $h->hexdump ($path);
This runs C<hexdump -C> on the given C<path>. The result is
@@ -1161,7 +1184,7 @@ See also: C<$h-E<gt>sfdisk_l>, C<$h-E<gt>sfdisk_N>
B<This command is dangerous. Without careful use you
can easily destroy all your data>.
-=item $h->sfdisk_N ($device, $n, $cyls, $heads, $sectors, $line);
+=item $h->sfdisk_N ($device, $partnum, $cyls, $heads, $sectors, $line);
This runs L<sfdisk(8)> option to modify just the single
partition C<n> (note: C<n> counts from 1).
@@ -1268,6 +1291,29 @@ underlying disk image.
You should always call this if you have modified a disk image, before
closing the handle.
+=item @lines = $h->tail ($path);
+
+This command returns up to the last 10 lines of a file as
+a list of strings.
+
+Because of the message protocol, there is a transfer limit
+of somewhere between 2MB and 4MB. To transfer large files you should use
+FTP.
+
+=item @lines = $h->tail_n ($nrlines, $path);
+
+If the parameter C<nrlines> is a positive number, this returns the last
+C<nrlines> lines of the file C<path>.
+
+If the parameter C<nrlines> is a negative number, this returns lines
+from the file C<path>, starting with the C<-nrlines>th line.
+
+If the parameter C<nrlines> is zero, this returns an empty list.
+
+Because of the message protocol, there is a transfer limit
+of somewhere between 2MB and 4MB. To transfer large files you should use
+FTP.
+
=item $h->tar_in ($tarfile, $directory);
This command uploads and unpacks local file C<tarfile> (an
diff --git a/python/guestfs-py.c b/python/guestfs-py.c
index 07f3c460..7d28af43 100644
--- a/python/guestfs-py.c
+++ b/python/guestfs-py.c
@@ -4153,18 +4153,18 @@ py_guestfs_sfdisk_N (PyObject *self, PyObject *args)
PyObject *py_r;
int r;
const char *device;
- int n;
+ int partnum;
int cyls;
int heads;
int sectors;
const char *line;
if (!PyArg_ParseTuple (args, (char *) "Osiiiis:guestfs_sfdisk_N",
- &py_g, &device, &n, &cyls, &heads, &sectors, &line))
+ &py_g, &device, &partnum, &cyls, &heads, &sectors, &line))
return NULL;
g = get_handle (py_g);
- r = guestfs_sfdisk_N (g, device, n, cyls, heads, sectors, line);
+ r = guestfs_sfdisk_N (g, device, partnum, cyls, heads, sectors, line);
if (r == -1) {
PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
return NULL;
@@ -4703,6 +4703,108 @@ py_guestfs_wc_c (PyObject *self, PyObject *args)
return py_r;
}
+static PyObject *
+py_guestfs_head (PyObject *self, PyObject *args)
+{
+ PyObject *py_g;
+ guestfs_h *g;
+ PyObject *py_r;
+ char **r;
+ const char *path;
+
+ if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_head",
+ &py_g, &path))
+ return NULL;
+ g = get_handle (py_g);
+
+ r = guestfs_head (g, path);
+ if (r == NULL) {
+ PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+ return NULL;
+ }
+
+ py_r = put_string_list (r);
+ free_strings (r);
+ return py_r;
+}
+
+static PyObject *
+py_guestfs_head_n (PyObject *self, PyObject *args)
+{
+ PyObject *py_g;
+ guestfs_h *g;
+ PyObject *py_r;
+ char **r;
+ int nrlines;
+ const char *path;
+
+ if (!PyArg_ParseTuple (args, (char *) "Ois:guestfs_head_n",
+ &py_g, &nrlines, &path))
+ return NULL;
+ g = get_handle (py_g);
+
+ r = guestfs_head_n (g, nrlines, path);
+ if (r == NULL) {
+ PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+ return NULL;
+ }
+
+ py_r = put_string_list (r);
+ free_strings (r);
+ return py_r;
+}
+
+static PyObject *
+py_guestfs_tail (PyObject *self, PyObject *args)
+{
+ PyObject *py_g;
+ guestfs_h *g;
+ PyObject *py_r;
+ char **r;
+ const char *path;
+
+ if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_tail",
+ &py_g, &path))
+ return NULL;
+ g = get_handle (py_g);
+
+ r = guestfs_tail (g, path);
+ if (r == NULL) {
+ PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+ return NULL;
+ }
+
+ py_r = put_string_list (r);
+ free_strings (r);
+ return py_r;
+}
+
+static PyObject *
+py_guestfs_tail_n (PyObject *self, PyObject *args)
+{
+ PyObject *py_g;
+ guestfs_h *g;
+ PyObject *py_r;
+ char **r;
+ int nrlines;
+ const char *path;
+
+ if (!PyArg_ParseTuple (args, (char *) "Ois:guestfs_tail_n",
+ &py_g, &nrlines, &path))
+ return NULL;
+ g = get_handle (py_g);
+
+ r = guestfs_tail_n (g, nrlines, path);
+ if (r == NULL) {
+ PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));
+ return NULL;
+ }
+
+ py_r = put_string_list (r);
+ free_strings (r);
+ return py_r;
+}
+
static PyMethodDef methods[] = {
{ (char *) "create", py_guestfs_create, METH_VARARGS, NULL },
{ (char *) "close", py_guestfs_close, METH_VARARGS, NULL },
@@ -4878,6 +4980,10 @@ static PyMethodDef methods[] = {
{ (char *) "wc_l", py_guestfs_wc_l, METH_VARARGS, NULL },
{ (char *) "wc_w", py_guestfs_wc_w, METH_VARARGS, NULL },
{ (char *) "wc_c", py_guestfs_wc_c, METH_VARARGS, NULL },
+ { (char *) "head", py_guestfs_head, METH_VARARGS, NULL },
+ { (char *) "head_n", py_guestfs_head_n, METH_VARARGS, NULL },
+ { (char *) "tail", py_guestfs_tail, METH_VARARGS, NULL },
+ { (char *) "tail_n", py_guestfs_tail_n, METH_VARARGS, NULL },
{ NULL, NULL, 0, NULL }
};
diff --git a/python/guestfs.py b/python/guestfs.py
index 01318ce1..30728be5 100644
--- a/python/guestfs.py
+++ b/python/guestfs.py
@@ -1478,7 +1478,7 @@ class GuestFS:
"""
return libguestfsmod.pvresize (self._o, device)
- def sfdisk_N (self, device, n, cyls, heads, sectors, line):
+ def sfdisk_N (self, device, partnum, cyls, heads, sectors, line):
u"""This runs sfdisk(8) option to modify just the single
partition "n" (note: "n" counts from 1).
@@ -1488,7 +1488,7 @@ class GuestFS:
This command is dangerous. Without careful use you can
easily destroy all your data.
"""
- return libguestfsmod.sfdisk_N (self._o, device, n, cyls, heads, sectors, line)
+ return libguestfsmod.sfdisk_N (self._o, device, partnum, cyls, heads, sectors, line)
def sfdisk_l (self, device):
u"""This displays the partition table on "device", in the
@@ -1745,3 +1745,65 @@ class GuestFS:
"""
return libguestfsmod.wc_c (self._o, path)
+ def head (self, path):
+ u"""This command returns up to the first 10 lines of a file
+ as a list of strings.
+
+ This function returns a list of strings.
+
+ Because of the message protocol, there is a transfer
+ limit of somewhere between 2MB and 4MB. To transfer
+ large files you should use FTP.
+ """
+ return libguestfsmod.head (self._o, path)
+
+ def head_n (self, nrlines, path):
+ u"""If the parameter "nrlines" is a positive number, this
+ returns the first "nrlines" lines of the file "path".
+
+ If the parameter "nrlines" is a negative number, this
+ returns lines from the file "path", excluding the last
+ "nrlines" lines.
+
+ If the parameter "nrlines" is zero, this returns an
+ empty list.
+
+ This function returns a list of strings.
+
+ Because of the message protocol, there is a transfer
+ limit of somewhere between 2MB and 4MB. To transfer
+ large files you should use FTP.
+ """
+ return libguestfsmod.head_n (self._o, nrlines, path)
+
+ def tail (self, path):
+ u"""This command returns up to the last 10 lines of a file
+ as a list of strings.
+
+ This function returns a list of strings.
+
+ Because of the message protocol, there is a transfer
+ limit of somewhere between 2MB and 4MB. To transfer
+ large files you should use FTP.
+ """
+ return libguestfsmod.tail (self._o, path)
+
+ def tail_n (self, nrlines, path):
+ u"""If the parameter "nrlines" is a positive number, this
+ returns the last "nrlines" lines of the file "path".
+
+ If the parameter "nrlines" is a negative number, this
+ returns lines from the file "path", starting with the
+ "-nrlines"th line.
+
+ If the parameter "nrlines" is zero, this returns an
+ empty list.
+
+ This function returns a list of strings.
+
+ Because of the message protocol, there is a transfer
+ limit of somewhere between 2MB and 4MB. To transfer
+ large files you should use FTP.
+ """
+ return libguestfsmod.tail_n (self._o, nrlines, path)
+
diff --git a/ruby/ext/guestfs/_guestfs.c b/ruby/ext/guestfs/_guestfs.c
index 00736bc0..a48ecabb 100644
--- a/ruby/ext/guestfs/_guestfs.c
+++ b/ruby/ext/guestfs/_guestfs.c
@@ -3869,7 +3869,7 @@ static VALUE ruby_guestfs_pvresize (VALUE gv, VALUE devicev)
return Qnil;
}
-static VALUE ruby_guestfs_sfdisk_N (VALUE gv, VALUE devicev, VALUE nv, VALUE cylsv, VALUE headsv, VALUE sectorsv, VALUE linev)
+static VALUE ruby_guestfs_sfdisk_N (VALUE gv, VALUE devicev, VALUE partnumv, VALUE cylsv, VALUE headsv, VALUE sectorsv, VALUE linev)
{
guestfs_h *g;
Data_Get_Struct (gv, guestfs_h, g);
@@ -3881,7 +3881,7 @@ static VALUE ruby_guestfs_sfdisk_N (VALUE gv, VALUE devicev, VALUE nv, VALUE cyl
if (!device)
rb_raise (rb_eTypeError, "expected string for parameter %s of %s",
"device", "sfdisk_N");
- int n = NUM2INT (nv);
+ int partnum = NUM2INT (partnumv);
int cyls = NUM2INT (cylsv);
int heads = NUM2INT (headsv);
int sectors = NUM2INT (sectorsv);
@@ -3893,7 +3893,7 @@ static VALUE ruby_guestfs_sfdisk_N (VALUE gv, VALUE devicev, VALUE nv, VALUE cyl
int r;
- r = guestfs_sfdisk_N (g, device, n, cyls, heads, sectors, line);
+ r = guestfs_sfdisk_N (g, device, partnum, cyls, heads, sectors, line);
if (r == -1)
rb_raise (e_Error, "%s", guestfs_last_error (g));
@@ -4399,6 +4399,128 @@ static VALUE ruby_guestfs_wc_c (VALUE gv, VALUE pathv)
return INT2NUM (r);
}
+static VALUE ruby_guestfs_head (VALUE gv, VALUE pathv)
+{
+ guestfs_h *g;
+ Data_Get_Struct (gv, guestfs_h, g);
+ if (!g)
+ rb_raise (rb_eArgError, "%s: used handle after closing it", "head");
+
+ Check_Type (pathv, T_STRING);
+ const char *path = StringValueCStr (pathv);
+ if (!path)
+ rb_raise (rb_eTypeError, "expected string for parameter %s of %s",
+ "path", "head");
+
+ char **r;
+
+ r = guestfs_head (g, path);
+ if (r == NULL)
+ rb_raise (e_Error, "%s", guestfs_last_error (g));
+
+ int i, len = 0;
+ for (i = 0; r[i] != NULL; ++i) len++;
+ VALUE rv = rb_ary_new2 (len);
+ for (i = 0; r[i] != NULL; ++i) {
+ rb_ary_push (rv, rb_str_new2 (r[i]));
+ free (r[i]);
+ }
+ free (r);
+ return rv;
+}
+
+static VALUE ruby_guestfs_head_n (VALUE gv, VALUE nrlinesv, VALUE pathv)
+{
+ guestfs_h *g;
+ Data_Get_Struct (gv, guestfs_h, g);
+ if (!g)
+ rb_raise (rb_eArgError, "%s: used handle after closing it", "head_n");
+
+ int nrlines = NUM2INT (nrlinesv);
+ Check_Type (pathv, T_STRING);
+ const char *path = StringValueCStr (pathv);
+ if (!path)
+ rb_raise (rb_eTypeError, "expected string for parameter %s of %s",
+ "path", "head_n");
+
+ char **r;
+
+ r = guestfs_head_n (g, nrlines, path);
+ if (r == NULL)
+ rb_raise (e_Error, "%s", guestfs_last_error (g));
+
+ int i, len = 0;
+ for (i = 0; r[i] != NULL; ++i) len++;
+ VALUE rv = rb_ary_new2 (len);
+ for (i = 0; r[i] != NULL; ++i) {
+ rb_ary_push (rv, rb_str_new2 (r[i]));
+ free (r[i]);
+ }
+ free (r);
+ return rv;
+}
+
+static VALUE ruby_guestfs_tail (VALUE gv, VALUE pathv)
+{
+ guestfs_h *g;
+ Data_Get_Struct (gv, guestfs_h, g);
+ if (!g)
+ rb_raise (rb_eArgError, "%s: used handle after closing it", "tail");
+
+ Check_Type (pathv, T_STRING);
+ const char *path = StringValueCStr (pathv);
+ if (!path)
+ rb_raise (rb_eTypeError, "expected string for parameter %s of %s",
+ "path", "tail");
+
+ char **r;
+
+ r = guestfs_tail (g, path);
+ if (r == NULL)
+ rb_raise (e_Error, "%s", guestfs_last_error (g));
+
+ int i, len = 0;
+ for (i = 0; r[i] != NULL; ++i) len++;
+ VALUE rv = rb_ary_new2 (len);
+ for (i = 0; r[i] != NULL; ++i) {
+ rb_ary_push (rv, rb_str_new2 (r[i]));
+ free (r[i]);
+ }
+ free (r);
+ return rv;
+}
+
+static VALUE ruby_guestfs_tail_n (VALUE gv, VALUE nrlinesv, VALUE pathv)
+{
+ guestfs_h *g;
+ Data_Get_Struct (gv, guestfs_h, g);
+ if (!g)
+ rb_raise (rb_eArgError, "%s: used handle after closing it", "tail_n");
+
+ int nrlines = NUM2INT (nrlinesv);
+ Check_Type (pathv, T_STRING);
+ const char *path = StringValueCStr (pathv);
+ if (!path)
+ rb_raise (rb_eTypeError, "expected string for parameter %s of %s",
+ "path", "tail_n");
+
+ char **r;
+
+ r = guestfs_tail_n (g, nrlines, path);
+ if (r == NULL)
+ rb_raise (e_Error, "%s", guestfs_last_error (g));
+
+ int i, len = 0;
+ for (i = 0; r[i] != NULL; ++i) len++;
+ VALUE rv = rb_ary_new2 (len);
+ for (i = 0; r[i] != NULL; ++i) {
+ rb_ary_push (rv, rb_str_new2 (r[i]));
+ free (r[i]);
+ }
+ free (r);
+ return rv;
+}
+
/* Initialize the module. */
void Init__guestfs ()
{
@@ -4753,4 +4875,12 @@ void Init__guestfs ()
ruby_guestfs_wc_w, 1);
rb_define_method (c_guestfs, "wc_c",
ruby_guestfs_wc_c, 1);
+ rb_define_method (c_guestfs, "head",
+ ruby_guestfs_head, 1);
+ rb_define_method (c_guestfs, "head_n",
+ ruby_guestfs_head_n, 2);
+ rb_define_method (c_guestfs, "tail",
+ ruby_guestfs_tail, 1);
+ rb_define_method (c_guestfs, "tail_n",
+ ruby_guestfs_tail_n, 2);
}
diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR
index 52bd8e43..fc902f4f 100644
--- a/src/MAX_PROC_NR
+++ b/src/MAX_PROC_NR
@@ -1 +1 @@
-120
+124
diff --git a/src/guestfs-actions.c b/src/guestfs-actions.c
index ce4cfe1e..4a38b453 100644
--- a/src/guestfs-actions.c
+++ b/src/guestfs-actions.c
@@ -9024,7 +9024,7 @@ static void sfdisk_N_reply_cb (guestfs_h *g, void *data, XDR *xdr)
int guestfs_sfdisk_N (guestfs_h *g,
const char *device,
- int n,
+ int partnum,
int cyls,
int heads,
int sectors,
@@ -9041,7 +9041,7 @@ int guestfs_sfdisk_N (guestfs_h *g,
memset (&ctx, 0, sizeof ctx);
args.device = (char *) device;
- args.n = n;
+ args.partnum = partnum;
args.cyls = cyls;
args.heads = heads;
args.sectors = sectors;
@@ -10989,3 +10989,395 @@ int guestfs_wc_c (guestfs_h *g,
return ctx.ret.chars;
}
+struct head_ctx {
+ /* This flag is set by the callbacks, so we know we've done
+ * the callbacks as expected, and in the right sequence.
+ * 0 = not called, 1 = reply_cb called.
+ */
+ int cb_sequence;
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+ struct guestfs_head_ret ret;
+};
+
+static void head_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ struct head_ctx *ctx = (struct head_ctx *) data;
+
+ /* This should definitely not happen. */
+ if (ctx->cb_sequence != 0) {
+ ctx->cb_sequence = 9999;
+ error (g, "%s: internal error: reply callback called twice", "guestfs_head");
+ return;
+ }
+
+ ml->main_loop_quit (ml, g);
+
+ if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+ error (g, "%s: failed to parse reply header", "guestfs_head");
+ return;
+ }
+ if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+ error (g, "%s: failed to parse reply error", "guestfs_head");
+ return;
+ }
+ goto done;
+ }
+ if (!xdr_guestfs_head_ret (xdr, &ctx->ret)) {
+ error (g, "%s: failed to parse reply", "guestfs_head");
+ return;
+ }
+ done:
+ ctx->cb_sequence = 1;
+}
+
+char **guestfs_head (guestfs_h *g,
+ const char *path)
+{
+ struct guestfs_head_args args;
+ struct head_ctx ctx;
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ int serial;
+
+ if (check_state (g, "guestfs_head") == -1) return NULL;
+ guestfs_set_busy (g);
+
+ memset (&ctx, 0, sizeof ctx);
+
+ args.path = (char *) path;
+ serial = guestfs__send_sync (g, GUESTFS_PROC_HEAD,
+ (xdrproc_t) xdr_guestfs_head_args, (char *) &args);
+ if (serial == -1) {
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ guestfs__switch_to_receiving (g);
+ ctx.cb_sequence = 0;
+ guestfs_set_reply_callback (g, head_reply_cb, &ctx);
+ (void) ml->main_loop_run (ml, g);
+ guestfs_set_reply_callback (g, NULL, NULL);
+ if (ctx.cb_sequence != 1) {
+ error (g, "%s reply failed, see earlier error messages", "guestfs_head");
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_HEAD, serial) == -1) {
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", ctx.err.error_message);
+ free (ctx.err.error_message);
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ guestfs_end_busy (g);
+ /* caller will free this, but we need to add a NULL entry */
+ ctx.ret.lines.lines_val =
+ safe_realloc (g, ctx.ret.lines.lines_val,
+ sizeof (char *) * (ctx.ret.lines.lines_len + 1));
+ ctx.ret.lines.lines_val[ctx.ret.lines.lines_len] = NULL;
+ return ctx.ret.lines.lines_val;
+}
+
+struct head_n_ctx {
+ /* This flag is set by the callbacks, so we know we've done
+ * the callbacks as expected, and in the right sequence.
+ * 0 = not called, 1 = reply_cb called.
+ */
+ int cb_sequence;
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+ struct guestfs_head_n_ret ret;
+};
+
+static void head_n_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ struct head_n_ctx *ctx = (struct head_n_ctx *) data;
+
+ /* This should definitely not happen. */
+ if (ctx->cb_sequence != 0) {
+ ctx->cb_sequence = 9999;
+ error (g, "%s: internal error: reply callback called twice", "guestfs_head_n");
+ return;
+ }
+
+ ml->main_loop_quit (ml, g);
+
+ if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+ error (g, "%s: failed to parse reply header", "guestfs_head_n");
+ return;
+ }
+ if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+ error (g, "%s: failed to parse reply error", "guestfs_head_n");
+ return;
+ }
+ goto done;
+ }
+ if (!xdr_guestfs_head_n_ret (xdr, &ctx->ret)) {
+ error (g, "%s: failed to parse reply", "guestfs_head_n");
+ return;
+ }
+ done:
+ ctx->cb_sequence = 1;
+}
+
+char **guestfs_head_n (guestfs_h *g,
+ int nrlines,
+ const char *path)
+{
+ struct guestfs_head_n_args args;
+ struct head_n_ctx ctx;
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ int serial;
+
+ if (check_state (g, "guestfs_head_n") == -1) return NULL;
+ guestfs_set_busy (g);
+
+ memset (&ctx, 0, sizeof ctx);
+
+ args.nrlines = nrlines;
+ args.path = (char *) path;
+ serial = guestfs__send_sync (g, GUESTFS_PROC_HEAD_N,
+ (xdrproc_t) xdr_guestfs_head_n_args, (char *) &args);
+ if (serial == -1) {
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ guestfs__switch_to_receiving (g);
+ ctx.cb_sequence = 0;
+ guestfs_set_reply_callback (g, head_n_reply_cb, &ctx);
+ (void) ml->main_loop_run (ml, g);
+ guestfs_set_reply_callback (g, NULL, NULL);
+ if (ctx.cb_sequence != 1) {
+ error (g, "%s reply failed, see earlier error messages", "guestfs_head_n");
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_HEAD_N, serial) == -1) {
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", ctx.err.error_message);
+ free (ctx.err.error_message);
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ guestfs_end_busy (g);
+ /* caller will free this, but we need to add a NULL entry */
+ ctx.ret.lines.lines_val =
+ safe_realloc (g, ctx.ret.lines.lines_val,
+ sizeof (char *) * (ctx.ret.lines.lines_len + 1));
+ ctx.ret.lines.lines_val[ctx.ret.lines.lines_len] = NULL;
+ return ctx.ret.lines.lines_val;
+}
+
+struct tail_ctx {
+ /* This flag is set by the callbacks, so we know we've done
+ * the callbacks as expected, and in the right sequence.
+ * 0 = not called, 1 = reply_cb called.
+ */
+ int cb_sequence;
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+ struct guestfs_tail_ret ret;
+};
+
+static void tail_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ struct tail_ctx *ctx = (struct tail_ctx *) data;
+
+ /* This should definitely not happen. */
+ if (ctx->cb_sequence != 0) {
+ ctx->cb_sequence = 9999;
+ error (g, "%s: internal error: reply callback called twice", "guestfs_tail");
+ return;
+ }
+
+ ml->main_loop_quit (ml, g);
+
+ if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+ error (g, "%s: failed to parse reply header", "guestfs_tail");
+ return;
+ }
+ if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+ error (g, "%s: failed to parse reply error", "guestfs_tail");
+ return;
+ }
+ goto done;
+ }
+ if (!xdr_guestfs_tail_ret (xdr, &ctx->ret)) {
+ error (g, "%s: failed to parse reply", "guestfs_tail");
+ return;
+ }
+ done:
+ ctx->cb_sequence = 1;
+}
+
+char **guestfs_tail (guestfs_h *g,
+ const char *path)
+{
+ struct guestfs_tail_args args;
+ struct tail_ctx ctx;
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ int serial;
+
+ if (check_state (g, "guestfs_tail") == -1) return NULL;
+ guestfs_set_busy (g);
+
+ memset (&ctx, 0, sizeof ctx);
+
+ args.path = (char *) path;
+ serial = guestfs__send_sync (g, GUESTFS_PROC_TAIL,
+ (xdrproc_t) xdr_guestfs_tail_args, (char *) &args);
+ if (serial == -1) {
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ guestfs__switch_to_receiving (g);
+ ctx.cb_sequence = 0;
+ guestfs_set_reply_callback (g, tail_reply_cb, &ctx);
+ (void) ml->main_loop_run (ml, g);
+ guestfs_set_reply_callback (g, NULL, NULL);
+ if (ctx.cb_sequence != 1) {
+ error (g, "%s reply failed, see earlier error messages", "guestfs_tail");
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_TAIL, serial) == -1) {
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", ctx.err.error_message);
+ free (ctx.err.error_message);
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ guestfs_end_busy (g);
+ /* caller will free this, but we need to add a NULL entry */
+ ctx.ret.lines.lines_val =
+ safe_realloc (g, ctx.ret.lines.lines_val,
+ sizeof (char *) * (ctx.ret.lines.lines_len + 1));
+ ctx.ret.lines.lines_val[ctx.ret.lines.lines_len] = NULL;
+ return ctx.ret.lines.lines_val;
+}
+
+struct tail_n_ctx {
+ /* This flag is set by the callbacks, so we know we've done
+ * the callbacks as expected, and in the right sequence.
+ * 0 = not called, 1 = reply_cb called.
+ */
+ int cb_sequence;
+ struct guestfs_message_header hdr;
+ struct guestfs_message_error err;
+ struct guestfs_tail_n_ret ret;
+};
+
+static void tail_n_reply_cb (guestfs_h *g, void *data, XDR *xdr)
+{
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ struct tail_n_ctx *ctx = (struct tail_n_ctx *) data;
+
+ /* This should definitely not happen. */
+ if (ctx->cb_sequence != 0) {
+ ctx->cb_sequence = 9999;
+ error (g, "%s: internal error: reply callback called twice", "guestfs_tail_n");
+ return;
+ }
+
+ ml->main_loop_quit (ml, g);
+
+ if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {
+ error (g, "%s: failed to parse reply header", "guestfs_tail_n");
+ return;
+ }
+ if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {
+ if (!xdr_guestfs_message_error (xdr, &ctx->err)) {
+ error (g, "%s: failed to parse reply error", "guestfs_tail_n");
+ return;
+ }
+ goto done;
+ }
+ if (!xdr_guestfs_tail_n_ret (xdr, &ctx->ret)) {
+ error (g, "%s: failed to parse reply", "guestfs_tail_n");
+ return;
+ }
+ done:
+ ctx->cb_sequence = 1;
+}
+
+char **guestfs_tail_n (guestfs_h *g,
+ int nrlines,
+ const char *path)
+{
+ struct guestfs_tail_n_args args;
+ struct tail_n_ctx ctx;
+ guestfs_main_loop *ml = guestfs_get_main_loop (g);
+ int serial;
+
+ if (check_state (g, "guestfs_tail_n") == -1) return NULL;
+ guestfs_set_busy (g);
+
+ memset (&ctx, 0, sizeof ctx);
+
+ args.nrlines = nrlines;
+ args.path = (char *) path;
+ serial = guestfs__send_sync (g, GUESTFS_PROC_TAIL_N,
+ (xdrproc_t) xdr_guestfs_tail_n_args, (char *) &args);
+ if (serial == -1) {
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ guestfs__switch_to_receiving (g);
+ ctx.cb_sequence = 0;
+ guestfs_set_reply_callback (g, tail_n_reply_cb, &ctx);
+ (void) ml->main_loop_run (ml, g);
+ guestfs_set_reply_callback (g, NULL, NULL);
+ if (ctx.cb_sequence != 1) {
+ error (g, "%s reply failed, see earlier error messages", "guestfs_tail_n");
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_TAIL_N, serial) == -1) {
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {
+ error (g, "%s", ctx.err.error_message);
+ free (ctx.err.error_message);
+ guestfs_end_busy (g);
+ return NULL;
+ }
+
+ guestfs_end_busy (g);
+ /* caller will free this, but we need to add a NULL entry */
+ ctx.ret.lines.lines_val =
+ safe_realloc (g, ctx.ret.lines.lines_val,
+ sizeof (char *) * (ctx.ret.lines.lines_len + 1));
+ ctx.ret.lines.lines_val[ctx.ret.lines.lines_len] = NULL;
+ return ctx.ret.lines.lines_val;
+}
+
diff --git a/src/guestfs-actions.h b/src/guestfs-actions.h
index cbdf0fbf..42951cbc 100644
--- a/src/guestfs-actions.h
+++ b/src/guestfs-actions.h
@@ -169,7 +169,7 @@ extern char **guestfs_strings_e (guestfs_h *handle, const char *encoding, const
extern char *guestfs_hexdump (guestfs_h *handle, const char *path);
extern int guestfs_zerofree (guestfs_h *handle, const char *device);
extern int guestfs_pvresize (guestfs_h *handle, const char *device);
-extern int guestfs_sfdisk_N (guestfs_h *handle, const char *device, int n, int cyls, int heads, int sectors, const char *line);
+extern int guestfs_sfdisk_N (guestfs_h *handle, const char *device, int partnum, int cyls, int heads, int sectors, const char *line);
extern char *guestfs_sfdisk_l (guestfs_h *handle, const char *device);
extern char *guestfs_sfdisk_kernel_geometry (guestfs_h *handle, const char *device);
extern char *guestfs_sfdisk_disk_geometry (guestfs_h *handle, const char *device);
@@ -191,3 +191,7 @@ extern char *guestfs_mkdtemp (guestfs_h *handle, const char *template);
extern int guestfs_wc_l (guestfs_h *handle, const char *path);
extern int guestfs_wc_w (guestfs_h *handle, const char *path);
extern int guestfs_wc_c (guestfs_h *handle, const char *path);
+extern char **guestfs_head (guestfs_h *handle, const char *path);
+extern char **guestfs_head_n (guestfs_h *handle, int nrlines, const char *path);
+extern char **guestfs_tail (guestfs_h *handle, const char *path);
+extern char **guestfs_tail_n (guestfs_h *handle, int nrlines, const char *path);
diff --git a/src/guestfs_protocol.c b/src/guestfs_protocol.c
index bdcc2042..3f08084d 100644
--- a/src/guestfs_protocol.c
+++ b/src/guestfs_protocol.c
@@ -1644,7 +1644,7 @@ xdr_guestfs_sfdisk_N_args (XDR *xdrs, guestfs_sfdisk_N_args *objp)
return FALSE;
buf = XDR_INLINE (xdrs, 4 * BYTES_PER_XDR_UNIT);
if (buf == NULL) {
- if (!xdr_int (xdrs, &objp->n))
+ if (!xdr_int (xdrs, &objp->partnum))
return FALSE;
if (!xdr_int (xdrs, &objp->cyls))
return FALSE;
@@ -1654,7 +1654,7 @@ xdr_guestfs_sfdisk_N_args (XDR *xdrs, guestfs_sfdisk_N_args *objp)
return FALSE;
} else {
- IXDR_PUT_LONG(buf, objp->n);
+ IXDR_PUT_LONG(buf, objp->partnum);
IXDR_PUT_LONG(buf, objp->cyls);
IXDR_PUT_LONG(buf, objp->heads);
IXDR_PUT_LONG(buf, objp->sectors);
@@ -1667,7 +1667,7 @@ xdr_guestfs_sfdisk_N_args (XDR *xdrs, guestfs_sfdisk_N_args *objp)
return FALSE;
buf = XDR_INLINE (xdrs, 4 * BYTES_PER_XDR_UNIT);
if (buf == NULL) {
- if (!xdr_int (xdrs, &objp->n))
+ if (!xdr_int (xdrs, &objp->partnum))
return FALSE;
if (!xdr_int (xdrs, &objp->cyls))
return FALSE;
@@ -1677,7 +1677,7 @@ xdr_guestfs_sfdisk_N_args (XDR *xdrs, guestfs_sfdisk_N_args *objp)
return FALSE;
} else {
- objp->n = IXDR_GET_LONG(buf);
+ objp->partnum = IXDR_GET_LONG(buf);
objp->cyls = IXDR_GET_LONG(buf);
objp->heads = IXDR_GET_LONG(buf);
objp->sectors = IXDR_GET_LONG(buf);
@@ -1689,7 +1689,7 @@ xdr_guestfs_sfdisk_N_args (XDR *xdrs, guestfs_sfdisk_N_args *objp)
if (!xdr_string (xdrs, &objp->device, ~0))
return FALSE;
- if (!xdr_int (xdrs, &objp->n))
+ if (!xdr_int (xdrs, &objp->partnum))
return FALSE;
if (!xdr_int (xdrs, &objp->cyls))
return FALSE;
@@ -2043,6 +2043,94 @@ xdr_guestfs_wc_c_ret (XDR *xdrs, guestfs_wc_c_ret *objp)
}
bool_t
+xdr_guestfs_head_args (XDR *xdrs, guestfs_head_args *objp)
+{
+ register int32_t *buf;
+
+ if (!xdr_string (xdrs, &objp->path, ~0))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_guestfs_head_ret (XDR *xdrs, guestfs_head_ret *objp)
+{
+ register int32_t *buf;
+
+ if (!xdr_array (xdrs, (char **)&objp->lines.lines_val, (u_int *) &objp->lines.lines_len, ~0,
+ sizeof (str), (xdrproc_t) xdr_str))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_guestfs_head_n_args (XDR *xdrs, guestfs_head_n_args *objp)
+{
+ register int32_t *buf;
+
+ if (!xdr_int (xdrs, &objp->nrlines))
+ return FALSE;
+ if (!xdr_string (xdrs, &objp->path, ~0))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_guestfs_head_n_ret (XDR *xdrs, guestfs_head_n_ret *objp)
+{
+ register int32_t *buf;
+
+ if (!xdr_array (xdrs, (char **)&objp->lines.lines_val, (u_int *) &objp->lines.lines_len, ~0,
+ sizeof (str), (xdrproc_t) xdr_str))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_guestfs_tail_args (XDR *xdrs, guestfs_tail_args *objp)
+{
+ register int32_t *buf;
+
+ if (!xdr_string (xdrs, &objp->path, ~0))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_guestfs_tail_ret (XDR *xdrs, guestfs_tail_ret *objp)
+{
+ register int32_t *buf;
+
+ if (!xdr_array (xdrs, (char **)&objp->lines.lines_val, (u_int *) &objp->lines.lines_len, ~0,
+ sizeof (str), (xdrproc_t) xdr_str))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_guestfs_tail_n_args (XDR *xdrs, guestfs_tail_n_args *objp)
+{
+ register int32_t *buf;
+
+ if (!xdr_int (xdrs, &objp->nrlines))
+ return FALSE;
+ if (!xdr_string (xdrs, &objp->path, ~0))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_guestfs_tail_n_ret (XDR *xdrs, guestfs_tail_n_ret *objp)
+{
+ register int32_t *buf;
+
+ if (!xdr_array (xdrs, (char **)&objp->lines.lines_val, (u_int *) &objp->lines.lines_len, ~0,
+ sizeof (str), (xdrproc_t) xdr_str))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
xdr_guestfs_procedure (XDR *xdrs, guestfs_procedure *objp)
{
register int32_t *buf;
diff --git a/src/guestfs_protocol.h b/src/guestfs_protocol.h
index 0c31e79e..7fe3a32a 100644
--- a/src/guestfs_protocol.h
+++ b/src/guestfs_protocol.h
@@ -849,7 +849,7 @@ typedef struct guestfs_pvresize_args guestfs_pvresize_args;
struct guestfs_sfdisk_N_args {
char *device;
- int n;
+ int partnum;
int cyls;
int heads;
int sectors;
@@ -1037,6 +1037,60 @@ struct guestfs_wc_c_ret {
};
typedef struct guestfs_wc_c_ret guestfs_wc_c_ret;
+struct guestfs_head_args {
+ char *path;
+};
+typedef struct guestfs_head_args guestfs_head_args;
+
+struct guestfs_head_ret {
+ struct {
+ u_int lines_len;
+ str *lines_val;
+ } lines;
+};
+typedef struct guestfs_head_ret guestfs_head_ret;
+
+struct guestfs_head_n_args {
+ int nrlines;
+ char *path;
+};
+typedef struct guestfs_head_n_args guestfs_head_n_args;
+
+struct guestfs_head_n_ret {
+ struct {
+ u_int lines_len;
+ str *lines_val;
+ } lines;
+};
+typedef struct guestfs_head_n_ret guestfs_head_n_ret;
+
+struct guestfs_tail_args {
+ char *path;
+};
+typedef struct guestfs_tail_args guestfs_tail_args;
+
+struct guestfs_tail_ret {
+ struct {
+ u_int lines_len;
+ str *lines_val;
+ } lines;
+};
+typedef struct guestfs_tail_ret guestfs_tail_ret;
+
+struct guestfs_tail_n_args {
+ int nrlines;
+ char *path;
+};
+typedef struct guestfs_tail_n_args guestfs_tail_n_args;
+
+struct guestfs_tail_n_ret {
+ struct {
+ u_int lines_len;
+ str *lines_val;
+ } lines;
+};
+typedef struct guestfs_tail_n_ret guestfs_tail_n_ret;
+
enum guestfs_procedure {
GUESTFS_PROC_MOUNT = 1,
GUESTFS_PROC_SYNC = 2,
@@ -1158,7 +1212,11 @@ enum guestfs_procedure {
GUESTFS_PROC_WC_L = 118,
GUESTFS_PROC_WC_W = 119,
GUESTFS_PROC_WC_C = 120,
- GUESTFS_PROC_NR_PROCS = 120 + 1,
+ GUESTFS_PROC_HEAD = 121,
+ GUESTFS_PROC_HEAD_N = 122,
+ GUESTFS_PROC_TAIL = 123,
+ GUESTFS_PROC_TAIL_N = 124,
+ GUESTFS_PROC_NR_PROCS = 124 + 1,
};
typedef enum guestfs_procedure guestfs_procedure;
#define GUESTFS_MESSAGE_MAX 4194304
@@ -1376,6 +1434,14 @@ extern bool_t xdr_guestfs_wc_w_args (XDR *, guestfs_wc_w_args*);
extern bool_t xdr_guestfs_wc_w_ret (XDR *, guestfs_wc_w_ret*);
extern bool_t xdr_guestfs_wc_c_args (XDR *, guestfs_wc_c_args*);
extern bool_t xdr_guestfs_wc_c_ret (XDR *, guestfs_wc_c_ret*);
+extern bool_t xdr_guestfs_head_args (XDR *, guestfs_head_args*);
+extern bool_t xdr_guestfs_head_ret (XDR *, guestfs_head_ret*);
+extern bool_t xdr_guestfs_head_n_args (XDR *, guestfs_head_n_args*);
+extern bool_t xdr_guestfs_head_n_ret (XDR *, guestfs_head_n_ret*);
+extern bool_t xdr_guestfs_tail_args (XDR *, guestfs_tail_args*);
+extern bool_t xdr_guestfs_tail_ret (XDR *, guestfs_tail_ret*);
+extern bool_t xdr_guestfs_tail_n_args (XDR *, guestfs_tail_n_args*);
+extern bool_t xdr_guestfs_tail_n_ret (XDR *, guestfs_tail_n_ret*);
extern bool_t xdr_guestfs_procedure (XDR *, guestfs_procedure*);
extern bool_t xdr_guestfs_message_direction (XDR *, guestfs_message_direction*);
extern bool_t xdr_guestfs_message_status (XDR *, guestfs_message_status*);
@@ -1552,6 +1618,14 @@ extern bool_t xdr_guestfs_wc_w_args ();
extern bool_t xdr_guestfs_wc_w_ret ();
extern bool_t xdr_guestfs_wc_c_args ();
extern bool_t xdr_guestfs_wc_c_ret ();
+extern bool_t xdr_guestfs_head_args ();
+extern bool_t xdr_guestfs_head_ret ();
+extern bool_t xdr_guestfs_head_n_args ();
+extern bool_t xdr_guestfs_head_n_ret ();
+extern bool_t xdr_guestfs_tail_args ();
+extern bool_t xdr_guestfs_tail_ret ();
+extern bool_t xdr_guestfs_tail_n_args ();
+extern bool_t xdr_guestfs_tail_n_ret ();
extern bool_t xdr_guestfs_procedure ();
extern bool_t xdr_guestfs_message_direction ();
extern bool_t xdr_guestfs_message_status ();
diff --git a/src/guestfs_protocol.x b/src/guestfs_protocol.x
index e0f106c0..fd8953f1 100644
--- a/src/guestfs_protocol.x
+++ b/src/guestfs_protocol.x
@@ -658,7 +658,7 @@ struct guestfs_pvresize_args {
struct guestfs_sfdisk_N_args {
string device<>;
- int n;
+ int partnum;
int cyls;
int heads;
int sectors;
@@ -800,6 +800,40 @@ struct guestfs_wc_c_ret {
int chars;
};
+struct guestfs_head_args {
+ string path<>;
+};
+
+struct guestfs_head_ret {
+ str lines<>;
+};
+
+struct guestfs_head_n_args {
+ int nrlines;
+ string path<>;
+};
+
+struct guestfs_head_n_ret {
+ str lines<>;
+};
+
+struct guestfs_tail_args {
+ string path<>;
+};
+
+struct guestfs_tail_ret {
+ str lines<>;
+};
+
+struct guestfs_tail_n_args {
+ int nrlines;
+ string path<>;
+};
+
+struct guestfs_tail_n_ret {
+ str lines<>;
+};
+
enum guestfs_procedure {
GUESTFS_PROC_MOUNT = 1,
GUESTFS_PROC_SYNC = 2,
@@ -921,6 +955,10 @@ enum guestfs_procedure {
GUESTFS_PROC_WC_L = 118,
GUESTFS_PROC_WC_W = 119,
GUESTFS_PROC_WC_C = 120,
+ GUESTFS_PROC_HEAD = 121,
+ GUESTFS_PROC_HEAD_N = 122,
+ GUESTFS_PROC_TAIL = 123,
+ GUESTFS_PROC_TAIL_N = 124,
GUESTFS_PROC_NR_PROCS
};