int main(int argc, char *argv[]) { int fcopy_fd, len; int error; int daemonize = 1, long_index = 0, opt; int version = FCOPY_CURRENT_VERSION; char *buffer[4096 * 2]; struct hv_fcopy_hdr *in_msg; int in_handshake = 1; __u32 kernel_modver; static struct option long_options[] = { {"help", no_argument, 0, 'h' }, {"no-daemon", no_argument, 0, 'n' }, {0, 0, 0, 0 } }; while ((opt = getopt_long(argc, argv, "hn", long_options, &long_index)) != -1) { switch (opt) { case 'n': daemonize = 0; break; case 'h': default: print_usage(argv); exit(EXIT_FAILURE); } } if (daemonize && daemon(1, 0)) { syslog(LOG_ERR, "daemon() failed; error: %s", strerror(errno)); exit(EXIT_FAILURE); } openlog("HV_FCOPY", 0, LOG_USER); syslog(LOG_INFO, "starting; pid is:%d", getpid()); fcopy_fd = open("/dev/vmbus/hv_fcopy", O_RDWR); if (fcopy_fd < 0) { syslog(LOG_ERR, "open /dev/vmbus/hv_fcopy failed; error: %d %s", errno, strerror(errno)); exit(EXIT_FAILURE); } /* * Register with the kernel. */ if ((write(fcopy_fd, &version, sizeof(int))) != sizeof(int)) { syslog(LOG_ERR, "Registration failed: %s", strerror(errno)); exit(EXIT_FAILURE); } while (1) { /* * In this loop we process fcopy messages after the * handshake is complete. */ len = pread(fcopy_fd, buffer, (4096 * 2), 0); if (len < 0) { syslog(LOG_ERR, "pread failed: %s", strerror(errno)); exit(EXIT_FAILURE); } if (in_handshake) { if (len != sizeof(kernel_modver)) { syslog(LOG_ERR, "invalid version negotiation"); exit(EXIT_FAILURE); } kernel_modver = *(__u32 *)buffer; in_handshake = 0; syslog(LOG_INFO, "kernel module version: %d", kernel_modver); continue; } in_msg = (struct hv_fcopy_hdr *)buffer; switch (in_msg->operation) { case START_FILE_COPY: error = hv_start_fcopy((struct hv_start_fcopy *)in_msg); break; case WRITE_TO_FILE: error = hv_copy_data((struct hv_do_fcopy *)in_msg); break; case COMPLETE_FCOPY: error = hv_copy_finished(); break; case CANCEL_FCOPY: error = hv_copy_cancel(); break; default: syslog(LOG_ERR, "Unknown operation: %d", in_msg->operation); } if (pwrite(fcopy_fd, &error, sizeof(int), 0) != sizeof(int)) { syslog(LOG_ERR, "pwrite failed: %s", strerror(errno)); exit(EXIT_FAILURE); } } }
int main(int argc, char *argv[]) { int fcopy_fd; int error; int daemonize = 1, long_index = 0, opt; int version = FCOPY_CURRENT_VERSION; union { struct hv_fcopy_hdr hdr; struct hv_start_fcopy start; struct hv_do_fcopy copy; __u32 kernel_modver; } buffer = { }; int in_handshake = 1; static struct option long_options[] = { {"help", no_argument, 0, 'h' }, {"no-daemon", no_argument, 0, 'n' }, {0, 0, 0, 0 } }; while ((opt = getopt_long(argc, argv, "hn", long_options, &long_index)) != -1) { switch (opt) { case 'n': daemonize = 0; break; case 'h': default: print_usage(argv); exit(EXIT_FAILURE); } } if (daemonize && daemon(1, 0)) { syslog(LOG_ERR, "daemon() failed; error: %s", strerror(errno)); exit(EXIT_FAILURE); } openlog("HV_FCOPY", 0, LOG_USER); syslog(LOG_INFO, "version %s starting; pid is:%d", HV_DRV_VERSION, getpid()); fcopy_fd = open("/dev/vmbus/hv_fcopy", O_RDWR); if (fcopy_fd < 0) { syslog(LOG_ERR, "open /dev/vmbus/hv_fcopy failed; error: %d %s", errno, strerror(errno)); syslog(LOG_ERR, "The Hyper-V Guest Services may not be enabled for this VM"); exit(EXIT_FAILURE); } /* * Register with the kernel. */ if ((write(fcopy_fd, &version, sizeof(int))) != sizeof(int)) { syslog(LOG_ERR, "Registration failed: %s", strerror(errno)); exit(EXIT_FAILURE); } while (1) { /* * In this loop we process fcopy messages after the * handshake is complete. */ ssize_t len; len = pread(fcopy_fd, &buffer, sizeof(buffer), 0); if (len < 0) { syslog(LOG_ERR, "pread failed: %s", strerror(errno)); exit(EXIT_FAILURE); } if (in_handshake) { if (len != sizeof(buffer.kernel_modver)) { syslog(LOG_ERR, "invalid version negotiation"); exit(EXIT_FAILURE); } in_handshake = 0; syslog(LOG_INFO, "kernel module version: %u", buffer.kernel_modver); continue; } switch (buffer.hdr.operation) { case START_FILE_COPY: error = hv_start_fcopy(&buffer.start); break; case WRITE_TO_FILE: error = hv_copy_data(&buffer.copy); break; case COMPLETE_FCOPY: error = hv_copy_finished(); break; case CANCEL_FCOPY: error = hv_copy_cancel(); break; default: syslog(LOG_ERR, "Unknown operation: %d", buffer.hdr.operation); } if (pwrite(fcopy_fd, &error, sizeof(int), 0) != sizeof(int)) { syslog(LOG_ERR, "pwrite failed: %s", strerror(errno)); exit(EXIT_FAILURE); } } }