Generated code for head/tail commands.
authorRichard W.M. Jones <rjones@redhat.com>
Mon, 29 Jun 2009 10:47:07 +0000 (11:47 +0100)
committerRichard W.M. Jones <rjones@redhat.com>
Mon, 29 Jun 2009 10:47:07 +0000 (11:47 +0100)
25 files changed:
capitests/tests.c
daemon/actions.h
daemon/stubs.c
fish/cmds.c
fish/completion.c
guestfish-actions.pod
guestfs-actions.pod
haskell/Guestfs.hs
images/Makefile.am
java/com/redhat/et/libguestfs/GuestFS.java
java/com_redhat_et_libguestfs_GuestFS.c
ocaml/guestfs.ml
ocaml/guestfs.mli
ocaml/guestfs_c_actions.c
perl/Guestfs.xs
perl/lib/Sys/Guestfs.pm
python/guestfs-py.c
python/guestfs.py
ruby/ext/guestfs/_guestfs.c
src/MAX_PROC_NR
src/guestfs-actions.c
src/guestfs-actions.h
src/guestfs_protocol.c
src/guestfs_protocol.h
src/guestfs_protocol.x

index 0254437..7a30498 100644 (file)
@@ -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");
index 2de9aa2..8beeed6 100644 (file)
@@ -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);
index ab58473..170726c 100644 (file)
@@ -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);
   }
index 89fa1fb..9bd53ec 100644 (file)
@@ -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;
index f81e047..a2febb7 100644 (file)
@@ -187,6 +187,10 @@ static const char *const commands[] = {
   "wc-l",
   "wc-w",
   "wc-c",
+  "head",
+  "head-n",
+  "tail",
+  "tail-n",
   NULL
 };
 
index ee0b14d..d45c001 100644 (file)
@@ -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
index 530a413..68357d6 100644 (file)
@@ -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,
index 8101b52..dfa385a 100644 (file)
@@ -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
index 46488eb..71d63a8 100644 (file)
@@ -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 $@
index 64b0802..3091332 100644 (file)
@@ -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;
+
 }
index 3a16259..501e8d1 100644 (file)
@@ -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;
+}
+
index b84504e..c631024 100644 (file)
@@ -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"
index 4c1ef72..97180b0 100644 (file)
@@ -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 *)
+
index beb41d7..d8b0567 100644 (file)
@@ -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);
+}
+
index 1dc634f..bcd7304 100644 (file)
@@ -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);
+
index 8871b68..3d15738 100644 (file)
@@ -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
index 07f3c46..7d28af4 100644 (file)
@@ -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 }
 };
 
index 01318ce..30728be 100644 (file)
@@ -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)
+
index 00736bc..a48ecab 100644 (file)
@@ -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);
 }
index 52bd8e4..fc902f4 100644 (file)
@@ -1 +1 @@
-120
+124
index ce4cfe1..4a38b45 100644 (file)
@@ -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;
+}
+
index cbdf0fb..42951cb 100644 (file)
@@ -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);
index bdcc204..3f08084 100644 (file)
@@ -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;
index 0c31e79..7fe3a32 100644 (file)
@@ -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 ();
index e0f106c..fd8953f 100644 (file)
@@ -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
 };