New API: file-architecture
[libguestfs.git] / src / generator.ml
index 71421bc..77c7642 100755 (executable)
@@ -559,15 +559,13 @@ handle is closed.  We don't currently have any method to enable
 changes to be committed, although qemu can support this.
 
 This is equivalent to the qemu parameter
 changes to be committed, although qemu can support this.
 
 This is equivalent to the qemu parameter
-C<-drive file=filename,snapshot=on,readonly=on,if=...>.
+C<-drive file=filename,snapshot=on,if=...>.
 
 C<if=...> is set at compile time by the configuration option
 C<./configure --with-drive-if=...>.  In the rare case where you
 might need to change this at run time, use C<guestfs_add_drive_with_if>
 or C<guestfs_add_drive_ro_with_if>.
 
 
 C<if=...> is set at compile time by the configuration option
 C<./configure --with-drive-if=...>.  In the rare case where you
 might need to change this at run time, use C<guestfs_add_drive_with_if>
 or C<guestfs_add_drive_ro_with_if>.
 
-C<readonly=on> is only added where qemu supports this option.
-
 Note that this call checks for the existence of C<filename>.  This
 stops you from specifying other types of drive which are supported
 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
 Note that this call checks for the existence of C<filename>.  This
 stops you from specifying other types of drive which are supported
 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
@@ -858,7 +856,7 @@ see L<guestfs(3)>.");
    "enable or disable command traces",
    "\
 If the command trace flag is set to 1, then commands are
    "enable or disable command traces",
    "\
 If the command trace flag is set to 1, then commands are
-printed on stdout before they are executed in a format
+printed on stderr before they are executed in a format
 which is very similar to the one used by guestfish.  In
 other words, you can run a program with this enabled, and
 you will get out a script which you can feed to guestfish
 which is very similar to the one used by guestfish.  In
 other words, you can run a program with this enabled, and
 you will get out a script which you can feed to guestfish
@@ -942,6 +940,134 @@ to specify the QEMU interface emulation to use at run time.");
 This is the same as C<guestfs_add_drive_ro> but it allows you
 to specify the QEMU interface emulation to use at run time.");
 
 This is the same as C<guestfs_add_drive_ro> but it allows you
 to specify the QEMU interface emulation to use at run time.");
 
