hv_fcopy_daemon.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. /*
  2. * An implementation of host to guest copy functionality for Linux.
  3. *
  4. * Copyright (C) 2014, Microsoft, Inc.
  5. *
  6. * Author : K. Y. Srinivasan <kys@microsoft.com>
  7. *
  8. * This program is free software; you can redistribute it and/or modify it
  9. * under the terms of the GNU General Public License version 2 as published
  10. * by the Free Software Foundation.
  11. *
  12. * This program is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
  15. * NON INFRINGEMENT. See the GNU General Public License for more
  16. * details.
  17. */
  18. #include <sys/types.h>
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <unistd.h>
  22. #include <errno.h>
  23. #include <linux/hyperv.h>
  24. #include <syslog.h>
  25. #include <sys/stat.h>
  26. #include <fcntl.h>
  27. #include <getopt.h>
  28. static int target_fd;
  29. static char target_fname[W_MAX_PATH];
  30. static unsigned long long filesize;
  31. static int hv_start_fcopy(struct hv_start_fcopy *smsg)
  32. {
  33. int error = HV_E_FAIL;
  34. char *q, *p;
  35. filesize = 0;
  36. p = (char *)smsg->path_name;
  37. snprintf(target_fname, sizeof(target_fname), "%s/%s",
  38. (char *)smsg->path_name, (char *)smsg->file_name);
  39. syslog(LOG_INFO, "Target file name: %s", target_fname);
  40. /*
  41. * Check to see if the path is already in place; if not,
  42. * create if required.
  43. */
  44. while ((q = strchr(p, '/')) != NULL) {
  45. if (q == p) {
  46. p++;
  47. continue;
  48. }
  49. *q = '\0';
  50. if (access((char *)smsg->path_name, F_OK)) {
  51. if (smsg->copy_flags & CREATE_PATH) {
  52. if (mkdir((char *)smsg->path_name, 0755)) {
  53. syslog(LOG_ERR, "Failed to create %s",
  54. (char *)smsg->path_name);
  55. goto done;
  56. }
  57. } else {
  58. syslog(LOG_ERR, "Invalid path: %s",
  59. (char *)smsg->path_name);
  60. goto done;
  61. }
  62. }
  63. p = q + 1;
  64. *q = '/';
  65. }
  66. if (!access(target_fname, F_OK)) {
  67. syslog(LOG_INFO, "File: %s exists", target_fname);
  68. if (!(smsg->copy_flags & OVER_WRITE)) {
  69. error = HV_ERROR_ALREADY_EXISTS;
  70. goto done;
  71. }
  72. }
  73. target_fd = open(target_fname,
  74. O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0744);
  75. if (target_fd == -1) {
  76. syslog(LOG_INFO, "Open Failed: %s", strerror(errno));
  77. goto done;
  78. }
  79. error = 0;
  80. done:
  81. return error;
  82. }
  83. static int hv_copy_data(struct hv_do_fcopy *cpmsg)
  84. {
  85. ssize_t bytes_written;
  86. int ret = 0;
  87. bytes_written = pwrite(target_fd, cpmsg->data, cpmsg->size,
  88. cpmsg->offset);
  89. filesize += cpmsg->size;
  90. if (bytes_written != cpmsg->size) {
  91. switch (errno) {
  92. case ENOSPC:
  93. ret = HV_ERROR_DISK_FULL;
  94. break;
  95. default:
  96. ret = HV_E_FAIL;
  97. break;
  98. }
  99. syslog(LOG_ERR, "pwrite failed to write %llu bytes: %ld (%s)",
  100. filesize, (long)bytes_written, strerror(errno));
  101. }
  102. return ret;
  103. }
  104. static int hv_copy_finished(void)
  105. {
  106. close(target_fd);
  107. return 0;
  108. }
  109. static int hv_copy_cancel(void)
  110. {
  111. close(target_fd);
  112. unlink(target_fname);
  113. return 0;
  114. }
  115. void print_usage(char *argv[])
  116. {
  117. fprintf(stderr, "Usage: %s [options]\n"
  118. "Options are:\n"
  119. " -n, --no-daemon stay in foreground, don't daemonize\n"
  120. " -h, --help print this help\n", argv[0]);
  121. }
  122. int main(int argc, char *argv[])
  123. {
  124. int fcopy_fd, len;
  125. int error;
  126. int daemonize = 1, long_index = 0, opt;
  127. int version = FCOPY_CURRENT_VERSION;
  128. char *buffer[4096 * 2];
  129. struct hv_fcopy_hdr *in_msg;
  130. int in_handshake = 1;
  131. __u32 kernel_modver;
  132. static struct option long_options[] = {
  133. {"help", no_argument, 0, 'h' },
  134. {"no-daemon", no_argument, 0, 'n' },
  135. {0, 0, 0, 0 }
  136. };
  137. while ((opt = getopt_long(argc, argv, "hn", long_options,
  138. &long_index)) != -1) {
  139. switch (opt) {
  140. case 'n':
  141. daemonize = 0;
  142. break;
  143. case 'h':
  144. default:
  145. print_usage(argv);
  146. exit(EXIT_FAILURE);
  147. }
  148. }
  149. if (daemonize && daemon(1, 0)) {
  150. syslog(LOG_ERR, "daemon() failed; error: %s", strerror(errno));
  151. exit(EXIT_FAILURE);
  152. }
  153. openlog("HV_FCOPY", 0, LOG_USER);
  154. syslog(LOG_INFO, "starting; pid is:%d", getpid());
  155. fcopy_fd = open("/dev/vmbus/hv_fcopy", O_RDWR);
  156. if (fcopy_fd < 0) {
  157. syslog(LOG_ERR, "open /dev/vmbus/hv_fcopy failed; error: %d %s",
  158. errno, strerror(errno));
  159. exit(EXIT_FAILURE);
  160. }
  161. /*
  162. * Register with the kernel.
  163. */
  164. if ((write(fcopy_fd, &version, sizeof(int))) != sizeof(int)) {
  165. syslog(LOG_ERR, "Registration failed: %s", strerror(errno));
  166. exit(EXIT_FAILURE);
  167. }
  168. while (1) {
  169. /*
  170. * In this loop we process fcopy messages after the
  171. * handshake is complete.
  172. */
  173. len = pread(fcopy_fd, buffer, (4096 * 2), 0);
  174. if (len < 0) {
  175. syslog(LOG_ERR, "pread failed: %s", strerror(errno));
  176. exit(EXIT_FAILURE);
  177. }
  178. if (in_handshake) {
  179. if (len != sizeof(kernel_modver)) {
  180. syslog(LOG_ERR, "invalid version negotiation");
  181. exit(EXIT_FAILURE);
  182. }
  183. kernel_modver = *(__u32 *)buffer;
  184. in_handshake = 0;
  185. syslog(LOG_INFO, "kernel module version: %d",
  186. kernel_modver);
  187. continue;
  188. }
  189. in_msg = (struct hv_fcopy_hdr *)buffer;
  190. switch (in_msg->operation) {
  191. case START_FILE_COPY:
  192. error = hv_start_fcopy((struct hv_start_fcopy *)in_msg);
  193. break;
  194. case WRITE_TO_FILE:
  195. error = hv_copy_data((struct hv_do_fcopy *)in_msg);
  196. break;
  197. case COMPLETE_FCOPY:
  198. error = hv_copy_finished();
  199. break;
  200. case CANCEL_FCOPY:
  201. error = hv_copy_cancel();
  202. break;
  203. default:
  204. syslog(LOG_ERR, "Unknown operation: %d",
  205. in_msg->operation);
  206. }
  207. if (pwrite(fcopy_fd, &error, sizeof(int), 0) != sizeof(int)) {
  208. syslog(LOG_ERR, "pwrite failed: %s", strerror(errno));
  209. exit(EXIT_FAILURE);
  210. }
  211. }
  212. }