#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include "dvm2.h" void send_file(const char *fname, int view_only) { const char *base; char sendbuf[DVM_FILENAME_SIZE] = {0}; size_t sendbuf_size = DVM_FILENAME_SIZE; int fd = open(fname, O_RDONLY); if (fd < 0) gui_fatal("open %s", fname); _Static_assert(DVM_FILENAME_SIZE > sizeof(DVM_VIEW_ONLY_PREFIX), "DVM_FILENAME_SIZE > sizeof(DVM_VIEW_ONLY_PREFIX)"); if (view_only) { strncpy(sendbuf, DVM_VIEW_ONLY_PREFIX, sendbuf_size); sendbuf_size -= strlen(DVM_VIEW_ONLY_PREFIX); } base = rindex(fname, '/'); if (!base) base = fname; else base++; if (strlen(base) >= sendbuf_size) base += strlen(base) - sendbuf_size + 1; strncat(sendbuf,base,sendbuf_size - 1); /* fills out with NULs */ sendbuf[DVM_FILENAME_SIZE - 1] = '\0'; if (!write_all(1, sendbuf, DVM_FILENAME_SIZE)) gui_fatal("send filename to dispVM"); if (!copy_fd_all(1, fd)) gui_fatal("send file to dispVM"); close(1); close(fd); } int copy_and_return_nonemptiness(int tmpfd) { struct stat st; if (!copy_fd_all(tmpfd, 0)) gui_fatal("receiving file from dispVM"); if (fstat(tmpfd, &st)) gui_fatal("fstat"); close(tmpfd); return st.st_size > 0; } void recv_file_nowrite(const char *fname) { char *tempfile; char *errmsg; int tmpfd = -1; if (asprintf(&tempfile, "/tmp/file_edited_in_dvm.XXXXXX") != -1) tmpfd = mkstemp(tempfile); if (tmpfd < 0) gui_fatal("unable to create any temporary file, aborting"); if (!copy_and_return_nonemptiness(tmpfd)) { unlink(tempfile); return; } if (asprintf(&errmsg, "The file %s has been edited in Disposable VM and the modified content has been received, " "but this file is in nonwritable directory and thus cannot be modified safely. The edited file has been " "saved to %s", fname, tempfile) != -1) gui_nonfatal(errmsg); } void actually_recv_file(const char *fname, const char *tempfile, int tmpfd) { if (!copy_and_return_nonemptiness(tmpfd)) { unlink(tempfile); return; } if (rename(tempfile, fname)) gui_fatal("rename"); } void recv_file(const char *fname) { int tmpfd = -1; char *tempfile; if (asprintf(&tempfile, "%s.XXXXXX", fname) != -1) { tmpfd = mkstemp(tempfile); } if (tmpfd < 0) recv_file_nowrite(fname); else actually_recv_file(fname, tempfile, tmpfd); } int main(int argc, char ** argv) { char *fname; int view_only = 0; int ret; const struct option opts[] = { {"view-only", no_argument, &view_only, 1}, {0} }; while ((ret=getopt_long(argc, argv, "", opts, NULL)) != -1) { if (ret == '?') { exit(2); } } signal(SIGPIPE, SIG_IGN); if (optind >= argc) gui_fatal("OpenInVM - no file given?"); fname = argv[optind]; send_file(fname, view_only); if (!view_only) { recv_file(fname); } else { /* discard received data */ int null_fd = open("/dev/null", O_WRONLY); copy_fd_all(null_fd, 0); close(null_fd); } return 0; }