static int beagle_getxattr (const char *path, const char *key, char *buf, size_t len) { beagle_inode_t *inode; int ret; if (strlen (key) < BEAGLEFS_XATTR_PREFIX_LEN + 1) return -ENODATA; if (strncmp (key, BEAGLEFS_XATTR_PREFIX, BEAGLEFS_XATTR_PREFIX_LEN)) return -ENODATA; key += BEAGLEFS_XATTR_PREFIX_LEN; ret = -ENOENT; beagle_dir_read_lock (); inode = beagle_dir_get_inode (path); if (inode) { if (!strcmp (key, "mime_type")) ret = copy_xattr (buf, beagle_inode_get_mime_type (inode), len); else if (!strcmp (key, "type")) ret = copy_xattr (buf, beagle_inode_get_type (inode), len); else if (!strcmp (key, "uri")) ret = copy_xattr (buf, beagle_inode_get_uri (inode), len); else if (!strcmp (key, "source")) ret = copy_xattr (buf, beagle_inode_get_source (inode), len); else if (!strcmp (key, "score")) ret = copy_xattr (buf, beagle_inode_get_score (inode), len); else ret = -ENODATA; } beagle_dir_read_unlock (); return ret; }
static value copy_xattr_list (const struct guestfs_xattr_list *xattrs) { CAMLparam0 (); CAMLlocal2 (rv, v); unsigned int i; if (xattrs->len == 0) CAMLreturn (Atom (0)); else { rv = caml_alloc (xattrs->len, 0); for (i = 0; i < xattrs->len; ++i) { v = copy_xattr (&xattrs->val[i]); Store_field (rv, i, v); } CAMLreturn (rv); } }
static int raw_import_finish(RawImport *i) { int r; assert(i); assert(i->output_fd >= 0); assert(i->temp_path); assert(i->final_path); /* In case this was a sparse file, make sure the file system is right */ if (i->written_uncompressed > 0) { if (ftruncate(i->output_fd, i->written_uncompressed) < 0) return log_error_errno(errno, "Failed to truncate file: %m"); } r = raw_import_maybe_convert_qcow2(i); if (r < 0) return r; if (S_ISREG(i->st.st_mode)) { (void) copy_times(i->input_fd, i->output_fd); (void) copy_xattr(i->input_fd, i->output_fd); } if (i->read_only) { r = import_make_read_only_fd(i->output_fd); if (r < 0) return r; } if (i->force_local) (void) rm_rf(i->final_path, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME); r = rename_noreplace(AT_FDCWD, i->temp_path, AT_FDCWD, i->final_path); if (r < 0) return log_error_errno(r, "Failed to move image into place: %m"); free(i->temp_path); i->temp_path = NULL; return 0; }
static int raw_pull_make_local_copy(RawPull *i) { _cleanup_free_ char *tp = NULL; _cleanup_close_ int dfd = -1; const char *p; int r; assert(i); assert(i->raw_job); if (!i->local) return 0; if (i->raw_job->etag_exists) { /* We have downloaded this one previously, reopen it */ assert(i->raw_job->disk_fd < 0); i->raw_job->disk_fd = open(i->final_path, O_RDONLY|O_NOCTTY|O_CLOEXEC); if (i->raw_job->disk_fd < 0) return log_error_errno(errno, "Failed to open vendor image: %m"); } else { /* We freshly downloaded the image, use it */ assert(i->raw_job->disk_fd >= 0); if (lseek(i->raw_job->disk_fd, SEEK_SET, 0) == (off_t) -1) return log_error_errno(errno, "Failed to seek to beginning of vendor image: %m"); } p = strjoina(i->image_root, "/", i->local, ".raw"); if (i->force_local) (void) rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME); r = tempfn_random(p, NULL, &tp); if (r < 0) return log_oom(); dfd = open(tp, O_WRONLY|O_CREAT|O_EXCL|O_NOCTTY|O_CLOEXEC, 0664); if (dfd < 0) return log_error_errno(errno, "Failed to create writable copy of image: %m"); /* Turn off COW writing. This should greatly improve * performance on COW file systems like btrfs, since it * reduces fragmentation caused by not allowing in-place * writes. */ r = chattr_fd(dfd, FS_NOCOW_FL, FS_NOCOW_FL); if (r < 0) log_warning_errno(r, "Failed to set file attributes on %s: %m", tp); r = copy_bytes(i->raw_job->disk_fd, dfd, (uint64_t) -1, COPY_REFLINK); if (r < 0) { unlink(tp); return log_error_errno(r, "Failed to make writable copy of image: %m"); } (void) copy_times(i->raw_job->disk_fd, dfd); (void) copy_xattr(i->raw_job->disk_fd, dfd); dfd = safe_close(dfd); r = rename(tp, p); if (r < 0) { r = log_error_errno(errno, "Failed to move writable image into place: %m"); unlink(tp); return r; } log_info("Created new local image '%s'.", i->local); if (i->roothash) { r = raw_pull_copy_auxiliary_file(i, ".roothash", &i->roothash_path); if (r < 0) return r; } if (i->settings) { r = raw_pull_copy_auxiliary_file(i, ".nspawn", &i->settings_path); if (r < 0) return r; } return 0; }
static int raw_export_process(RawExport *e) { ssize_t l; int r; assert(e); if (!e->tried_reflink && e->compress.type == IMPORT_COMPRESS_UNCOMPRESSED) { /* If we shall take an uncompressed snapshot we can * reflink source to destination directly. Let's see * if this works. */ r = btrfs_reflink(e->input_fd, e->output_fd); if (r >= 0) { r = 0; goto finish; } e->tried_reflink = true; } if (!e->tried_sendfile && e->compress.type == IMPORT_COMPRESS_UNCOMPRESSED) { l = sendfile(e->output_fd, e->input_fd, NULL, COPY_BUFFER_SIZE); if (l < 0) { if (errno == EAGAIN) return 0; e->tried_sendfile = true; } else if (l == 0) { r = 0; goto finish; } else { e->written_uncompressed += l; e->written_compressed += l; raw_export_report_progress(e); return 0; } } while (e->buffer_size <= 0) { uint8_t input[COPY_BUFFER_SIZE]; if (e->eof) { r = 0; goto finish; } l = read(e->input_fd, input, sizeof(input)); if (l < 0) { r = log_error_errno(errno, "Failed to read raw file: %m"); goto finish; } if (l == 0) { e->eof = true; r = import_compress_finish(&e->compress, &e->buffer, &e->buffer_size, &e->buffer_allocated); } else { e->written_uncompressed += l; r = import_compress(&e->compress, input, l, &e->buffer, &e->buffer_size, &e->buffer_allocated); } if (r < 0) { r = log_error_errno(r, "Failed to encode: %m"); goto finish; } } l = write(e->output_fd, e->buffer, e->buffer_size); if (l < 0) { if (errno == EAGAIN) return 0; r = log_error_errno(errno, "Failed to write output file: %m"); goto finish; } assert((size_t) l <= e->buffer_size); memmove(e->buffer, (uint8_t*) e->buffer + l, e->buffer_size - l); e->buffer_size -= l; e->written_compressed += l; raw_export_report_progress(e); return 0; finish: if (r >= 0) { (void) copy_times(e->input_fd, e->output_fd); (void) copy_xattr(e->input_fd, e->output_fd); } if (e->on_finished) e->on_finished(e, r, e->userdata); else sd_event_exit(e->event, r); return 0; }