~ubuntu-branches/ubuntu/natty/libvirt/natty-proposed

« back to all changes in this revision

Viewing changes to .pc/9019-Remove-wrong-check-for-uml-monitor-response-size.patch/src/uml/uml_driver.c

  • Committer: Bazaar Package Importer
  • Author(s): Soren Hansen
  • Date: 2010-08-23 14:24:06 UTC
  • Revision ID: james.westby@ubuntu.com-20100823142406-1jsss896fyjl13qp
Tags: 0.8.3-1ubuntu6
* FFe: LP: #622682.
* Replace 9019-Remove-wrong-check-for-uml-monitor-response-size.patch with
  9019-uml-fix-logic-bug-in-checking-reply-length.patch which is what ended
  up getting applied upstream.
* Add the following patches taken from upstream git:
  - 9021-Allow-chardev-of-type-file-for-UML-domains.patch
  - 9022-Rename-qemudShrinkDisks-to-virDomainDiskRemove-and-m.patch
  - 9023-Support-virDomainAttachDevice-and-virDomainDetachDev.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * uml_driver.c: core driver methods for managing UML guests
3
 
 *
4
 
 * Copyright (C) 2006-2010 Red Hat, Inc.
5
 
 * Copyright (C) 2006-2008 Daniel P. Berrange
6
 
 *
7
 
 * This library is free software; you can redistribute it and/or
8
 
 * modify it under the terms of the GNU Lesser General Public
9
 
 * License as published by the Free Software Foundation; either
10
 
 * version 2.1 of the License, or (at your option) any later version.
11
 
 *
12
 
 * This library is distributed in the hope that it will be useful,
13
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 
 * Lesser General Public License for more details.
16
 
 *
17
 
 * You should have received a copy of the GNU Lesser General Public
18
 
 * License along with this library; if not, write to the Free Software
19
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
20
 
 *
21
 
 * Author: Daniel P. Berrange <berrange@redhat.com>
22
 
 */
23
 
 
24
 
#include <config.h>
25
 
 
26
 
#include <sys/types.h>
27
 
#include <sys/poll.h>
28
 
#include <dirent.h>
29
 
#include <limits.h>
30
 
#include <string.h>
31
 
#include <stdio.h>
32
 
#include <stdarg.h>
33
 
#include <stdlib.h>
34
 
#include <unistd.h>
35
 
#include <errno.h>
36
 
#include <sys/utsname.h>
37
 
#include <sys/stat.h>
38
 
#include <fcntl.h>
39
 
#include <signal.h>
40
 
#include <paths.h>
41
 
#include <pwd.h>
42
 
#include <stdio.h>
43
 
#include <sys/wait.h>
44
 
#include <sys/ioctl.h>
45
 
#include <sys/inotify.h>
46
 
#include <sys/un.h>
47
 
 
48
 
#include "uml_driver.h"
49
 
#include "uml_conf.h"
50
 
#include "event.h"
51
 
#include "buf.h"
52
 
#include "util.h"
53
 
#include "nodeinfo.h"
54
 
#include "stats_linux.h"
55
 
#include "capabilities.h"
56
 
#include "memory.h"
57
 
#include "uuid.h"
58
 
#include "domain_conf.h"
59
 
#include "datatypes.h"
60
 
#include "logging.h"
61
 
 
62
 
#define VIR_FROM_THIS VIR_FROM_UML
63
 
 
64
 
/* For storing short-lived temporary files. */
65
 
#define TEMPDIR LOCAL_STATE_DIR "/cache/libvirt"
66
 
 
67
 
typedef struct _umlDomainObjPrivate umlDomainObjPrivate;
68
 
typedef umlDomainObjPrivate *umlDomainObjPrivatePtr;
69
 
struct _umlDomainObjPrivate {
70
 
    int monitor;
71
 
    int monitorWatch;
72
 
};
73
 
 
74
 
 
75
 
static int umlShutdown(void);
76
 
 
77
 
static void *umlDomainObjPrivateAlloc(void)
78
 
{
79
 
    umlDomainObjPrivatePtr priv;
80
 
 
81
 
    if (VIR_ALLOC(priv) < 0)
82
 
        return NULL;
83
 
 
84
 
    priv->monitor = -1;
85
 
    priv->monitorWatch = -1;
86
 
 
87
 
    return priv;
88
 
}
89
 
 
90
 
static void umlDomainObjPrivateFree(void *data)
91
 
{
92
 
    umlDomainObjPrivatePtr priv = data;
93
 
 
94
 
    VIR_FREE(priv);
95
 
}
96
 
 
97
 
 
98
 
static void umlDriverLock(struct uml_driver *driver)
99
 
{
100
 
    virMutexLock(&driver->lock);
101
 
}
102
 
static void umlDriverUnlock(struct uml_driver *driver)
103
 
{
104
 
    virMutexUnlock(&driver->lock);
105
 
}
106
 
 
107
 
 
108
 
static int umlOpenMonitor(struct uml_driver *driver,
109
 
                          virDomainObjPtr vm);
110
 
static int umlReadPidFile(struct uml_driver *driver,
111
 
                          virDomainObjPtr vm);
112
 
 
113
 
static int umlSetCloseExec(int fd) {
114
 
    int flags;
115
 
    if ((flags = fcntl(fd, F_GETFD)) < 0)
116
 
        goto error;
117
 
    flags |= FD_CLOEXEC;
118
 
    if ((fcntl(fd, F_SETFD, flags)) < 0)
119
 
        goto error;
120
 
    return 0;
121
 
 error:
122
 
    VIR_ERROR0(_("Failed to set close-on-exec file descriptor flag"));
123
 
    return -1;
124
 
}
125
 
 
126
 
static int umlStartVMDaemon(virConnectPtr conn,
127
 
                            struct uml_driver *driver,
128
 
                            virDomainObjPtr vm);
129
 
 
130
 
static void umlShutdownVMDaemon(virConnectPtr conn,
131
 
                                struct uml_driver *driver,
132
 
                                virDomainObjPtr vm);
133
 
 
134
 
 
135
 
static int umlMonitorCommand(const struct uml_driver *driver,
136
 
                             const virDomainObjPtr vm,
137
 
                             const char *cmd,
138
 
                             char **reply);
139
 
 
140
 
static struct uml_driver *uml_driver = NULL;
141
 
 
142
 
struct umlAutostartData {
143
 
    struct uml_driver *driver;
144
 
    virConnectPtr conn;
145
 
};
146
 
 
147
 
static void
148
 
umlAutostartDomain(void *payload, const char *name ATTRIBUTE_UNUSED, void *opaque)
149
 
{
150
 
    virDomainObjPtr vm = payload;
151
 
    const struct umlAutostartData *data = opaque;
152
 
 
153
 
    virDomainObjLock(vm);
154
 
    if (vm->autostart &&
155
 
        !virDomainObjIsActive(vm)) {
156
 
        virResetLastError();
157
 
        if (umlStartVMDaemon(data->conn, data->driver, vm) < 0) {
158
 
            virErrorPtr err = virGetLastError();
159
 
            VIR_ERROR(_("Failed to autostart VM '%s': %s"),
160
 
                      vm->def->name, err ? err->message : _("unknown error"));
161
 
        }
162
 
    }
163
 
    virDomainObjUnlock(vm);
164
 
}
165
 
 
166
 
static void
167
 
umlAutostartConfigs(struct uml_driver *driver) {
168
 
    /* XXX: Figure out a better way todo this. The domain
169
 
     * startup code needs a connection handle in order
170
 
     * to lookup the bridge associated with a virtual
171
 
     * network
172
 
     */
173
 
    virConnectPtr conn = virConnectOpen(driver->privileged ?
174
 
                                        "uml:///system" :
175
 
                                        "uml:///session");
176
 
    /* Ignoring NULL conn which is mostly harmless here */
177
 
 
178
 
    struct umlAutostartData data = { driver, conn };
179
 
 
180
 
    virHashForEach(driver->domains.objs, umlAutostartDomain, &data);
181
 
 
182
 
    if (conn)
183
 
        virConnectClose(conn);
184
 
}
185
 
 
186
 
 
187
 
static int
188
 
umlIdentifyOneChrPTY(struct uml_driver *driver,
189
 
                     virDomainObjPtr dom,
190
 
                     virDomainChrDefPtr def,
191
 
                     const char *dev)
192
 
{
193
 
    char *cmd;
194
 
    char *res = NULL;
195
 
    int retries = 0;
196
 
    if (virAsprintf(&cmd, "config %s%d", dev, def->target.port) < 0) {
197
 
        virReportOOMError();
198
 
        return -1;
199
 
    }
200
 
requery:
201
 
    if (umlMonitorCommand(driver, dom, cmd, &res) < 0)
202
 
        return -1;
203
 
 
204
 
    if (res && STRPREFIX(res, "pts:")) {
205
 
        VIR_FREE(def->data.file.path);
206
 
        if ((def->data.file.path = strdup(res + 4)) == NULL) {
207
 
            virReportOOMError();
208
 
            VIR_FREE(res);
209
 
            VIR_FREE(cmd);
210
 
            return -1;
211
 
        }
212
 
    } else if (!res || STRPREFIX(res, "pts")) {
213
 
        /* It can take a while to startup, so retry for
214
 
           upto 5 seconds */
215
 
        /* XXX should do this in a better non-blocking
216
 
           way somehow ...perhaps register a timer */
217
 
        if (retries++ < 50) {
218
 
            usleep(1000*10);
219
 
            goto requery;
220
 
        }
221
 
    }
222
 
 
223
 
    VIR_FREE(cmd);
224
 
    VIR_FREE(res);
225
 
    return 0;
226
 
}
227
 
 
228
 
static int
229
 
umlIdentifyChrPTY(struct uml_driver *driver,
230
 
                  virDomainObjPtr dom)
231
 
{
232
 
    int i;
233
 
 
234
 
    if (dom->def->console &&
235
 
        dom->def->console->type == VIR_DOMAIN_CHR_TYPE_PTY)
236
 
        if (umlIdentifyOneChrPTY(driver, dom,
237
 
                                 dom->def->console, "con") < 0)
238
 
            return -1;
239
 
 
240
 
    for (i = 0 ; i < dom->def->nserials; i++)
241
 
        if (dom->def->serials[i]->type == VIR_DOMAIN_CHR_TYPE_PTY &&
242
 
            umlIdentifyOneChrPTY(driver, dom,
243
 
                                 dom->def->serials[i], "ssl") < 0)
244
 
            return -1;
245
 
 
246
 
    return 0;
247
 
}
248
 
 
249
 
