qopen-in-vm.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  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 <gui-fatal.h>
  13. #include "dvm2.h"
  14. void send_file(const char *fname)
  15. {
  16. const char *base;
  17. char sendbuf[DVM_FILENAME_SIZE];
  18. int fd = open(fname, O_RDONLY);
  19. if (fd < 0)
  20. gui_fatal("open %s", fname);
  21. base = rindex(fname, '/');
  22. if (!base)
  23. base = fname;
  24. else
  25. base++;
  26. if (strlen(base) >= DVM_FILENAME_SIZE)
  27. base += strlen(base) - DVM_FILENAME_SIZE + 1;
  28. strncpy(sendbuf,base,DVM_FILENAME_SIZE - 1); /* fills out with NULs */
  29. sendbuf[DVM_FILENAME_SIZE - 1] = '\0';
  30. if (!write_all(1, sendbuf, DVM_FILENAME_SIZE))
  31. gui_fatal("send filename to dispVM");
  32. if (!copy_fd_all(1, fd))
  33. gui_fatal("send file to dispVM");
  34. close(1);
  35. close(fd);
  36. }
  37. int copy_and_return_nonemptiness(int tmpfd)
  38. {
  39. struct stat st;
  40. if (!copy_fd_all(tmpfd, 0))
  41. gui_fatal("receiving file from dispVM");
  42. if (fstat(tmpfd, &st))
  43. gui_fatal("fstat");
  44. close(tmpfd);
  45. return st.st_size > 0;
  46. }
  47. void recv_file_nowrite(const char *fname)
  48. {
  49. char *tempfile;
  50. char *errmsg;
  51. int tmpfd = -1;
  52. if (asprintf(&tempfile, "/tmp/file_edited_in_dvm.XXXXXX") != -1)
  53. tmpfd = mkstemp(tempfile);
  54. if (tmpfd < 0)
  55. gui_fatal("unable to create any temporary file, aborting");
  56. if (!copy_and_return_nonemptiness(tmpfd)) {
  57. unlink(tempfile);
  58. return;
  59. }
  60. if (asprintf(&errmsg,
  61. "The file %s has been edited in Disposable VM and the modified content has been received, "
  62. "but this file is in nonwritable directory and thus cannot be modified safely. The edited file has been "
  63. "saved to %s", fname, tempfile) != -1)
  64. gui_nonfatal(errmsg);
  65. }
  66. void actually_recv_file(const char *fname, const char *tempfile, int tmpfd)
  67. {
  68. if (!copy_and_return_nonemptiness(tmpfd)) {
  69. unlink(tempfile);
  70. return;
  71. }
  72. if (rename(tempfile, fname))
  73. gui_fatal("rename");
  74. }
  75. void recv_file(const char *fname)
  76. {
  77. int tmpfd = -1;
  78. char *tempfile;
  79. if (asprintf(&tempfile, "%s.XXXXXX", fname) != -1) {
  80. tmpfd = mkstemp(tempfile);
  81. }
  82. if (tmpfd < 0)
  83. recv_file_nowrite(fname);
  84. else
  85. actually_recv_file(fname, tempfile, tmpfd);
  86. }
  87. void talk_to_daemon(const char *fname)
  88. {
  89. send_file(fname);
  90. recv_file(fname);
  91. }
  92. int main(int argc, char ** argv)
  93. {
  94. signal(SIGPIPE, SIG_IGN);
  95. if (argc!=2)
  96. gui_fatal("OpenInVM - no file given?");
  97. talk_to_daemon(argv[1]);
  98. return 0;
  99. }