int main (int argc, char *argv[]) { guestfs_h *g; int r, default_memsize; /* What's the default memsize? */ g = guestfs_create (); if (!g) error (EXIT_FAILURE, errno, "guestfs_create"); default_memsize = guestfs_get_memsize (g); if (default_memsize == -1) exit (EXIT_FAILURE); guestfs_close (g); /* Check that guestfs_create parses the environment. */ setenv ("LIBGUESTFS_MEMSIZE", "799", 1); g = guestfs_create (); if (!g) error (EXIT_FAILURE, errno, "guestfs_create"); assert (guestfs_get_memsize (g) == 799); guestfs_close (g); /* Check that guestfs_create_flags with no flags parses the environment. */ setenv ("LIBGUESTFS_MEMSIZE", "798", 1); g = guestfs_create_flags (0); if (!g) error (EXIT_FAILURE, errno, "guestfs_create_flags"); assert (guestfs_get_memsize (g) == 798); guestfs_close (g); /* Check guestfs_create_flags + explicit guestfs_parse_environment. */ setenv ("LIBGUESTFS_MEMSIZE", "797", 1); g = guestfs_create_flags (GUESTFS_CREATE_NO_ENVIRONMENT); assert (guestfs_get_memsize (g) == default_memsize); if (!g) error (EXIT_FAILURE, errno, "guestfs_create_flags"); setenv ("LIBGUESTFS_MEMSIZE", "796", 1); r = guestfs_parse_environment (g); if (r == -1) exit (EXIT_FAILURE); assert (guestfs_get_memsize (g) == 796); guestfs_close (g); /* Check guestfs_parse_environment_list. */ setenv ("LIBGUESTFS_MEMSIZE", "795", 1); g = guestfs_create_flags (GUESTFS_CREATE_NO_ENVIRONMENT); assert (guestfs_get_memsize (g) == default_memsize); if (!g) error (EXIT_FAILURE, errno, "guestfs_create_flags"); setenv ("LIBGUESTFS_MEMSIZE", "794", 1); const char *local_environment[] = { "LIBGUESTFS_MEMSIZE=793", "LIBGUESTFS_MEMSIZE_NOT_REALLY_A_VARIABLE=1", "FOO=bar", "HOME=/homes", "BLAH", NULL }; r = guestfs_parse_environment_list (g, (char **) local_environment); if (r == -1) exit (EXIT_FAILURE); assert (guestfs_get_memsize (g) == 793); guestfs_close (g); exit (EXIT_SUCCESS); }
int main (int argc, char *argv[]) { pthread_t thread[NR_THREADS]; int data[NR_THREADS]; int i, r, errors; guestfs_h *g; char *backend; /* Test is only meaningful if the backend "direct" is used. */ g = guestfs_create (); if (!g) error (EXIT_FAILURE, errno, "guestfs_create"); backend = guestfs_get_backend (g); if (backend == NULL) { guestfs_close (g); exit (EXIT_FAILURE); } if (STRNEQ (backend, "direct")) { fprintf (stderr, "%s: test skipped because backend isn't 'direct'.\n", guestfs_int_program_name); free (backend); guestfs_close (g); exit (77); } free (backend); guestfs_close (g); /* Ensure error messages are not translated. */ setenv ("LC_ALL", "C", 1); pthread_barrier_init (&barrier, NULL, NR_THREADS); /* Create the other threads which will set up their own libguestfs * handle then wait at a barrier before launching. */ for (i = 0; i < NR_THREADS; ++i) { data[i] = i; r = pthread_create (&thread[i], NULL, start_thread, &data[i]); if (r != 0) error (EXIT_FAILURE, r, "pthread_create"); } /* Wait for the threads to exit. */ errors = 0; for (i = 0; i < NR_THREADS; ++i) { int *ret; r = pthread_join (thread[i], (void **) &ret); if (r != 0) error (EXIT_FAILURE, r, "pthread_join"); if (*ret == -1) errors++; } exit (errors == 0 ? EXIT_SUCCESS : EXIT_FAILURE); }
static void run_test (void) { guestfs_h *g; size_t i; printf ("Warming up the libguestfs cache ...\n"); for (i = 0; i < NR_WARMUP_PASSES; ++i) { g = create_handle (); add_drive (g); if (guestfs_launch (g) == -1) exit (EXIT_FAILURE); guestfs_close (g); } printf ("Running the tests in %d passes ...\n", NR_TEST_PASSES); for (i = 0; i < NR_TEST_PASSES; ++i) { g = create_handle (); set_up_event_handlers (g, i); start_libvirt_thread (i); add_drive (g); if (guestfs_launch (g) == -1) exit (EXIT_FAILURE); guestfs_close (g); stop_libvirt_thread (); printf (" pass %zu: %zu events collected in %" PRIi64 " ns\n", i+1, pass_data[i].nr_events, pass_data[i].elapsed_ns); } if (verbose) dump_pass_data (); printf ("Analyzing the results ...\n"); check_pass_data (); construct_timeline (); analyze_timeline (); if (verbose) dump_timeline (); printf ("\n"); g = create_handle (); test_info (g, NR_TEST_PASSES); guestfs_close (g); printf ("\n"); print_analysis (); printf ("\n"); printf ("Longest activities:\n"); printf ("\n"); print_longest_to_shortest (); free_pass_data (); free_final_timeline (); }
int main (int argc, char *argv[]) { guestfs_h *g; int r; g = guestfs_create (); if (g == NULL) error (EXIT_FAILURE, errno, "guestfs_create"); /* If these fail, the default error handler will print an error * message to stderr, so we don't need to print anything. This code * is very pedantic, but after all we are testing the details of the * C API. */ if (guestfs_set_verbose (g, 1) == -1) exit (EXIT_FAILURE); r = guestfs_get_verbose (g); if (r == -1) exit (EXIT_FAILURE); if (!r) error (EXIT_FAILURE, 0, "set_verbose not true"); if (guestfs_set_verbose (g, 0) == -1) exit (EXIT_FAILURE); r = guestfs_get_verbose (g); if (r == -1) exit (EXIT_FAILURE); if (r) error (EXIT_FAILURE, 0, "set_verbose not false"); guestfs_close (g); exit (EXIT_SUCCESS); }
JNIEXPORT void JNICALL Java_com_redhat_et_libguestfs_GuestFS__1close (JNIEnv *env, jobject obj, jlong jg) { guestfs_h *g = (guestfs_h *) (long) jg; size_t len; struct callback_data **data; /* There is a nasty, difficult to solve case here where the * user deletes events in one of the callbacks that we are * about to invoke, resulting in a double-free. XXX */ data = get_all_event_callbacks (env, g, &len); guestfs_close (g); if (len > 0) { size_t i; for (i = 0; i < len; ++i) { (*env)->DeleteGlobalRef (env, data[i]->callback); free (data[i]); } free (data); } }
static void usage (int exitcode) { guestfs_h *g; int default_memsize = -1; g = guestfs_create (); if (g) { default_memsize = guestfs_get_memsize (g); guestfs_close (g); } fprintf (stderr, "boot-analysis: Trace and analyze the appliance boot process.\n" "Usage:\n" " boot-analysis [--options]\n" "Options:\n" " --help Display this usage text and exit.\n" " --append OPTS Append OPTS to kernel command line.\n" " --colour Output colours, even if not a terminal.\n" " -m MB\n" " --memsize MB Set memory size in MB (default: %d).\n" " --smp N Enable N virtual CPUs (default: 1).\n" " -v|--verbose Verbose output, useful for debugging.\n", default_memsize); exit (exitcode); }
static void test_stringsbuf (void) { guestfs_h *g; DECLARE_STRINGSBUF (sb); g = guestfs_create (); assert (g); guestfs_int_add_string (g, &sb, "aaa"); guestfs_int_add_string (g, &sb, "bbb"); guestfs_int_add_string (g, &sb, "ccc"); guestfs_int_add_string (g, &sb, ""); guestfs_int_end_stringsbuf (g, &sb); assert (sb.size == 5 /* 4 strings + terminating NULL */); assert (STREQ (sb.argv[0], "aaa")); assert (STREQ (sb.argv[1], "bbb")); assert (STREQ (sb.argv[2], "ccc")); assert (STREQ (sb.argv[3], "")); assert (sb.argv[4] == NULL); assert (guestfs_int_count_strings (sb.argv) == 4); guestfs_int_free_stringsbuf (&sb); guestfs_close (g); }
static void test_match (void) { guestfs_h *g; char *ret, *ret2; g = guestfs_create (); assert (g); assert (match (g, "aaaaab", test_match_re)); assert (! match (g, "aaaaacb", test_match_re)); assert (! match (g, "", test_match_re)); ret = match1 (g, "aaab", test_match1_re); assert (STREQ (ret, "aaa")); free (ret); assert (! match1 (g, "aaacb", test_match1_re)); assert (! match1 (g, "", test_match1_re)); assert (match2 (g, "aaabc", test_match2_re, &ret, &ret2)); assert (STREQ (ret, "aaa")); assert (STREQ (ret2, "b")); free (ret); free (ret2); guestfs_close (g); }
PyObject * py_guestfs_close (PyObject *self, PyObject *args) { PyThreadState *py_save = NULL; PyObject *py_g; guestfs_h *g; size_t i, len; PyObject **callbacks; if (!PyArg_ParseTuple (args, (char *) "O:guestfs_close", &py_g)) return NULL; g = get_handle (py_g); /* As in the OCaml bindings, there is a hard to solve case where the * caller can delete a callback from within the callback, resulting * in a double-free here. XXX */ callbacks = get_all_event_callbacks (g, &len); if (PyEval_ThreadsInitialized ()) py_save = PyEval_SaveThread (); guestfs_close (g); if (PyEval_ThreadsInitialized ()) PyEval_RestoreThread (py_save); for (i = 0; i < len; ++i) Py_XDECREF (callbacks[i]); free (callbacks); Py_INCREF (Py_None); return Py_None; }
/** * Test C<guestfs_int_new_command> etc. * * XXX These tests could be made much more thorough. So far we simply * test that it's not obviously broken. */ static void test_command (void) { guestfs_h *g; struct command *cmd; int r; g = guestfs_create (); assert (g); /* argv-style */ cmd = guestfs_int_new_command (g); assert (cmd); guestfs_int_cmd_add_arg (cmd, "touch"); guestfs_int_cmd_add_arg (cmd, "test-utils-test-command"); r = guestfs_int_cmd_run (cmd); assert (r == 0); guestfs_int_cmd_close (cmd); /* system-style */ cmd = guestfs_int_new_command (g); assert (cmd); guestfs_int_cmd_add_string_unquoted (cmd, "rm "); guestfs_int_cmd_add_string_quoted (cmd, "test-utils-test-command"); r = guestfs_int_cmd_run (cmd); assert (r == 0); guestfs_int_cmd_close (cmd); guestfs_close (g); }
/* Allocate handles and deal with finalization. */ static void guestfs_finalize (value gv) { guestfs_h *g = Guestfs_val (gv); if (g) { /* There is a nasty, difficult to solve case here where the * user deletes events in one of the callbacks that we are * about to invoke, resulting in a double-free. XXX */ size_t len, i; value **roots = get_all_event_callbacks (g, &len); value *v = guestfs_get_private (g, "_ocaml_g"); /* Close the handle: this could invoke callbacks from the list * above, which is why we don't want to delete them before * closing the handle. */ guestfs_close (g); /* Now unregister the global roots. */ for (i = 0; i < len; ++i) { caml_remove_global_root (roots[i]); free (roots[i]); } free (roots); caml_remove_global_root (v); free (v); } }
int main (int argc, char *argv[]) { guestfs_h *g = guestfs_create (); /* Call some non-daemon functions that have a String parameter, but * setting that parameter to NULL. Previously this would cause a * segfault inside libguestfs. After this bug was fixed, this * turned into an error message. */ assert (guestfs_add_drive (g, NULL) == -1); assert (guestfs_config (g, NULL, NULL) == -1); /* This optional argument must not be NULL. */ assert (guestfs_add_drive_opts (g, "/dev/null", GUESTFS_ADD_DRIVE_OPTS_FORMAT, NULL, -1) == -1); /* These can be safely set to NULL, should be no error. */ assert (guestfs_set_path (g, NULL) == 0); assert (guestfs_set_append (g, NULL) == 0); assert (guestfs_set_qemu (g, NULL) == 0); guestfs_close (g); exit (EXIT_SUCCESS); }
int main (int argc, char *argv[]) { guestfs_h *g; const char *key; void *data; size_t count; g = guestfs_create (); if (g == NULL) error (EXIT_FAILURE, errno, "guestfs_create"); if (guestfs_set_event_callback (g, close_callback, GUESTFS_EVENT_CLOSE, 0, NULL) == -1) exit (EXIT_FAILURE); guestfs_set_private (g, PREFIX "a", (void *) 1); guestfs_set_private (g, PREFIX "b", (void *) 2); guestfs_set_private (g, PREFIX "c", (void *) 3); guestfs_set_private (g, PREFIX "a", (void *) 4); /* overwrites previous */ /* Check we can fetch keys. */ assert (guestfs_get_private (g, PREFIX "a") == (void *) 4); assert (guestfs_get_private (g, PREFIX "b") == (void *) 2); assert (guestfs_get_private (g, PREFIX "c") == (void *) 3); assert (guestfs_get_private (g, PREFIX "d") == NULL); /* Check we can count keys by iterating. */ count = 0; data = guestfs_first_private (g, &key); while (data != NULL) { if (strncmp (key, PREFIX, strlen (PREFIX)) == 0) count++; data = guestfs_next_private (g, &key); } assert (count == 3); /* Delete some keys. */ guestfs_set_private (g, PREFIX "a", NULL); guestfs_set_private (g, PREFIX "b", NULL); /* Count them again. */ count = 0; data = guestfs_first_private (g, &key); while (data != NULL) { if (strncmp (key, PREFIX, strlen (PREFIX)) == 0) count++; data = guestfs_next_private (g, &key); } assert (count == 1); /* Closing should implicitly call the close_callback function. */ guestfs_close (g); assert (close_callback_called == 1); exit (EXIT_SUCCESS); }
int main (int argc, char *argv[]) { guestfs_h *g; int r; char *data; size_t i, size; if (test_start_nbdkit ("-n", NBDKIT_PLUGIN ("file"), "file=file-data", NULL) == -1) exit (EXIT_FAILURE); g = guestfs_create (); if (g == NULL) { perror ("guestfs_create"); exit (EXIT_FAILURE); } /* Using any exportname causes qemu to use the newstyle protocol. */ r = guestfs_add_drive_opts (g, "/" /* exportname */, GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw", GUESTFS_ADD_DRIVE_OPTS_PROTOCOL, "nbd", GUESTFS_ADD_DRIVE_OPTS_SERVER, server, -1); if (r == -1) exit (EXIT_FAILURE); if (guestfs_launch (g) == -1) exit (EXIT_FAILURE); /* Check the data in the file is \x01-\x08 repeated 512 times. */ data = guestfs_pread_device (g, "/dev/sda", 8 * 512, 0, &size); if (!data) exit (EXIT_FAILURE); if (size != 8 * 512) { fprintf (stderr, "%s FAILED: unexpected size (actual: %zu, expected: 512)\n", program_name, size); exit (EXIT_FAILURE); } for (i = 0; i < 512 * 8; i += 8) { if (data[i] != 1 || data[i+1] != 2 || data[i+2] != 3 || data[i+3] != 4 || data[i+4] != 5 || data[i+5] != 6 || data[i+6] != 7 || data[i+7] != 8) { fprintf (stderr, "%s FAILED: unexpected data returned at offset %zu\n", program_name, i); exit (EXIT_FAILURE); } } free (data); guestfs_close (g); exit (EXIT_SUCCESS); }
int main (int argc, char *argv[]) { char *str; guestfs_h *g; char tmp[] = "/tmp/charsetXXXXXX"; int fd; size_t i; struct filesystem *fs; /* Allow this test to be skipped. */ str = getenv ("SKIP_TEST_CHARSET_FIDELITY"); if (str && STREQ (str, "1")) { printf ("%s: test skipped because environment variable is set.\n", argv[0]); exit (77); } g = guestfs_create (); if (g == NULL) error (EXIT_FAILURE, 0, "failed to create handle"); fd = mkstemp (tmp); if (fd == -1) error (EXIT_FAILURE, errno, "mkstemp"); if (ftruncate (fd, 1024 * 1024 * 1024) == -1) error (EXIT_FAILURE, errno, "ftruncate: %s", tmp); if (close (fd) == -1) error (EXIT_FAILURE, errno, "close: %s", tmp); if (guestfs_add_drive_opts (g, tmp, -1) == -1) exit (EXIT_FAILURE); if (guestfs_launch (g) == -1) exit (EXIT_FAILURE); if (guestfs_part_disk (g, "/dev/sda", "mbr") == -1) exit (EXIT_FAILURE); for (i = 0; i < sizeof filesystems / sizeof filesystems[0]; ++i) { fs = &filesystems[i]; test_filesystem (g, fs); } guestfs_close (g); unlink (tmp); exit (EXIT_SUCCESS); }
int main (int argc, char *argv[]) { guestfs_h *g; size_t i; int lengths[] = { 0, 1, 1024, GUESTFS_ERROR_LEN-2, GUESTFS_ERROR_LEN-1, GUESTFS_ERROR_LEN, GUESTFS_ERROR_LEN+1, GUESTFS_ERROR_LEN+2, GUESTFS_ERROR_LEN*2, -1 }; char len_s[64]; char *args[2]; g = guestfs_create (); if (g == NULL) { perror ("guestfs_create"); exit (EXIT_FAILURE); } if (guestfs_add_drive (g, "/dev/null") == -1) exit (EXIT_FAILURE); if (guestfs_launch (g) == -1) exit (EXIT_FAILURE); guestfs_push_error_handler (g, NULL, NULL); for (i = 0; lengths[i] != -1; ++i) { snprintf (len_s, sizeof len_s, "%d", lengths[i]); args[0] = len_s; args[1] = NULL; if (guestfs_debug (g, "error", args) != NULL) { fprintf (stderr, "%s: unexpected return value from 'debug error'\n", argv[0]); exit (EXIT_FAILURE); } /* EROFS is a magic value returned by debug_error in the daemon. */ if (guestfs_last_errno (g) != EROFS) { fprintf (stderr, "%s: unexpected error from 'debug error': %s\n", argv[0], guestfs_last_error (g)); exit (EXIT_FAILURE); } /* else OK */ } guestfs_pop_error_handler (g); guestfs_close (g); exit (EXIT_SUCCESS); }
int main (int argc, char *argv[]) { guestfs_h *g; g = guestfs_create (); if (g == NULL) { fprintf (stderr, "failed to create handle\n"); exit (EXIT_FAILURE); } guestfs_close (g); exit (EXIT_SUCCESS); }
static size_t add_disks_to_handle_reverse (struct disk *disk, size_t *errors_r) { size_t nr_disks_added; if (disk == NULL) return 0; nr_disks_added = add_disks_to_handle_reverse (disk->next, errors_r); struct guestfs_add_drive_opts_argv optargs = { .bitmask = 0 }; optargs.bitmask |= GUESTFS_ADD_DRIVE_OPTS_READONLY_BITMASK; optargs.readonly = 1; if (disk->format) { optargs.bitmask |= GUESTFS_ADD_DRIVE_OPTS_FORMAT_BITMASK; optargs.format = disk->format; } if (guestfs_add_drive_opts_argv (g, disk->filename, &optargs) == -1) { (*errors_r)++; disk->failed = 1; return nr_disks_added; } return nr_disks_added+1; } /* Close and reopen the libguestfs handle. */ static void reset_guestfs_handle (void) { /* Copy the settings from the old handle. */ int verbose = guestfs_get_verbose (g); int trace = guestfs_get_trace (g); guestfs_close (g); g = guestfs_create (); if (g == NULL) { fprintf (stderr, _("guestfs_create: failed to create handle\n")); exit (EXIT_FAILURE); } guestfs_set_verbose (g, verbose); guestfs_set_trace (g, trace); }
int main (int argc, char *argv[]) { guestfs_h *g; const char *filename = "test.log"; FILE *debugfp; debugfp = fopen (filename, "w"); if (debugfp == NULL) { perror (filename); exit (EXIT_FAILURE); } g = guestfs_create (); if (g == NULL) { fprintf (stderr, "failed to create handle\n"); exit (EXIT_FAILURE); } if (guestfs_set_event_callback (g, debug_to_file, GUESTFS_EVENT_LIBRARY | GUESTFS_EVENT_APPLIANCE | GUESTFS_EVENT_WARNING | GUESTFS_EVENT_TRACE, 0, debugfp) == -1) exit (EXIT_FAILURE); if (guestfs_set_verbose (g, 1) == -1) exit (EXIT_FAILURE); if (guestfs_set_trace (g, 1) == -1) exit (EXIT_FAILURE); if (guestfs_add_drive_opts (g, "/dev/null", GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw", GUESTFS_ADD_DRIVE_OPTS_READONLY, 1, -1) == -1) exit (EXIT_FAILURE); if (guestfs_launch (g) == -1) exit (EXIT_FAILURE); guestfs_close (g); exit (EXIT_SUCCESS); }
/** * Test C<guestfs_int_qemu_escape_param> * * XXX I wanted to make this test run qemu, passing some parameters * which need to be escaped, but I cannot think of a way to do that * without launching a VM. */ static void test_qemu_escape_param (void) { CLEANUP_FREE char *ret1 = NULL, *ret2 = NULL, *ret3 = NULL; guestfs_h *g; g = guestfs_create (); assert (g); ret1 = guestfs_int_qemu_escape_param (g, "name,with,commas"); assert (STREQ (ret1, "name,,with,,commas")); ret2 = guestfs_int_qemu_escape_param (g, ",,,,"); assert (STREQ (ret2, ",,,,,,,,")); ret3 = guestfs_int_qemu_escape_param (g, ""); assert (STREQ (ret3, "")); guestfs_close (g); }
int main (int argc, char *argv[]) { void *lib; guestfs_create_t guestfs_create; guestfs_get_program_t guestfs_get_program; guestfs_close_t guestfs_close; guestfs_h *g; if (access (LIBRARY, X_OK) == -1) { fprintf (stderr, "test skipped because %s cannot be accessed: %m\n", LIBRARY); exit (77); } lib = dlopen (LIBRARY, RTLD_LAZY); if (lib == NULL) { fprintf (stderr, "could not open %s: %s\n", LIBRARY, dlerror ()); exit (EXIT_FAILURE); } guestfs_create = read_symbol (lib, "guestfs_create"); guestfs_get_program = read_symbol (lib, "guestfs_get_program"); guestfs_close = read_symbol (lib, "guestfs_close"); g = guestfs_create (); if (g == NULL) { fprintf (stderr, "failed to create handle\n"); exit (EXIT_FAILURE); } printf ("program = %s\n", guestfs_get_program (g)); guestfs_close (g); if (dlclose (lib) != 0) { fprintf (stderr, "could not close %s: %s\n", LIBRARY, dlerror ()); exit (EXIT_FAILURE); } exit (EXIT_SUCCESS); }
/** * Test C<guestfs_int_getumask>. */ static void test_getumask (void) { guestfs_h *g; int orig_umask = umask (0777); g = guestfs_create (); assert (g); assert (guestfs_int_getumask (g) == 0777); umask (0022); assert (guestfs_int_getumask (g) == 0022); assert (guestfs_int_getumask (g) == 0022); umask (0222); assert (guestfs_int_getumask (g) == 0222); umask (0000); assert (guestfs_int_getumask (g) == 0000); umask (orig_umask); /* Restore original umask. */ guestfs_close (g); }
int main (int argc, char *argv[]) { char *str; guestfs_h *g; size_t i; struct filesystem *fs; /* Allow this test to be skipped. */ str = getenv (ourenvvar); if (str && STREQ (str, "1")) { printf ("%s: test skipped because environment variable is set.\n", program_name); exit (77); } g = guestfs_create (); if (g == NULL) error (EXIT_FAILURE, 0, "failed to create handle"); if (guestfs_add_drive_scratch (g, 1024*1024*1024, -1) == -1) exit (EXIT_FAILURE); if (guestfs_launch (g) == -1) exit (EXIT_FAILURE); if (guestfs_part_disk (g, "/dev/sda", "mbr") == -1) exit (EXIT_FAILURE); for (i = 0; i < sizeof filesystems / sizeof filesystems[0]; ++i) { fs = &filesystems[i]; test_filesystem (g, fs); } guestfs_close (g); exit (EXIT_SUCCESS); }
int main (int argc, char *argv[]) { size_t nr_failed; guestfs_h *g; setbuf (stdout, NULL); no_test_warnings (); g = create_handle (); nr_failed = perform_tests (g); guestfs_close (g); if (nr_failed > 0) { printf ("***** %zu / %zu tests FAILED *****\n", nr_failed, nr_tests); exit (EXIT_FAILURE); } exit (EXIT_SUCCESS); }
static void * start_srcthread (void *arg) { struct threaddata *threaddata = arg; guestfs_h *srcg; char fdname[128]; /* Open the source domain. */ srcg = guestfs_create (); if (!srcg) { perror ("failed to create libguestfs handle"); pthread_cancel (threaddata->mainthread); exit (EXIT_FAILURE); } if (open_guest (srcg, threaddata->src, 1) == -1) { pthread_cancel (threaddata->mainthread); exit (EXIT_FAILURE); } /* Begin the download. */ snprintf (fdname, sizeof fdname, "/dev/fd/%d", threaddata->fd); if (guestfs_tar_out (srcg, threaddata->srcdir, fdname) == -1) { pthread_cancel (threaddata->mainthread); exit (EXIT_FAILURE); } /* Close the pipe; this will cause the receiver to finish the upload. */ if (close (threaddata->fd) == -1) { pthread_cancel (threaddata->mainthread); exit (EXIT_FAILURE); } /* Clean up. */ guestfs_close (srcg); return NULL; }
int main (int argc, char *argv[]) { /* Current time for --time-days, --time-relative output. */ time (&now); setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEBASEDIR); textdomain (PACKAGE); enum { HELP_OPTION = CHAR_MAX + 1 }; static const char *options = "a:c:d:hlRvVx"; static const struct option long_options[] = { { "add", 1, 0, 'a' }, { "checksum", 2, 0, 0 }, { "checksums", 2, 0, 0 }, { "csv", 0, 0, 0 }, { "connect", 1, 0, 'c' }, { "domain", 1, 0, 'd' }, { "echo-keys", 0, 0, 0 }, { "extra-stat", 0, 0, 0 }, { "extra-stats", 0, 0, 0 }, { "format", 2, 0, 0 }, { "help", 0, 0, HELP_OPTION }, { "human-readable", 0, 0, 'h' }, { "keys-from-stdin", 0, 0, 0 }, { "long", 0, 0, 'l' }, { "long-options", 0, 0, 0 }, { "recursive", 0, 0, 'R' }, { "time", 0, 0, 0 }, { "times", 0, 0, 0 }, { "time-days", 0, 0, 0 }, { "time-relative", 0, 0, 0 }, { "time-t", 0, 0, 0 }, { "uid", 0, 0, 0 }, { "uids", 0, 0, 0 }, { "verbose", 0, 0, 'v' }, { "version", 0, 0, 'V' }, { 0, 0, 0, 0 } }; struct drv *drvs = NULL; struct drv *drv; const char *format = NULL; int c; int option_index; #define MODE_LS_L 1 #define MODE_LS_R 2 #define MODE_LS_LR (MODE_LS_L|MODE_LS_R) int mode = 0; g = guestfs_create (); if (g == NULL) { fprintf (stderr, _("guestfs_create: failed to create handle\n")); exit (EXIT_FAILURE); } for (;;) { c = getopt_long (argc, argv, options, long_options, &option_index); if (c == -1) break; switch (c) { case 0: /* options which are long only */ if (STREQ (long_options[option_index].name, "long-options")) display_long_options (long_options); else if (STREQ (long_options[option_index].name, "keys-from-stdin")) { keys_from_stdin = 1; } else if (STREQ (long_options[option_index].name, "echo-keys")) { echo_keys = 1; } else if (STREQ (long_options[option_index].name, "format")) { if (!optarg || STREQ (optarg, "")) format = NULL; else format = optarg; } else if (STREQ (long_options[option_index].name, "checksum") || STREQ (long_options[option_index].name, "checksums")) { if (!optarg || STREQ (optarg, "")) checksum = "md5"; else checksum = optarg; } else if (STREQ (long_options[option_index].name, "csv")) { csv = 1; } else if (STREQ (long_options[option_index].name, "extra-stat") || STREQ (long_options[option_index].name, "extra-stats")) { enable_extra_stats = 1; } else if (STREQ (long_options[option_index].name, "time") || STREQ (long_options[option_index].name, "times")) { enable_times = 1; } else if (STREQ (long_options[option_index].name, "time-t")) { enable_times = 1; time_t_output = 1; } else if (STREQ (long_options[option_index].name, "time-relative")) { enable_times = 1; time_t_output = 1; time_relative = 1; } else if (STREQ (long_options[option_index].name, "time-days")) { enable_times = 1; time_t_output = 1; time_relative = 2; } else if (STREQ (long_options[option_index].name, "uid") || STREQ (long_options[option_index].name, "uids")) { enable_uids = 1; } else { fprintf (stderr, _("%s: unknown long option: %s (%d)\n"), program_name, long_options[option_index].name, option_index); exit (EXIT_FAILURE); } break; case 'a': OPTION_a; break; case 'c': OPTION_c; break; case 'd': OPTION_d; break; case 'h': human = 1; break; case 'l': mode |= MODE_LS_L; break; case 'R': mode |= MODE_LS_R; break; case 'v': OPTION_v; break; case 'V': OPTION_V; break; case 'x': OPTION_x; break; case HELP_OPTION: usage (EXIT_SUCCESS); default: usage (EXIT_FAILURE); } } /* Old-style syntax? There were no -a or -d options in the old * virt-ls which is how we detect this. */ if (drvs == NULL) { /* argc - 1 because last parameter is the single directory name. */ while (optind < argc - 1) { if (strchr (argv[optind], '/') || access (argv[optind], F_OK) == 0) { /* simulate -a option */ drv = calloc (1, sizeof (struct drv)); if (!drv) { perror ("malloc"); exit (EXIT_FAILURE); } drv->type = drv_a; drv->a.filename = strdup (argv[optind]); if (!drv->a.filename) { perror ("strdup"); exit (EXIT_FAILURE); } drv->next = drvs; drvs = drv; } else { /* simulate -d option */ drv = calloc (1, sizeof (struct drv)); if (!drv) { perror ("malloc"); exit (EXIT_FAILURE); } drv->type = drv_d; drv->d.guest = argv[optind]; drv->next = drvs; drvs = drv; } optind++; } } /* These are really constants, but they have to be variables for the * options parsing code. Assert here that they have known-good * values. */ assert (read_only == 1); assert (inspector == 1); assert (live == 0); /* Many flags only apply to -lR mode. */ if (mode != MODE_LS_LR && (csv || human || enable_uids || enable_times || enable_extra_stats || checksum)) { fprintf (stderr, _("%s: used a flag which can only be combined with -lR mode\nFor more information, read the virt-ls(1) man page.\n"), program_name); exit (EXIT_FAILURE); } /* CSV && human is unsafe because spreadsheets fail to parse these * fields correctly. (RHBZ#600977). */ if (human && csv) { fprintf (stderr, _("%s: you cannot use -h and --csv options together.\n"), program_name); exit (EXIT_FAILURE); } /* User must specify at least one directory name on the command line. */ if (optind >= argc || argc - optind < 1) usage (EXIT_FAILURE); /* User must have specified some drives. */ if (drvs == NULL) usage (EXIT_FAILURE); /* Add drives, inspect and mount. Note that inspector is always true, * and there is no -m option. */ add_drives (drvs, 'a'); if (guestfs_launch (g) == -1) exit (EXIT_FAILURE); inspect_mount (); /* Free up data structures, no longer needed after this point. */ free_drives (drvs); unsigned errors = 0; while (optind < argc) { const char *dir = argv[optind]; switch (mode) { case 0: /* no -l or -R option */ if (do_ls (dir) == -1) errors++; break; case MODE_LS_L: /* virt-ls -l */ if (do_ls_l (dir) == -1) errors++; break; case MODE_LS_R: /* virt-ls -R */ if (do_ls_R (dir) == -1) errors++; break; case MODE_LS_LR: /* virt-ls -lR */ if (do_ls_lR (dir) == -1) errors++; break; default: abort (); /* can't happen */ } optind++; } guestfs_close (g); exit (errors == 0 ? EXIT_SUCCESS : EXIT_FAILURE); }
/* Worker thread. */ static void * start_thread (void *thread_data_vp) { struct thread_data *thread_data = thread_data_vp; int quit = 0; int err; size_t i; guestfs_h *g; unsigned errors = 0; for (;;) { /* Take the next process. */ err = pthread_mutex_lock (&mutex); if (err != 0) { fprintf (stderr, "%s: pthread_mutex_lock: %s", guestfs_int_program_name, strerror (err)); goto error; } i = n; if (i > 0) { printf ("%zu to go ... \r", n); fflush (stdout); n--; } else quit = 1; err = pthread_mutex_unlock (&mutex); if (err != 0) { fprintf (stderr, "%s: pthread_mutex_unlock: %s", guestfs_int_program_name, strerror (err)); goto error; } if (quit) /* Work finished. */ break; g = guestfs_create (); if (g == NULL) { perror ("guestfs_create"); errors++; if (!ignore_errors) goto error; } guestfs_set_trace (g, trace); guestfs_set_verbose (g, verbose); if (guestfs_add_drive_ro (g, "/dev/null") == -1) { errors++; if (!ignore_errors) goto error; } if (guestfs_launch (g) == -1) { errors++; if (!ignore_errors) goto error; } if (guestfs_shutdown (g) == -1) { errors++; if (!ignore_errors) goto error; } guestfs_close (g); } if (errors > 0) { fprintf (stderr, "%s: thread %d: %u errors were ignored\n", guestfs_int_program_name, thread_data->thread_num, errors); goto error; } thread_data->r = 0; return &thread_data->r; error: thread_data->r = -1; return &thread_data->r; }
int main (int argc, char *argv[]) { pthread_t thread[NR_THREADS]; int data[NR_THREADS]; int i, r, errors; guestfs_h *g; char *attach_method; /* Test is only meaningful if the attach-method "appliance" is used. */ g = guestfs_create (); if (!g) { perror ("guestfs_create"); exit (EXIT_FAILURE); } attach_method = guestfs_get_attach_method (g); if (attach_method == NULL) { guestfs_close (g); exit (EXIT_FAILURE); } if (STRNEQ (attach_method, "appliance")) { fprintf (stderr, "%s: test skipped because attach method isn't 'appliance'.\n", argv[0]); free (attach_method); guestfs_close (g); exit (77); } free (attach_method); guestfs_close (g); /* Ensure error messages are not translated. */ setenv ("LC_ALL", "C", 1); pthread_barrier_init (&barrier, NULL, NR_THREADS); /* Create the other threads which will set up their own libguestfs * handle then wait at a barrier before launching. */ for (i = 0; i < NR_THREADS; ++i) { data[i] = i; r = pthread_create (&thread[i], NULL, start_thread, &data[i]); if (r != 0) { fprintf (stderr, "pthread_create: %s\n", strerror (r)); exit (EXIT_FAILURE); } } /* Wait for the threads to exit. */ errors = 0; for (i = 0; i < NR_THREADS; ++i) { int *ret; r = pthread_join (thread[i], (void **) &ret); if (r != 0) { fprintf (stderr, "pthread_join: %s\n", strerror (r)); exit (EXIT_FAILURE); } if (*ret == -1) errors++; } exit (errors == 0 ? EXIT_SUCCESS : EXIT_FAILURE); }
static void * start_thread (void *vi) { guestfs_h *g; int r, thread_id = *(int *)vi; const char *error; g = guestfs_create (); if (g == NULL) { perror ("guestfs_create"); *(int *)vi = -1; pthread_exit (vi); } if (guestfs_add_drive_opts (g, "/dev/null", GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw", GUESTFS_ADD_DRIVE_OPTS_READONLY, 1, -1) == -1) { *(int *)vi = -1; pthread_exit (vi); } /* Fake out qemu. */ if (guestfs_set_qemu (g, "/bin/true") == -1) { *(int *)vi = -1; pthread_exit (vi); } /* Wait for the other threads to finish starting up. */ r = pthread_barrier_wait (&barrier); if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD) { fprintf (stderr, "pthread_barrier_wait: [thread %d]: %s\n", thread_id, strerror (r)); *(int *)vi = -1; pthread_exit (vi); } /* Launch the handle. Because of the faked out qemu, we expect this * will fail with "child process died unexpectedly". We are * interested in other failures. */ guestfs_push_error_handler (g, NULL, NULL); r = guestfs_launch (g); error = guestfs_last_error (g); if (r == 0) { /* This should NOT happen. */ fprintf (stderr, "rhbz790721: [thread %d]: " "strangeness in test: expected launch to fail, but it didn't!\n", thread_id); *(int *)vi = -1; pthread_exit (vi); } if (error == NULL) { /* This also should NOT happen. */ fprintf (stderr, "rhbz790721: [thread %d]: " "strangeness in test: no error message!\n", thread_id); *(int *)vi = -1; pthread_exit (vi); } /* If this happens, it indicates a bug/race in the appliance * building code which is what this regression test is designed to * spot. */ if (STRNEQ (error, "child process died unexpectedly")) { fprintf (stderr, "rhbz790721: [thread %d]: error: %s\n", thread_id, error); *(int *)vi = -1; pthread_exit (vi); } guestfs_pop_error_handler (g); /* Close the handle. */ guestfs_close (g); *(int *)vi = 0; pthread_exit (vi); }
/* Close all open handles (called from atexit(3)). */ static void close_handles (void) { while (handles) guestfs_close (handles); }