static void
250
 
umlInotifyEvent(int watch,
251
 
                int fd,
252
 
                int events ATTRIBUTE_UNUSED,
253
 
                void *data)
254
 
{
255
 
    char buf[1024];
256
 
    struct inotify_event *e;
257
 
    int got;
258
 
    char *tmp, *name;
259
 
    struct uml_driver *driver = data;
260
 
    virDomainObjPtr dom;
261
 
 
262
 
    umlDriverLock(driver);
263
 
    if (watch != driver->inotifyWatch)
264
 
        goto cleanup;
265
 
 
266
 
reread:
267
 
    got = read(fd, buf, sizeof(buf));
268
 
    if (got == -1) {
269
 
        if (errno == EINTR)
270
 
            goto reread;
271
 
        goto cleanup;
272
 
    }
273
 
 
274
 
    tmp = buf;
275
 
    while (got) {
276
 
        if (got < sizeof(struct inotify_event))
277
 
            goto cleanup; /* bad */
278
 
 
279
 
        e = (struct inotify_event *)tmp;
280
 
        tmp += sizeof(struct inotify_event);
281
 
        got -= sizeof(struct inotify_event);
282
 
 
283
 
        if (got < e->len)
284
 
            goto cleanup;
285
 
 
286
 
        tmp += e->len;
287
 
        got -= e->len;
288
 
 
289
 
        name = (char *)&(e->name);
290
 
 
291
 
        dom = virDomainFindByName(&driver->domains, name);
292
 
 
293
 
        if (!dom) {
294
 
            continue;
295
 
        }
296
 
 
297
 
        if (e->mask & IN_DELETE) {
298
 
            VIR_DEBUG("Got inotify domain shutdown '%s'", name);
299
 
            if (!virDomainObjIsActive(dom)) {
300
 
                virDomainObjUnlock(dom);
301
 
                continue;
302
 
            }
303
 
 
304
 
            umlShutdownVMDaemon(NULL, driver, dom);
305
 
        } else if (e->mask & (IN_CREATE | IN_MODIFY)) {
306
 
            VIR_DEBUG("Got inotify domain startup '%s'", name);
307
 
            if (virDomainObjIsActive(dom)) {
308
 
                virDomainObjUnlock(dom);
309
 
                continue;
310
 
            }
311
 
 
312
 
            if (umlReadPidFile(driver, dom) < 0) {
313
 
                virDomainObjUnlock(dom);
314
 
                continue;
315
 
            }
316
 
 
317
 
            dom->def->id = driver->nextvmid++;
318
 
            dom->state = VIR_DOMAIN_RUNNING;
319
 
 
320
 
            if (umlOpenMonitor(driver, dom) < 0) {
321
 
                VIR_WARN0("Could not open monitor for new domain");
322
 
                umlShutdownVMDaemon(NULL, driver, dom);
323
 
            } else if (umlIdentifyChrPTY(driver, dom) < 0) {
324
 
                VIR_WARN0("Could not identify charater devices for new domain");
325
 
                umlShutdownVMDaemon(NULL, driver, dom);
326
 
            }
327
 
        }
328
 
        virDomainObjUnlock(dom);
329
 
    }
330
 
 
331
 
cleanup:
332
 
    umlDriverUnlock(driver);
333
 
}
334
 
 
335
 
/**
336
 
 * umlStartup:
337
 
 *
338
 
 * Initialization function for the Uml daemon
339
 
 */
340
 
static int
341
 
umlStartup(int privileged) {
342
 
    uid_t uid = geteuid();
343
 
    char *base = NULL;
344
 
    char driverConf[PATH_MAX];
345
 
    char *userdir = NULL;
346
 
 
347
 
    if (VIR_ALLOC(uml_driver) < 0)
348
 
        return -1;
349
 
 
350
 
    uml_driver->privileged = privileged;
351
 
 
352
 
    if (virMutexInit(&uml_driver->lock) < 0) {
353
 
        VIR_FREE(uml_driver);
354
 
        return -1;
355
 
    }
356
 
    umlDriverLock(uml_driver);
357
 
 
358
 
    /* Don't have a dom0 so start from 1 */
359
 
    uml_driver->nextvmid = 1;
360
 
    uml_driver->inotifyWatch = -1;
361
 
 
362
 
    if (virDomainObjListInit(&uml_driver->domains) < 0)
363
 
        goto error;
364
 
 
365
 
    userdir = virGetUserDirectory(uid);
366
 
    if (!userdir)
367
 
        goto error;
368
 
 
369
 
    if (privileged) {
370
 
        if (virAsprintf(&uml_driver->logDir,
371
 
                        "%s/log/libvirt/uml", LOCAL_STATE_DIR) == -1)
372
 
            goto out_of_memory;
373
 
 
374
 
        if ((base = strdup (SYSCONF_DIR "/libvirt")) == NULL)
375
 
            goto out_of_memory;
376
 
    } else {
377
 
 
378
 
        if (virAsprintf(&uml_driver->logDir,
379
 
                        "%s/.libvirt/uml/log", userdir) == -1)
380
 
            goto out_of_memory;
381
 
 
382
 
        if (virAsprintf(&base, "%s/.libvirt", userdir) == -1)
383
 
            goto out_of_memory;
384
 
    }
385
 
 
386
 
    if (virAsprintf(&uml_driver->monitorDir,
387
 
                    "%s/.uml", userdir) == -1)
388
 
        goto out_of_memory;
389
 
 
390
 
    /* Configuration paths are either ~/.libvirt/uml/... (session) or
391
 
     * /etc/libvirt/uml/... (system).
392
 
     */
393
 
    if (snprintf (driverConf, sizeof(driverConf), "%s/uml.conf", base) == -1)
394
 
        goto out_of_memory;
395
 
    driverConf[sizeof(driverConf)-1] = '\0';
396
 
 
397
 
    if (virAsprintf(&uml_driver->configDir, "%s/uml", base) == -1)
398
 
        goto out_of_memory;
399
 
 
400
 
    if (virAsprintf(&uml_driver->autostartDir, "%s/uml/autostart", base) == -1)
401
 
        goto out_of_memory;
402
 
 
403
 
    VIR_FREE(base);
404
 
 
405
 
    if ((uml_driver->caps = umlCapsInit()) == NULL)
406
 
        goto out_of_memory;
407
 
 
408
 
    uml_driver->caps->privateDataAllocFunc = umlDomainObjPrivateAlloc;
409
 
    uml_driver->caps->privateDataFreeFunc = umlDomainObjPrivateFree;
410
 
 
411
 
    if ((uml_driver->inotifyFD = inotify_init()) < 0) {
412
 
        VIR_ERROR0(_("cannot initialize inotify"));
413
 
        goto error;
414
 
    }
415
 
 
416
 
    if (virFileMakePath(uml_driver->monitorDir) != 0) {
417
 
        char ebuf[1024];
418
 
        VIR_ERROR(_("Failed to create monitor directory %s: %s"),
419
 
               uml_driver->monitorDir, virStrerror(errno, ebuf, sizeof ebuf));
420
 
        goto error;
421
 
    }
422
 
 
423
 
    VIR_INFO("Adding inotify watch on %s", uml_driver->monitorDir);
424
 
    if (inotify_add_watch(uml_driver->inotifyFD,
425
 
                          uml_driver->monitorDir,
426
 
                          IN_CREATE | IN_MODIFY | IN_DELETE) < 0) {
427
 
        goto error;
428
 
    }
429
 
 
430
 
    if ((uml_driver->inotifyWatch =
431
 
         virEventAddHandle(uml_driver->inotifyFD, POLLIN,
432
 
                           umlInotifyEvent, uml_driver, NULL)) < 0)
433
 
        goto error;
434
 
 
435
 
    if (virDomainLoadAllConfigs(uml_driver->caps,
436
 
                                &uml_driver->domains,
437
 
                                uml_driver->configDir,
438
 
                                uml_driver->autostartDir,
439
 
                                0, NULL, NULL) < 0)
440
 
        goto error;
441
 
 
442
 
    umlAutostartConfigs(uml_driver);
443
 
 
444
 
    umlDriverUnlock(uml_driver);
445
 
    VIR_FREE(userdir);
446
 
 
447
 
    return 0;
448
 
 
449
 
out_of_memory:
450
 
    VIR_ERROR0(_("umlStartup: out of memory"));
451
 
 
452
 
error:
453
 
    VIR_FREE(userdir);
454
 
    VIR_FREE(base);
455
 
    umlDriverUnlock(uml_driver);
456
 
    umlShutdown();
457
 
    return -1;
458
 
}
459
 
 
460
 
/**
461
 
 * umlReload:
462
 
 *
463
 
 * Function to restart the Uml daemon, it will recheck the configuration
464
 
 * files and update its state and the networking
465
 
 */
466
 
static int
467
 
umlReload(void) {
468
 
    if (!uml_driver)
469
 
        return 0;
470
 
 
471
 
    umlDriverLock(uml_driver);
472
 
    virDomainLoadAllConfigs(uml_driver->caps,
473
 
                            &uml_driver->domains,
474
 
                            uml_driver->configDir,
475
 
                            uml_driver->autostartDir,
476
 
                            0, NULL, NULL);
477
 
 
478
 
    umlAutostartConfigs(uml_driver);
479
 
    umlDriverUnlock(uml_driver);
480
 
 
481
 
    return 0;
482
 
}
483
 
 
484
 
/**
485
 
 * umlActive:
486
 
 *
487
 
 * Checks if the Uml daemon is active, i.e. has an active domain or
488
 
 * an active network
489
 
 *
490
 
 * Returns 1 if active, 0 otherwise
491
 
 */
492
 
static int
493
 
