diff --git a/ChangeLog b/ChangeLog index 5705e77906..a93a34d452 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,14 +1,23 @@ +Mon Aug 13 21:33:48 EST 2007 Daniel P. Berrange + + * 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 * 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 * 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 diff --git a/src/qemu_driver.c b/src/qemu_driver.c index e649060087..8125622ca0 100644 --- a/src/qemu_driver.c +++ b/src/qemu_driver.c @@ -1855,6 +1855,72 @@ static int qemudDomainGetInfo(virDomainPtr dom, } +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; diff --git a/src/util.c b/src/util.c index 4f80eef2ec..eb5785990e 100644 --- a/src/util.c +++ b/src/util.c @@ -189,3 +189,40 @@ virExecNonBlock(virConnectPtr conn, 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; +} diff --git a/src/util.h b/src/util.h index d11e6d9797..f69fac8601 100644 --- a/src/util.h +++ b/src/util.h @@ -24,3 +24,5 @@ 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);