+  ("file_architecture", (RString "arch", [Pathname "filename"]), -1, [],
+   [InitISOFS, Always, TestOutput (
+      [["file_architecture"; "/bin-i586-dynamic"]], "i386");
+    InitISOFS, Always, TestOutput (
+      [["file_architecture"; "/bin-sparc-dynamic"]], "sparc");
+    InitISOFS, Always, TestOutput (
+      [["file_architecture"; "/bin-win32.exe"]], "i386");
+    InitISOFS, Always, TestOutput (
+      [["file_architecture"; "/bin-win64.exe"]], "x86_64");
+    InitISOFS, Always, TestOutput (
+      [["file_architecture"; "/bin-x86_64-dynamic"]], "x86_64");
+    InitISOFS, Always, TestOutput (
+      [["file_architecture"; "/lib-i586.so"]], "i386");
+    InitISOFS, Always, TestOutput (
+      [["file_architecture"; "/lib-sparc.so"]], "sparc");
+    InitISOFS, Always, TestOutput (
+      [["file_architecture"; "/lib-win32.dll"]], "i386");
+    InitISOFS, Always, TestOutput (
+      [["file_architecture"; "/lib-win64.dll"]], "x86_64");
+    InitISOFS, Always, TestOutput (
+      [["file_architecture"; "/lib-x86_64.so"]], "x86_64");
+    InitISOFS, Always, TestOutput (
+      [["file_architecture"; "/initrd-x86_64.img"]], "x86_64");
+    InitISOFS, Always, TestOutput (
+      [["file_architecture"; "/initrd-x86_64.img.gz"]], "x86_64");],
+   "detect the architecture of a binary file",
+   "\
+This detects the architecture of the binary C<filename>,
+and returns it if known.
+
+Currently defined architectures are:
+
+=over 4
+
+=item \"i386\"
+
+This string is returned for all 32 bit i386, i486, i586, i686 binaries
+irrespective of the precise processor requirements of the binary.
+
+=item \"x86_64\"
+
+64 bit x86-64.
+
+=item \"sparc\"
+
+32 bit SPARC.
+
+=item \"sparc64\"
+
+64 bit SPARC V9 and above.
+
+=item \"ia64\"
+
+Intel Itanium.
+
+=item \"ppc\"
+
+32 bit Power PC.
+
+=item \"ppc64\"
+
+64 bit Power PC.
+
+=back
+
+Libguestfs may return other architecture strings in future.
+
+The function works on at least the following types of files:
+
+=over 4
+
+=item *
+
+many types of Un*x and Linux binary
+
+=item *
+
+many types of Un*x and Linux shared library
+
+=item *
+
+Windows Win32 and Win64 binaries
+
+=item *
+
+Windows Win32 and Win64 DLLs
+
+Win32 binaries and DLLs return C<i386>.
+
+Win64 binaries and DLLs return C<x86_64>.
+
+=item *
+
+Linux kernel modules
+
+=item *
+
+Linux new-style initrd images
+
+=item *
+
+some non-x86 Linux vmlinuz kernels
+
+=back
+
+What it can't do currently:
+
+=over 4
+
+=item *
+
+static libraries (libfoo.a)
+
+=item *
+
+Linux old-style initrd as compressed ext2 filesystem (RHEL 3)
+
+=item *
+
+x86 Linux vmlinuz kernels
+
+x86 vmlinuz images (bzImage format) consist of a mix of 16-, 32- and
+compressed code, and are horribly hard to unpack.  If you want to find
+the architecture of a kernel, use the architecture of the associated
+initrd or kernel module(s) instead.
+
+=back");
+
 ]
 
 (* daemon_functions are any functions which cause some action
 ]
 
 (* daemon_functions are any functions which cause some action
@@ -4918,6 +5044,53 @@ C<device> parameter must be the name of the LUKS mapping
 device (ie. C</dev/mapper/mapname>) and I<not> the name
 of the underlying block device.");
 
 device (ie. C</dev/mapper/mapname>) and I<not> the name
 of the underlying block device.");
 
+  ("luks_format", (RErr, [Device "device"; Key "key"; Int "keyslot"]), 260, [Optional "luks"; DangerWillRobinson],
+   [],
+   "format a block device as a LUKS encrypted device",
+   "\
+This command erases existing data on C<device> and formats
+the device as a LUKS encrypted device.  C<key> is the
+initial key, which is added to key slot C<slot>.  (LUKS
+supports 8 key slots, numbered 0-7).");
+
+  ("luks_format_cipher", (RErr, [Device "device"; Key "key"; Int "keyslot"; String "cipher"]), 261, [Optional "luks"; DangerWillRobinson],
+   [],
+   "format a block device as a LUKS encrypted device",
+   "\
+This command is the same as C<guestfs_luks_format> but
+it also allows you to set the C<cipher> used.");
+
+  ("luks_add_key", (RErr, [Device "device"; Key "key"; Key "newkey"; Int "keyslot"]), 262, [Optional "luks"],
+   [],
+   "add a key on a LUKS encrypted device",
+   "\
+This command adds a new key on LUKS device C<device>.
+C<key> is any existing key, and is used to access the device.
+C<newkey> is the new key to add.  C<keyslot> is the key slot
+that will be replaced.
+
+Note that if C<keyslot> already contains a key, then this
+command will fail.  You have to use C<guestfs_luks_kill_slot>
+first to remove that key.");
+
+  ("luks_kill_slot", (RErr, [Device "device"; Key "key"; Int "keyslot"]), 263, [Optional "luks"],
+   [],
+   "remove a key from a LUKS encrypted device",
+   "\
+This command deletes the key in key slot C<keyslot> from the
+encrypted LUKS device C<device>.  C<key> must be one of the
+I<other> keys.");
+
+  ("is_lv", (RBool "lvflag", [Device "device"]), 264, [Optional "lvm2"],
+   [InitBasicFSonLVM, IfAvailable "lvm2", TestOutputTrue (
+      [["is_lv"; "/dev/VG/LV"]]);
+    InitBasicFSonLVM, IfAvailable "lvm2", TestOutputFalse (
+      [["is_lv"; "/dev/sda1"]])],
+   "test if device is a logical volume",
+   "\
+This command tests whether C<device> is a logical volume, and
+returns true iff this is the case.");
+
 ]
 
 let all_functions = non_daemon_functions @ daemon_functions
 ]
 
 let all_functions = non_daemon_functions @ daemon_functions
@@ -5667,7 +5840,7 @@ let rec generate_actions_pod () =
 The string is owned by the guest handle and must I<not> be freed.\n\n"
          | RConstOptString _ ->
              pr "This function returns a string which may be NULL.
 The string is owned by the guest handle and must I<not> be freed.\n\n"
          | RConstOptString _ ->
              pr "This function returns a string which may be NULL.
-There is way to return an error from this function.
+There is no way to return an error from this function.
 The string is owned by the guest handle and must I<not> be freed.\n\n"
          | RString _ ->
              pr "This function returns a string, or NULL on error.
 The string is owned by the guest handle and must I<not> be freed.\n\n"
          | RString _ ->
              pr "This function returns a string, or NULL on error.
@@ -6014,13 +6187,6 @@ and generate_client_actions () =
 #include \"guestfs-internal-actions.h\"
 #include \"guestfs_protocol.h\"
 
 #include \"guestfs-internal-actions.h\"
 #include \"guestfs_protocol.h\"
 
-#define error guestfs_error
-//#define perrorf guestfs_perrorf
-#define safe_malloc guestfs_safe_malloc
-#define safe_realloc guestfs_safe_realloc
-//#define safe_strdup guestfs_safe_strdup
-#define safe_memdup guestfs_safe_memdup
-
 /* Check the return message from a call for validity. */
 static int
 check_reply_header (guestfs_h *g,
 /* Check the return message from a call for validity. */
 static int
 check_reply_header (guestfs_h *g,
@@ -6129,7 +6295,7 @@ check_state (guestfs_h *g, const char *caller)
       pr "\n"
     );
 
       pr "\n"
     );
 
-    pr "    printf (\"%s\");\n" shortname;
+    pr "    fprintf (stderr, \"%s\");\n" shortname;
     List.iter (
       function
       | String n                       (* strings *)
     List.iter (
       function
       | String n                       (* strings *)
@@ -6141,27 +6307,27 @@ check_state (guestfs_h *g, const char *caller)
       | BufferIn n
       | Key n ->
           (* guestfish doesn't support string escaping, so neither do we *)
       | BufferIn n
       | Key n ->
           (* guestfish doesn't support string escaping, so neither do we *)
-          pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
+          pr "    fprintf (stderr, \" \\\"%%s\\\"\", %s);\n" n
       | OptString n ->                 (* string option *)
       | OptString n ->                 (* string option *)
-          pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
-          pr "    else printf (\" null\");\n"
+          pr "    if (%s) fprintf (stderr, \" \\\"%%s\\\"\", %s);\n" n n;
+          pr "    else fprintf (stderr, \" null\");\n"
       | StringList n
       | DeviceList n ->                        (* string list *)
       | StringList n
       | DeviceList n ->                        (* string list *)
-          pr "    putchar (' ');\n";
-          pr "    putchar ('\"');\n";
+          pr "    fputc (' ', stderr);\n";
+          pr "    fputc ('\"', stderr);\n";
           pr "    for (i = 0; %s[i]; ++i) {\n" n;
           pr "    for (i = 0; %s[i]; ++i) {\n" n;
-          pr "      if (i > 0) putchar (' ');\n";
-          pr "      fputs (%s[i], stdout);\n" n;
+          pr "      if (i > 0) fputc (' ', stderr);\n";
+          pr "      fputs (%s[i], stderr);\n" n;
           pr "    }\n";
           pr "    }\n";
-          pr "    putchar ('\"');\n";
+          pr "    fputc ('\"', stderr);\n";
       | Bool n ->                      (* boolean *)
       | Bool n ->                      (* boolean *)
-          pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
+          pr "    fputs (%s ? \" true\" : \" false\", stderr);\n" n
       | Int n ->                       (* int *)
       | Int n ->                       (* int *)
-          pr "    printf (\" %%d\", %s);\n" n
+          pr "    fprintf (stderr, \" %%d\", %s);\n" n
       | Int64 n ->
       | Int64 n ->
-          pr "    printf (\" %%\" PRIi64, %s);\n" n
+          pr "    fprintf (stderr, \" %%\" PRIi64, %s);\n" n
     ) (snd style);
     ) (snd style);
-    pr "    putchar ('\\n');\n";
+    pr "    fputc ('\\n', stderr);\n";
     pr "  }\n";
     pr "\n";
   in
     pr "  }\n";
     pr "\n";
   in
@@ -7773,10 +7939,17 @@ and generate_fish_cmds () =
               name2 (String.concat " " (List.map name_of_argt args)) in
 
       let warnings =
               name2 (String.concat " " (List.map name_of_argt args)) in
 
       let warnings =
-        if List.mem ProtocolLimitWarning flags then
-          ("\n\n" ^ protocol_limit_warning)
+        if List.exists (function Key _ -> true | _ -> false) (snd style) then
+          "\n\nThis command has one or more key or passphrase parameters.
+Guestfish will prompt for these separately."
         else "" in
 
         else "" in
 
+      let warnings =
+        warnings ^
+          if List.mem ProtocolLimitWarning flags then
+            ("\n\n" ^ protocol_limit_warning)
+          else "" in
+
       (* For DangerWillRobinson commands, we should probably have
        * guestfish prompt before allowing you to use them (especially
        * in interactive mode). XXX
       (* For DangerWillRobinson commands, we should probably have
        * guestfish prompt before allowing you to use them (especially
        * in interactive mode). XXX
@@ -9444,25 +9617,35 @@ typedef int Py_ssize_t;
 
 #include \"guestfs.h\"
 
 
 #include \"guestfs.h\"
 
+#ifndef HAVE_PYCAPSULE_NEW
 typedef struct {
   PyObject_HEAD
   guestfs_h *g;
 } Pyguestfs_Object;
 typedef struct {
   PyObject_HEAD
   guestfs_h *g;
 } Pyguestfs_Object;
+#endif
 
 static guestfs_h *
 get_handle (PyObject *obj)
 {
   assert (obj);
   assert (obj != Py_None);
 
 static guestfs_h *
 get_handle (PyObject *obj)
 {
   assert (obj);
   assert (obj != Py_None);
+#ifndef HAVE_PYCAPSULE_NEW
   return ((Pyguestfs_Object *) obj)->g;
   return ((Pyguestfs_Object *) obj)->g;
+#else
+  return (guestfs_h*) PyCapsule_GetPointer(obj, \"guestfs_h\");
+#endif
 }
 
 static PyObject *
 put_handle (guestfs_h *g)
 {
   assert (g);
 }
 
 static PyObject *
 put_handle (guestfs_h *g)
 {
   assert (g);
+#ifndef HAVE_PYCAPSULE_NEW
   return
     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
   return
     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
+#else
+  return PyCapsule_New ((void *) g, \"guestfs_h\", NULL);
+#endif
 }
 
 /* This list should be freed (but not the strings) after use. */
 }
 
 /* This list should be freed (but not the strings) after use. */
@@ -9556,6 +9739,9 @@ py_guestfs_create (PyObject *self, PyObject *args)
     return NULL;
   }
   guestfs_set_error_handler (g, NULL, NULL);
     return NULL;
   }
   guestfs_set_error_handler (g, NULL, NULL);
+  /* This can return NULL, but in that case put_handle will have
+   * set the Python error string.
+   */
   return put_handle (g);
 }
 
   return put_handle (g);
 }
 
@@ -12311,8 +12497,8 @@ Run it from the top source directory using the command
   output_to "src/guestfs-structs.h" generate_structs_h;
   output_to "src/guestfs-actions.h" generate_actions_h;
   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
   output_to "src/guestfs-structs.h" generate_structs_h;
   output_to "src/guestfs-actions.h" generate_actions_h;
   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
-  output_to "src/guestfs-actions.c" generate_client_actions;
-  output_to "src/guestfs-bindtests.c" generate_bindtests;
+  output_to "src/actions.c" generate_client_actions;
+  output_to "src/bindtests.c" generate_bindtests;
   output_to "src/guestfs-structs.pod" generate_structs_pod;
   output_to "src/guestfs-actions.pod" generate_actions_pod;
   output_to "src/guestfs-availability.pod" generate_availability_pod;
   output_to "src/guestfs-structs.pod" generate_structs_pod;
   output_to "src/guestfs-actions.pod" generate_actions_pod;
   output_to "src/guestfs-availability.pod" generate_availability_pod;