umlActive(void) {
494
 
    int active = 0;
495
 
 
496
 
    if (!uml_driver)
497
 
        return 0;
498
 
 
499
 
    umlDriverLock(uml_driver);
500
 
    active = virDomainObjListNumOfDomains(&uml_driver->domains, 1);
501
 
    umlDriverUnlock(uml_driver);
502
 
 
503
 
    return active;
504
 
}
505
 
 
506
 
static void
507
 
umlShutdownOneVM(void *payload, const char *name ATTRIBUTE_UNUSED, void *opaque)
508
 
{
509
 
    virDomainObjPtr dom = payload;
510
 
    struct uml_driver *driver = opaque;
511
 
 
512
 
    virDomainObjLock(dom);
513
 
    if (virDomainObjIsActive(dom))
514
 
        umlShutdownVMDaemon(NULL, driver, dom);
515
 
    virDomainObjUnlock(dom);
516
 
}
517
 
 
518
 
/**
519
 
 * umlShutdown:
520
 
 *
521
 
 * Shutdown the Uml daemon, it will stop all active domains and networks
522
 
 */
523
 
static int
524
 
umlShutdown(void) {
525
 
    if (!uml_driver)
526
 
        return -1;
527
 
 
528
 
    umlDriverLock(uml_driver);
529
 
    if (uml_driver->inotifyWatch != -1)
530
 
        virEventRemoveHandle(uml_driver->inotifyWatch);
531
 
    close(uml_driver->inotifyFD);
532
 
    virCapabilitiesFree(uml_driver->caps);
533
 
 
534
 
    /* shutdown active VMs
535
 
     * XXX allow them to stay around & reconnect */
536
 
    virHashForEach(uml_driver->domains.objs, umlShutdownOneVM, uml_driver);
537
 
 
538
 
    virDomainObjListDeinit(&uml_driver->domains);
539
 
 
540
 
    VIR_FREE(uml_driver->logDir);
541
 
    VIR_FREE(uml_driver->configDir);
542
 
    VIR_FREE(uml_driver->autostartDir);
543
 
    VIR_FREE(uml_driver->monitorDir);
544
 
 
545
 
    if (uml_driver->brctl)
546
 
        brShutdown(uml_driver->brctl);
547
 
 
548
 
    umlDriverUnlock(uml_driver);
549
 
    virMutexDestroy(&uml_driver->lock);
550
 
    VIR_FREE(uml_driver);
551
 
 
552
 
    return 0;
553
 
}
554
 
 
555
 
 
556
 
static int umlReadPidFile(struct uml_driver *driver,
557
 
                          virDomainObjPtr vm)
558
 
{
559
 
    int rc = -1;
560
 
    FILE *file;
561
 
    char *pidfile = NULL;
562
 
    int retries = 0;
563
 
 
564
 
    vm->pid = -1;
565
 
    if (virAsprintf(&pidfile, "%s/%s/pid",
566
 
                    driver->monitorDir, vm->def->name) < 0) {
567
 
        virReportOOMError();
568
 
        return -1;
569
 
    }
570
 
 
571
 
reopen:
572
 
    if (!(file = fopen(pidfile, "r"))) {
573
 
        if (errno == ENOENT &&
574
 
            retries++ < 50) {
575
 
            usleep(1000 * 100);
576
 
            goto reopen;
577
 
        }
578
 
        goto cleanup;
579
 
    }
580
 
 
581
 
    if (fscanf(file, "%d", &vm->pid) != 1) {
582
 
        errno = EINVAL;
583
 
        fclose(file);
584
 
        goto cleanup;
585
 
    }
586
 
 
587
 
    if (fclose(file) < 0)
588
 
        goto cleanup;
589
 
 
590
 
    rc = 0;
591
 
 
592
 
 cleanup:
593
 
    if (rc != 0)
594
 
        virReportSystemError(errno,
595
 
                             _("failed to read pid: %s"),
596
 
                             pidfile);
597
 
    VIR_FREE(pidfile);
598
 
    return rc;
599
 
}
600
 
 
601
 
static int umlMonitorAddress(const struct uml_driver *driver,
602
 
                             virDomainObjPtr vm,
603
 
                             struct sockaddr_un *addr) {
604
 
    char *sockname;
605
 
    int retval = 0;
606
 
 
607
 
    if (virAsprintf(&sockname, "%s/%s/mconsole",
608
 
                    driver->monitorDir, vm->def->name) < 0) {
609
 
        virReportOOMError();
610
 
        return -1;
611
 
    }
612
 
 
613
 
    memset(addr, 0, sizeof *addr);
614
 
    addr->sun_family = AF_UNIX;
615
 
    if (virStrcpyStatic(addr->sun_path, sockname) == NULL) {
616
 
        umlReportError(VIR_ERR_INTERNAL_ERROR,
617
 
                       _("Unix path %s too long for destination"), sockname);
618
 
        retval = -1;
619
 
    }
620
 
    VIR_FREE(sockname);
621
 
    return retval;
622
 
}
623
 
 
624
 
static int umlOpenMonitor(struct uml_driver *driver,
625
 
                          virDomainObjPtr vm) {
626
 
    struct sockaddr_un addr;
627
 
    struct stat sb;
628
 
    int retries = 0;
629
 
    umlDomainObjPrivatePtr priv = vm->privateData;
630
 
 
631
 
    if (umlMonitorAddress(driver, vm, &addr) < 0)
632
 
        return -1;
633
 
 
634
 
    VIR_DEBUG("Dest address for monitor is '%s'", addr.sun_path);
635
 
restat:
636
 
    if (stat(addr.sun_path, &sb) < 0) {
637
 
        if (errno == ENOENT &&
638
 
            retries++ < 50) {
639
 
            usleep(1000 * 100);
640
 
            goto restat;
641
 
        }
642
 
        return -1;
643
 
    }
644
 
 
645
 
    if ((priv->monitor = socket(PF_UNIX, SOCK_DGRAM, 0)) < 0) {
646
 
        virReportSystemError(errno,
647
 
                             "%s", _("cannot open socket"));
648
 
        return -1;
649
 
    }
650
 
 
651
 
    memset(addr.sun_path, 0, sizeof addr.sun_path);
652
 
    sprintf(addr.sun_path + 1, "libvirt-uml-%u", vm->pid);
653
 
    VIR_DEBUG("Reply address for monitor is '%s'", addr.sun_path+1);
654
 
    if (bind(priv->monitor, (struct sockaddr *)&addr, sizeof addr) < 0) {
655
 
        virReportSystemError(errno,
656
 
                             "%s", _("cannot bind socket"));
657
 
        close(priv->monitor);
658
 
        priv->monitor = -1;
659
 
        return -1;
660
 
    }
661
 
 
662
 
    return 0;
663
 
}
664
 
 
665
 
 
666
 
#define MONITOR_MAGIC 0xcafebabe
667
 
#define MONITOR_BUFLEN 512
668
 
#define MONITOR_VERSION 2
669
 
 
670
 
struct monitor_request {
671
 
    uint32_t magic;
672
 
    uint32_t version;
673
 
    uint32_t length;
674
 
    char data[MONITOR_BUFLEN];
675
 
};
676
 
 
677
 
struct monitor_response {
678
 
    uint32_t error;
679
 
    uint32_t extra;
680
 
    uint32_t length;
681
 
    char data[MONITOR_BUFLEN];
682
 
};
683
 
 
684
 
 
685
 
static int umlMonitorCommand(const struct uml_driver *driver,
686
 
                             const virDomainObjPtr vm,
687
 
                             const char *cmd,
688
 
                             char **reply)
689
 
{
690
 
    struct monitor_request req;
691
 
    struct monitor_response res;
692
 
    char *retdata = NULL;
693
 
    int retlen = 0, ret = 0;
694
 
    struct sockaddr_un addr;
695
 
    unsigned int addrlen;
696
 
    umlDomainObjPrivatePtr priv = vm->privateData;
697
 
 
698
 
    VIR_DEBUG("Run command '%s'", cmd);
699
 
 
700
 
    *reply = NULL;
701
 
 
702
 
    if (umlMonitorAddress(driver, vm, &addr) < 0)
703
 
        return -1;
704
 
 
705
 
    memset(&req, 0, sizeof(req));
706
 
    req.magic = MONITOR_MAGIC;
707
 
    req.version = MONITOR_VERSION;
708
 
    req.length = strlen(cmd);
709
 
    if (req.length > (MONITOR_BUFLEN-1)) {
710
 
        virReportSystemError(EINVAL,
711
 
                             _("cannot send too long command %s (%d bytes)"),
712
 
                             cmd, req.length);
713
 
        return -1;
714
 
    }
715
 
    if (virStrcpyStatic(req.data, cmd) == NULL) {
716
 
        umlReportError(VIR_ERR_INTERNAL_ERROR,
717
 
                       _("Command %s too long for destination"), cmd);
718
 
        return -1;
719
 
    }
720
 
 
721
 
    if (sendto(priv->monitor, &req, sizeof req, 0,
722
 
               (struct sockaddr *)&addr, sizeof addr) != (sizeof req)) {
723
 
        virReportSystemError(errno,
724
 
                             _("cannot send command %s"),
725
 
                             cmd);
726
 
        return -1;
727
 
    }
728
 
 
729
 
    do {
730
 
        ssize_t nbytes;
731
 
        addrlen = sizeof(addr);
732
 
        nbytes = recvfrom(priv->monitor, &res, sizeof res, 0,
733
 
                          (struct sockaddr *)&addr, &addrlen);
734
 
        if (nbytes < 0) {
735
 
            if (errno == EAGAIN || errno == EINTR)
736
 
                continue;
737
 
            virReportSystemError(errno, _("cannot read reply %s"), cmd);
738
 
            goto error;
739
 
        }
740
 
        if (nbytes < sizeof res) {
741
 
            virReportSystemError(0, _("incomplete reply %s"), cmd);
742
 
            goto error;
743
 
        }
744
 
        if (sizeof res.data < res.length) {
745
 
            virReportSystemError(0, _("invalid length in reply %s"), cmd);
746
 
            goto error;
747
 
        }
748
 
 
749
 
        if (VIR_REALLOC_N(retdata, retlen + res.length) < 0) {
750
 
            virReportOOMError();
751
 
            goto error;
752
 
        }
753
 
        memcpy(retdata + retlen, res.data, res.length);
754
 
        retlen += res.length - 1;
755
 
        retdata[retlen] = '\0';
756
 
 
757
 
        if (res.error)
758
 
            ret = -1;
759
 
 
760
 
    } while (res.extra);
761
 
 
762
 
    VIR_DEBUG("Command reply is '%s'", NULLSTR(retdata));
763
 
 
764
 
    if (ret < 0)
765
 
        VIR_FREE(retdata);
766
 
    else
767
 
        *reply = retdata;
768
 
 
769
 
    return ret;
770
 
 
771
 
error:
772
 
    VIR_FREE(retdata);
773
 
    return -1;
774
 
}
775
 
 
776
 
 
777
 
