Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

New APIs: guestfs_create_flags, guestfs_parse_environment,

guestfs_parse_environment_list.

Add a new function for creating a handle:

 guestfs_h *guestfs_create_flags (unsigned flags [, ...]);

This variant lets you supply flags and extra arguments, although extra
arguments are not used at the moment.

Of particular interest is the ability to separate the creation of the
handle from the parsing of environment variables like
LIBGUESTFS_DEBUG.  guestfs_create does both together, which prevents
us from propagating errors from parsing environment variables back to
the caller (guestfs_create has always printed any errors on stderr and
then just ignored them).

If you are interested in these errors, you can now write:

 g = guestfs_create_flags (GUESTFS_CREATE_NO_ENVIRONMENT);
 if (!g)
   exit (EXIT_FAILURE);
 r = guestfs_parse_environment (g);
 if (!r)
   exit (EXIT_FAILURE);

Also you can *omit* the call to guestfs_parse_environment, which
creates a handle unaffected by the environment (which was not possible
before).

This commit also includes new (backwards compatible) changes to the
OCaml, Perl, Python, Ruby and Java constructors that let you use the
flags.
  • Loading branch information...
commit 9466060201600db47016133d80af22eb38091a49 1 parent 389cb60
rwmjones rwmjones authored
33 generator/actions.ml
@@ -2480,6 +2480,39 @@ call this function to pass the answer back to libvirt.
2480 2480
2481 2481 See L<guestfs(3)/LIBVIRT AUTHENTICATION> for documentation and example code." };
2482 2482
  2483 + { defaults with
  2484 + name = "parse_environment";
  2485 + style = RErr, [], [];
  2486 + tests = [];
  2487 + shortdesc = "parse the environment and set handle flags accordingly";
  2488 + longdesc = "\
  2489 +Parse the program's environment and set flags in the handle
  2490 +accordingly. For example if C<LIBGUESTFS_DEBUG=1> then the
  2491 +'verbose' flag is set in the handle.
  2492 +
  2493 +I<Most programs do not need to call this>. It is done implicitly
  2494 +when you call C<guestfs_create>.
  2495 +
  2496 +See L<guestfs(3)/ENVIRONMENT VARIABLES> for a list of environment
  2497 +variables that can affect libguestfs handles. See also
  2498 +L<guestfs(3)/guestfs_create_flags>, and
  2499 +C<guestfs_parse_environment_list>." };
  2500 +
  2501 + { defaults with
  2502 + name = "parse_environment_list";
  2503 + style = RErr, [StringList "environment"], [];
  2504 + tests = [];
  2505 + shortdesc = "parse the environment and set handle flags accordingly";
  2506 + longdesc = "\
  2507 +Parse the list of strings in the argument C<environment>
  2508 +and set flags in the handle accordingly.
  2509 +For example if C<LIBGUESTFS_DEBUG=1> is a string in the list,
  2510 +then the 'verbose' flag is set in the handle.
  2511 +
  2512 +This is the same as C<guestfs_parse_environment> except that
  2513 +it parses an explicit list of strings instead of the program's
  2514 +environment." };
  2515 +
2483 2516 ]
2484 2517
2485 2518 (* daemon_functions are any functions which cause some action
4 generator/c.ml
@@ -416,6 +416,9 @@ typedef struct guestfs_h guestfs_h;
416 416
417 417 /* Connection management. */
418 418 extern GUESTFS_DLL_PUBLIC guestfs_h *guestfs_create (void);
  419 +extern GUESTFS_DLL_PUBLIC guestfs_h *guestfs_create_flags (unsigned flags, ...);
  420 +#define GUESTFS_CREATE_NO_ENVIRONMENT (1 << 0)
  421 +#define GUESTFS_CREATE_NO_CLOSE_ON_EXIT (1 << 1)
419 422 extern GUESTFS_DLL_PUBLIC void guestfs_close (guestfs_h *g);
420 423
421 424 /* Error handling. */
@@ -1586,6 +1589,7 @@ and generate_linker_script () =
1586 1589
1587 1590 let globals = [
1588 1591 "guestfs_create";
  1592 + "guestfs_create_flags";
1589 1593 "guestfs_close";
1590 1594 "guestfs_delete_event_callback";
1591 1595 "guestfs_first_private";
34 generator/java.ml
@@ -56,15 +56,39 @@ public class GuestFS {
56 56 long g;
57 57
58 58 /**
  59 + * Create a libguestfs handle, setting flags.
  60 + *
  61 + * @throws LibGuestFSException
  62 + */
  63 + public GuestFS (Map<String, Object> optargs) throws LibGuestFSException
  64 + {
  65 + int flags = 0;
  66 +
  67 + /* Unpack optional args. */
  68 + Object _optobj;
  69 + _optobj = null;
  70 + if (optargs != null)
  71 + _optobj = optargs.get (\"environment\");
  72 + if (_optobj != null && !((Boolean) _optobj).booleanValue())
  73 + flags |= 1;
  74 + if (optargs != null)
  75 + _optobj = optargs.get (\"close_on_exit\");
  76 + if (_optobj != null && !((Boolean) _optobj).booleanValue())
  77 + flags |= 2;
  78 +
  79 + g = _create (flags);
  80 + }
  81 +
  82 + /**
59 83 * Create a libguestfs handle.
60 84 *
61 85 * @throws LibGuestFSException
62 86 */
63 87 public GuestFS () throws LibGuestFSException
64 88 {
65   - g = _create ();
  89 + g = _create (0);
66 90 }
67   - private native long _create () throws LibGuestFSException;
  91 + private native long _create (int flags) throws LibGuestFSException;
68 92
69 93 /**
70 94 * Close a libguestfs handle.
@@ -409,12 +433,12 @@ throw_exception (JNIEnv *env, const char *msg)
409 433 }
410 434
411 435 JNIEXPORT jlong JNICALL
412   -Java_com_redhat_et_libguestfs_GuestFS__1create
413   - (JNIEnv *env, jobject obj)
  436 +Java_com_redhat_et_libguestfs_GuestFS__1create (JNIEnv *env,
  437 + jobject obj_unused, jint flags)
414 438 {
415 439 guestfs_h *g;
416 440
417   - g = guestfs_create ();
  441 + g = guestfs_create_flags ((int) flags);
418 442 if (g == NULL) {
419 443 throw_exception (env, \"GuestFS.create: failed to allocate handle\");
420 444 return 0;
19 generator/ocaml.ml
@@ -62,8 +62,14 @@ exception Handle_closed of string
62 62 after calling {!close} on it. The string is the name of
63 63 the function. *)
64 64
65   -val create : unit -> t
66   -(** Create a {!t} handle. *)
  65 +val create : ?environment:bool -> ?close_on_exit:bool -> unit -> t
  66 +(** Create a {!t} handle.
  67 +
  68 + [?environment] defaults to [true]. If set to false, it sets
  69 + the [GUESTFS_CREATE_NO_ENVIRONMENT] flag.
  70 +
  71 + [?close_on_exit] defaults to [true]. If set to false, it sets
  72 + the [GUESTFS_CREATE_NO_CLOSE_ON_EXIT] flag. *)
67 73
68 74 val close : t -> unit
69 75 (** Close the {!t} handle and free up all resources used
@@ -171,7 +177,7 @@ val user_cancel : t -> unit
171 177 For example [g#]{{!guestfs.get_verbose}get_verbose} [()]
172 178 calls the method, whereas [g#get_verbose] is a function. *)
173 179
174   -class guestfs : unit -> object
  180 +class guestfs : ?environment:bool -> ?close_on_exit:bool -> unit -> object
175 181 method close : unit -> unit
176 182 method set_event_callback : event_callback -> event list -> event_handle
177 183 method delete_event_callback : event_handle -> unit
@@ -211,7 +217,8 @@ type t
211 217 exception Error of string
212 218 exception Handle_closed of string
213 219
214   -external create : unit -> t = \"ocaml_guestfs_create\"
  220 +external create : ?environment:bool -> ?close_on_exit:bool -> unit -> t =
  221 + \"ocaml_guestfs_create\"
215 222 external close : t -> unit = \"ocaml_guestfs_close\"
216 223
217 224 type event =
@@ -265,8 +272,8 @@ let () =
265 272
266 273 (* OO API. *)
267 274 pr "
268   -class guestfs () =
269   - let g = create () in
  275 +class guestfs ?environment ?close_on_exit () =
  276 + let g = create ?environment ?close_on_exit () in
270 277 object (self)
271 278 method close () = close g
272 279 method set_event_callback = set_event_callback g
27 generator/perl.ml
@@ -211,9 +211,10 @@ MODULE = Sys::Guestfs PACKAGE = Sys::Guestfs
211 211 PROTOTYPES: ENABLE
212 212
213 213 guestfs_h *
214   -_create ()
  214 +_create (flags)
  215 + unsigned flags;
215 216 CODE:
216   - RETVAL = guestfs_create ();
  217 + RETVAL = guestfs_create_flags (flags);
217 218 if (!RETVAL)
218 219 croak (\"could not create guestfs handle\");
219 220 guestfs_set_error_handler (RETVAL, NULL, NULL);
@@ -713,18 +714,29 @@ XSLoader::load ('Sys::Guestfs');
713 714
714 715 (* Methods. *)
715 716 pr "\
716   -=item $g = Sys::Guestfs->new ();
  717 +=item $g = Sys::Guestfs->new ([environment => 0,] [close_on_exit => 0]);
717 718
718 719 Create a new guestfs handle.
719 720
  721 +If the optional argument C<environment> is false, then
  722 +the C<GUESTFS_CREATE_NO_ENVIRONMENT> flag is set.
  723 +
  724 +If the optional argument C<close_on_exit> is false, then
  725 +the C<GUESTFS_CREATE_NO_CLOSE_ON_EXIT> flag is set.
  726 +
720 727 =cut
721 728
722 729 sub new {
723 730 my $proto = shift;
724 731 my $class = ref ($proto) || $proto;
  732 + my %%flags = @_;
  733 +
  734 + my $flags = 0;
  735 + $flags |= 1 if exists $flags{environment} && !$flags{environment};
  736 + $flags |= 2 if exists $flags{close_on_exit} && !$flags{close_on_exit};
725 737
726   - my $g = Sys::Guestfs::_create ();
727   - my $self = { _g => $g };
  738 + my $g = Sys::Guestfs::_create ($flags);
  739 + my $self = { _g => $g, _flags => $flags };
728 740 bless $self, $class;
729 741 return $self;
730 742 }
@@ -1013,10 +1025,11 @@ L<guestfs(3)/AVAILABILITY>.
1013 1025 =head1 STORING DATA IN THE HANDLE
1014 1026
1015 1027 The handle returned from L</new> is a hash reference. The hash
1016   -normally contains a single element:
  1028 +normally contains some elements:
1017 1029
1018 1030 {
1019   - _g => [private data used by libguestfs]
  1031 + _g => [private data used by libguestfs],
  1032 + _flags => [flags provided when creating the handle]
1020 1033 }
1021 1034
1022 1035 Callers can add other elements to this hash to store data for their own
7 generator/python.ml
@@ -645,9 +645,12 @@ class ClosedHandle(ValueError):
645 645 class GuestFS:
646 646 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
647 647
648   - def __init__ (self):
  648 + def __init__ (self, environment=True, close_on_exit=True):
649 649 \"\"\"Create a new libguestfs handle.\"\"\"
650   - self._o = libguestfsmod.create ()
  650 + flags = 0
  651 + if not environment: flags |= 1
  652 + if not close_on_exit: flags |= 2
  653 + self._o = libguestfsmod.create (flags)
651 654
652 655 def __del__ (self):
653 656 if self._o:
23 generator/ruby.ml
@@ -126,7 +126,7 @@ ruby_guestfs_free (void *gvp)
126 126
127 127 /*
128 128 * call-seq:
129   - * Guestfs::Guestfs.new() -> Guestfs::Guestfs
  129 + * Guestfs::Guestfs.new([{:environment => false, :close_on_exit => false}]) -> Guestfs::Guestfs
130 130 *
131 131 * Call
132 132 * +guestfs_create+[http://libguestfs.org/guestfs.3.html#guestfs_create]
@@ -134,11 +134,26 @@ ruby_guestfs_free (void *gvp)
134 134 * Ruby as an instance of the Guestfs::Guestfs class.
135 135 */
136 136 static VALUE
137   -ruby_guestfs_create (VALUE m)
  137 +ruby_guestfs_create (int argc, VALUE *argv, VALUE m)
138 138 {
139 139 guestfs_h *g;
140 140
141   - g = guestfs_create ();
  141 + if (argc > 1)
  142 + rb_raise (rb_eArgError, \"expecting 0 or 1 arguments\");
  143 +
  144 + volatile VALUE optargsv = argc == 1 ? argv[0] : rb_hash_new ();
  145 + Check_Type (optargsv, T_HASH);
  146 +
  147 + unsigned flags = 0;
  148 + volatile VALUE v;
  149 + v = rb_hash_lookup (optargsv, ID2SYM (rb_intern (\"environment\")));
  150 + if (v != Qnil && !RTEST (v))
  151 + flags |= GUESTFS_CREATE_NO_ENVIRONMENT;
  152 + v = rb_hash_lookup (optargsv, ID2SYM (rb_intern (\"close_on_exit\")));
  153 + if (v != Qnil && !RTEST (v))
  154 + flags |= GUESTFS_CREATE_NO_CLOSE_ON_EXIT;
  155 +
  156 + g = guestfs_create_flags (flags);
142 157 if (!g)
143 158 rb_raise (e_Error, \"failed to create guestfs handle\");
144 159
@@ -663,7 +678,7 @@ void Init__guestfs ()
663 678 rb_define_alloc_func (c_guestfs, ruby_guestfs_create);
664 679 #endif
665 680
666   - rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
  681 + rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, -1);
667 682 rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
668 683 rb_define_method (c_guestfs, \"set_event_callback\",
669 684 ruby_set_event_callback, 2);
17 ocaml/guestfs-c.c
@@ -48,7 +48,7 @@ static void event_callback_wrapper (guestfs_h *g, void *data, uint64_t event, in
48 48 #endif
49 49
50 50 /* These prototypes are solely to quiet gcc warning. */
51   -CAMLprim value ocaml_guestfs_create (value unitv);
  51 +CAMLprim value ocaml_guestfs_create (value environmentv, value close_on_exitv, value unitv);
52 52 CAMLprim value ocaml_guestfs_close (value gv);
53 53 CAMLprim value ocaml_guestfs_set_event_callback (value gv, value closure, value events);
54 54 CAMLprim value ocaml_guestfs_delete_event_callback (value gv, value eh);
@@ -141,14 +141,23 @@ ocaml_guestfs_raise_closed (const char *func)
141 141
142 142 /* Guestfs.create */
143 143 CAMLprim value
144   -ocaml_guestfs_create (value unitv)
  144 +ocaml_guestfs_create (value environmentv, value close_on_exitv, value unitv)
145 145 {
146   - CAMLparam1 (unitv);
  146 + CAMLparam3 (environmentv, close_on_exitv, unitv);
147 147 CAMLlocal1 (gv);
  148 + unsigned flags = 0;
148 149 guestfs_h *g;
149 150 value *v;
150 151
151   - g = guestfs_create ();
  152 + if (environmentv != Val_int (0) &&
  153 + !Bool_val (Field (environmentv, 0)))
  154 + flags |= GUESTFS_CREATE_NO_ENVIRONMENT;
  155 +
  156 + if (close_on_exitv != Val_int (0) &&
  157 + !Bool_val (Field (close_on_exitv, 0)))
  158 + flags |= GUESTFS_CREATE_NO_CLOSE_ON_EXIT;
  159 +
  160 + g = guestfs_create_flags (flags);
152 161 if (g == NULL)
153 162 caml_failwith ("failed to create guestfs handle");
154 163
5 python/guestfs-py-byhand.c
@@ -34,8 +34,11 @@ PyObject *
34 34 py_guestfs_create (PyObject *self, PyObject *args)
35 35 {
36 36 guestfs_h *g;
  37 + unsigned flags;
37 38
38   - g = guestfs_create ();
  39 + if (!PyArg_ParseTuple (args, (char *) "I:guestfs_create", &flags))
  40 + return NULL;
  41 + g = guestfs_create_flags (flags);
39 42 if (g == NULL) {
40 43 PyErr_SetString (PyExc_RuntimeError,
41 44 "guestfs.create: failed to allocate handle");
1  src/guestfs-internal.h
@@ -193,6 +193,7 @@ struct guestfs_h
193 193 bool enable_network; /* Enable the network. */
194 194 bool selinux; /* selinux enabled? */
195 195 bool pgroup; /* Create process group for children? */
  196 + bool close_on_exit; /* Is this handle on the atexit list? */
196 197
197 198 int smp; /* If > 1, -smp flag passed to qemu. */
198 199 int memsize; /* Size of RAM (megabytes). */
190 src/guestfs.c
@@ -100,14 +100,17 @@ init_libguestfs (void)
100 100 guestfs_h *
101 101 guestfs_create (void)
102 102 {
  103 + return guestfs_create_flags (0);
  104 +}
  105 +
  106 +guestfs_h *
  107 +guestfs_create_flags (unsigned flags, ...)
  108 +{
103 109 guestfs_h *g;
104   - const char *str;
105 110
106   - g = malloc (sizeof (*g));
  111 + g = calloc (1, sizeof (*g));
107 112 if (!g) return NULL;
108 113
109   - memset (g, 0, sizeof (*g));
110   -
111 114 g->state = CONFIG;
112 115
113 116 g->fd[0] = -1;
@@ -121,74 +124,45 @@ guestfs_create (void)
121 124 g->recovery_proc = 1;
122 125 g->autosync = 1;
123 126
124   - str = getenv ("LIBGUESTFS_DEBUG");
125   - g->verbose = str != NULL && STREQ (str, "1");
  127 + g->memsize = 500;
  128 +
  129 + /* Start with large serial numbers so they are easy to spot
  130 + * inside the protocol.
  131 + */
  132 + g->msg_next_serial = 0x00123400;
126 133
127   - str = getenv ("LIBGUESTFS_TRACE");
128   - g->trace = str != NULL && STREQ (str, "1");
  134 + /* Default is uniprocessor appliance. */
  135 + g->smp = 1;
129 136
130   - str = getenv ("LIBGUESTFS_PATH");
131   - g->path = str != NULL ? strdup (str) : strdup (GUESTFS_DEFAULT_PATH);
  137 + g->path = strdup (GUESTFS_DEFAULT_PATH);
132 138 if (!g->path) goto error;
133 139
134   - str = getenv ("LIBGUESTFS_QEMU");
135   - g->qemu = str != NULL ? strdup (str) : strdup (QEMU);
  140 + g->qemu = strdup (QEMU);
136 141 if (!g->qemu) goto error;
137 142
138   - str = getenv ("LIBGUESTFS_APPEND");
139   - if (str) {
140   - g->append = strdup (str);
141   - if (!g->append) goto error;
142   - }
143   -
144   - /* Choose a suitable memory size. Previously we tried to choose
145   - * a minimal memory size, but this isn't really necessary since
146   - * recent QEMU and KVM don't do anything nasty like locking
147   - * memory into core any more. Thus we can safely choose a
148   - * large, generous amount of memory, and it'll just get swapped
149   - * on smaller systems.
150   - */
151   - str = getenv ("LIBGUESTFS_MEMSIZE");
152   - if (str) {
153   - if (sscanf (str, "%d", &g->memsize) != 1 || g->memsize < 128) {
154   - warning (g, "non-numeric or too small value for LIBGUESTFS_MEMSIZE");
155   - goto error;
156   - }
157   - } else
158   - g->memsize = 500;
159   -
160   - str = getenv ("LIBGUESTFS_ATTACH_METHOD");
161   - if (str) {
162   - if (parse_attach_method (g, str) == -1) {
163   - warning (g, _("invalid or unknown value for LIBGUESTFS_ATTACH_METHOD environment variable"));
164   - goto error;
165   - }
166   - } else {
167   - if (parse_attach_method (g, DEFAULT_ATTACH_METHOD) == -1) {
168   - warning (g, _("libguestfs was built with an invalid default attach-method, using 'appliance' instead"));
169   - g->attach_method = ATTACH_METHOD_APPLIANCE;
170   - }
  143 + if (parse_attach_method (g, DEFAULT_ATTACH_METHOD) == -1) {
  144 + warning (g, _("libguestfs was built with an invalid default attach-method, using 'appliance' instead"));
  145 + g->attach_method = ATTACH_METHOD_APPLIANCE;
171 146 }
172 147
173   - /* Start with large serial numbers so they are easy to spot
174   - * inside the protocol.
175   - */
176   - g->msg_next_serial = 0x00123400;
  148 + if (!(flags & GUESTFS_CREATE_NO_ENVIRONMENT))
  149 + guestfs_parse_environment (g);
177 150
178   - /* Default is uniprocessor appliance. */
179   - g->smp = 1;
  151 + if (!(flags & GUESTFS_CREATE_NO_CLOSE_ON_EXIT)) {
  152 + g->close_on_exit = true;
180 153
181   - /* Link the handles onto a global list. */
182   - gl_lock_lock (handles_lock);
183   - g->next = handles;
184   - handles = g;
185   - if (!atexit_handler_set) {
186   - atexit (close_handles);
187   - atexit_handler_set = 1;
  154 + /* Link the handles onto a global list. */
  155 + gl_lock_lock (handles_lock);
  156 + g->next = handles;
  157 + handles = g;
  158 + if (!atexit_handler_set) {
  159 + atexit (close_handles);
  160 + atexit_handler_set = 1;
  161 + }
  162 + gl_lock_unlock (handles_lock);
188 163 }
189   - gl_lock_unlock (handles_lock);
190 164
191   - debug (g, "new guestfs handle %p", g);
  165 + debug (g, "create: flags = %u, handle = %p", flags, g);
192 166
193 167 return g;
194 168
@@ -201,10 +175,92 @@ guestfs_create (void)
201 175 return NULL;
202 176 }
203 177
  178 +static int
  179 +parse_environment (guestfs_h *g,
  180 + char *(*do_getenv) (const void *data, const char *),
  181 + const void *data)
  182 +{
  183 + int memsize;
  184 + char *str;
  185 +
  186 + /* Don't bother checking the return values of functions
  187 + * that cannot return errors.
  188 + */
  189 +
  190 + str = do_getenv (data, "LIBGUESTFS_DEBUG");
  191 + if (str != NULL && STREQ (str, "1"))
  192 + guestfs_set_verbose (g, 1);
  193 +
  194 + str = do_getenv (data, "LIBGUESTFS_TRACE");
  195 + if (str != NULL && STREQ (str, "1"))
  196 + guestfs_set_trace (g, 1);
  197 +
  198 + str = do_getenv (data, "LIBGUESTFS_PATH");
  199 + if (str)
  200 + guestfs_set_path (g, str);
  201 +
  202 + str = do_getenv (data, "LIBGUESTFS_QEMU");
  203 + if (str)
  204 + guestfs_set_qemu (g, str);
  205 +
  206 + str = do_getenv (data, "LIBGUESTFS_APPEND");
  207 + if (str)
  208 + guestfs_set_append (g, str);
  209 +
  210 + str = do_getenv (data, "LIBGUESTFS_MEMSIZE");
  211 + if (str) {
  212 + if (sscanf (str, "%d", &memsize) != 1 || memsize < 128) {
  213 + error (g, "non-numeric or too small value for LIBGUESTFS_MEMSIZE");
  214 + return -1;
  215 + }
  216 + guestfs_set_memsize (g, memsize);
  217 + }
  218 +
  219 + str = do_getenv (data, "LIBGUESTFS_ATTACH_METHOD");
  220 + if (str) {
  221 + if (guestfs_set_attach_method (g, str) == -1)
  222 + return -1;
  223 + }
  224 +
  225 + return 0;
  226 +}
  227 +
  228 +static char *
  229 +call_getenv (const void *data, const char *name)
  230 +{
  231 + return getenv (name);
  232 +}
  233 +
  234 +int
  235 +guestfs__parse_environment (guestfs_h *g)
  236 +{
  237 + return parse_environment (g, call_getenv, NULL);
  238 +}
  239 +
  240 +static char *
  241 +getenv_from_strings (const void *stringsv, const char *name)
  242 +{
  243 + char **strings = (char **) stringsv;
  244 + size_t len = strlen (name);
  245 + size_t i;
  246 +
  247 + for (i = 0; strings[i] != NULL; ++i)
  248 + if (STRPREFIX (strings[i], name) && strings[i][len] == '=')
  249 + return (char *) &strings[i][len+1];
  250 + return NULL;
  251 +}
  252 +
  253 +int
  254 +guestfs__parse_environment_list (guestfs_h *g, char * const *strings)
  255 +{
  256 + return parse_environment (g, getenv_from_strings, strings);
  257 +}
  258 +
204 259 void
205 260 guestfs_close (guestfs_h *g)
206 261 {
207 262 struct qemu_param *qp, *qp_next;
  263 + guestfs_h **gg;
208 264
209 265 if (g->state == NO_HANDLE) {
210 266 /* Not safe to call ANY callbacks here, so ... */
@@ -213,17 +269,13 @@ guestfs_close (guestfs_h *g)
213 269 }
214 270
215 271 /* Remove the handle from the handles list. */
216   - gl_lock_lock (handles_lock);
217   - if (handles == g)
218   - handles = g->next;
219   - else {
220   - guestfs_h *gg;
221   -
222   - for (gg = handles; gg->next != g; gg = gg->next)
  272 + if (g->close_on_exit) {
  273 + gl_lock_lock (handles_lock);
  274 + for (gg = &handles; *gg != g; gg = &(*gg)->next)
223 275 ;
224   - gg->next = g->next;
  276 + *gg = g->next;
  277 + gl_lock_unlock (handles_lock);
225 278 }
226   - gl_lock_unlock (handles_lock);
227 279
228 280 if (g->trace) {
229 281 const char trace_msg[] = "close";
68 src/guestfs.pod
Source Rendered
@@ -1628,8 +1628,9 @@ appropriate.
1628 1628 =head2 guestfs_h *
1629 1629
1630 1630 C<guestfs_h> is the opaque type representing a connection handle.
1631   -Create a handle by calling L</guestfs_create>. Call L</guestfs_close>
1632   -to free the handle and release all resources used.
  1631 +Create a handle by calling L</guestfs_create> or
  1632 +L</guestfs_create_flags>. Call L</guestfs_close> to free the handle
  1633 +and release all resources used.
1633 1634
1634 1635 For information on using multiple handles and threads, see the section
1635 1636 L</MULTIPLE HANDLES AND MULTIPLE THREADS> above.
@@ -1652,6 +1653,67 @@ After configuring the handle, you have to call L</guestfs_launch>.
1652 1653 You may also want to configure error handling for the handle. See the
1653 1654 L</ERROR HANDLING> section below.
1654 1655
  1656 +=head2 guestfs_create_flags
  1657 +
  1658 + guestfs_h *guestfs_create_flags (unsigned flags [, ...]);
  1659 +
  1660 +Create a connection handle, supplying extra flags and
  1661 +extra arguments to control how the handle is created.
  1662 +
  1663 +On success this returns a non-NULL pointer to a handle. On error it
  1664 +returns NULL.
  1665 +
  1666 +L</guestfs_create> is equivalent to calling C<guestfs_create_flags(0)>.
  1667 +
  1668 +The following flags may be logically ORed together. (Currently
  1669 +no extra arguments are used).
  1670 +
  1671 +=over 4
  1672 +
  1673 +=item C<GUESTFS_CREATE_NO_ENVIRONMENT>
  1674 +
  1675 +Don't parse any environment variables (such as C<LIBGUESTFS_DEBUG> etc).
  1676 +
  1677 +You can call L</guestfs_parse_environment> or
  1678 +L</guestfs_parse_environment_list> afterwards to parse environment
  1679 +variables. Alternately, I<don't> call these functions if you want the
  1680 +handle to be unaffected by environment variables. See the example below.
  1681 +
  1682 +The default (if this flag is not given) is to implicitly call
  1683 +L</guestfs_parse_environment>.
  1684 +
  1685 +=item C<GUESTFS_CREATE_NO_CLOSE_ON_EXIT>
  1686 +
  1687 +Don't try to close the handle in an L<atexit(3)> handler if the
  1688 +program exits without explicitly closing the handle.
  1689 +
  1690 +The default (if this flag is not given) is to install such an atexit
  1691 +handler.
  1692 +
  1693 +=back
  1694 +
  1695 +=head3 USING C<GUESTFS_CREATE_NO_ENVIRONMENT>
  1696 +
  1697 +You might use C<GUESTFS_CREATE_NO_ENVIRONMENT> and
  1698 +an explicit call to L</guestfs_parse_environment> like this:
  1699 +
  1700 + guestfs_h *g;
  1701 + int r;
  1702 +
  1703 + g = guestfs_create_flags (GUESTFS_CREATE_NO_ENVIRONMENT);
  1704 + if (!g)
  1705 + exit (EXIT_FAILURE);
  1706 + r = guestfs_parse_environment (g);
  1707 + if (!r)
  1708 + exit (EXIT_FAILURE);
  1709 +
  1710 +Or to create a handle which is unaffected by environment variables,
  1711 +omit the call to C<guestfs_parse_environment> from the above code.
  1712 +
  1713 +The above code has another advantage which is that any errors from
  1714 +parsing the environment are passed through the error handler, whereas
  1715 +C<guestfs_create> prints errors on stderr and ignores them.
  1716 +
1655 1717 =head2 guestfs_close
1656 1718
1657 1719 void guestfs_close (guestfs_h *g);
@@ -2785,7 +2847,7 @@ since these usually results in massive disk corruption).
2785 2847 libguestfs uses a state machine to model the child process:
2786 2848
2787 2849 |
2788   - guestfs_create
  2850 + guestfs_create / guestfs_create_flags
2789 2851 |
2790 2852 |
2791 2853 ____V_____

0 comments on commit 9466060

Please sign in to comment.
Something went wrong with that request. Please try again.