mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-21 20:15:17 +00:00
* src/Makefile.am src/openvz_conf.c src/openvz_conf.h
src/openvz_driver.c src/qemu_driver.c src/util.c src/util.h: cleanup patches from Shuveb Hussain, with new util module for common code shared between drivers. Daniel
This commit is contained in:
parent
e2ea955881
commit
68ef3443d4
@ -1,3 +1,10 @@
|
||||
Thu Jul 19 18:21:47 CEST 2007 Daniel Veillard <veillard@redhat.com>
|
||||
|
||||
* src/Makefile.am src/openvz_conf.c src/openvz_conf.h
|
||||
src/openvz_driver.c src/qemu_driver.c src/util.c src/util.h:
|
||||
cleanup patches from Shuveb Hussain, with new util module for
|
||||
common code shared between drivers.
|
||||
|
||||
Thu Jul 19 16:35:00 BST 2007 Richard W.M. Jones <rjones@redhat.com>
|
||||
|
||||
* configure.in, src/xen_internal.c: Newer Xen uses
|
||||
|
@ -51,6 +51,7 @@ typedef enum {
|
||||
VIR_FROM_NET, /* Error when operating on a network */
|
||||
VIR_FROM_TEST, /* Error from test driver */
|
||||
VIR_FROM_REMOTE, /* Error from remote driver */
|
||||
VIR_FROM_OPENVZ, /* Error from OpenVZ driver */
|
||||
} virErrorDomain;
|
||||
|
||||
|
||||
|
@ -49,7 +49,8 @@ CLIENT_SOURCES = \
|
||||
qemu_driver.c qemu_driver.h \
|
||||
qemu_conf.c qemu_conf.h \
|
||||
openvz_conf.c openvz_conf.h \
|
||||
openvz_driver.c openvz_driver.h
|
||||
openvz_driver.c openvz_driver.h \
|
||||
util.c util.h
|
||||
|
||||
SERVER_SOURCES = \
|
||||
../qemud/protocol.h ../qemud/protocol.c \
|
||||
|
@ -57,7 +57,8 @@ error (virConnectPtr conn, virErrorNumber code, const char *info)
|
||||
errmsg, info);
|
||||
}
|
||||
|
||||
struct openvz_vm *openvzFindVMByID(const struct openvz_driver *driver, int id) {
|
||||
struct openvz_vm
|
||||
*openvzFindVMByID(const struct openvz_driver *driver, int id) {
|
||||
struct openvz_vm *vm = driver->vms;
|
||||
|
||||
while (vm) {
|
||||
@ -69,7 +70,8 @@ struct openvz_vm *openvzFindVMByID(const struct openvz_driver *driver, int id) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct openvz_vm *openvzFindVMByUUID(const struct openvz_driver *driver,
|
||||
struct openvz_vm
|
||||
*openvzFindVMByUUID(const struct openvz_driver *driver,
|
||||
const unsigned char *uuid) {
|
||||
struct openvz_vm *vm = driver->vms;
|
||||
|
||||
@ -82,7 +84,8 @@ struct openvz_vm *openvzFindVMByUUID(const struct openvz_driver *driver,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct openvz_vm *openvzFindVMByName(const struct openvz_driver *driver,
|
||||
struct openvz_vm
|
||||
*openvzFindVMByName(const struct openvz_driver *driver,
|
||||
const char *name) {
|
||||
struct openvz_vm *vm = driver->vms;
|
||||
|
||||
@ -96,7 +99,8 @@ struct openvz_vm *openvzFindVMByName(const struct openvz_driver *driver,
|
||||
}
|
||||
|
||||
/* Free all memory associated with a struct openvz_vm object */
|
||||
void openvzFreeVMDef(struct openvz_vm_def *def) {
|
||||
void
|
||||
openvzFreeVMDef(struct openvz_vm_def *def) {
|
||||
struct ovz_quota *quota = def->fs.quota;
|
||||
struct ovz_ip *ip = def->net.ips;
|
||||
struct ovz_ns *ns = def->net.ns;
|
||||
@ -124,8 +128,9 @@ void openvzFreeVMDef(struct openvz_vm_def *def) {
|
||||
* Parses a libvirt XML definition of a guest, and populates the
|
||||
* the openvz_vm struct with matching data about the guests config
|
||||
*/
|
||||
static struct openvz_vm_def *openvzParseXML(virConnectPtr conn,
|
||||
xmlDocPtr xml) {
|
||||
static struct openvz_vm_def
|
||||
*openvzParseXML(virConnectPtr conn,
|
||||
xmlDocPtr xml) {
|
||||
xmlNodePtr root = NULL;
|
||||
xmlChar *prop = NULL;
|
||||
xmlXPathContextPtr ctxt = NULL;
|
||||
@ -249,7 +254,7 @@ openvzGetVPSInfo(virConnectPtr conn) {
|
||||
FILE *fp;
|
||||
int veid, ret;
|
||||
char status[16];
|
||||
char uuidstr[(VIR_UUID_BUFLEN * 2) + 1];
|
||||
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
||||
struct openvz_vm *vm;
|
||||
struct openvz_vm **pnext;
|
||||
struct openvz_driver *driver;
|
||||
@ -296,15 +301,9 @@ openvzGetVPSInfo(virConnectPtr conn) {
|
||||
|
||||
snprintf(vmdef->name, OPENVZ_NAME_MAX, "%i", veid);
|
||||
openvzGetVPSUUID(veid, uuidstr);
|
||||
ret = sscanf(uuidstr, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
||||
(unsigned int *)&vmdef->uuid[0], (unsigned int *)&vmdef->uuid[1], (unsigned int *)&vmdef->uuid[2],
|
||||
(unsigned int *)&vmdef->uuid[3], (unsigned int *)&vmdef->uuid[4], (unsigned int *)&vmdef->uuid[5],
|
||||
(unsigned int *)&vmdef->uuid[6], (unsigned int *)&vmdef->uuid[7], (unsigned int *)&vmdef->uuid[8],
|
||||
(unsigned int *)&vmdef->uuid[9], (unsigned int *)&vmdef->uuid[10], (unsigned int *)&vmdef->uuid[11],
|
||||
(unsigned int *)&vmdef->uuid[12], (unsigned int *)&vmdef->uuid[13], (unsigned int *)&vmdef->uuid[14],
|
||||
(unsigned int *)&vmdef->uuid[15]);
|
||||
ret = virUUIDParse(uuidstr, vmdef->uuid);
|
||||
|
||||
if(ret != 16) {
|
||||
if(ret == -1) {
|
||||
error(conn, VIR_ERR_INTERNAL_ERROR, "UUID in config file malformed");
|
||||
return NULL;
|
||||
}
|
||||
@ -315,7 +314,8 @@ openvzGetVPSInfo(virConnectPtr conn) {
|
||||
return vm;
|
||||
}
|
||||
|
||||
char *openvzLocateConfDir(void)
|
||||
static char
|
||||
*openvzLocateConfDir(void)
|
||||
{
|
||||
const char *conf_dir_list[] = {"/etc/vz/conf", "/usr/local/etc/conf", NULL};
|
||||
int i=0;
|
||||
@ -330,9 +330,8 @@ char *openvzLocateConfDir(void)
|
||||
}
|
||||
|
||||
/* Richard Steven's classic readline() function */
|
||||
|
||||
static
|
||||
int openvz_readline(int fd, char *ptr, int maxlen)
|
||||
int
|
||||
openvz_readline(int fd, char *ptr, int maxlen)
|
||||
{
|
||||
int n, rc;
|
||||
char c;
|
||||
@ -356,7 +355,8 @@ int openvz_readline(int fd, char *ptr, int maxlen)
|
||||
return n;
|
||||
}
|
||||
|
||||
int openvzGetVPSUUID(int vpsid, char *uuidbuf)
|
||||
static int
|
||||
openvzGetVPSUUID(int vpsid, char *uuidbuf)
|
||||
{
|
||||
char conf_file[PATH_MAX];
|
||||
char line[1024];
|
||||
@ -385,7 +385,7 @@ int openvzGetVPSUUID(int vpsid, char *uuidbuf)
|
||||
|
||||
sscanf(line, "%s %s\n", iden, uuid);
|
||||
if(!strcmp(iden, "#UUID:")) {
|
||||
strncpy(uuidbuf, uuid, (VIR_UUID_BUFLEN * 2) +1);
|
||||
strncpy(uuidbuf, uuid, VIR_UUID_STRING_BUFLEN);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -396,10 +396,11 @@ int openvzGetVPSUUID(int vpsid, char *uuidbuf)
|
||||
* assign if not present.
|
||||
*/
|
||||
|
||||
int openvzSetUUID(int vpsid)
|
||||
static int
|
||||
openvzSetUUID(int vpsid)
|
||||
{
|
||||
char conf_file[PATH_MAX];
|
||||
char uuid[(VIR_UUID_BUFLEN * 2) + 1];
|
||||
char uuid[VIR_UUID_STRING_BUFLEN];
|
||||
unsigned char new_uuid[VIR_UUID_BUFLEN];
|
||||
char *conf_dir;
|
||||
int fd, ret, i;
|
||||
@ -418,7 +419,7 @@ int openvzSetUUID(int vpsid)
|
||||
|
||||
if(uuid[0] == (int)NULL) {
|
||||
virUUIDGenerate(new_uuid);
|
||||
bzero(uuid, (VIR_UUID_BUFLEN * 2) + 1);
|
||||
bzero(uuid, VIR_UUID_STRING_BUFLEN);
|
||||
for(i = 0; i < VIR_UUID_BUFLEN; i ++)
|
||||
sprintf(uuid + (i * 2), "%02x", (unsigned char)new_uuid[i]);
|
||||
|
||||
|
@ -94,8 +94,8 @@ struct openvz_vm {
|
||||
struct openvz_vm *next;
|
||||
};
|
||||
|
||||
char *openvzLocateConfDir(void);
|
||||
int readline(int fd, char *ptr, int maxlen);
|
||||
static char *openvzLocateConfDir(void);
|
||||
int openvz_readline(int fd, char *ptr, int maxlen);
|
||||
static void error (virConnectPtr conn, virErrorNumber code, const char *info);
|
||||
struct openvz_vm *openvzFindVMByID(const struct openvz_driver *driver, int id);
|
||||
struct openvz_vm *openvzFindVMByUUID(const struct openvz_driver *driver,
|
||||
@ -108,7 +108,7 @@ struct openvz_vm_def *openvzParseVMDef(virConnectPtr conn, const char *xmlStr,
|
||||
const char *displayName);
|
||||
struct openvz_vm *openvzGetVPSInfo(virConnectPtr conn);
|
||||
void openvzGenerateUUID(unsigned char *uuid);
|
||||
int openvzGetVPSUUID(int vpsid, char *uuidbuf);
|
||||
int openvzSetUUID(int vpsid);
|
||||
static int openvzGetVPSUUID(int vpsid, char *uuidbuf);
|
||||
static int openvzSetUUID(int vpsid);
|
||||
int openvzAssignUUIDs(void);
|
||||
#endif /* OPENVZ_CONF_H */
|
||||
|
@ -52,6 +52,7 @@
|
||||
|
||||
#include "event.h"
|
||||
#include "buf.h"
|
||||
#include "util.h"
|
||||
#include "openvz_driver.h"
|
||||
#include "openvz_conf.h"
|
||||
|
||||
@ -284,6 +285,11 @@ static virDrvOpenStatus openvzOpen(virConnectPtr conn,
|
||||
if (strcmp(name, "openvz:///system"))
|
||||
return VIR_DRV_OPEN_DECLINED;
|
||||
}
|
||||
/* See if we are running an OpenVZ enabled kernel */
|
||||
if(access("/proc/vz/veinfo", F_OK) == -1 ||
|
||||
access("/proc/user_beancounters", F_OK) == -1) {
|
||||
return VIR_DRV_OPEN_DECLINED;
|
||||
}
|
||||
|
||||
conn->privateData = &ovz_driver;
|
||||
|
||||
@ -323,19 +329,25 @@ static const char *openvzGetType(virConnectPtr conn ATTRIBUTE_UNUSED) {
|
||||
|
||||
static int openvzListDomains(virConnectPtr conn, int *ids, int nids) {
|
||||
int got = 0;
|
||||
int veid;
|
||||
FILE *fp;
|
||||
int veid, pid, outfd, errfd;
|
||||
int ret;
|
||||
char buf[32];
|
||||
const char *cmd[] = {VZLIST, "-ovpsid", "-H" , NULL};
|
||||
|
||||
if((fp = popen(VZLIST " -o vpsid -H 2> /dev/null", "r")) == NULL){
|
||||
error(conn, VIR_ERR_INTERNAL_ERROR, "Could not popen " VZLIST);
|
||||
ret = virExec(conn, (char **)cmd, &pid, &outfd, &errfd);
|
||||
if(ret == -1) {
|
||||
error(conn, VIR_ERR_INTERNAL_ERROR, "Could not exec " VZLIST);
|
||||
return (int)NULL;
|
||||
}
|
||||
|
||||
while(!(feof(fp)) && got < nids){
|
||||
fscanf(fp, "%d\n", &veid);
|
||||
while(got < nids){
|
||||
ret = openvz_readline(outfd, buf, 32);
|
||||
if(!ret) break;
|
||||
sscanf(buf, "%d", &veid);
|
||||
ids[got] = veid;
|
||||
got ++;
|
||||
}
|
||||
waitpid(pid, NULL, 0);
|
||||
|
||||
return got;
|
||||
}
|
||||
@ -347,23 +359,27 @@ static int openvzNumDomains(virConnectPtr conn) {
|
||||
static int openvzListDefinedDomains(virConnectPtr conn,
|
||||
char **const names, int nnames) {
|
||||
int got = 0;
|
||||
FILE *fp;
|
||||
int veid;
|
||||
int veid, pid, outfd, errfd, ret;
|
||||
char vpsname[OPENVZ_NAME_MAX];
|
||||
char buf[32];
|
||||
const char *cmd[] = {VZLIST, "-ovpsid", "-H", NULL};
|
||||
|
||||
/* the -S options lists only stopped domains */
|
||||
if((fp = popen(VZLIST " -S -o vpsid -H 2> /dev/null", "r")) == NULL){
|
||||
error(conn, VIR_ERR_INTERNAL_ERROR, "Could not popen " VZLIST);
|
||||
ret = virExec(conn, (char **)cmd, &pid, &outfd, &errfd);
|
||||
if(ret == -1) {
|
||||
error(conn, VIR_ERR_INTERNAL_ERROR, "Could not exec " VZLIST);
|
||||
return (int)NULL;
|
||||
}
|
||||
|
||||
while(!(feof(fp)) && got < nnames){
|
||||
fscanf(fp, "%d\n", &veid);
|
||||
while(got < nnames){
|
||||
ret = openvz_readline(outfd, buf, 32);
|
||||
if(!ret) break;
|
||||
sscanf(buf, "%d\n", &veid);
|
||||
sprintf(vpsname, "%d", veid);
|
||||
names[got] = strdup(vpsname);
|
||||
got ++;
|
||||
}
|
||||
|
||||
waitpid(pid, NULL, 0);
|
||||
return got;
|
||||
}
|
||||
|
||||
|
@ -50,6 +50,7 @@
|
||||
|
||||
#include "event.h"
|
||||
#include "buf.h"
|
||||
#include "util.h"
|
||||
#include "qemu_driver.h"
|
||||
#include "qemu_conf.h"
|
||||
|
||||
@ -330,91 +331,6 @@ qemudShutdown(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
qemudExec(virConnectPtr conn,
|
||||
char **argv,
|
||||
int *retpid, int *outfd, int *errfd) {
|
||||
int pid, null;
|
||||
int pipeout[2] = {-1,-1};
|
||||
int pipeerr[2] = {-1,-1};
|
||||
|
||||
if ((null = open(_PATH_DEVNULL, O_RDONLY)) < 0) {
|
||||
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot open %s : %s",
|
||||
_PATH_DEVNULL, strerror(errno));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((outfd != NULL && pipe(pipeout) < 0) ||
|
||||
(errfd != NULL && pipe(pipeerr) < 0)) {
|
||||
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot create pipe : %s",
|
||||
strerror(errno));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((pid = fork()) < 0) {
|
||||
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot fork child process : %s",
|
||||
strerror(errno));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (pid) { /* parent */
|
||||
close(null);
|
||||
if (outfd) {
|
||||
close(pipeout[1]);
|
||||
qemudSetNonBlock(pipeout[0]);
|
||||
qemudSetCloseExec(pipeout[0]);
|
||||
*outfd = pipeout[0];
|
||||
}
|
||||
if (errfd) {
|
||||
close(pipeerr[1]);
|
||||
qemudSetNonBlock(pipeerr[0]);
|
||||
qemudSetCloseExec(pipeerr[0]);
|
||||
*errfd = pipeerr[0];
|
||||
}
|
||||
*retpid = pid;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* child */
|
||||
|
||||
if (pipeout[0] > 0 && close(pipeout[0]) < 0)
|
||||
_exit(1);
|
||||
if (pipeerr[0] > 0 && close(pipeerr[0]) < 0)
|
||||
_exit(1);
|
||||
|
||||
if (dup2(null, STDIN_FILENO) < 0)
|
||||
_exit(1);
|
||||
if (dup2(pipeout[1] > 0 ? pipeout[1] : null, STDOUT_FILENO) < 0)
|
||||
_exit(1);
|
||||
if (dup2(pipeerr[1] > 0 ? pipeerr[1] : null, STDERR_FILENO) < 0)
|
||||
_exit(1);
|
||||
|
||||
close(null);
|
||||
if (pipeout[1] > 0)
|
||||
close(pipeout[1]);
|
||||
if (pipeerr[1] > 0)
|
||||
close(pipeerr[1]);
|
||||
|
||||
execvp(argv[0], argv);
|
||||
|
||||
_exit(1);
|
||||
|
||||
return 0;
|
||||
|
||||
cleanup:
|
||||
if (pipeerr[0] > 0)
|
||||
close(pipeerr[0]);
|
||||
if (pipeerr[1] > 0)
|
||||
close(pipeerr[1]);
|
||||
if (pipeout[0] > 0)
|
||||
close(pipeout[0]);
|
||||
if (pipeout[1] > 0)
|
||||
close(pipeout[1]);
|
||||
if (null > 0)
|
||||
close(null);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Return -1 for error, 1 to continue reading and 0 for success */
|
||||
typedef int qemudHandlerMonitorOutput(virConnectPtr conn,
|
||||
struct qemud_driver *driver,
|
||||
@ -722,7 +638,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
|
||||
qemudLog(QEMUD_WARN, "Unable to write argv to logfile %d: %s",
|
||||
errno, strerror(errno));
|
||||
|
||||
if (qemudExec(conn, argv, &vm->pid, &vm->stdout, &vm->stderr) == 0) {
|
||||
if (virExecNonBlock(conn, argv, &vm->pid, &vm->stdout, &vm->stderr) == 0) {
|
||||
vm->id = driver->nextvmid++;
|
||||
vm->state = VIR_DOMAIN_RUNNING;
|
||||
|
||||
@ -981,7 +897,7 @@ dhcpStartDhcpDaemon(virConnectPtr conn,
|
||||
if (qemudBuildDnsmasqArgv(conn, network, &argv) < 0)
|
||||
return -1;
|
||||
|
||||
ret = qemudExec(conn, argv, &network->dnsmasqPid, NULL, NULL);
|
||||
ret = virExecNonBlock(conn, argv, &network->dnsmasqPid, NULL, NULL);
|
||||
|
||||
for (i = 0; argv[i]; i++)
|
||||
free(argv[i]);
|
||||
|
192
src/util.c
Normal file
192
src/util.c
Normal file
@ -0,0 +1,192 @@
|
||||
/*
|
||||
* utils.c: common, generic utility functions
|
||||
*
|
||||
* Copyright (C) 2006, 2007 Red Hat, Inc.
|
||||
* Copyright (C) 2006 Daniel P. Berrange
|
||||
* Copyright (C) 2006, 2007 Binary Karma
|
||||
* Copyright (C) 2006 Shuveb Hussain
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Daniel P. Berrange <berrange@redhat.com>
|
||||
* File created Jul 18, 2007 - Shuveb Hussain <shuveb@binarykarma.com>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <paths.h>
|
||||
#include <errno.h>
|
||||
#include <libvirt/virterror.h>
|
||||
#include "event.h"
|
||||
#include "buf.h"
|
||||
|
||||
#define MAX_ERROR_LEN 1024
|
||||
|
||||
static void
|
||||
ReportError(virConnectPtr conn,
|
||||
virDomainPtr dom,
|
||||
virNetworkPtr net,
|
||||
int code, const char *fmt, ...) {
|
||||
va_list args;
|
||||
char errorMessage[MAX_ERROR_LEN];
|
||||
|
||||
if (fmt) {
|
||||
va_start(args, fmt);
|
||||
vsnprintf(errorMessage, MAX_ERROR_LEN-1, fmt, args);
|
||||
va_end(args);
|
||||
} else {
|
||||
errorMessage[0] = '\0';
|
||||
}
|
||||
__virRaiseError(conn, dom, net, VIR_FROM_NONE, code, VIR_ERR_ERROR,
|
||||
NULL, NULL, NULL, -1, -1, errorMessage);
|
||||
}
|
||||
|
||||
static int virSetCloseExec(int fd) {
|
||||
int flags;
|
||||
if ((flags = fcntl(fd, F_GETFD)) < 0)
|
||||
return -1;
|
||||
flags |= FD_CLOEXEC;
|
||||
if ((fcntl(fd, F_SETFD, flags)) < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int virSetNonBlock(int fd) {
|
||||
int flags;
|
||||
if ((flags = fcntl(fd, F_GETFL)) < 0)
|
||||
return -1;
|
||||
flags |= O_NONBLOCK;
|
||||
if ((fcntl(fd, F_SETFL, flags)) < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_virExec(virConnectPtr conn,
|
||||
char **argv,
|
||||
int *retpid, int *outfd, int *errfd, int non_block) {
|
||||
int pid, null;
|
||||
int pipeout[2] = {-1,-1};
|
||||
int pipeerr[2] = {-1,-1};
|
||||
|
||||
if ((null = open(_PATH_DEVNULL, O_RDONLY)) < 0) {
|
||||
ReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot open %s : %s",
|
||||
_PATH_DEVNULL, strerror(errno));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((outfd != NULL && pipe(pipeout) < 0) ||
|
||||
(errfd != NULL && pipe(pipeerr) < 0)) {
|
||||
ReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot create pipe : %s",
|
||||
strerror(errno));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((pid = fork()) < 0) {
|
||||
ReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot fork child process : %s",
|
||||
strerror(errno));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (pid) { /* parent */
|
||||
close(null);
|
||||
if (outfd) {
|
||||
close(pipeout[1]);
|
||||
if(non_block)
|
||||
if(virSetNonBlock(pipeout[0]) == -1)
|
||||
ReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
"Failed to set non-blocking file descriptor flag");
|
||||
|
||||
if(virSetCloseExec(pipeout[0]) == -1)
|
||||
ReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
"Failed to set close-on-exec file descriptor flag");
|
||||
*outfd = pipeout[0];
|
||||
}
|
||||
if (errfd) {
|
||||
close(pipeerr[1]);
|
||||
if(non_block)
|
||||
if(virSetNonBlock(pipeerr[0]) == -1)
|
||||
ReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
"Failed to set non-blocking file descriptor flag");
|
||||
|
||||
if(virSetCloseExec(pipeerr[0]) == -1)
|
||||
ReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
"Failed to set close-on-exec file descriptor flag");
|
||||
*errfd = pipeerr[0];
|
||||
}
|
||||
*retpid = pid;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* child */
|
||||
|
||||
if (pipeout[0] > 0 && close(pipeout[0]) < 0)
|
||||
_exit(1);
|
||||
if (pipeerr[0] > 0 && close(pipeerr[0]) < 0)
|
||||
_exit(1);
|
||||
|
||||
if (dup2(null, STDIN_FILENO) < 0)
|
||||
_exit(1);
|
||||
if (dup2(pipeout[1] > 0 ? pipeout[1] : null, STDOUT_FILENO) < 0)
|
||||
_exit(1);
|
||||
if (dup2(pipeerr[1] > 0 ? pipeerr[1] : null, STDERR_FILENO) < 0)
|
||||
_exit(1);
|
||||
|
||||
close(null);
|
||||
if (pipeout[1] > 0)
|
||||
close(pipeout[1]);
|
||||
if (pipeerr[1] > 0)
|
||||
close(pipeerr[1]);
|
||||
|
||||
execvp(argv[0], argv);
|
||||
|
||||
_exit(1);
|
||||
|
||||
return 0;
|
||||
|
||||
cleanup:
|
||||
if (pipeerr[0] > 0)
|
||||
close(pipeerr[0]);
|
||||
if (pipeerr[1] > 0)
|
||||
close(pipeerr[1]);
|
||||
if (pipeout[0] > 0)
|
||||
close(pipeout[0]);
|
||||
if (pipeout[1] > 0)
|
||||
close(pipeout[1]);
|
||||
if (null > 0)
|
||||
close(null);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
virExec(virConnectPtr conn,
|
||||
char **argv,
|
||||
int *retpid, int *outfd, int *errfd) {
|
||||
|
||||
_virExec(conn, argv, retpid, outfd, errfd, 0);
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
virExecNonBlock(virConnectPtr conn,
|
||||
char **argv,
|
||||
int *retpid, int *outfd, int *errfd) {
|
||||
|
||||
_virExec(conn, argv, retpid, outfd, errfd, 1);
|
||||
|
||||
}
|
||||
|
26
src/util.h
Normal file
26
src/util.h
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* utils.h: common, generic utility functions
|
||||
*
|
||||
* Copyright (C) 2006, 2007 Binary Karma
|
||||
* Copyright (C) 2006 Shuveb Hussain
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* File created Jul 18, 2007 - Shuveb Hussain <shuveb@binarykarma.com>
|
||||
*/
|
||||
|
||||
int virExec(virConnectPtr conn, char **argv, int *retpid, int *outfd, int *errfd);
|
||||
int virExecNonBlock(virConnectPtr conn, char **argv, int *retpid, int *outfd, int *errfd);
|
||||
|
Loading…
x
Reference in New Issue
Block a user