static int umlCleanupTapDevices(virConnectPtr conn ATTRIBUTE_UNUSED,
778
 
                                virDomainObjPtr vm) {
779
 
    int i;
780
 
    int err;
781
 
    int ret = 0;
782
 
    brControl *brctl = NULL;
783
 
    VIR_ERROR0(_("Cleanup tap"));
784
 
    if (brInit(&brctl) < 0)
785
 
        return -1;
786
 
 
787
 
    for (i = 0 ; i < vm->def->nnets ; i++) {
788
 
        virDomainNetDefPtr def = vm->def->nets[i];
789
 
 
790
 
        if (def->type != VIR_DOMAIN_NET_TYPE_BRIDGE &&
791
 
            def->type != VIR_DOMAIN_NET_TYPE_NETWORK)
792
 
            continue;
793
 
 
794
 
        VIR_ERROR(_("Cleanup '%s'"), def->ifname);
795
 
        err = brDeleteTap(brctl, def->ifname);
796
 
        if (err) {
797
 
            VIR_ERROR(_("Cleanup failed %d"), err);
798
 
            ret = -1;
799
 
        }
800
 
    }
801
 
    VIR_ERROR0(_("Cleanup tap done"));
802
 
    brShutdown(brctl);
803
 
    return ret;
804
 
}
805
 
 
806
 
static int umlStartVMDaemon(virConnectPtr conn,
807
 
                            struct uml_driver *driver,
808
 
                            virDomainObjPtr vm) {
809
 
    const char **argv = NULL, **tmp;
810
 
    const char **progenv = NULL;
811
 
    int i, ret;
812
 
    pid_t pid;
813
 
    char *logfile;
814
 
    int logfd = -1;
815
 
    struct stat sb;
816
 
    fd_set keepfd;
817
 
    char ebuf[1024];
818
 
    umlDomainObjPrivatePtr priv = vm->privateData;
819
 
 
820
 
    FD_ZERO(&keepfd);
821
 
 
822
 
    if (virDomainObjIsActive(vm)) {
823
 
        umlReportError(VIR_ERR_INTERNAL_ERROR, "%s",
824
 
                       _("VM is already active"));
825
 
        return -1;
826
 
    }
827
 
 
828
 
    if (!vm->def->os.kernel) {
829
 
        umlReportError(VIR_ERR_INTERNAL_ERROR, "%s",
830
 
                       _("no kernel specified"));
831
 
        return -1;
832
 
    }
833
 
    /* Make sure the binary we are about to try exec'ing exists.
834
 
     * Technically we could catch the exec() failure, but that's
835
 
     * in a sub-process so its hard to feed back a useful error
836
 
     */
837
 
    if (stat(vm->def->os.kernel, &sb) < 0) {
838
 
        virReportSystemError(errno,
839
 
                             _("Cannot find UML kernel %s"),
840
 
                             vm->def->os.kernel);
841
 
        return -1;
842
 
    }
843
 
 
844
 
    if (virFileMakePath(driver->logDir) != 0) {
845
 
        virReportSystemError(errno,
846
 
                             _("cannot create log directory %s"),
847
 
                             driver->logDir);
848
 
        return -1;
849
 
    }
850
 
 
851
 
    if (virAsprintf(&logfile, "%s/%s.log",
852
 
                    driver->logDir, vm->def->name) < 0) {
853
 
        virReportOOMError();
854
 
        return -1;
855
 
    }
856
 
 
857
 
    if ((logfd = open(logfile, O_CREAT | O_TRUNC | O_WRONLY,
858
 
                      S_IRUSR | S_IWUSR)) < 0) {
859
 
        virReportSystemError(errno,
860
 
                             _("failed to create logfile %s"),
861
 
                             logfile);
862
 
        VIR_FREE(logfile);
863
 
        return -1;
864
 
    }
865
 
    VIR_FREE(logfile);
866
 
 
867
 
    if (umlSetCloseExec(logfd) < 0) {
868
 
        virReportSystemError(errno,
869
 
                             "%s", _("Unable to set VM logfile close-on-exec flag"));
870
 
        close(logfd);
871
 
        return -1;
872
 
    }
873
 
 
874
 
    if (umlBuildCommandLine(conn, driver, vm,
875
 
                            &argv, &progenv) < 0) {
876
 
        close(logfd);
877
 
        umlCleanupTapDevices(conn, vm);
878
 
        return -1;
879
 
    }
880
 
 
881
 
    tmp = progenv;
882
 
    while (*tmp) {
883
 
        if (safewrite(logfd, *tmp, strlen(*tmp)) < 0)
884
 
            VIR_WARN("Unable to write envv to logfile: %s",
885
 
                   virStrerror(errno, ebuf, sizeof ebuf));
886
 
        if (safewrite(logfd, " ", 1) < 0)
887
 
            VIR_WARN("Unable to write envv to logfile: %s",
888
 
                   virStrerror(errno, ebuf, sizeof ebuf));
889
 
        tmp++;
890
 
    }
891
 
    tmp = argv;
892
 
    while (*tmp) {
893
 
        if (safewrite(logfd, *tmp, strlen(*tmp)) < 0)
894
 
            VIR_WARN("Unable to write argv to logfile: %s",
895
 
                   virStrerror(errno, ebuf, sizeof ebuf));
896
 
        if (safewrite(logfd, " ", 1) < 0)
897
 
            VIR_WARN("Unable to write argv to logfile: %s",
898
 
                   virStrerror(errno, ebuf, sizeof ebuf));
899
 
        tmp++;
900
 
    }
901
 
    if (safewrite(logfd, "\n", 1) < 0)
902
 
        VIR_WARN("Unable to write argv to logfile: %s",
903
 
                 virStrerror(errno, ebuf, sizeof ebuf));
904
 
 
905
 
    priv->monitor = -1;
906
 
 
907
 
    ret = virExecDaemonize(argv, progenv, &keepfd, &pid,
908
 
                           -1, &logfd, &logfd,
909
 
                           VIR_EXEC_CLEAR_CAPS,
910
 
                           NULL, NULL, NULL);
911
 
    close(logfd);
912
 
 
913
 
    for (i = 0 ; argv[i] ; i++)
914
 
        VIR_FREE(argv[i]);
915
 
    VIR_FREE(argv);
916
 
 
917
 
    for (i = 0 ; progenv[i] ; i++)
918
 
        VIR_FREE(progenv[i]);
919
 
    VIR_FREE(progenv);
920
 
 
921
 
    if (ret < 0)
922
 
        umlCleanupTapDevices(conn, vm);
923
 
 
924
 
    /* NB we don't mark it running here - we do that async
925
 
       with inotify */
926
 
    /* XXX what if someone else tries to start it again
927
 
       before we get the inotification ? Sounds like
928
 
       trouble.... */
929
 
 
930
 
    return ret;
931
 
}
932
 
 
933
 
static void umlShutdownVMDaemon(virConnectPtr conn ATTRIBUTE_UNUSED,
934
 
                                struct uml_driver *driver ATTRIBUTE_UNUSED,
935
 
                                virDomainObjPtr vm)
936
 
{
937
 
    int ret;
938
 
    umlDomainObjPrivatePtr priv = vm->privateData;
939
 
 
940
 
    if (!virDomainObjIsActive(vm))
941
 
        return;
942
 
 
943
 
    virKillProcess(vm->pid, SIGTERM);
944
 
 
945
 
    if (priv->monitor != -1)
946
 
        close(priv->monitor);
947
 
    priv->monitor = -1;
948
 
 
949
 
    if ((ret = waitpid(vm->pid, NULL, 0)) != vm->pid) {
950
 
        VIR_WARN("Got unexpected pid %d != %d",
951
 
               ret, vm->pid);
952
 
    }
953
 
 
954
 
    vm->pid = -1;
955
 
    vm->def->id = -1;
956
 
    vm->state = VIR_DOMAIN_SHUTOFF;
957
 
 
958
 
    umlCleanupTapDevices(conn, vm);
959
 
 
960
 
    if (vm->newDef) {
961
 
        virDomainDefFree(vm->def);
962
 
        vm->def = vm->newDef;
963
 
        vm->def->id = -1;
964
 
        vm->newDef = NULL;
965
 
    }
966
 
}
967
 
 
968
 
 
969
 
static virDrvOpenStatus umlOpen(virConnectPtr conn,
970
 
                                virConnectAuthPtr auth ATTRIBUTE_UNUSED,
971
 
                                int flags ATTRIBUTE_UNUSED) {
972
 
    if (conn->uri == NULL) {
973
 
        if (uml_driver == NULL)
974
 
            return VIR_DRV_OPEN_DECLINED;
975
 
 
976
 
        conn->uri = xmlParseURI(uml_driver->privileged ?
977
 
                                "uml:///system" :
978
 
                                "uml:///session");
979
 
        if (!conn->uri) {
980
 
            virReportOOMError();
981
 
            return VIR_DRV_OPEN_ERROR;
982
 
        }
983
 
    } else {
984
 
        if (conn->uri->scheme == NULL ||
985
 
            STRNEQ (conn->uri->scheme, "uml"))
986
 
            return VIR_DRV_OPEN_DECLINED;
987
 
 
988
 
        /* Allow remote driver to deal with URIs with hostname server */
989
 
        if (conn->uri->server != NULL)
990
 
            return VIR_DRV_OPEN_DECLINED;
991
 
 
992
 
 
993
 
        /* Check path and tell them correct path if they made a mistake */
994
 
        if (uml_driver->privileged) {
995
 
            if (STRNEQ (conn->uri->path, "/system") &&
996
 
                STRNEQ (conn->uri->path, "/session")) {
997
 
                umlReportError(VIR_ERR_INTERNAL_ERROR,
998
 
                               _("unexpected UML URI path '%s', try uml:///system"),
999
 
                               conn->uri->path);
1000
 
                return VIR_DRV_OPEN_ERROR;
1001
 
            }
1002
 
        } else {
1003
 
            if (STRNEQ (conn->uri->path, "/session")) {
1004
 
                umlReportError(VIR_ERR_INTERNAL_ERROR,
1005
 
                               _("unexpected UML URI path '%s', try uml:///session"),
1006
 
                               conn->uri->path);
1007
 
                return VIR_DRV_OPEN_ERROR;
1008
 
            }
1009
 
        }
1010
 
 
1011
 
        /* URI was good, but driver isn't active */
1012
 
        if (uml_driver == NULL) {
1013
 
            umlReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1014
 
                           _("uml state driver is not active"));
1015
 
            return VIR_DRV_OPEN_ERROR;
1016
 
        }
1017
 
    }
