+Mon Aug 13 21:33:48 EST 2007 Daniel P. Berrange <berrange@redhat.com>
+
+ * src/qemu_driver.c: added qemudEscapeShellArg() helper function
+ for future save impl. Patch from Jim Paris
+ * src/util.c, src/util.h: Added saferead/safewrite convenience
+ functions for doing read/write safe from signals. Patch from
+ Jim Paris
+
Mon Aug 13 21:26:48 EST 2007 Daniel P. Berrange <berrange@redhat.com>
* src/qemu_conf.c, src/qemu_conf.h, src/qemu_driver.c: Add support
- for passing -incoming option to QEMU for migration/restore.
+ for passing -incoming option to QEMU for migration/restore. Patch
+ from Jim Paris
Mon Aug 13 21:18:48 EST 2007 Daniel P. Berrange <berrange@redhat.com>
* src/util.h, src/util.c: Allow a file descriptor to be supplied
for STDIN when calling virExec(), or if -1, redirect from /dev/null
* src/qemu_driver.c, src/openvz_driver.c: Pass in -1 for new stdin
- parameter above where neccessary
+ parameter above where neccessary. Patch from Jim Paris
Mon Aug 13 20:13:48 EST 2007 Daniel P. Berrange <berrange@redhat.com>
}
+static char *qemudEscapeShellArg(const char *in)
+{
+ int len = 0;
+ int i, j;
+ char *out;
+
+ /* To pass through the QEMU monitor, we need to use escape
+ sequences: \r, \n, \", \\
+
+ To pass through both QEMU + the shell, we need to escape
+ the single character ' as the five characters '\\''
+ */
+
+ for (i = 0; in[i] != '\0'; i++) {
+ switch(in[i]) {
+ case '\r':
+ case '\n':
+ case '"':
+ case '\\':
+ len += 2;
+ break;
+ case '\'':
+ len += 5;
+ break;
+ default:
+ len += 1;
+ break;
+ }
+ }
+
+ if ((out = (char *)malloc(len + 1)) == NULL)
+ return NULL;
+
+ for (i = j = 0; in[i] != '\0'; i++) {
+ switch(in[i]) {
+ case '\r':
+ out[j++] = '\\';
+ out[j++] = 'r';
+ break;
+ case '\n':
+ out[j++] = '\\';
+ out[j++] = 'n';
+ break;
+ case '"':
+ case '\\':
+ out[j++] = '\\';
+ out[j++] = in[i];
+ break;
+ case '\'':
+ out[j++] = '\'';
+ out[j++] = '\\';
+ out[j++] = '\\';
+ out[j++] = '\'';
+ out[j++] = '\'';
+ break;
+ default:
+ out[j++] = in[i];
+ break;
+ }
+ }
+ out[j] = '\0';
+
+ return out;
+}
+
+
static int qemudDomainSave(virDomainPtr dom,
const char *path ATTRIBUTE_UNUSED) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
return(_virExec(conn, argv, retpid, infd, outfd, errfd, 1));
}
+/* Like read(), but restarts after EINTR */
+int saferead(int fd, void *buf, size_t count)
+{
+ size_t nread = 0;
+ while (count > 0) {
+ int r = read(fd, buf, count);
+ if (r < 0 && errno == EINTR)
+ continue;
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return nread;
+ buf = (unsigned char *)buf + r;
+ count -= r;
+ nread += r;
+ }
+ return nread;
+}
+
+/* Like write(), but restarts after EINTR */
+ssize_t safewrite(int fd, const void *buf, size_t count)
+{
+ size_t nwritten = 0;
+ while (count > 0) {
+ int r = write(fd, buf, count);
+ if (r < 0 && errno == EINTR)
+ continue;
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return nwritten;
+ buf = (unsigned char *)buf + r;
+ count -= r;
+ nwritten += r;
+ }
+ return nwritten;
+}
int virExec(virConnectPtr conn, char **argv, int *retpid, int infd, int *outfd, int *errfd);
int virExecNonBlock(virConnectPtr conn, char **argv, int *retpid, int infd, int *outfd, int *errfd);
+int saferead(int fd, void *buf, size_t count);
+ssize_t safewrite(int fd, const void *buf, size_t count);