void prep_postlaunch_lv (const char *filename, prep_data *data, const char *device) { if (guestfs_part_disk (g, device, data->params[2]) == -1) prep_error (data, filename, _("failed to partition disk: %s"), guestfs_last_error (g)); CLEANUP_FREE char *vg; CLEANUP_FREE char *lv; if (vg_lv_parse (data->params[0], &vg, &lv) == -1) prep_error (data, filename, _("incorrect format for LV name, use '/dev/VG/LV'")); CLEANUP_FREE char *part; if (asprintf (&part, "%s1", device) == -1) { perror ("asprintf"); exit (EXIT_FAILURE); } if (guestfs_pvcreate (g, part) == -1) prep_error (data, filename, _("failed to create PV: %s: %s"), part, guestfs_last_error (g)); char *parts[] = { part, NULL }; if (guestfs_vgcreate (g, vg, parts) == -1) prep_error (data, filename, _("failed to create VG: %s: %s"), vg, guestfs_last_error (g)); /* Create the largest possible LV. */ if (guestfs_lvcreate_free (g, lv, vg, 100) == -1) prep_error (data, filename, _("failed to create LV: /dev/%s/%s: %s"), vg, lv, guestfs_last_error (g)); }
void prep_postlaunch_bootrootlv (const char *filename, prep_data *data, const char *device) { off_t bootsize; if (parse_size (data->params[4], &bootsize) == -1) prep_error (data, filename, _("could not parse boot size")); const int sector = guestfs_blockdev_getss (g, device); if (sector == -1) prep_error (data, filename, _("failed to get sector size of disk: %s"), guestfs_last_error (g)); if (guestfs_part_init (g, device, data->params[5]) == -1) prep_error (data, filename, _("failed to partition disk: %s"), guestfs_last_error (g)); off_t lastbootsect = 64 + bootsize/sector - 1; if (guestfs_part_add (g, device, "primary", 64, lastbootsect) == -1) prep_error (data, filename, _("failed to add boot partition: %s"), guestfs_last_error (g)); if (guestfs_part_add (g, device, "primary", lastbootsect+1, -64) == -1) prep_error (data, filename, _("failed to add root partition: %s"), guestfs_last_error (g)); CLEANUP_FREE char *vg; CLEANUP_FREE char *lv; if (vg_lv_parse (data->params[0], &vg, &lv) == -1) prep_error (data, filename, _("incorrect format for LV name, use '/dev/VG/LV'")); CLEANUP_FREE char *part; if (asprintf (&part, "%s1", device) == -1) error (EXIT_FAILURE, errno, "asprintf"); if (guestfs_mkfs (g, data->params[1], part) == -1) prep_error (data, filename, _("failed to create boot filesystem: %s"), guestfs_last_error (g)); CLEANUP_FREE char *part2; if (asprintf (&part2, "%s2", device) == -1) error (EXIT_FAILURE, errno, "asprintf"); if (guestfs_pvcreate (g, part2) == -1) prep_error (data, filename, _("failed to create PV: %s: %s"), part2, guestfs_last_error (g)); char *parts[] = { part2, NULL }; if (guestfs_vgcreate (g, vg, parts) == -1) prep_error (data, filename, _("failed to create VG: %s: %s"), vg, guestfs_last_error (g)); /* Create the largest possible LV. */ if (guestfs_lvcreate_free (g, lv, vg, 100) == -1) prep_error (data, filename, _("failed to create LV: /dev/%s/%s: %s"), vg, lv, guestfs_last_error (g)); if (guestfs_mkfs (g, data->params[2], data->params[0]) == -1) prep_error (data, filename, _("failed to create root filesystem: %s"), guestfs_last_error (g)); }
void prep_postlaunch_fs (const char *filename, prep_data *data, const char *device) { if (guestfs_part_disk (g, device, data->params[2]) == -1) prep_error (data, filename, _("failed to partition disk: %s"), guestfs_last_error (g)); CLEANUP_FREE char *part; if (asprintf (&part, "%s1", device) == -1) error (EXIT_FAILURE, errno, "asprintf"); if (guestfs_mkfs (g, data->params[0], part) == -1) prep_error (data, filename, _("failed to create filesystem (%s): %s"), data->params[0], guestfs_last_error (g)); }
void prep_postlaunch_part (const char *filename, prep_data *data, const char *device) { if (guestfs_part_disk (g, device, data->params[1]) == -1) prep_error (data, filename, _("failed to partition disk: %s"), guestfs_last_error (g)); }
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); }
void ocaml_guestfs_raise_error (guestfs_h *g, const char *func) { CAMLparam0 (); CAMLlocal1 (v); const char *msg; msg = guestfs_last_error (g); if (msg) v = caml_copy_string (msg); else v = caml_copy_string (func); caml_raise_with_arg (*caml_named_value ("ocaml_guestfs_error"), v); CAMLnoreturn; }
PyObject * py_guestfs_set_event_callback (PyObject *self, PyObject *args) { PyObject *py_g; guestfs_h *g; PyObject *py_callback; unsigned PY_LONG_LONG events; int eh; PyObject *py_eh; char key[64]; if (!PyArg_ParseTuple (args, (char *) "OOK:guestfs_set_event_callback", &py_g, &py_callback, &events)) return NULL; if (!PyCallable_Check (py_callback)) { PyErr_SetString (PyExc_TypeError, "callback parameter is not callable " "(eg. lambda or function)"); return NULL; } g = get_handle (py_g); eh = guestfs_set_event_callback (g, py_guestfs_event_callback_wrapper, events, 0, py_callback); if (eh == -1) { PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); return NULL; } /* Increase the refcount for this callback since we are storing it * in the opaque C libguestfs handle. We need to remember that we * did this, so we can decrease the refcount for all undeleted * callbacks left around at close time (see py_guestfs_close). */ Py_XINCREF (py_callback); snprintf (key, sizeof key, "_python_event_%d", eh); guestfs_set_private (g, key, py_callback); py_eh = PyLong_FromLong ((long) eh); return py_eh; }
JNIEXPORT jint JNICALL Java_com_redhat_et_libguestfs_GuestFS__1set_1event_1callback (JNIEnv *env, jobject obj, jlong jg, jobject jcallback, jlong jevents) { guestfs_h *g = (guestfs_h *) (long) jg; int r; struct callback_data *data; jclass callback_class; jmethodID method; char key[64]; callback_class = (*env)->GetObjectClass (env, jcallback); method = (*env)->GetMethodID (env, callback_class, METHOD_NAME, METHOD_SIGNATURE); if (method == 0) { throw_exception (env, "GuestFS.set_event_callback: callback class does not implement the EventCallback interface"); return -1; } data = malloc (sizeof *data); if (data == NULL) { throw_out_of_memory (env, "malloc"); return -1; } (*env)->GetJavaVM (env, &data->jvm); data->method = method; r = guestfs_set_event_callback (g, java_callback, (uint64_t) jevents, 0, data); if (r == -1) { free (data); throw_exception (env, guestfs_last_error (g)); return -1; } /* Register jcallback as a global reference so the GC won't free it. */ data->callback = (*env)->NewGlobalRef (env, jcallback); /* Store 'data' in the handle, so we can free it at some point. */ snprintf (key, sizeof key, "_java_event_%d", r); guestfs_set_private (g, key, data); return (jint) r; }
void prep_postlaunch_bootroot (const char *filename, prep_data *data, const char *device) { off_t bootsize; if (parse_size (data->params[3], &bootsize) == -1) prep_error (data, filename, _("could not parse boot size")); int sector = guestfs_blockdev_getss (g, device); if (sector == -1) prep_error (data, filename, _("failed to get sector size of disk: %s"), guestfs_last_error (g)); if (guestfs_part_init (g, device, data->params[4]) == -1) prep_error (data, filename, _("failed to partition disk: %s"), guestfs_last_error (g)); off_t lastbootsect = 64 + bootsize/sector - 1; if (guestfs_part_add (g, device, "primary", 64, lastbootsect) == -1) prep_error (data, filename, _("failed to add boot partition: %s"), guestfs_last_error (g)); if (guestfs_part_add (g, device, "primary", lastbootsect+1, -64) == -1) prep_error (data, filename, _("failed to add root partition: %s"), guestfs_last_error (g)); CLEANUP_FREE char *part; if (asprintf (&part, "%s1", device) == -1) { perror ("asprintf"); exit (EXIT_FAILURE); } if (guestfs_mkfs (g, data->params[0], part) == -1) prep_error (data, filename, _("failed to create boot filesystem: %s"), guestfs_last_error (g)); CLEANUP_FREE char *part2; if (asprintf (&part2, "%s2", device) == -1) { perror ("asprintf"); exit (EXIT_FAILURE); } if (guestfs_mkfs (g, data->params[1], part2) == -1) prep_error (data, filename, _("failed to create root filesystem: %s"), guestfs_last_error (g)); }
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); }
static int do_make_fs (const char *input, const char *output_str) { const char *dev, *options; CLEANUP_UNLINK_FREE char *output = NULL; uint64_t estimate, size; struct guestfs_disk_create_argv optargs; CLEANUP_FREE char *ifmt = NULL; CLEANUP_FREE char *ifile = NULL; pid_t pid; int status, fd; /* Use of CLEANUP_UNLINK_FREE *output ensures the output file is * deleted unless we successfully reach the end of this function. */ output = strdup (output_str); if (output == NULL) { perror ("strdup"); return -1; } /* Input. What is it? Estimate how much space it will need. */ if (estimate_input (input, &estimate, &ifmt) == -1) return -1; if (verbose) { fprintf (stderr, "input format = %s\n", ifmt); fprintf (stderr, "estimate = %" PRIu64 " bytes " "(%" PRIu64 " 1K blocks, %" PRIu64 " 4K blocks)\n", estimate, estimate / 1024, estimate / 4096); } estimate += 256 * 1024; /* For superblocks &c. */ if (STRPREFIX (type, "ext") && type[3] >= '3') { /* For ext3+, add some more for the journal. */ estimate += 1024 * 1024; } else if (STREQ (type, "ntfs")) { estimate += 4 * 1024 * 1024; /* NTFS journal. */ } else if (STREQ (type, "btrfs")) { /* For BTRFS, the minimum metadata allocation is 256MB, with data * additional to that. Note that we disable data and metadata * duplication below. */ estimate += 256 * 1024 * 1024; } /* Add 10%, see above. */ estimate *= 1.10; /* Calculate the output size. */ if (size_str == NULL) size = estimate; else if (parse_size (size_str, estimate, &size) == -1) return -1; /* Create the output disk. */ optargs.bitmask = 0; if (STREQ (format, "qcow2")) { optargs.bitmask |= GUESTFS_DISK_CREATE_PREALLOCATION_BITMASK; optargs.preallocation = "metadata"; } if (guestfs_disk_create_argv (g, output, format, size, &optargs) == -1) return -1; if (guestfs_add_drive_opts (g, output, GUESTFS_ADD_DRIVE_OPTS_FORMAT, format, -1) == -1) return -1; if (guestfs_launch (g) == -1) return -1; if (check_ntfs_available () == -1) return -1; /* Partition the disk. */ dev = "/dev/sda"; if (partition) { int mbr_id = 0; if (STREQ (partition, "")) partition = "mbr"; if (guestfs_part_disk (g, dev, partition) == -1) return -1; dev = "/dev/sda1"; /* Set the partition type byte if it's MBR and the filesystem type * is one that we know about. */ if (STREQ (partition, "mbr") || STREQ (partition, "msdos")) { if (STREQ (type, "msdos")) /* According to Wikipedia. However I have not actually tried this. */ mbr_id = 0x1; else if (STREQ (type, "vfat") || STREQ (type, "fat")) mbr_id = 0xb; else if (STREQ (type, "ntfs")) mbr_id = 0x7; else if (STRPREFIX (type, "ext")) mbr_id = 0x83; else if (STREQ (type, "minix")) mbr_id = 0x81; } if (mbr_id != 0) { if (guestfs_part_set_mbr_id (g, "/dev/sda", 1, mbr_id) == -1) return -1; } } if (verbose) fprintf (stderr, "creating %s filesystem on %s ...\n", type, dev); /* Create the filesystem. */ if (STRNEQ (type, "btrfs")) { int r; struct guestfs_mkfs_opts_argv optargs = { .bitmask = 0 }; if (label) { optargs.label = label; optargs.bitmask |= GUESTFS_MKFS_OPTS_LABEL_BITMASK; } guestfs_push_error_handler (g, NULL, NULL); r = guestfs_mkfs_opts_argv (g, type, dev, &optargs); guestfs_pop_error_handler (g); if (r == -1) { /* Provide more guidance in the error message (RHBZ#823883). */ fprintf (stderr, "%s: 'mkfs' (create filesystem) operation failed: %s\n", guestfs_int_program_name, guestfs_last_error (g)); if (STREQ (type, "fat")) fprintf (stderr, "Instead of 'fat', try 'vfat' (long filenames) or 'msdos' (short filenames).\n"); else fprintf (stderr, "Is '%s' a correct filesystem type?\n", type); return -1; } } else {
static void test_virtio_serial (void) { int fd, r, eh; char tmpfile[] = "/tmp/speedtestXXXXXX"; struct sigaction sa, old_sa; if (!virtio_serial_upload && !virtio_serial_download) return; /* Create a sparse file. We could upload from /dev/zero, but we * won't get progress messages because libguestfs tests if the * source file is a regular file. */ fd = mkstemp (tmpfile); if (fd == -1) error (EXIT_FAILURE, errno, "mkstemp: %s", tmpfile); if (ftruncate (fd, TEST_SERIAL_MAX_SIZE) == -1) error (EXIT_FAILURE, errno, "ftruncate"); if (close (fd) == -1) error (EXIT_FAILURE, errno, "close"); g = guestfs_create (); if (!g) error (EXIT_FAILURE, errno, "guestfs_create"); if (guestfs_add_drive_scratch (g, INT64_C (100*1024*1024), -1) == -1) exit (EXIT_FAILURE); if (guestfs_launch (g) == -1) exit (EXIT_FAILURE); /* Make and mount a filesystem which will be used by the download test. */ if (guestfs_mkfs (g, "ext4", "/dev/sda") == -1) exit (EXIT_FAILURE); if (guestfs_mount (g, "/dev/sda", "/") == -1) exit (EXIT_FAILURE); /* Time out the upload after TEST_SERIAL_MAX_TIME seconds have passed. */ memset (&sa, 0, sizeof sa); sa.sa_handler = stop_transfer; sa.sa_flags = SA_RESTART; sigaction (SIGALRM, &sa, &old_sa); /* Get progress messages, which will tell us how much data has been * transferred. */ eh = guestfs_set_event_callback (g, progress_cb, GUESTFS_EVENT_PROGRESS, 0, NULL); if (eh == -1) exit (EXIT_FAILURE); if (virtio_serial_upload) { gettimeofday (&start, NULL); rate = -1; operation = "upload"; alarm (max_time_override > 0 ? max_time_override : TEST_SERIAL_MAX_TIME); /* For the upload test, upload the sparse file to /dev/null in the * appliance. Hopefully this is mostly testing just virtio-serial. */ guestfs_push_error_handler (g, NULL, NULL); r = guestfs_upload (g, tmpfile, "/dev/null"); alarm (0); unlink (tmpfile); guestfs_pop_error_handler (g); /* It's possible that the upload will finish before the alarm fires, * or that the upload will be stopped by the alarm. */ if (r == -1 && guestfs_last_errno (g) != EINTR) { fprintf (stderr, "%s: expecting upload command to return EINTR\n%s\n", guestfs_int_program_name, guestfs_last_error (g)); exit (EXIT_FAILURE); } if (rate == -1) { rate_error: fprintf (stderr, "%s: internal error: progress callback was not called! (r=%d, errno=%d)\n", guestfs_int_program_name, r, guestfs_last_errno (g)); exit (EXIT_FAILURE); } print_rate ("virtio-serial upload rate:", rate); } if (virtio_serial_download) { /* For the download test, download a sparse file within the * appliance to /dev/null on the host. */ if (guestfs_touch (g, "/sparse") == -1) exit (EXIT_FAILURE); if (guestfs_truncate_size (g, "/sparse", TEST_SERIAL_MAX_SIZE) == -1) exit (EXIT_FAILURE); gettimeofday (&start, NULL); rate = -1; operation = "download"; alarm (max_time_override > 0 ? max_time_override : TEST_SERIAL_MAX_TIME); guestfs_push_error_handler (g, NULL, NULL); r = guestfs_download (g, "/sparse", "/dev/null"); alarm (0); guestfs_pop_error_handler (g); if (r == -1 && guestfs_last_errno (g) != EINTR) { fprintf (stderr, "%s: expecting download command to return EINTR\n%s\n", guestfs_int_program_name, guestfs_last_error (g)); exit (EXIT_FAILURE); } if (rate == -1) goto rate_error; print_rate ("virtio-serial download rate:", rate); } if (guestfs_shutdown (g) == -1) exit (EXIT_FAILURE); guestfs_close (g); /* Restore SIGALRM signal handler. */ sigaction (SIGALRM, &old_sa, NULL); }
static void do_output_filesystems (void) { size_t i; CLEANUP_FREE_STRING_LIST char **fses = guestfs_list_filesystems (g); if (fses == NULL) exit (EXIT_FAILURE); for (i = 0; fses[i] != NULL; i += 2) { CLEANUP_FREE char *dev = NULL, *vfs_label = NULL, *vfs_uuid = NULL; CLEANUP_FREE_STRING_LIST char **parents = NULL; int64_t size = -1; /* Skip swap and unknown, unless --extra flag was given. */ if (!(output & OUTPUT_FILESYSTEMS_EXTRA) && (STREQ (fses[i+1], "swap") || STREQ (fses[i+1], "unknown"))) continue; dev = guestfs_canonical_device_name (g, fses[i]); if (dev == NULL) exit (EXIT_FAILURE); /* Only bother to look these up if we will be displaying them, * otherwise pass them as NULL. */ if ((columns & COLUMN_VFS_LABEL)) { guestfs_push_error_handler (g, NULL, NULL); vfs_label = guestfs_vfs_label (g, fses[i]); guestfs_pop_error_handler (g); if (vfs_label == NULL) { vfs_label = strdup (""); if (!vfs_label) error (EXIT_FAILURE, errno, "strdup"); } } if ((columns & COLUMN_UUID)) { guestfs_push_error_handler (g, NULL, NULL); vfs_uuid = guestfs_vfs_uuid (g, fses[i]); guestfs_pop_error_handler (g); if (vfs_uuid == NULL) { vfs_uuid = strdup (""); if (!vfs_uuid) error (EXIT_FAILURE, errno, "strdup"); } } if ((columns & COLUMN_SIZE)) { CLEANUP_FREE char *device = guestfs_mountable_device (g, fses[i]); CLEANUP_FREE char *subvolume = NULL; guestfs_push_error_handler (g, NULL, NULL); subvolume = guestfs_mountable_subvolume (g, fses[i]); if (subvolume == NULL && guestfs_last_errno (g) != EINVAL) { fprintf (stderr, _("%s: cannot determine the subvolume for %s: %s: %s\n"), getprogname (), fses[i], guestfs_last_error (g), strerror (guestfs_last_errno (g))); exit (EXIT_FAILURE); } guestfs_pop_error_handler (g); if (!device || !subvolume) { size = guestfs_blockdev_getsize64 (g, fses[i]); if (size == -1) exit (EXIT_FAILURE); } } if (is_md (fses[i])) parents = parents_of_md (fses[i]); else parents = no_parents (); write_row (dev, "filesystem", fses[i+1], vfs_label, -1, size, parents, vfs_uuid); } }