1018
 
 
1019
 
    conn->privateData = uml_driver;
1020
 
 
1021
 
    return VIR_DRV_OPEN_SUCCESS;
1022
 
}
1023
 
 
1024
 
static int umlClose(virConnectPtr conn) {
1025
 
    /*struct uml_driver *driver = conn->privateData;*/
1026
 
 
1027
 
    conn->privateData = NULL;
1028
 
 
1029
 
    return 0;
1030
 
}
1031
 
 
1032
 
static const char *umlGetType(virConnectPtr conn ATTRIBUTE_UNUSED) {
1033
 
    return "UML";
1034
 
}
1035
 
 
1036
 
 
1037
 
static int umlIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED)
1038
 
{
1039
 
    /* Trivially secure, since always inside the daemon */
1040
 
    return 1;
1041
 
}
1042
 
 
1043
 
 
1044
 
static int umlIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
1045
 
{
1046
 
    /* Not encrypted, but remote driver takes care of that */
1047
 
    return 0;
1048
 
}
1049
 
 
1050
 
 
1051
 
static char *umlGetCapabilities(virConnectPtr conn) {
1052
 
    struct uml_driver *driver = (struct uml_driver *)conn->privateData;
1053
 
    char *xml;
1054
 
 
1055
 
    umlDriverLock(driver);
1056
 
    if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL)
1057
 
        virReportOOMError();
1058
 
    umlDriverUnlock(driver);
1059
 
 
1060
 
    return xml;
1061
 
}
1062
 
 
1063
 
 
1064
 
 
1065
 
static int umlGetProcessInfo(unsigned long long *cpuTime, int pid) {
1066
 
    char proc[PATH_MAX];
1067
 
    FILE *pidinfo;
1068
 
    unsigned long long usertime, systime;
1069
 
 
1070
 
    if (snprintf(proc, sizeof(proc), "/proc/%d/stat", pid) >= (int)sizeof(proc)) {
1071
 
        return -1;
1072
 
    }
1073
 
 
1074
 
    if (!(pidinfo = fopen(proc, "r"))) {
1075
 
        /*printf("cannot read pid info");*/
1076
 
        /* VM probably shut down, so fake 0 */
1077
 
        *cpuTime = 0;
1078
 
        return 0;
1079
 
    }
1080
 
 
1081
 
    if (fscanf(pidinfo, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %llu %llu", &usertime, &systime) != 2) {
1082
 
        umlDebug("not enough arg");
1083
 
        fclose(pidinfo);
1084
 
        return -1;
1085
 
    }
1086
 
 
1087
 
    /* We got jiffies
1088
 
     * We want nanoseconds
1089
 
     * _SC_CLK_TCK is jiffies per second
1090
 
     * So calulate thus....
1091
 
     */
1092
 
    *cpuTime = 1000ull * 1000ull * 1000ull * (usertime + systime) / (unsigned long long)sysconf(_SC_CLK_TCK);
1093
 
 
1094
 
    umlDebug("Got %llu %llu %llu", usertime, systime, *cpuTime);
1095
 
 
1096
 
    fclose(pidinfo);
1097
 
 
1098
 
    return 0;
1099
 
}
1100
 
 
1101
 
 
1102
 
static virDomainPtr umlDomainLookupByID(virConnectPtr conn,
1103
 
                                          int id) {
1104
 
    struct uml_driver *driver = (struct uml_driver *)conn->privateData;
1105
 
    virDomainObjPtr vm;
1106
 
    virDomainPtr dom = NULL;
1107
 
 
1108
 
    umlDriverLock(driver);
1109
 
    vm = virDomainFindByID(&driver->domains, id);
1110
 
    umlDriverUnlock(driver);
1111
 
 
1112
 
    if (!vm) {
1113
 
        umlReportError(VIR_ERR_NO_DOMAIN, NULL);
1114
 
        goto cleanup;
1115
 
    }
1116
 
 
1117
 
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
1118
 
    if (dom) dom->id = vm->def->id;
1119
 
 
1120
 
cleanup:
1121
 
    if (vm)
1122
 
        virDomainObjUnlock(vm);
1123
 
    return dom;
1124
 
}
1125
 
 
1126
 
static virDomainPtr umlDomainLookupByUUID(virConnectPtr conn,
1127
 
                                            const unsigned char *uuid) {
1128
 
    struct uml_driver *driver = (struct uml_driver *)conn->privateData;
1129
 
    virDomainObjPtr vm;
1130
 
    virDomainPtr dom = NULL;
1131
 
 
1132
 
    umlDriverLock(driver);
1133
 
    vm = virDomainFindByUUID(&driver->domains, uuid);
1134
 
    umlDriverUnlock(driver);
1135
 
 
1136
 
    if (!vm) {
1137
 
        umlReportError(VIR_ERR_NO_DOMAIN, NULL);
1138
 
        goto cleanup;
1139
 
    }
1140
 
 
1141
 
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
1142
 
    if (dom) dom->id = vm->def->id;
1143
 
 
1144
 
cleanup:
1145
 
    if (vm)
1146
 
        virDomainObjUnlock(vm);
1147
 
    return dom;
1148
 
}
1149
 
 
1150
 
static virDomainPtr umlDomainLookupByName(virConnectPtr conn,
1151
 
                                            const char *name) {
1152
 
    struct uml_driver *driver = (struct uml_driver *)conn->privateData;
1153
 
    virDomainObjPtr vm;
1154
 
    virDomainPtr dom = NULL;
1155
 
 
1156
 
    umlDriverLock(driver);
1157
 
    vm = virDomainFindByName(&driver->domains, name);
1158
 
    umlDriverUnlock(driver);
1159
 
 
1160
 
    if (!vm) {
1161
 
        umlReportError(VIR_ERR_NO_DOMAIN, NULL);
1162
 
        goto cleanup;
1163
 
    }
1164
 
 
1165
 
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
1166
 
    if (dom) dom->id = vm->def->id;
1167
 
 
1168
 
cleanup:
1169
 
    if (vm)
1170
 
        virDomainObjUnlock(vm);
1171
 
    return dom;
1172
 
}
1173
 
 
1174
 
 
1175
 
static int umlDomainIsActive(virDomainPtr dom)
1176
 
{
1177
 
    struct uml_driver *driver = dom->conn->privateData;
1178
 
    virDomainObjPtr obj;
1179
 
    int ret = -1;
1180
 
 
1181
 
    umlDriverLock(driver);
1182
 
    obj = virDomainFindByUUID(&driver->domains, dom->uuid);
1183
 
    umlDriverUnlock(driver);
1184
 
    if (!obj) {
1185
 
        umlReportError(VIR_ERR_NO_DOMAIN, NULL);
1186
 
        goto cleanup;
1187
 
    }
1188
 
    ret = virDomainObjIsActive(obj);
1189
 
 
1190
 
cleanup:
1191
 
    if (obj)
1192
 
        virDomainObjUnlock(obj);
1193
 
    return ret;
1194
 
}
1195
 
 
1196
 
 
1197
 
static int umlDomainIsPersistent(virDomainPtr dom)
1198
 
{
1199
 
    struct uml_driver *driver = dom->conn->privateData;
1200
 
    virDomainObjPtr obj;
1201
 
    int ret = -1;
1202
 
 
1203
 
    umlDriverLock(driver);
1204
 
    obj = virDomainFindByUUID(&driver->domains, dom->uuid);
1205
 
    umlDriverUnlock(driver);
1206
 
    if (!obj) {
1207
 
        umlReportError(VIR_ERR_NO_DOMAIN, NULL);
1208
 
        goto cleanup;
1209
 
    }
1210
 
    ret = obj->persistent;
1211
 
 
1212
 
cleanup:
1213
 
    if (obj)
1214
 
        virDomainObjUnlock(obj);
1215
 
    return ret;
1216
 
}
1217
 
 
1218
 
 
1219
 
static int umlGetVersion(virConnectPtr conn, unsigned long *version) {
1220
 
    struct uml_driver *driver = conn->privateData;
1221
 
    struct utsname ut;
1222
 
    int ret = -1;
1223
 
 
1224
 
    umlDriverLock(driver);
1225
 
 
1226
 
    if (driver->umlVersion == 0) {
1227
 
        uname(&ut);
1228
 
 
1229
 
        if (virParseVersionString(ut.release, &driver->umlVersion) < 0) {
1230
 
            umlReportError(VIR_ERR_INTERNAL_ERROR,
1231
 
                           _("cannot parse version %s"), ut.release);
1232
 
            goto cleanup;
1233
 
        }
1234
 
    }
1235
 
 
1236
 
    *version = driver->umlVersion;
1237
 
    ret = 0;
1238
 
 
1239
 
cleanup:
1240
 
    umlDriverUnlock(driver);
1241
 
    return ret;
1242
 
}
1243
 
 
1244
 
static int umlListDomains(virConnectPtr conn, int *ids, int nids) {
1245
 
    struct uml_driver *driver = conn->privateData;
1246
 
    int n;
1247
 
 
1248
 
    umlDriverLock(driver);
1249
 
    n = virDomainObjListGetActiveIDs(&driver->domains, ids, nids);
1250
 
    umlDriverUnlock(driver);
1251
 
 
1252
 
    return n;
1253
 
}
1254
 
static int umlNumDomains(virConnectPtr conn) {
1255
 
    struct uml_driver *driver = conn->privateData;
1256
 
    int n;
1257
 
 
1258
 
    umlDriverLock(driver);
1259
 
    n = virDomainObjListNumOfDomains(&driver->domains, 1);
1260
 
    umlDriverUnlock(driver);
1261
 
 
1262
 
    return n;
1263
 
}
1264
 
static virDomainPtr umlDomainCreate(virConnectPtr conn, const char *xml,
1265
 
                                      unsigned int flags) {
1266
 
    struct uml_driver *driver = conn->privateData;
1267
 
    virDomainDefPtr def;
1268
 
    virDomainObjPtr vm = NULL;
1269
 
    virDomainPtr dom = NULL;
1270
 
 
1271
 
    virCheckFlags(0, NULL);
1272
 
 
1273
 
    umlDriverLock(driver);
1274
 
    if (!(def = virDomainDefParseString(driver->caps, xml,
1275
 
                                        VIR_DOMAIN_XML_INACTIVE)))
1276
 
        goto cleanup;
1277
 
 
1278
 
    if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0)
1279
 
        goto cleanup;
1280
 
 
1281
 
    if (!(vm = virDomainAssignDef(driver->caps,
1282
 
                                  &driver->domains,
1283
 
                                  def, false)))
1284
 
        goto cleanup;
1285
 
    def = NULL;
1286
 
 
1287
 
    if (umlStartVMDaemon(conn, driver, vm) < 0) {
1288
 
        virDomainRemoveInactive(&driver->domains,
1289
 
                                vm);
1290
 
        vm = NULL;
1291
 
        goto cleanup;
1292
 
    }
1293
 
 
1294
 
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
1295
 
    if (dom) dom->id = vm->def->id;
1296
 
 
1297
 
cleanup:
1298
 
    virDomainDefFree(def);
1299
 
    if (vm)
1300
 
        virDomainObjUnlock(vm);
1301
 
    umlDriverUnlock(driver);
1302
 
    return dom;
1303
 
}
1304
 
 
1305
 
 
1306
 
