mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-21 22:53:37 +00:00
daemon: Send back the errno as a string.
This changes the protocol again so that if the errno is available, it is converted to a string (like "EIO") and sent back over the protocol to the library. In this commit the library just discards the string.
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -46,6 +46,8 @@ configure
|
||||
cscope.out
|
||||
csharp/
|
||||
daemon/actions.h
|
||||
daemon/errnostring.c
|
||||
daemon/errnostring.h
|
||||
daemon/guestfsd
|
||||
daemon/guestfsd.exe
|
||||
daemon/guestfs_protocol.c
|
||||
@@ -250,6 +252,8 @@ ruby/ext/guestfs/mkmf.log
|
||||
ruby/Rakefile
|
||||
src/actions.c
|
||||
src/bindtests.c
|
||||
src/errnostring.c
|
||||
src/errnostring.h
|
||||
src/guestfs-actions.h
|
||||
src/guestfs-internal-actions.h
|
||||
src/guestfs_protocol.c
|
||||
|
||||
@@ -36,7 +36,9 @@ $(generatorsrcdir)/stamp-generator: force
|
||||
BUILT_SOURCES = \
|
||||
$(generator_built) \
|
||||
guestfs_protocol.c \
|
||||
guestfs_protocol.h
|
||||
guestfs_protocol.h \
|
||||
errnostring.c \
|
||||
errnostring.h
|
||||
|
||||
EXTRA_DIST = $(BUILT_SOURCES) \
|
||||
.gitignore
|
||||
@@ -60,6 +62,13 @@ $(libsrcdir)/guestfs_protocol.c: force
|
||||
$(libsrcdir)/guestfs_protocol.h: force
|
||||
$(MAKE) -C $(libsrcdir) guestfs_protocol.h
|
||||
|
||||
errnostring.c: $(libsrcdir)/errnostring.c
|
||||
rm -f $@
|
||||
ln $< $@
|
||||
errnostring.h: $(libsrcdir)/errnostring.h
|
||||
rm -f $@
|
||||
ln $< $@
|
||||
|
||||
noinst_PROGRAMS = guestfsd
|
||||
guestfsd_SOURCES = \
|
||||
actions.h \
|
||||
@@ -82,6 +91,8 @@ guestfsd_SOURCES = \
|
||||
dropcaches.c \
|
||||
du.c \
|
||||
echo_daemon.c \
|
||||
errnostring.h \
|
||||
errnostring.c \
|
||||
ext2.c \
|
||||
fallocate.c \
|
||||
file.c \
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
#include "daemon.h"
|
||||
#include "guestfs_protocol.h"
|
||||
#include "errnostring.h"
|
||||
|
||||
/* The message currently being processed. */
|
||||
int proc_nr;
|
||||
@@ -247,7 +248,11 @@ send_error (int errnum, const char *msg)
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
err.linux_errno = errnum;
|
||||
/* These strings are not going to be freed. We just cast them
|
||||
* to (char *) because they are defined that way in the XDR structs.
|
||||
*/
|
||||
err.errno_string =
|
||||
(char *) (errnum > 0 ? guestfs___errno_to_string (errnum) : "");
|
||||
err.error_message = (char *) msg;
|
||||
|
||||
if (!xdr_guestfs_message_error (&xdr, &err)) {
|
||||
|
||||
@@ -115,15 +115,19 @@ generator_bindtests.cmo: generator_utils.cmi generator_types.cmo \
|
||||
generator_bindtests.cmx: generator_utils.cmx generator_types.cmx \
|
||||
generator_structs.cmx generator_pr.cmx generator_optgroups.cmx \
|
||||
generator_docstrings.cmx generator_c.cmx generator_actions.cmx
|
||||
generator_errnostring.cmo: generator_utils.cmi generator_types.cmo \
|
||||
generator_pr.cmi generator_docstrings.cmo
|
||||
generator_errnostring.cmx: generator_utils.cmx generator_types.cmx \
|
||||
generator_pr.cmx generator_docstrings.cmx
|
||||
generator_main.cmo: generator_xdr.cmo generator_structs.cmi \
|
||||
generator_ruby.cmo generator_python.cmo generator_pr.cmi \
|
||||
generator_php.cmo generator_perl.cmo generator_ocaml.cmo \
|
||||
generator_java.cmo generator_haskell.cmo generator_fish.cmo \
|
||||
generator_daemon.cmo generator_csharp.cmo generator_capitests.cmo \
|
||||
generator_c.cmo generator_bindtests.cmo
|
||||
generator_errnostring.cmo generator_daemon.cmo generator_csharp.cmo \
|
||||
generator_capitests.cmo generator_c.cmo generator_bindtests.cmo
|
||||
generator_main.cmx: generator_xdr.cmx generator_structs.cmx \
|
||||
generator_ruby.cmx generator_python.cmx generator_pr.cmx \
|
||||
generator_php.cmx generator_perl.cmx generator_ocaml.cmx \
|
||||
generator_java.cmx generator_haskell.cmx generator_fish.cmx \
|
||||
generator_daemon.cmx generator_csharp.cmx generator_capitests.cmx \
|
||||
generator_c.cmx generator_bindtests.cmx
|
||||
generator_errnostring.cmx generator_daemon.cmx generator_csharp.cmx \
|
||||
generator_capitests.cmx generator_c.cmx generator_bindtests.cmx
|
||||
|
||||
@@ -44,6 +44,7 @@ SOURCES = \
|
||||
generator_csharp.ml \
|
||||
generator_php.ml \
|
||||
generator_bindtests.ml \
|
||||
generator_errnostring.ml \
|
||||
generator_main.ml
|
||||
|
||||
SOURCES_ML = $(filter %.ml,$(SOURCES))
|
||||
|
||||
@@ -804,6 +804,7 @@ check_state (guestfs_h *g, const char *caller)
|
||||
pr " if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
|
||||
pr " error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
|
||||
pr " free (err.error_message);\n";
|
||||
pr " free (err.errno_string);\n";
|
||||
pr " guestfs___end_busy (g);\n";
|
||||
pr " return %s;\n" error_code;
|
||||
pr " }\n";
|
||||
|
||||
273
generator/generator_errnostring.ml
Normal file
273
generator/generator_errnostring.ml
Normal file
@@ -0,0 +1,273 @@
|
||||
(* libguestfs
|
||||
* Copyright (C) 2010 Red Hat Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*)
|
||||
|
||||
(* Please read generator/README first. *)
|
||||
|
||||
open Printf
|
||||
|
||||
open Generator_types
|
||||
open Generator_utils
|
||||
open Generator_pr
|
||||
open Generator_docstrings
|
||||
|
||||
(* Generate the functions errno_to_string and string_to_errno which
|
||||
* convert errno (eg. EINVAL) into string ("EINVAL") and back again,
|
||||
* allowing us to portably pass error values over the protocol between
|
||||
* different versions of Un*x.
|
||||
*)
|
||||
|
||||
(* Errors found in POSIX plus additional errors found in the Linux
|
||||
* header files. NOTE keep this sorted and avoid duplicates.
|
||||
*)
|
||||
let errnos = [
|
||||
"E2BIG";
|
||||
"EACCES";
|
||||
"EADDRINUSE";
|
||||
"EADDRNOTAVAIL";
|
||||
"EADV";
|
||||
"EAFNOSUPPORT";
|
||||
"EAGAIN";
|
||||
"EALREADY";
|
||||
"EBADE";
|
||||
"EBADF";
|
||||
"EBADFD";
|
||||
"EBADMSG";
|
||||
"EBADR";
|
||||
"EBADRQC";
|
||||
"EBADSLT";
|
||||
"EBFONT";
|
||||
"EBUSY";
|
||||
"ECANCELED";
|
||||
"ECHILD";
|
||||
"ECHRNG";
|
||||
"ECOMM";
|
||||
"ECONNABORTED";
|
||||
"ECONNREFUSED";
|
||||
"ECONNRESET";
|
||||
(*"EDEADLK"; - same as EDEADLOCK*)
|
||||
"EDEADLOCK";
|
||||
"EDESTADDRREQ";
|
||||
"EDOM";
|
||||
"EDOTDOT";
|
||||
"EDQUOT";
|
||||
"EEXIST";
|
||||
"EFAULT";
|
||||
"EFBIG";
|
||||
"EHOSTDOWN";
|
||||
"EHOSTUNREACH";
|
||||
"EIDRM";
|
||||
"EILSEQ";
|
||||
"EINPROGRESS";
|
||||
"EINTR";
|
||||
"EINVAL";
|
||||
"EIO";
|
||||
"EISCONN";
|
||||
"EISDIR";
|
||||
"EISNAM";
|
||||
"EKEYEXPIRED";
|
||||
"EKEYREJECTED";
|
||||
"EKEYREVOKED";
|
||||
"EL2HLT";
|
||||
"EL2NSYNC";
|
||||
"EL3HLT";
|
||||
"EL3RST";
|
||||
"ELIBACC";
|
||||
"ELIBBAD";
|
||||
"ELIBEXEC";
|
||||
"ELIBMAX";
|
||||
"ELIBSCN";
|
||||
"ELNRNG";
|
||||
"ELOOP";
|
||||
"EMEDIUMTYPE";
|
||||
"EMFILE";
|
||||
"EMLINK";
|
||||
"EMSGSIZE";
|
||||
"EMULTIHOP";
|
||||
"ENAMETOOLONG";
|
||||
"ENAVAIL";
|
||||
"ENETDOWN";
|
||||
"ENETRESET";
|
||||
"ENETUNREACH";
|
||||
"ENFILE";
|
||||
"ENOANO";
|
||||
"ENOBUFS";
|
||||
"ENOCSI";
|
||||
"ENODATA";
|
||||
"ENODEV";
|
||||
"ENOENT";
|
||||
"ENOEXEC";
|
||||
"ENOKEY";
|
||||
"ENOLCK";
|
||||
"ENOLINK";
|
||||
"ENOMEDIUM";
|
||||
"ENOMEM";
|
||||
"ENOMSG";
|
||||
"ENONET";
|
||||
"ENOPKG";
|
||||
"ENOPROTOOPT";
|
||||
"ENOSPC";
|
||||
"ENOSR";
|
||||
"ENOSTR";
|
||||
"ENOSYS";
|
||||
"ENOTBLK";
|
||||
"ENOTCONN";
|
||||
"ENOTDIR";
|
||||
"ENOTEMPTY";
|
||||
"ENOTNAM";
|
||||
"ENOTRECOVERABLE";
|
||||
"ENOTSOCK";
|
||||
"ENOTSUP";
|
||||
"ENOTTY";
|
||||
"ENOTUNIQ";
|
||||
"ENXIO";
|
||||
(*"EOPNOTSUPP"; - duplicates another error, and we don't care because
|
||||
it's a network error *)
|
||||
"EOVERFLOW";
|
||||
"EOWNERDEAD";
|
||||
"EPERM";
|
||||
"EPFNOSUPPORT";
|
||||
"EPIPE";
|
||||
"EPROTO";
|
||||
"EPROTONOSUPPORT";
|
||||
"EPROTOTYPE";
|
||||
"ERANGE";
|
||||
"EREMCHG";
|
||||
"EREMOTE";
|
||||
"EREMOTEIO";
|
||||
"ERESTART";
|
||||
"ERFKILL";
|
||||
"EROFS";
|
||||
"ESHUTDOWN";
|
||||
"ESOCKTNOSUPPORT";
|
||||
"ESPIPE";
|
||||
"ESRCH";
|
||||
"ESRMNT";
|
||||
"ESTALE";
|
||||
"ESTRPIPE";
|
||||
"ETIME";
|
||||
"ETIMEDOUT";
|
||||
"ETOOMANYREFS";
|
||||
"ETXTBSY";
|
||||
"EUCLEAN";
|
||||
"EUNATCH";
|
||||
"EUSERS";
|
||||
(*"EWOULDBLOCK"; - same as EAGAIN*)
|
||||
"EXDEV";
|
||||
"EXFULL";
|
||||
|
||||
(* This is a non-existent errno which is simply used to test that
|
||||
* the generated code can handle such cases on future platforms
|
||||
* where one of the above error codes might not exist.
|
||||
*)
|
||||
"EZZZ";
|
||||
]
|
||||
|
||||
let () =
|
||||
(* Check list is sorted and no duplicates. *)
|
||||
let file = "generator/generator_errnostring.ml" in
|
||||
let check str =
|
||||
let len = String.length str in
|
||||
if len == 0 || len > 32 then
|
||||
failwithf "%s: errno empty or length > 32 (%s)" file str;
|
||||
if str.[0] <> 'E' then
|
||||
failwithf "%s: errno string does not begin with letter 'E' (%s)" file str;
|
||||
for i = 0 to len-1 do
|
||||
let c = str.[i] in
|
||||
if Char.uppercase c <> c then
|
||||
failwithf "%s: errno string is not all uppercase (%s)" file str
|
||||
done
|
||||
in
|
||||
let rec loop = function
|
||||
| [] -> ()
|
||||
| x :: y :: xs when x = y ->
|
||||
failwithf "%s: errnos list contains duplicates (%s)" file x
|
||||
| x :: y :: xs when x > y ->
|
||||
failwithf "%s: errnos list is not sorted (%s > %s)" file x y
|
||||
| x :: xs -> check x; loop xs
|
||||
in
|
||||
loop errnos
|
||||
|
||||
let generate_errnostring_h () =
|
||||
generate_header CStyle LGPLv2plus;
|
||||
|
||||
pr "
|
||||
#ifndef GUESTFS_ERRNOSTRING_H_
|
||||
#define GUESTFS_ERRNOSTRING_H_
|
||||
|
||||
/* Convert errno (eg. EIO) to its string representation (\"EIO\").
|
||||
* This only works for a set of errors that are listed in the generator
|
||||
* AND are supported on the local operating system. For other errors
|
||||
* the string (\"EINVAL\") is returned.
|
||||
*
|
||||
* NOTE: It is an error to call this function with errnum == 0.
|
||||
*/
|
||||
extern const char *guestfs___errno_to_string (int errnum);
|
||||
|
||||
/* Convert string representation of an error (eg. \"EIO\") to the errno
|
||||
* value (EIO). As for the function above, this only works for a
|
||||
* subset of errors. For errors not supported by the local operating
|
||||
* system, EINVAL is returned (all POSIX-conforming systems must
|
||||
* support EINVAL).
|
||||
*/
|
||||
//extern int guestfs___string_to_errno (const char *errnostr);
|
||||
|
||||
#endif /* GUESTFS_ERRNOSTRING_H_ */
|
||||
"
|
||||
|
||||
let generate_errnostring_c () =
|
||||
generate_header CStyle LGPLv2plus;
|
||||
|
||||
pr "\
|
||||
#include <config.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include \"errnostring.h\"
|
||||
|
||||
static const char *errno_to_string[] = {
|
||||
";
|
||||
|
||||
List.iter (
|
||||
fun e ->
|
||||
pr "#ifdef %s\n" e;
|
||||
pr " [%s] = \"%s\",\n" e e;
|
||||
pr "#endif\n"
|
||||
) errnos;
|
||||
|
||||
pr "\
|
||||
};
|
||||
|
||||
#define ERRNO_TO_STRING_SIZE \\
|
||||
(sizeof errno_to_string / sizeof errno_to_string[0])
|
||||
|
||||
const char *
|
||||
guestfs___errno_to_string (int errnum)
|
||||
{
|
||||
/* See function documentation. */
|
||||
if (errnum == 0)
|
||||
abort ();
|
||||
|
||||
if (errnum < 0 || (size_t) errnum >= ERRNO_TO_STRING_SIZE ||
|
||||
errno_to_string[errnum] == NULL)
|
||||
return \"EINVAL\";
|
||||
else
|
||||
return errno_to_string[errnum];
|
||||
}
|
||||
|
||||
"
|
||||
@@ -38,6 +38,7 @@ open Generator_haskell
|
||||
open Generator_csharp
|
||||
open Generator_php
|
||||
open Generator_bindtests
|
||||
open Generator_errnostring
|
||||
|
||||
let perror msg = function
|
||||
| Unix_error (err, _, _) ->
|
||||
@@ -80,6 +81,8 @@ Run it from the top source directory using the command
|
||||
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/errnostring.c" generate_errnostring_c;
|
||||
output_to "src/errnostring.h" generate_errnostring_h;
|
||||
output_to "src/MAX_PROC_NR" generate_max_proc_nr;
|
||||
output_to "src/libguestfs.syms" generate_linker_script;
|
||||
output_to "daemon/actions.h" generate_daemon_actions_h;
|
||||
|
||||
@@ -157,7 +157,7 @@ let generate_xdr () =
|
||||
*/
|
||||
|
||||
const GUESTFS_PROGRAM = 0x2000F5F5;
|
||||
const GUESTFS_PROTOCOL_VERSION = 2;
|
||||
const GUESTFS_PROTOCOL_VERSION = 3;
|
||||
|
||||
/* These constants must be larger than any possible message length. */
|
||||
const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
|
||||
@@ -181,7 +181,8 @@ enum guestfs_message_status {
|
||||
|
||||
pr "\
|
||||
struct guestfs_message_error {
|
||||
int linux_errno; /* Linux errno if available. */
|
||||
string errno_string<32>; /* errno eg. \"EINVAL\", empty string
|
||||
if errno not available */
|
||||
string error_message<GUESTFS_ERROR_LEN>;
|
||||
};
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ daemon/dmesg.c
|
||||
daemon/dropcaches.c
|
||||
daemon/du.c
|
||||
daemon/echo_daemon.c
|
||||
daemon/errnostring.c
|
||||
daemon/ext2.c
|
||||
daemon/fallocate.c
|
||||
daemon/file.c
|
||||
@@ -118,6 +119,7 @@ ruby/ext/guestfs/_guestfs.c
|
||||
src/actions.c
|
||||
src/appliance.c
|
||||
src/bindtests.c
|
||||
src/errnostring.c
|
||||
src/guestfs.c
|
||||
src/inspect.c
|
||||
src/launch.c
|
||||
|
||||
@@ -781,6 +781,9 @@ fuse/guestmount.c.
|
||||
In libguestfs 1.5.4, the protocol was changed so that the
|
||||
Linux errno is sent back from the daemon.
|
||||
|
||||
In libguestfs 1.7.1, the protocol was changed again to send the
|
||||
errno back as a string (for portability between differing Un*xes).
|
||||
|
||||
=item Ambiguity between devices and paths
|
||||
|
||||
There is a subtle ambiguity in the API between a device name
|
||||
|
||||
Reference in New Issue
Block a user