static int do_fusermount (guestfs_h *g, const char *localmountpoint, int error_fd) { pid_t pid; int status; pid = fork (); if (pid == -1) { perrorf (g, "fork"); return -1; } if (pid == 0) { /* child */ /* Ensure stdout and stderr point to the error_fd. */ dup2 (error_fd, STDOUT_FILENO); dup2 (error_fd, STDERR_FILENO); close (error_fd); execlp ("fusermount", "fusermount", "-u", localmountpoint, NULL); perror ("exec: fusermount"); _exit (EXIT_FAILURE); } /* Parent. */ if (waitpid (pid, &status, 0) == -1) { perrorf (g, "waitpid"); return -1; } if (!WIFEXITED (status) || WEXITSTATUS (status) != EXIT_SUCCESS) return 0; /* it failed to unmount the mountpoint */ return 1; /* unmount was successful */ }
static int rlc_insert (guestfs_h *g, const char *path, const char *name, time_t now, char *link) { struct rlc_entry *entry; size_t len; entry = malloc (sizeof *entry); if (entry == NULL) { perrorf (g, "malloc"); return -1; } len = strlen (path) + strlen (name) + 2; entry->c.pathname = malloc (len); if (entry->c.pathname == NULL) { perrorf (g, "malloc"); free (entry); return -1; } if (STREQ (path, "/")) snprintf (entry->c.pathname, len, "/%s", name); else snprintf (entry->c.pathname, len, "%s/%s", path, name); entry->link = link; entry->c.timeout = now + g->ml_dir_cache_timeout; return gen_replace (g, g->rlc_ht, (struct entry_common *) entry, rlc_free); }
int filecopy(FILE *in, FILE *out, char *outname, size_t insiz) { char buffer[BSIZ]; size_t nread, total = 0; int ret = 0, lastprogress = 0; while((nread = fread(buffer, sizeof buffer[0], BSIZ, in)) > 0){ if(fwrite(buffer, sizeof buffer[0], nread, out) <= 0){ perrorf("fwrite()"); ret = 1; goto bail; } if(++lastprogress > PROGRESS_COUNT){ progress(outname, total += nread, insiz); lastprogress = 0; } } progressdone(outname, insiz); if(ferror(in)){ perrorf("fread()"); ret = 1; } bail: return ret; }
char * guestfs_impl_read_file (guestfs_h *g, const char *path, size_t *size_r) { int fd = -1; size_t size; CLEANUP_UNLINK_FREE char *tmpfile = NULL; char *ret = NULL; struct stat statbuf; tmpfile = guestfs_int_make_temp_path (g, "cat", NULL); if (tmpfile == NULL) goto err; if (guestfs_download (g, path, tmpfile) == -1) goto err; fd = open (tmpfile, O_RDONLY|O_CLOEXEC); if (fd == -1) { perrorf (g, "open: %s", tmpfile); goto err; } /* Read the whole file into memory. */ if (fstat (fd, &statbuf) == -1) { perrorf (g, "stat: %s", tmpfile); goto err; } /* Don't use safe_malloc, because we want to return an errno to the caller. */ size = statbuf.st_size; ret = malloc (size + 1); if (!ret) { perrorf (g, "malloc: %zu bytes", size + 1); goto err; } if (full_read (fd, ret, size) != size) { perrorf (g, "full-read: %s: %zu bytes", tmpfile, size + 1); goto err; } ret[size] = '\0'; if (close (fd) == -1) { perrorf (g, "close: %s", tmpfile); goto err; } /* Mustn't touch *size_r until we are sure that we won't return any * error (RHBZ#589039). */ *size_r = size; return ret; err: free (ret); if (fd >= 0) close (fd); return NULL; }
/* We need to make all tmpdir paths absolute because lots of places in * the code assume this. Do it at the time we set the path or read * the environment variable (RHBZ#882417). */ static int set_abs_path (guestfs_h *g, const char *tmpdir, char **tmpdir_ret) { char *ret; struct stat statbuf; /* Free the old path, and set it to NULL so that if we fail below * we don't end up with a pointer to freed memory. */ free (*tmpdir_ret); *tmpdir_ret = NULL; if (tmpdir == NULL) return 0; ret = realpath (tmpdir, NULL); if (ret == NULL) { perrorf (g, _("failed to set temporary directory: %s"), tmpdir); return -1; } if (stat (ret, &statbuf) == -1) { perrorf (g, _("failed to set temporary directory: %s"), tmpdir); return -1; } if (!S_ISDIR (statbuf.st_mode)) { error (g, _("temporary directory '%s' is not a directory"), tmpdir); return -1; } *tmpdir_ret = ret; return 0; }
static struct guestfs_xattr_list * copy_xattr_list (guestfs_h *g, const struct guestfs_xattr *first, size_t num) { struct guestfs_xattr_list *xattrs; size_t i; xattrs = malloc (sizeof *xattrs); if (xattrs == NULL) { perrorf (g, "malloc"); return NULL; } xattrs->len = num; xattrs->val = malloc (num * sizeof (struct guestfs_xattr)); if (xattrs->val == NULL) { perrorf (g, "malloc"); free (xattrs); return NULL; } for (i = 0; i < num; ++i) { xattrs->val[i].attrname = strdup (first[i].attrname); xattrs->val[i].attrval_len = first[i].attrval_len; xattrs->val[i].attrval = malloc (first[i].attrval_len); memcpy (xattrs->val[i].attrval, first[i].attrval, first[i].attrval_len); } return xattrs; }
static int lazy_make_tmpdir (guestfs_h *g, char *(*getdir) (guestfs_h *g), char **dest) { if (!*dest) { CLEANUP_FREE char *tmpdir = getdir (g); char *tmppath = safe_asprintf (g, "%s/libguestfsXXXXXX", tmpdir); if (mkdtemp (tmppath) == NULL) { perrorf (g, _("%s: cannot create temporary directory"), tmppath); free (tmppath); return -1; } /* Allow qemu (which may be running as qemu.qemu) to read in this * temporary directory; we are storing either sockets, or temporary * disks which qemu needs to access to. (RHBZ#610880). * We do this only for root, as for normal users qemu will be run * under the same user. */ if (geteuid () == 0 && chmod (tmppath, 0755) == -1) { perrorf (g, "chmod: %s", tmppath); free (tmppath); return -1; } *dest = tmppath; } return 0; }
/* Create a new socket connection, connected. * * As above, but the caller passes us a connected daemon_sock * and promises not to call accept_connection. */ struct connection * guestfs_int_new_conn_socket_connected (guestfs_h *g, int daemon_sock, int console_sock) { struct connection_socket *conn; assert (daemon_sock >= 0); if (fcntl (daemon_sock, F_SETFL, O_NONBLOCK) == -1) { perrorf (g, "new_conn_socket_connected: fcntl"); return NULL; } if (console_sock >= 0) { if (fcntl (console_sock, F_SETFL, O_NONBLOCK) == -1) { perrorf (g, "new_conn_socket_connected: fcntl"); return NULL; } } conn = safe_malloc (g, sizeof *conn); /* Set the operations. */ conn->ops = &ops; /* Set the internal state. */ conn->console_sock = console_sock; conn->daemon_sock = daemon_sock; conn->daemon_accept_sock = -1; return (struct connection *) conn; }
static int write_or_append (guestfs_h *g, const char *path, const char *content, size_t size, int append) { CLEANUP_UNLINK_FREE char *tmpfile = NULL; int fd = -1; int64_t filesize; /* If the content is small enough, use guestfs_internal_write{,_append} * since that call is more efficient. */ if (size <= 2*1024*1024) return (!append ? guestfs_internal_write : guestfs_internal_write_append) (g, path, content, size); if (guestfs_int_lazy_make_tmpdir (g) == -1) goto err; /* Write the content out to a temporary file. */ tmpfile = safe_asprintf (g, "%s/write%d", g->tmpdir, ++g->unique); fd = open (tmpfile, O_WRONLY|O_CREAT|O_NOCTTY|O_CLOEXEC, 0600); if (fd == -1) { perrorf (g, "open: %s", tmpfile); goto err; } if (full_write (fd, content, size) != size) { perrorf (g, "write: %s", tmpfile); goto err; } if (close (fd) == -1) { perrorf (g, "close: %s", tmpfile); goto err; } fd = -1; if (!append) { if (guestfs_upload (g, tmpfile, path) == -1) goto err; } else { /* XXX Should have an 'upload-append' call to make this atomic. */ filesize = guestfs_filesize (g, path); if (filesize == -1) goto err; if (guestfs_upload_offset (g, tmpfile, path, filesize) == -1) goto err; } return 0; err: if (fd >= 0) close (fd); return -1; }
/* Download a guest file to a local temporary file. The file is * cached in the temporary directory, and is not downloaded again. * * The name of the temporary (downloaded) file is returned. The * caller must free the pointer, but does *not* need to delete the * temporary file. It will be deleted when the handle is closed. * * Refuse to download the guest file if it is larger than max_size. * On this and other errors, NULL is returned. * * There is actually one cache per 'struct inspect_fs *' in order * to handle the case of multiple roots. */ char * guestfs___download_to_tmp (guestfs_h *g, struct inspect_fs *fs, const char *filename, const char *basename, uint64_t max_size) { char *r; int fd; char devfd[32]; int64_t size; /* Make the basename unique by prefixing it with the fs number. * This also ensures there is one cache per filesystem. */ if (asprintf (&r, "%s/%td-%s", g->tmpdir, fs - g->fses, basename) == -1) { perrorf (g, "asprintf"); return NULL; } /* If the file has already been downloaded, return. */ if (access (r, R_OK) == 0) return r; /* Check size of remote file. */ size = guestfs_filesize (g, filename); if (size == -1) /* guestfs_filesize failed and has already set error in handle */ goto error; if ((uint64_t) size > max_size) { error (g, _("size of %s is unreasonably large (%" PRIi64 " bytes)"), filename, size); goto error; } fd = open (r, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY|O_CLOEXEC, 0600); if (fd == -1) { perrorf (g, "open: %s", r); goto error; } snprintf (devfd, sizeof devfd, "/dev/fd/%d", fd); if (guestfs_download (g, filename, devfd) == -1) { unlink (r); close (fd); goto error; } if (close (fd) == -1) { perrorf (g, "close: %s", r); unlink (r); goto error; } return r; error: free (r); return NULL; }
/* Send a file. * Returns: * 0 OK * -1 error * -2 daemon cancelled (we must read the error message) */ int guestfs___send_file (guestfs_h *g, const char *filename) { char buf[GUESTFS_MAX_CHUNK_SIZE]; int fd, r = 0, err; g->user_cancel = 0; fd = open (filename, O_RDONLY|O_CLOEXEC); if (fd == -1) { perrorf (g, "open: %s", filename); send_file_cancellation (g); return -1; } fadvise_sequential (fd); /* Send file in chunked encoding. */ while (!g->user_cancel) { r = read (fd, buf, sizeof buf); if (r == -1 && (errno == EINTR || errno == EAGAIN)) continue; if (r <= 0) break; err = send_file_data (g, buf, r); if (err < 0) { if (err == -2) /* daemon sent cancellation */ send_file_cancellation (g); close (fd); return err; } } if (r == -1) { perrorf (g, "read: %s", filename); send_file_cancellation (g); close (fd); return -1; } if (g->user_cancel) { error (g, _("operation cancelled by user")); g->last_errnum = EINTR; send_file_cancellation (g); close (fd); return -1; } /* End of file, but before we send that, we need to close * the file and check for errors. */ if (close (fd) == -1) { perrorf (g, "close: %s", filename); send_file_cancellation (g); return -1; } return send_file_complete (g); }
/** * Fallback method of getting the umask using fork. */ static int get_umask_from_fork (guestfs_h *g) { pid_t pid; int fd[2], r; int mask; int status; r = pipe2 (fd, O_CLOEXEC); if (r == -1) { perrorf (g, "pipe2"); return -1; } pid = fork (); if (pid == -1) { perrorf (g, "fork"); close (fd[0]); close (fd[1]); return -1; } if (pid == 0) { /* The child process must ONLY call async-safe functions. */ close (fd[0]); /* umask can't fail. */ mask = umask (0); if (write (fd[1], &mask, sizeof mask) != sizeof mask) _exit (EXIT_FAILURE); if (close (fd[1]) == -1) _exit (EXIT_FAILURE); _exit (EXIT_SUCCESS); } /* Parent. */ close (fd[1]); /* Read the umask. */ if (read (fd[0], &mask, sizeof mask) != sizeof mask) { perrorf (g, "read"); close (fd[0]); guestfs_int_waitpid_noerror (pid); return -1; } close (fd[0]); if (guestfs_int_waitpid (g, pid, &status, "umask") == -1) return -1; else if (!WIFEXITED (status) || WEXITSTATUS (status) != 0) { guestfs_int_external_command_failed (g, status, "umask", NULL); return -1; } return mask; }
int copy(char *dest, char *src) { FILE *in, *out; int ret; char *actualdest = dest; if(samefile(dest, src)){ eprintf("`%s' and `%s' are the same file", dest, src); return 1; } if(!(in = fopen(src, "r"))){ perrorf("open (for read): `%s'", src); return 1; } /* TODO: make dir if it doesn't exist */ if(!(out = fopen(dest, "w"))){ if(errno == EISDIR){ char *srcbase = strrchr(src, '/'); if(!srcbase) srcbase = src; actualdest = alloca(strlen(dest) + strlen(srcbase) + 2); sprintf(actualdest, "%s/%s", dest, srcbase); if(samefile(actualdest, src)){ eprintf("`%s' and `%s' are the same file", actualdest, src); fclose(in); return 1; } out = fopen(actualdest, "w"); if(!out){ perrorf("open (for write): `%s'", actualdest); fclose(in); return 1; } }else{ perrorf("open (for write): `%s'", dest); fclose(in); return 1; } } ret = filecopy(in, out, actualdest, filelen(src)); fclose(in); fclose(out); if(!i_am_cp && remove(src)) perrorf("non-fatal: remove: `%s'", src); return ret; }
static int read_osinfo_db_three_levels (guestfs_h *g, const char *directory) { DIR *dir; int r; dir = opendir (directory); if (!dir) { debug (g, "osinfo: %s: %s", directory, strerror (errno)); return 0; /* This is not an error: RHBZ#948324. */ } debug (g, "osinfo: loading 3-level-directories database from %s", directory); for (;;) { struct dirent *d; CLEANUP_FREE char *pathname = NULL; struct stat sb; errno = 0; d = readdir (dir); if (!d) break; pathname = safe_asprintf (g, "%s/%s", directory, d->d_name); /* Iterate only on directories. */ if (stat (pathname, &sb) == 0 && S_ISDIR (sb.st_mode)) { r = read_osinfo_db_directory (g, pathname); if (r == -1) goto error; } } /* Check for failure in readdir. */ if (errno != 0) { perrorf (g, "readdir: %s", directory); goto error; } /* Close the directory handle. */ r = closedir (dir); dir = NULL; if (r == -1) { perrorf (g, "closedir: %s", directory); goto error; } return 1; error: if (dir) closedir (dir); return -1; }
/* Read the whole file into a memory buffer and return it. The file * should be a regular, local, trusted file. */ static int read_whole_file (guestfs_h *g, const char *filename, char **data_r, size_t *size_r) { int fd; char *data; off_t size; off_t n; ssize_t r; struct stat statbuf; fd = open (filename, O_RDONLY|O_CLOEXEC); if (fd == -1) { perrorf (g, "open: %s", filename); return -1; } if (fstat (fd, &statbuf) == -1) { perrorf (g, "stat: %s", filename); close (fd); return -1; } size = statbuf.st_size; data = safe_malloc (g, size); n = 0; while (n < size) { r = read (fd, &data[n], size - n); if (r == -1) { perrorf (g, "read: %s", filename); free (data); close (fd); return -1; } if (r == 0) { error (g, _("read: %s: unexpected end of file"), filename); free (data); close (fd); return -1; } n += r; } if (close (fd) == -1) { perrorf (g, "close: %s", filename); free (data); return -1; } *data_r = data; *size_r = size; return 0; }
static int read_osinfo_db_directory (guestfs_h *g, const char *directory) { DIR *dir; int r; dir = opendir (directory); if (!dir) { debug (g, "osinfo: %s: %s", directory, strerror (errno)); return 0; /* This is not an error: RHBZ#948324. */ } for (;;) { struct dirent *d; errno = 0; d = readdir (dir); if (!d) break; if (STRSUFFIX (d->d_name, ".xml")) { CLEANUP_FREE char *pathname = NULL; pathname = safe_asprintf (g, "%s/%s", directory, d->d_name); r = read_osinfo_db_xml (g, pathname); if (r == -1) goto error; } } /* Check for failure in readdir. */ if (errno != 0) { perrorf (g, "readdir: %s", directory); goto error; } /* Close the directory handle. */ r = closedir (dir); dir = NULL; if (r == -1) { perrorf (g, "closedir: %s", directory); goto error; } return 1; error: if (dir) closedir (dir); return -1; }
static int run_qemu_img_info (guestfs_h *g, const char *filename, cmd_stdout_callback fn, void *data) { char *abs_filename = NULL; char *safe_filename = NULL; struct command *cmd; int r; if (guestfs___lazy_make_tmpdir (g) == -1) return -1; safe_filename = safe_asprintf (g, "%s/format.%d", g->tmpdir, ++g->unique); /* 'filename' must be an absolute path so we can link to it. */ abs_filename = realpath (filename, NULL); if (abs_filename == NULL) { perrorf (g, "realpath"); goto error; } if (symlink (abs_filename, safe_filename) == -1) { perrorf (g, "symlink"); goto error; } cmd = guestfs___new_command (g); guestfs___cmd_add_arg (cmd, "qemu-img"); guestfs___cmd_add_arg (cmd, "info"); guestfs___cmd_add_arg (cmd, safe_filename); guestfs___cmd_set_stdout_callback (cmd, fn, data, 0); r = guestfs___cmd_run (cmd); guestfs___cmd_close (cmd); if (r == -1) goto error; if (!WIFEXITED (r) || WEXITSTATUS (r) != 0) { error (g, _("qemu-img: %s: child process failed"), filename); goto error; } free (safe_filename); free (abs_filename); return 0; error: free (safe_filename); free (abs_filename); return -1; }
void set_nonblocking(int fd) { int flags = 0; flags = fcntl(fd, F_GETFL, 0); if (flags == -1) { perrorf("fcntl(fd=%d)", fd); abort(); } if (-1 == fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { perrorf("fcntl(fd=%d)", fd); abort(); } }
int init_files() { snprintf(dir, PATH_LEN, "%s:%s", host, port); if(mkdir(dir, 0700)){ if(errno == EEXIST){ fprintf(stderr, "not overwriting %s\n", dir); return 2; }else{ perror("mkdir()"); return 1; } /* unreachable */ } snprintf(file_input, PATH_LEN, "%s/%s", dir, "in"); snprintf(file_cmd, PATH_LEN, "%s/%s", dir, "cmd"); snprintf(file_output, PATH_LEN, "%s/%s", dir, "out"); snprintf(file_info, PATH_LEN, "%s/%s", dir, "server"); snprintf(file_clients, PATH_LEN, "%s/%s", dir, "clients"); snprintf(file_err, PATH_LEN, "%s/%s", dir, "err"); if(mkfifo(file_input, 0600) == -1 && errno != EEXIST){ perrorf("mkfifo(): %s: ", file_input); return 1; /* ya */ } if(mkfifo(file_cmd, 0600) == -1 && errno != EEXIST){ perrorf("mkfifo(): %s: ", file_cmd); goto bail; } if((fd_input = open(file_input, O_RDONLY | O_NONBLOCK, 0600)) == -1){ perrorf("open(): %s: ", file_input); goto bail; } if((fd_cmd = open(file_cmd, O_RDONLY | O_NONBLOCK, 0600)) == -1){ perrorf("open(): %s: ", file_cmd); close(fd_input); goto bail; } return 0; bail: remove(file_input); remove(file_cmd); return 1; }
int nand_info(struct cmd_param *params) { struct chip_param_io chip_params; int fd = -1, ret = 0; int block_size; off_t chip_size, media_size; const char *dev; if ((dev = param_get_string(params, "dev")) == NULL) { fprintf(stderr, "Please supply 'dev' parameter, eg. " "'dev=/dev/gnand0'\n"); return (1); } if ((fd = g_open(dev, 1)) == -1) { perrorf("Cannot open %s", dev); return (1); } if (ioctl(fd, NAND_IO_GET_CHIP_PARAM, &chip_params) == -1) { perrorf("Cannot ioctl(NAND_IO_GET_CHIP_PARAM)"); ret = 1; goto out; } if (ioctl(fd, DIOCGMEDIASIZE, &media_size) == -1) { perrorf("Cannot ioctl(DIOCGMEDIASIZE)"); ret = 1; goto out; } block_size = chip_params.page_size * chip_params.pages_per_block; chip_size = block_size * chip_params.blocks; printf("Device:\t\t\t%s\n", dev); printf("Page size:\t\t%d bytes\n", chip_params.page_size); printf("Block size:\t\t%d bytes (%d KB)\n", block_size, block_size / 1024); printf("OOB size per page:\t%d bytes\n", chip_params.oob_size); printf("Chip size:\t\t%jd MB\n", (uintmax_t)(chip_size / 1024 / 1024)); printf("Slice size:\t\t%jd MB\n", (uintmax_t)(media_size / 1024 / 1024)); out: g_close(fd); return (ret); }
/** * For Linux E<ge> 4.7 get the umask from F</proc/self/status>. * * On failure this returns C<-1>. However if we could not open the * F</proc> file or find the C<Umask> entry in it, return C<-2> which * causes the fallback path to run. */ static int get_umask_from_proc (guestfs_h *g) { CLEANUP_FCLOSE FILE *fp = NULL; CLEANUP_FREE char *line = NULL; size_t allocsize = 0; ssize_t len; unsigned int mask; bool found = false; fp = fopen ("/proc/self/status", "r"); if (fp == NULL) { if (errno == ENOENT || errno == ENOTDIR) return -2; /* fallback */ perrorf (g, "open: /proc/self/status"); return -1; } while ((len = getline (&line, &allocsize, fp)) != -1) { if (len > 0 && line[len-1] == '\n') line[--len] = '\0'; /* Looking for: "Umask: 0022" */ if (sscanf (line, "Umask: %o", &mask) == 1) { found = true; break; } } if (!found) return -2; /* fallback */ return (int) mask; }
static int can_read_data (guestfs_h *g, struct connection *connv) { struct connection_socket *conn = (struct connection_socket *) connv; struct pollfd fd; int r; if (conn->daemon_sock == -1) { error (g, _("can_read_data: socket not connected")); return -1; } fd.fd = conn->daemon_sock; fd.events = POLLIN; fd.revents = 0; again: r = poll (&fd, 1, 0); if (r == -1) { if (errno == EINTR || errno == EAGAIN) goto again; perrorf (g, "can_read_data: poll"); return -1; } return (fd.revents & POLLIN) != 0 ? 1 : 0; }
bool compress(char *param, void *conf) { clientConfig *c=(clientConfig*)conf; int i=0; char buffer[MSGSIZE]; char archive[MSGSIZE]; /* direxists -> makesubdir*/ for(i=0;i<MSGSIZE;i++) buffer[i]=0; sendCommand(CMD_COMPRESS, NULL, &(c->sock)); if (recvCommand(buffer, &(c->sock)) != CMD_SEND) { printf("* compress \"%s\" failed. no file sent or server error\n",param); return false; } sendCommand(CMD_ACK, NULL, &(c->sock)); printf("* downloading remote archive \"%s\"\n",buffer); pullfile(buffer, &(c->sock)); strcpy(archive,param); addSlash(archive); strcat(archive,buffer); printf("* moving file \"%s\" to %s\n",buffer,archive); if (rename(buffer,archive)<0) perrorf("rename()"); return true; }
static int disk_create_raw_block (guestfs_h *g, const char *filename) { int fd; fd = open (filename, O_WRONLY|O_NOCTTY|O_CLOEXEC, 0666); if (fd == -1) { perrorf (g, _("cannot open block device: %s"), filename); return -1; } /* Just discard blocks, if possible. However don't try too hard. */ #if defined(BLKGETSIZE64) && defined(BLKDISCARD) uint64_t size; uint64_t range[2]; if (ioctl (fd, BLKGETSIZE64, &size) == 0) { range[0] = 0; range[1] = size; if (ioctl (fd, BLKDISCARD, range) == 0) debug (g, "disk_create: %s: BLKDISCARD failed on this device: %m", filename); } #endif close (fd); return 0; }
int dircopy(char *base, char *src[], int nsrc) { char *dest = NULL; int baselen = strlen(base) + 1; /* +1 for '/' */ int i, destlen = 0, ret = 0; #define BAIL() do{ ret = 1; goto bail; } while(0) for(i = 0; i < nsrc; i++){ int newlen = baselen + strlen(src[i]) + 1; if(destlen < newlen){ char *tmp = realloc(dest, newlen); if(!tmp){ perrorf("realloc()"); BAIL(); } dest = tmp; } if(*src[i] != '/') sprintf(dest, "%s/%s", base, src[i]); else strcpy(dest, src[i]); if(copy(dest, src[i])) BAIL(); } bail: free(dest); return ret; }
int guestfs__mount_local_run (guestfs_h *g) { int r, mounted; gl_lock_lock (mount_local_lock); mounted = g->localmountpoint != NULL; gl_lock_unlock (mount_local_lock); if (!mounted) { error (g, _("you must call guestfs_mount_local first")); return -1; } debug (g, "%s: entering fuse_loop", __func__); /* Enter the main loop. */ r = fuse_loop (g->fuse); if (r != 0) perrorf (g, _("fuse_loop: %s"), g->localmountpoint); debug (g, "%s: leaving fuse_loop", __func__); guestfs___free_fuse (g); gl_lock_lock (mount_local_lock); g->localmountpoint = NULL; gl_lock_unlock (mount_local_lock); /* By inspection, I found that fuse_loop only returns 0 or -1, but * don't rely on this in future. */ return r == 0 ? 0 : -1; }
/* This is called if conn->console_sock becomes ready to read while we * are doing one of the connection operations above. It reads and * deals with the log message. * * Returns: * 1 = log message(s) were handled successfully * 0 = connection to appliance closed * -1 = error */ static int handle_log_message (guestfs_h *g, struct connection_socket *conn) { char buf[BUFSIZ]; ssize_t n; /* Carried over from ancient proto.c code. The comment there was: * * "QEMU's console emulates a 16550A serial port. The real 16550A * device has a small FIFO buffer (16 bytes) which means here we * see lots of small reads of 1-16 bytes in length, usually single * bytes. Sleeping here for a very brief period groups reads * together (so we usually get a few lines of output at once) and * improves overall throughput, as well as making the event * interface a bit more sane for callers. With a virtio-serial * based console (not yet implemented) we may be able to remove * this. XXX" */ usleep (1000); n = read (conn->console_sock, buf, sizeof buf); if (n == 0) return 0; if (n == -1) { if (errno == EINTR || errno == EAGAIN) return 1; /* not an error */ perrorf (g, _("error reading console messages from the appliance")); return -1; } /* It's an actual log message, send it upwards. */ guestfs_int_log_message_callback (g, buf, n); #ifdef VALGRIND_DAEMON /* Find the canary printed by appliance/init if valgrinding of the * daemon fails, and exit abruptly. Note this is only used in * developer builds, and should never be enabled in ordinary/ * production builds. */ if (g->verbose) { const char *valgrind_canary = "DAEMON VALGRIND FAILED"; if (memmem (buf, n, valgrind_canary, strlen (valgrind_canary)) != NULL) { fprintf (stderr, "Detected valgrind failure in the daemon! Exiting with exit code 119.\n" "See log messages printed above.\n" "Note: This happens because libguestfs was configured with\n" "'--enable-valgrind-daemon' which should not be used in production builds.\n"); exit (119); } } #endif return 1; }
int lewp() { struct pollfd pfd[2]; static char buffer[MAX_LINE_LEN], *nl; int nread; pfd[0].fd = fd_input; pfd[1].fd = fd_cmd; pfd[0].events = pfd[1].events = POLLIN; while(!finito){ if(comm_recv(&commt, &commcallback)){ outputf(file_err, "comm_recv() failed: %s\n", comm_lasterr(&commt)); return 1; } switch(poll(pfd, 2, FIFO_POLL_WAIT)){ case 0: /* notan happan */ continue; case -1: perrorf("%s", "poll()"); return 1; } #define READ(fd) \ nread = read(fd, buffer, MAX_LINE_LEN); \ \ switch(nread){ \ case -1: \ perrorf("%s", "read()"); \ return 1; \ case 0: \ break; \ default: \ buffer[nread-1] = '\0'; \ if((nl = strchr(buffer, '\n'))) \ *nl = '\0'; \ } #define BIT(x, b) (((x) & (b)) == (b)) if(BIT(pfd[0].revents, POLLIN)){ READ(pfd[0].fd); if(nread > 0) /* message */ comm_sendmessage(&commt, buffer); } if(BIT(pfd[1].revents, POLLIN)){ READ(pfd[1].fd); if(nread > 0) proc_cmd(buffer); } } return 0; }
bool quit(char *param, void *conf) { clientConfig *c=(clientConfig*)conf; if (close(c->sock) < 0) perrorf("close()"); else printf("* socket closed, bye...\n"); exit(0); return false; }
int guestfs_impl_copy_in (guestfs_h *g, const char *localpath, const char *remotedir) { CLEANUP_CMD_CLOSE struct command *cmd = guestfs_int_new_command (g); int fd; int r; char fdbuf[64]; size_t buf_len = strlen (localpath) + 1; char buf[buf_len]; const char *dirname, *basename; int remote_is_dir = guestfs_is_dir (g, remotedir); if (remote_is_dir == -1) return -1; if (!remote_is_dir) { error (g, _("target '%s' is not a directory"), remotedir); return -1; } if (split_path (g, buf, buf_len, localpath, &dirname, &basename) == -1) return -1; guestfs_int_cmd_add_arg (cmd, "tar"); if (dirname) { guestfs_int_cmd_add_arg (cmd, "-C"); guestfs_int_cmd_add_arg (cmd, dirname); } guestfs_int_cmd_add_arg (cmd, "-cf"); guestfs_int_cmd_add_arg (cmd, "-"); guestfs_int_cmd_add_arg (cmd, basename); r = guestfs_int_cmd_run_async (cmd, NULL, NULL, &fd, NULL); if (r == -1) return -1; snprintf (fdbuf, sizeof fdbuf, "/dev/fd/%d", fd); r = guestfs_tar_in (g, fdbuf, remotedir); if (close (fd) == -1) { perrorf (g, "close (tar subprocess)"); return -1; } r = guestfs_int_cmd_wait (cmd); if (r == -1) return -1; if (!(WIFEXITED (r) && WEXITSTATUS (r) == 0)) return -1; return 0; }