static int umlDomainShutdown(virDomainPtr dom) {
1307
 
    struct uml_driver *driver = dom->conn->privateData;
1308
 
    virDomainObjPtr vm;
1309
 
    char *info = NULL;
1310
 
    int ret = -1;
1311
 
 
1312
 
    umlDriverLock(driver);
1313
 
    vm = virDomainFindByID(&driver->domains, dom->id);
1314
 
    umlDriverUnlock(driver);
1315
 
    if (!vm) {
1316
 
        umlReportError(VIR_ERR_INVALID_DOMAIN,
1317
 
                       _("no domain with matching id %d"), dom->id);
1318
 
        goto cleanup;
1319
 
    }
1320
 
 
1321
 
#if 0
1322
 
    if (umlMonitorCommand(driver, vm, "system_powerdown", &info) < 0) {
1323
 
        umlReportError(VIR_ERR_OPERATION_FAILED, "%s",
1324
 
                       _("shutdown operation failed"));
1325
 
        goto cleanup;
1326
 
    }
1327
 
    ret = 0;
1328
 
#endif
1329
 
 
1330
 
cleanup:
1331
 
    VIR_FREE(info);
1332
 
    if (vm)
1333
 
        virDomainObjUnlock(vm);
1334
 
    return ret;
1335
 
}
1336
 
 
1337
 
 
1338
 
static int umlDomainDestroy(virDomainPtr dom) {
1339
 
    struct uml_driver *driver = dom->conn->privateData;
1340
 
    virDomainObjPtr vm;
1341
 
    int ret = -1;
1342
 
 
1343
 
    umlDriverLock(driver);
1344
 
    vm = virDomainFindByID(&driver->domains, dom->id);
1345
 
    if (!vm) {
1346
 
        umlReportError(VIR_ERR_INVALID_DOMAIN,
1347
 
                       _("no domain with matching id %d"), dom->id);
1348
 
        goto cleanup;
1349
 
    }
1350
 
 
1351
 
    umlShutdownVMDaemon(dom->conn, driver, vm);
1352
 
    if (!vm->persistent) {
1353
 
        virDomainRemoveInactive(&driver->domains,
1354
 
                                vm);
1355
 
        vm = NULL;
1356
 
    }
1357
 
    ret = 0;
1358
 
 
1359
 
cleanup:
1360
 
    if (vm)
1361
 
        virDomainObjUnlock(vm);
1362
 
    umlDriverUnlock(driver);
1363
 
    return ret;
1364
 
}
1365
 
 
1366
 
 
1367
 
static char *umlDomainGetOSType(virDomainPtr dom) {
1368
 
    struct uml_driver *driver = dom->conn->privateData;
1369
 
    virDomainObjPtr vm;
1370
 
    char *type = NULL;
1371
 
 
1372
 
    umlDriverLock(driver);
1373
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
1374
 
    umlDriverUnlock(driver);
1375
 
    if (!vm) {
1376
 
        umlReportError(VIR_ERR_INVALID_DOMAIN, "%s",
1377
 
                       _("no domain with matching uuid"));
1378
 
        goto cleanup;
1379
 
    }
1380
 
 
1381
 
    if (!(type = strdup(vm->def->os.type)))
1382
 
        virReportOOMError();
1383
 
 
1384
 
cleanup:
1385
 
    if (vm)
1386
 
        virDomainObjUnlock(vm);
1387
 
    return type;
1388
 
}
1389
 
 
1390
 
/* Returns max memory in kb, 0 if error */
1391
 
static unsigned long umlDomainGetMaxMemory(virDomainPtr dom) {
1392
 
    struct uml_driver *driver = dom->conn->privateData;
1393
 
    virDomainObjPtr vm;
1394
 
    unsigned long ret = 0;
1395
 
 
1396
 
    umlDriverLock(driver);
1397
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
1398
 
    umlDriverUnlock(driver);
1399
 
 
1400
 
    if (!vm) {
1401
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
1402
 
 
1403
 
        virUUIDFormat(dom->uuid, uuidstr);
1404
 
        umlReportError(VIR_ERR_INVALID_DOMAIN,
1405
 
                       _("no domain with matching uuid '%s'"), uuidstr);
1406
 
        goto cleanup;
1407
 
    }
1408
 
    ret = vm->def->maxmem;
1409
 
 
1410
 
cleanup:
1411
 
    if (vm)
1412
 
        virDomainObjUnlock(vm);
1413
 
    return ret;
1414
 
}
1415
 
 
1416
 
static int umlDomainSetMaxMemory(virDomainPtr dom, unsigned long newmax) {
1417
 
    struct uml_driver *driver = dom->conn->privateData;
1418
 
    virDomainObjPtr vm;
1419
 
    int ret = -1;
1420
 
 
1421
 
    umlDriverLock(driver);
1422
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
1423
 
    umlDriverUnlock(driver);
1424
 
 
1425
 
    if (!vm) {
1426
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
1427
 
 
1428
 
        virUUIDFormat(dom->uuid, uuidstr);
1429
 
        umlReportError(VIR_ERR_INVALID_DOMAIN,
1430
 
                       _("no domain with matching uuid '%s'"), uuidstr);
1431
 
        goto cleanup;
1432
 
    }
1433
 
 
1434
 
    if (newmax < vm->def->memory) {
1435
 
        umlReportError(VIR_ERR_INVALID_ARG, "%s",
1436
 
                       _("cannot set max memory lower than current memory"));
1437
 
        goto cleanup;
1438
 
    }
1439
 
 
1440
 
    vm->def->maxmem = newmax;
1441
 
    ret = 0;
1442
 
 
1443
 
cleanup:
1444
 
    if (vm)
1445
 
        virDomainObjUnlock(vm);
1446
 
    return ret;
1447
 
}
1448
 
 
1449
 
static int umlDomainSetMemory(virDomainPtr dom, unsigned long newmem) {
1450
 
    struct uml_driver *driver = dom->conn->privateData;
1451
 
    virDomainObjPtr vm;
1452
 
    int ret = -1;
1453
 
 
1454
 
    umlDriverLock(driver);
1455
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
1456
 
    umlDriverUnlock(driver);
1457
 
 
1458
 
    if (!vm) {
1459
 
        char uuidstr[VIR_UUID_STRING_BUFLEN];
1460
 
 
1461
 
        virUUIDFormat(dom->uuid, uuidstr);
1462
 
        umlReportError(VIR_ERR_INVALID_DOMAIN,
1463
 
                       _("no domain with matching uuid '%s'"), uuidstr);
1464
 
        goto cleanup;
1465
 
    }
1466
 
 
1467
 
    if (virDomainObjIsActive(vm)) {
1468
 
        umlReportError(VIR_ERR_NO_SUPPORT, "%s",
1469
 
                       _("cannot set memory of an active domain"));
1470
 
        goto cleanup;
1471
 
    }
1472
 
 
1473
 
    if (newmem > vm->def->maxmem) {
1474
 
        umlReportError(VIR_ERR_INVALID_ARG, "%s",
1475
 
                       _("cannot set memory higher than max memory"));
1476
 
        goto cleanup;
1477
 
    }
1478
 
 
1479
 
    vm->def->memory = newmem;
1480
 
    ret = 0;
1481
 
 
1482
 
cleanup:
1483
 
    if (vm)
1484
 
        virDomainObjUnlock(vm);
1485
 
    return ret;
1486
 
}
1487
 
 
1488
 
