X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=src%2Fguestfs.c;h=1fa3c0aec3c6d29e9bc88a96c6b035b1ab6e2240;hb=d82438431c1551610eb7d9945fa76d6387534582;hp=776214e49a6abd2837cc100d896922b75cb62583;hpb=4e0cf4dbf8a8a96288f70114fdc3939da0aa7ad1;p=libguestfs.git diff --git a/src/guestfs.c b/src/guestfs.c index 776214e..1fa3c0a 100644 --- a/src/guestfs.c +++ b/src/guestfs.c @@ -1,5 +1,5 @@ /* libguestfs - * Copyright (C) 2009-2010 Red Hat Inc. + * Copyright (C) 2009-2011 Red Hat Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -72,6 +72,7 @@ #include "guestfs_protocol.h" static void default_error_cb (guestfs_h *g, void *data, const char *msg); +static void remove_tmpdir (guestfs_h *g); static void close_handles (void); gl_lock_define_initialized (static, handles_lock); @@ -168,16 +169,19 @@ guestfs_create (void) void guestfs_close (guestfs_h *g) { - int i; - char filename[256]; - guestfs_h *gg; - if (g->state == NO_HANDLE) { /* Not safe to call ANY callbacks here, so ... */ fprintf (stderr, _("guestfs_close: called twice on the same handle\n")); return; } + if (g->trace) { + const char trace_msg[] = "close"; + + guestfs___call_callbacks_message (g, GUESTFS_EVENT_TRACE, + trace_msg, strlen (trace_msg)); + } + debug (g, "closing guestfs handle %p (state %d)", g, g->state); /* Try to sync if autosync flag is set. */ @@ -215,17 +219,12 @@ guestfs_close (guestfs_h *g) if (g->pid > 0) waitpid (g->pid, NULL, 0); if (g->recoverypid > 0) waitpid (g->recoverypid, NULL, 0); - /* Remove tmpfiles. */ - if (g->tmpdir) { - snprintf (filename, sizeof filename, "%s/sock", g->tmpdir); - unlink (filename); - - rmdir (g->tmpdir); - - free (g->tmpdir); - } + /* Remove whole temporary directory. */ + remove_tmpdir (g); if (g->cmdline) { + size_t i; + for (i = 0; i < g->cmdline_size; ++i) free (g->cmdline[i]); free (g->cmdline); @@ -238,6 +237,8 @@ guestfs_close (guestfs_h *g) if (handles == g) handles = g->next; else { + guestfs_h *gg; + for (gg = handles; gg->next != g; gg = gg->next) ; gg->next = g->next; @@ -255,6 +256,43 @@ guestfs_close (guestfs_h *g) free (g); } +/* g->tmpdir can contain any files (but not subdirectories). Remove + * those and the directory itself. Note that errors in this function + * aren't really that important: if we end up not deleting temporary + * files it's only annoying. + */ +static void +remove_tmpdir (guestfs_h *g) +{ + DIR *dir; + struct dirent *d; + + if (!g->tmpdir) + return; + + dir = opendir (g->tmpdir); + if (dir == NULL) { + perror (g->tmpdir); + return; + } + + while ((d = readdir (dir)) != NULL) { + if (STRNEQ (d->d_name, ".") && STRNEQ (d->d_name, "..")) { + if (unlinkat (dirfd (dir), d->d_name, 0) == -1) + perror (d->d_name); + } + } + + if (closedir (dir) == -1) + perror (g->tmpdir); + + if (rmdir (g->tmpdir) == -1) + perror (g->tmpdir); + + free (g->tmpdir); + g->tmpdir = NULL; +} + /* Close all open handles (called from atexit(3)). */ static void close_handles (void) @@ -540,6 +578,12 @@ guestfs_get_error_handler (guestfs_h *g, void **data_rtn) return g->error_cb; } +void +guestfs_user_cancel (guestfs_h *g) +{ + g->user_cancel = 1; +} + int guestfs__set_verbose (guestfs_h *g, int v) { @@ -763,6 +807,19 @@ guestfs__get_attach_method (guestfs_h *g) return ret; } +int +guestfs__set_pgroup (guestfs_h *g, int v) +{ + g->pgroup = !!v; + return 0; +} + +int +guestfs__get_pgroup (guestfs_h *g) +{ + return g->pgroup; +} + /* Note the private data area is allocated lazily, since the vast * majority of callers will never use it. This means g->pda is * likely to be NULL.