qopen-in-vm.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #define _GNU_SOURCE
  2. #include <dirent.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <sys/stat.h>
  6. #include <signal.h>
  7. #include <fcntl.h>
  8. #include <malloc.h>
  9. #include <stdlib.h>
  10. #include <libqubes-rpc-filecopy.h>
  11. #include <unistd.h>
  12. #include <getopt.h>
  13. #include <gui-fatal.h>
  14. #include "dvm2.h"
  15. void send_file(const char *fname)
  16. {
  17. const char *base;
  18. char sendbuf[DVM_FILENAME_SIZE];
  19. int fd = open(fname, O_RDONLY);
  20. if (fd < 0)
  21. gui_fatal("open %s", fname);
  22. base = rindex(fname, '/');
  23. if (!base)
  24. base = fname;
  25. else
  26. base++;
  27. if (strlen(base) >= DVM_FILENAME_SIZE)
  28. base += strlen(base) - DVM_FILENAME_SIZE + 1;
  29. strncpy(sendbuf,base,DVM_FILENAME_SIZE - 1); /* fills out with NULs */
  30. sendbuf[DVM_FILENAME_SIZE - 1] = '\0';
  31. if (!write_all(1, sendbuf, DVM_FILENAME_SIZE))
  32. gui_fatal("send filename to dispVM");
  33. if (!copy_fd_all(1, fd))
  34. gui_fatal("send file to dispVM");
  35. close(1);
  36. close(fd);
  37. }
  38. int copy_and_return_nonemptiness(int tmpfd)
  39. {
  40. struct stat st;
  41. if (!copy_fd_all(tmpfd, 0))
  42. gui_fatal("receiving file from dispVM");
  43. if (fstat(tmpfd, &st))
  44. gui_fatal("fstat");
  45. close(tmpfd);
  46. return st.st_size > 0;
  47. }
  48. void recv_file_nowrite(const char *fname)
  49. {
  50. char *tempfile;
  51. char *errmsg;
  52. int tmpfd = -1;
  53. if (asprintf(&tempfile, "/tmp/file_edited_in_dvm.XXXXXX") != -1)
  54. tmpfd = mkstemp(tempfile);
  55. if (tmpfd < 0)
  56. gui_fatal("unable to create any temporary file, aborting");
  57. if (!copy_and_return_nonemptiness(tmpfd)) {
  58. unlink(tempfile);
  59. return;
  60. }
  61. if (asprintf(&errmsg,
  62. "The file %s has been edited in Disposable VM and the modified content has been received, "
  63. "but this file is in nonwritable directory and thus cannot be modified safely. The edited file has been "
  64. "saved to %s", fname, tempfile) != -1)
  65. gui_nonfatal(errmsg);
  66. }
  67. void actually_recv_file(const char *fname, const char *tempfile, int tmpfd)
  68. {
  69. if (!copy_and_return_nonemptiness(tmpfd)) {
  70. unlink(tempfile);
  71. return;
  72. }
  73. if (rename(tempfile, fname))
  74. gui_fatal("rename");
  75. }
  76. void recv_file(const char *fname)
  77. {
  78. int tmpfd = -1;
  79. char *tempfile;
  80. if (asprintf(&tempfile, "%s.XXXXXX", fname) != -1) {
  81. tmpfd = mkstemp(tempfile);
  82. }
  83. if (tmpfd < 0)
  84. recv_file_nowrite(fname);
  85. else
  86. actually_recv_file(fname, tempfile, tmpfd);
  87. }
  88. int main(int argc, char ** argv)
  89. {
  90. char *fname;
  91. int view_only = 0;
  92. int ret;
  93. const struct option opts[] = {
  94. {"view-only", no_argument, &view_only, 1},
  95. {0}
  96. };
  97. while ((ret=getopt_long(argc, argv, "", opts, NULL)) != -1) {
  98. if (ret == '?') {
  99. exit(2);
  100. }
  101. }
  102. signal(SIGPIPE, SIG_IGN);
  103. if (optind >= argc)
  104. gui_fatal("OpenInVM - no file given?");
  105. fname = argv[optind];
  106. send_file(fname);
  107. if (!view_only) {
  108. recv_file(fname);
  109. } else {
  110. /* discard received data */
  111. int null_fd = open("/dev/null", O_WRONLY);
  112. copy_fd_all(null_fd, 0);
  113. close(null_fd);
  114. }
  115. return 0;
  116. }