static int umlDomainGetInfo(virDomainPtr dom,
1489
 
                              virDomainInfoPtr info) {
1490
 
    struct uml_driver *driver = dom->conn->privateData;
1491
 
    virDomainObjPtr vm;
1492
 
    int ret = -1;
1493
 
 
1494
 
    umlDriverLock(driver);
1495
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
1496
 
    umlDriverUnlock(driver);
1497
 
 
1498
 
    if (!vm) {
1499
 
        umlReportError(VIR_ERR_INVALID_DOMAIN, "%s",
1500
 
                       _("no domain with matching uuid"));
1501
 
        goto cleanup;
1502
 
    }
1503
 
 
1504
 
    info->state = vm->state;
1505
 
 
1506
 
    if (!virDomainObjIsActive(vm)) {
1507
 
        info->cpuTime = 0;
1508
 
    } else {
1509
 
        if (umlGetProcessInfo(&(info->cpuTime), vm->pid) < 0) {
1510
 
            umlReportError(VIR_ERR_OPERATION_FAILED, "%s",
1511
 
                           _("cannot read cputime for domain"));
1512
 
            goto cleanup;
1513
 
        }
1514
 
    }
1515
 
 
1516
 
    info->maxMem = vm->def->maxmem;
1517
 
    info->memory = vm->def->memory;
1518
 
    info->nrVirtCpu = vm->def->vcpus;
1519
 
    ret = 0;
1520
 
 
1521
 
cleanup:
1522
 
    if (vm)
1523
 
        virDomainObjUnlock(vm);
1524
 
    return ret;
1525
 
}
1526
 
 
1527
 
 
1528
 
static char *umlDomainDumpXML(virDomainPtr dom,
1529
 
                                int flags ATTRIBUTE_UNUSED) {
1530
 
    struct uml_driver *driver = dom->conn->privateData;
1531
 
    virDomainObjPtr vm;
1532
 
    char *ret = NULL;
1533
 
 
1534
 
    umlDriverLock(driver);
1535
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
1536
 
    umlDriverUnlock(driver);
1537
 
 
1538
 
    if (!vm) {
1539
 
        umlReportError(VIR_ERR_INVALID_DOMAIN, "%s",
1540
 
                       _("no domain with matching uuid"));
1541
 
        goto cleanup;
1542
 
    }
1543
 
 
1544
 
    ret = virDomainDefFormat((flags & VIR_DOMAIN_XML_INACTIVE) && vm->newDef ?
1545
 
                             vm->newDef : vm->def,
1546
 
                             flags);
1547
 
 
1548
 
cleanup:
1549
 
    if (vm)
1550
 
        virDomainObjUnlock(vm);
1551
 
    return ret;
1552
 
}
1553
 
 
1554
 
 
1555
 
static int umlListDefinedDomains(virConnectPtr conn,
1556
 
                            char **const names, int nnames) {
1557
 
    struct uml_driver *driver = conn->privateData;
1558
 
    int n;
1559
 
 
1560
 
    umlDriverLock(driver);
1561
 
    n = virDomainObjListGetInactiveNames(&driver->domains, names, nnames);
1562
 
    umlDriverUnlock(driver);
1563
 
 
1564
 
    return n;
1565
 
}
1566
 
 
1567
 
static int umlNumDefinedDomains(virConnectPtr conn) {
1568
 
    struct uml_driver *driver = conn->privateData;
1569
 
    int n;
1570
 
 
1571
 
    umlDriverLock(driver);
1572
 
    n = virDomainObjListNumOfDomains(&driver->domains, 0);
1573
 
    umlDriverUnlock(driver);
1574
 
 
1575
 
    return n;
1576
 
}
1577
 
 
1578
 
 
1579
 
static int umlDomainStartWithFlags(virDomainPtr dom, unsigned int flags) {
1580
 
    struct uml_driver *driver = dom->conn->privateData;
1581
 
    virDomainObjPtr vm;
1582
 
    int ret = -1;
1583
 
 
1584
 
    virCheckFlags(0, -1);
1585
 
 
1586
 
    umlDriverLock(driver);
1587
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
1588
 
 
1589
 
    if (!vm) {
1590
 
        umlReportError(VIR_ERR_INVALID_DOMAIN, "%s",
1591
 
                       _("no domain with matching uuid"));
1592
 
        goto cleanup;
1593
 
    }
1594
 
 
1595
 
    ret = umlStartVMDaemon(dom->conn, driver, vm);
1596
 
 
1597
 
cleanup:
1598
 
    if (vm)
1599
 
        virDomainObjUnlock(vm);
1600
 
    umlDriverUnlock(driver);
1601
 
    return ret;
1602
 
}
1603
 
 
1604
 
static int umlDomainStart(virDomainPtr dom) {
1605
 
    return umlDomainStartWithFlags(dom, 0);
1606
 
}
1607
 
 
1608
 
static virDomainPtr umlDomainDefine(virConnectPtr conn, const char *xml) {
1609
 
    struct uml_driver *driver = conn->privateData;
1610
 
    virDomainDefPtr def;
1611
 
    virDomainObjPtr vm = NULL;
1612
 
    virDomainPtr dom = NULL;
1613
 
 
1614
 
    umlDriverLock(driver);
1615
 
    if (!(def = virDomainDefParseString(driver->caps, xml,
1616
 
                                        VIR_DOMAIN_XML_INACTIVE)))
1617
 
        goto cleanup;
1618
 
 
1619
 
    if (virDomainObjIsDuplicate(&driver->domains, def, 0) < 0)
1620
 
        goto cleanup;
1621
 
 
1622
 
    if (!(vm = virDomainAssignDef(driver->caps,
1623
 
                                  &driver->domains,
1624
 
                                  def, false)))
1625
 
        goto cleanup;
1626
 
    def = NULL;
1627
 
    vm->persistent = 1;
1628
 
 
1629
 
    if (virDomainSaveConfig(driver->configDir,
1630
 
                            vm->newDef ? vm->newDef : vm->def) < 0) {
1631
 
        virDomainRemoveInactive(&driver->domains,
1632
 
                                vm);
1633
 
        vm = NULL;
1634
 
        goto cleanup;
1635
 
    }
1636
 
 
1637
 
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
1638
 
    if (dom) dom->id = vm->def->id;
1639
 
 
1640
 
cleanup:
1641
 
    virDomainDefFree(def);
1642
 
    if (vm)
1643
 
        virDomainObjUnlock(vm);
1644
 
    umlDriverUnlock(driver);
1645
 
    return dom;
1646
 
}
1647
 
 
1648
 
static int umlDomainUndefine(virDomainPtr dom) {
1649
 
    struct uml_driver *driver = dom->conn->privateData;
1650
 
    virDomainObjPtr vm;
1651
 
    int ret = -1;
1652
 
 
1653
 
    umlDriverLock(driver);
1654
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
1655
 
    if (!vm) {
1656
 
        umlReportError(VIR_ERR_INVALID_DOMAIN, "%s",
1657
 
                       _("no domain with matching uuid"));
1658
 
        goto cleanup;
1659
 
    }
1660
 
 
1661
 
    if (virDomainObjIsActive(vm)) {
1662
 
        umlReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1663
 
                       _("cannot delete active domain"));
1664
 
        goto cleanup;
1665
 
    }
1666
 
 
1667
 
    if (!vm->persistent) {
1668
 
        umlReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1669
 
                       _("cannot undefine transient domain"));
1670
 
        goto cleanup;
1671
 
    }
1672
 
 
1673
 
    if (virDomainDeleteConfig(driver->configDir, driver->autostartDir, vm) < 0)
1674
 
        goto cleanup;
1675
 
 
1676
 
    virDomainRemoveInactive(&driver->domains,
1677
 
                            vm);
1678
 
    vm = NULL;
1679
 
    ret = 0;
1680
 
 
1681
 
cleanup:
1682
 
    if (vm)
1683
 
        virDomainObjUnlock(vm);
1684
 
    umlDriverUnlock(driver);
1685
 
    return ret;
1686
 
}
1687
 
 
1688
 
 
1689
 
 
1690
 
static int umlDomainGetAutostart(virDomainPtr dom,
1691
 
                            int *autostart) {
1692
 
    struct uml_driver *driver = dom->conn->privateData;
1693
 
    virDomainObjPtr vm;
1694
 
    int ret = -1;
1695
 
 
1696
 
    umlDriverLock(driver);
1697
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
1698
 
 
1699
 
    if (!vm) {
1700
 
        umlReportError(VIR_ERR_INVALID_DOMAIN, "%s",
1701
 
                       _("no domain with matching uuid"));
1702
 
        goto cleanup;
1703
 
    }
1704
 
 
1705
 
    *autostart = vm->autostart;
1706
 
    ret = 0;
1707
 
 
1708
 
cleanup:
1709
 
    if (vm)
1710
 
        virDomainObjUnlock(vm);
1711
 
    umlDriverUnlock(driver);
1712
 
    return ret;
1713
 
}
1714
 
 
1715
 
static int umlDomainSetAutostart(virDomainPtr dom,
1716
 
                                   int autostart) {
1717
 
    struct uml_driver *driver = dom->conn->privateData;
1718
 
    virDomainObjPtr vm;
1719
 
    char *configFile = NULL, *autostartLink = NULL;
1720
 
    int ret = -1;
1721
 
 
1722
 
    umlDriverLock(driver);
1723
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
1724
 
 
1725
 
    if (!vm) {
1726
 
        umlReportError(VIR_ERR_INVALID_DOMAIN, "%s",
1727
 
                       _("no domain with matching uuid"));
1728
 
        goto cleanup;
1729
 
    }
1730
 
 
1731
 
    if (!vm->persistent) {
1732
 
        umlReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1733
 
                       _("cannot set autostart for transient domain"));
1734
 
        goto cleanup;
1735
 
    }
1736
 
 
1737
 
    autostart = (autostart != 0);
1738
 
 
1739
 
    if (vm->autostart != autostart) {
1740
 
        if ((configFile = virDomainConfigFile(driver->configDir, vm->def->name)) == NULL)
1741
 
            goto cleanup;
1742
 
        if ((autostartLink = virDomainConfigFile(driver->autostartDir, vm->def->name)) == NULL)
1743
 
            goto cleanup;
1744
 
 
1745
 
        if (autostart) {
1746
 
            int err;
1747
 
 
1748
 
            if ((err = virFileMakePath(driver->autostartDir))) {
1749
 
                virReportSystemError(err,
1750
 
                                     _("cannot create autostart directory %s"),
1751
 
                                     driver->autostartDir);
1752
 
                goto cleanup;
1753
 
            }
1754
 
 
1755
 
            if (symlink(configFile, autostartLink) < 0) {
1756
 
                virReportSystemError(errno,
1757
 
                                     _("Failed to create symlink '%s to '%s'"),
1758
 
                                     autostartLink, configFile);
1759
 
                goto cleanup;
1760
 
            }
1761
 
        } else {
1762
 
            if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
1763
 
                virReportSystemError(errno,
1764
 
                                     _("Failed to delete symlink '%s'"),
1765
 
                                     autostartLink);
1766
 
                goto cleanup;
1767
 
            }
1768
 
        }
1769
 
 
1770
 
        vm->autostart = autostart;
1771
 
    }
1772
 
    ret = 0;
1773
 
 
1774
 
cleanup:
1775
 
    VIR_FREE(configFile);
1776
 
    VIR_FREE(autostartLink);
1777
 
    if (vm)
1778
 
        virDomainObjUnlock(vm);
1779
 
    umlDriverUnlock(driver);
1780
 
    return ret;
1781
 
}
1782
 
 
1783
 
 
1784
 
static int
1785
 
umlDomainBlockPeek (virDomainPtr dom,
1786
 
                      const char *path,
1787
 
                      unsigned long long offset, size_t size,
1788
 
                      void *buffer,
1789
 
                      unsigned int flags ATTRIBUTE_UNUSED)
1790
 
{
1791
 
    struct uml_driver *driver = dom->conn->privateData;
1792
 
    virDomainObjPtr vm;
1793
 
    int fd = -1, ret = -1, i;
1794
 
 
1795
 
    umlDriverLock(driver);
1796
 
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
1797
 
    umlDriverUnlock(driver);
1798
 
 
1799
 
    if (!vm) {
1800
 
        umlReportError(VIR_ERR_INVALID_DOMAIN, "%s",
1801
 
                       _("no domain with matching uuid"));
1802
 
        goto cleanup;
1803
 
    }
1804
 
 
1805
 
    if (!path || path[0] == '\0') {
1806
 
        umlReportError(VIR_ERR_INVALID_ARG, "%s",
1807
 
                       _("NULL or empty path"));
1808
 
        goto cleanup;
1809
 
    }
1810
 
 
1811
 
    /* Check the path belongs to this domain. */
1812
 
    for (i = 0 ; i < vm->def->ndisks ; i++) {
1813
 
        if (vm->def->disks[i]->src != NULL &&
1814
 
            STREQ (vm->def->disks[i]->src, path)) {
1815
 
            ret = 0;
1816
 
            break;
1817
 
        }
1818
 
    }
1819
 
 
1820
 
    if (ret == 0) {
1821
 
        ret = -1;
1822
 
        /* The path is correct, now try to open it and get its size. */
1823
 
        fd = open (path, O_RDONLY);
1824
 
        if (fd == -1) {
1825
 
            virReportSystemError(errno,
1826
 
                                 _("cannot open %s"), path);
1827
 
            goto cleanup;
1828
 
        }
1829
 
 
1830
 
        /* Seek and read. */
1831
 
        /* NB. Because we configure with AC_SYS_LARGEFILE, off_t should
1832
 
         * be 64 bits on all platforms.
1833
 
         */
1834
 
        if (lseek (fd, offset, SEEK_SET) == (off_t) -1 ||
1835
 
            saferead (fd, buffer, size) == (ssize_t) -1) {
1836
 
            virReportSystemError(errno,
1837
 
                                 _("cannot read %s"), path);
1838
 
            goto cleanup;
1839
 
        }
1840
 
 
1841
 
        ret = 0;
1842
 
    } else {
1843
 
        umlReportError(VIR_ERR_INVALID_ARG, "%s",
1844
 
                       _("invalid path"));
1845
 
    }
1846
 
 
1847
 
cleanup:
1848
 
    if (fd >= 0) close (fd);
1849
 
    if (vm)
1850
 
        virDomainObjUnlock(vm);
1851
 
    return ret;
1852
 
}
1853
 
 
1854
 
 
1855
 
 
1856
 
static virDriver umlDriver = {
1857
 
    VIR_DRV_UML,
1858
 
    "UML",
1859
 
    umlOpen, /* open */
1860
 
    umlClose, /* close */
1861
 
    NULL, /* supports_feature */
1862
 
    umlGetType, /* type */
1863
 
    umlGetVersion, /* version */
1864
 
    NULL, /* libvirtVersion (impl. in libvirt.c) */
1865
 
    virGetHostname, /* getHostname */
1866
 
    NULL, /* getMaxVcpus */
1867
 
    nodeGetInfo, /* nodeGetInfo */
1868
 
    umlGetCapabilities, /* getCapabilities */
1869
 
    umlListDomains, /* listDomains */
1870
 
    umlNumDomains, /* numOfDomains */
1871
 
    umlDomainCreate, /* domainCreateXML */
1872
 
    umlDomainLookupByID, /* domainLookupByID */
1873
 
    umlDomainLookupByUUID, /* domainLookupByUUID */
1874
 
    umlDomainLookupByName, /* domainLookupByName */
1875
 
    NULL, /* domainSuspend */
1876
 
    NULL, /* domainResume */
1877
 
    umlDomainShutdown, /* domainShutdown */
1878
 
    NULL, /* domainReboot */
1879
 
    umlDomainDestroy, /* domainDestroy */
1880
 
    umlDomainGetOSType, /* domainGetOSType */
1881
 
    umlDomainGetMaxMemory, /* domainGetMaxMemory */
1882
 
    umlDomainSetMaxMemory, /* domainSetMaxMemory */
1883
 
    umlDomainSetMemory, /* domainSetMemory */
1884
 
    umlDomainGetInfo, /* domainGetInfo */
1885
 
    NULL, /* domainSave */
1886
 
    NULL, /* domainRestore */
1887
 
    NULL, /* domainCoreDump */
1888
 
    NULL, /* domainSetVcpus */
1889
 
    NULL, /* domainPinVcpu */
1890
 
    NULL, /* domainGetVcpus */
1891
 
    NULL, /* domainGetMaxVcpus */
1892
 
    NULL, /* domainGetSecurityLabel */
1893
 
    NULL, /* nodeGetSecurityModel */
1894
 
    umlDomainDumpXML, /* domainDumpXML */
1895
 
    NULL, /* domainXMLFromNative */
1896
 
    NULL, /* domainXMLToNative */
1897
 
    umlListDefinedDomains, /* listDefinedDomains */
1898
 
    umlNumDefinedDomains, /* numOfDefinedDomains */
1899
 
    umlDomainStart, /* domainCreate */
1900
 
    umlDomainStartWithFlags, /* domainCreateWithFlags */
1901
 
    umlDomainDefine, /* domainDefineXML */
1902
 
    umlDomainUndefine, /* domainUndefine */
1903
 
    NULL, /* domainAttachDevice */
1904
 
    NULL, /* domainAttachDeviceFlags */
1905
 
    NULL, /* domainDetachDevice */
1906
 
    NULL, /* domainDetachDeviceFlags */
1907
 
    NULL, /* domainUpdateDeviceFlags */
1908
 
    umlDomainGetAutostart, /* domainGetAutostart */
1909
 
    umlDomainSetAutostart, /* domainSetAutostart */
1910
 
    NULL, /* domainGetSchedulerType */
1911
 
    NULL, /* domainGetSchedulerParameters */
1912
 
    NULL, /* domainSetSchedulerParameters */
1913
 
    NULL, /* domainMigratePrepare */
1914
 
    NULL, /* domainMigratePerform */
1915
 
    NULL, /* domainMigrateFinish */
1916
 
    NULL, /* domainBlockStats */
1917
 
    NULL, /* domainInterfaceStats */
1918
 
    NULL, /* domainMemoryStats */
1919
 
    umlDomainBlockPeek, /* domainBlockPeek */
1920
 
    NULL, /* domainMemoryPeek */
1921
 
    NULL, /* domainGetBlockInfo */
1922
 
    nodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */
1923
 
    nodeGetFreeMemory,  /* getFreeMemory */
1924
 
    NULL, /* domainEventRegister */
1925
 
    NULL, /* domainEventDeregister */
1926
 
    NULL, /* domainMigratePrepare2 */
1927
 
    NULL, /* domainMigrateFinish2 */
1928
 
    NULL, /* nodeDeviceDettach */
1929
 
    NULL, /* nodeDeviceReAttach */
1930
 
    NULL, /* nodeDeviceReset */
1931
 
    NULL, /* domainMigratePrepareTunnel */
1932
 
    umlIsEncrypted, /* isEncrypted */
1933
 
    umlIsSecure, /* isSecure */
1934
 
    umlDomainIsActive, /* domainIsActive */
1935
 
    umlDomainIsPersistent, /* domainIsPersistent */
1936
 
    NULL, /* cpuCompare */
1937
 
    NULL, /* cpuBaseline */
1938
 
    NULL, /* domainGetJobInfo */
1939
 
    NULL, /* domainAbortJob */
1940
 
    NULL, /* domainMigrateSetMaxDowntime */
1941
 
    NULL, /* domainEventRegisterAny */
1942
 
    NULL, /* domainEventDeregisterAny */
1943
 
    NULL, /* domainManagedSave */
1944
 
    NULL, /* domainHasManagedSaveImage */
1945
 
    NULL, /* domainManagedSaveRemove */
1946
 
    NULL, /* domainSnapshotCreateXML */
1947
 
    NULL, /* domainSnapshotDumpXML */
1948
 
    NULL, /* domainSnapshotNum */
1949
 
    NULL, /* domainSnapshotListNames */
1950
 
    NULL, /* domainSnapshotLookupByName */
1951
 
    NULL, /* domainHasCurrentSnapshot */
1952
 
    NULL, /* domainSnapshotCurrent */
1953
 
    NULL, /* domainRevertToSnapshot */
1954
 
    NULL, /* domainSnapshotDelete */
1955
 
    NULL, /* qemuDomainMonitorCommand */
1956
 
};
1957
 
 
1958
 
 
1959
 
static virStateDriver umlStateDriver = {
1960
 
    .name = "UML",
1961
 
    .initialize = umlStartup,
1962
 
    .cleanup = umlShutdown,
1963
 
    .reload = umlReload,
1964
 
    .active = umlActive,
1965
 
};
1966
 
 
1967
 
int umlRegister(void) {
1968
 
    virRegisterDriver(&umlDriver);
1969
 
    virRegisterStateDriver(&umlStateDriver);
1970
 
    return 0;
1971
 
}