You need to sign in or sign up before continuing.
storage_backend.c 52.8 KB
Newer Older
1
/*
2
 * storage_backend.c: internal storage driver backend contract
3
 *
4
 * Copyright (C) 2007-2013 Red Hat, Inc.
5 6 7 8 9 10 11 12 13 14 15 16 17
 * Copyright (C) 2007-2008 Daniel P. Berrange
 *
 * 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
18
 * License along with this library.  If not, see
O
Osier Yang 已提交
19
 * <http://www.gnu.org/licenses/>.
20 21 22 23 24 25 26
 *
 * Author: Daniel P. Berrange <berrange@redhat.com>
 */

#include <config.h>

#include <string.h>
27
#include <stdio.h>
28
#include <regex.h>
29
#include <sys/types.h>
E
Eric Blake 已提交
30
#include <sys/wait.h>
31
#include <unistd.h>
32 33
#include <fcntl.h>
#include <sys/stat.h>
34
#include <sys/param.h>
35
#include <dirent.h>
36
#include "dirname.h"
37 38 39 40
#ifdef __linux__
# include <sys/ioctl.h>
# include <linux/fs.h>
#endif
41

42
#if WITH_SELINUX
43
# include <selinux/selinux.h>
44
#endif
45

46
#include "datatypes.h"
47
#include "virerror.h"
48
#include "viralloc.h"
49
#include "internal.h"
50
#include "secret_conf.h"
51
#include "viruuid.h"
52
#include "virstoragefile.h"
D
Daniel P. Berrange 已提交
53
#include "storage_backend.h"
54
#include "virlog.h"
E
Eric Blake 已提交
55
#include "virfile.h"
56
#include "stat-time.h"
57
#include "virstring.h"
58

59
#if WITH_STORAGE_LVM
60
# include "storage_backend_logical.h"
61 62
#endif
#if WITH_STORAGE_ISCSI
63
# include "storage_backend_iscsi.h"
64
#endif
65
#if WITH_STORAGE_SCSI
66
# include "storage_backend_scsi.h"
67
#endif
D
Dave Allan 已提交
68
#if WITH_STORAGE_MPATH
69
# include "storage_backend_mpath.h"
D
Dave Allan 已提交
70
#endif
71
#if WITH_STORAGE_DISK
72
# include "storage_backend_disk.h"
73 74
#endif
#if WITH_STORAGE_DIR
75
# include "storage_backend_fs.h"
76
#endif
77 78 79
#if WITH_STORAGE_RBD
# include "storage_backend_rbd.h"
#endif
80 81 82
#if WITH_STORAGE_SHEEPDOG
# include "storage_backend_sheepdog.h"
#endif
83

84 85
#define VIR_FROM_THIS VIR_FROM_STORAGE

86 87 88 89 90 91 92 93 94 95 96 97 98 99
static virStorageBackendPtr backends[] = {
#if WITH_STORAGE_DIR
    &virStorageBackendDirectory,
#endif
#if WITH_STORAGE_FS
    &virStorageBackendFileSystem,
    &virStorageBackendNetFileSystem,
#endif
#if WITH_STORAGE_LVM
    &virStorageBackendLogical,
#endif
#if WITH_STORAGE_ISCSI
    &virStorageBackendISCSI,
#endif
100 101 102
#if WITH_STORAGE_SCSI
    &virStorageBackendSCSI,
#endif
D
Dave Allan 已提交
103 104 105
#if WITH_STORAGE_MPATH
    &virStorageBackendMpath,
#endif
106 107
#if WITH_STORAGE_DISK
    &virStorageBackendDisk,
108 109 110
#endif
#if WITH_STORAGE_RBD
    &virStorageBackendRBD,
111 112 113
#endif
#if WITH_STORAGE_SHEEPDOG
    &virStorageBackendSheepdog,
114 115 116
#endif
    NULL
};
117

118 119 120 121 122 123
enum {
    TOOL_QEMU_IMG,
    TOOL_KVM_IMG,
    TOOL_QCOW_CREATE,
};

124 125 126
#define READ_BLOCK_SIZE_DEFAULT  (1024 * 1024)
#define WRITE_BLOCK_SIZE_DEFAULT (4 * 1024)

127
static int ATTRIBUTE_NONNULL(2)
128
virStorageBackendCopyToFD(virStorageVolDefPtr vol,
129 130
                          virStorageVolDefPtr inputvol,
                          int fd,
131 132
                          unsigned long long *total,
                          int is_dest_file)
133 134 135
{
    int inputfd = -1;
    int amtread = -1;
136
    int ret = 0;
137 138 139
    size_t rbytes = READ_BLOCK_SIZE_DEFAULT;
    size_t wbytes = 0;
    int interval;
140
    char *zerobuf = NULL;
141
    char *buf = NULL;
142
    struct stat st;
143

144
    if ((inputfd = open(inputvol->target.path, O_RDONLY)) < 0) {
145
        ret = -errno;
146
        virReportSystemError(errno,
147 148 149
                             _("could not open input path '%s'"),
                             inputvol->target.path);
        goto cleanup;
150 151
    }

152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
#ifdef __linux__
    if (ioctl(fd, BLKBSZGET, &wbytes) < 0) {
        wbytes = 0;
    }
#endif
    if ((wbytes == 0) && fstat(fd, &st) == 0)
        wbytes = st.st_blksize;
    if (wbytes < WRITE_BLOCK_SIZE_DEFAULT)
        wbytes = WRITE_BLOCK_SIZE_DEFAULT;

    if (VIR_ALLOC_N(zerobuf, wbytes) < 0) {
        ret = -errno;
        virReportOOMError();
        goto cleanup;
    }
167

168
    if (VIR_ALLOC_N(buf, rbytes) < 0) {
169
        ret = -errno;
170
        virReportOOMError();
171 172 173 174 175 176
        goto cleanup;
    }

    while (amtread != 0) {
        int amtleft;

177 178
        if (*total < rbytes)
            rbytes = *total;
179

180
        if ((amtread = saferead(inputfd, buf, rbytes)) < 0) {
181
            ret = -errno;
182
            virReportSystemError(errno,
183 184 185 186
                                 _("failed reading from file '%s'"),
                                 inputvol->target.path);
            goto cleanup;
        }
187
        *total -= amtread;
188 189 190 191 192

        /* Loop over amt read in 512 byte increments, looking for sparse
         * blocks */
        amtleft = amtread;
        do {
193
            interval = ((wbytes > amtleft) ? amtleft : wbytes);
194 195
            int offset = amtread - amtleft;

196
            if (is_dest_file && memcmp(buf+offset, zerobuf, interval) == 0) {
197
                if (lseek(fd, interval, SEEK_CUR) < 0) {
198
                    ret = -errno;
199
                    virReportSystemError(errno,
200 201 202 203 204
                                         _("cannot extend file '%s'"),
                                         vol->target.path);
                    goto cleanup;
                }
            } else if (safewrite(fd, buf+offset, interval) < 0) {
205
                ret = -errno;
206
                virReportSystemError(errno,
207 208 209 210 211
                                     _("failed writing to file '%s'"),
                                     vol->target.path);
                goto cleanup;

            }
212
        } while ((amtleft -= interval) > 0);
213 214
    }

215 216 217 218 219 220 221 222
    if (fdatasync(fd) < 0) {
        ret = -errno;
        virReportSystemError(errno, _("cannot sync data to file '%s'"),
                             vol->target.path);
        goto cleanup;
    }


223
    if (VIR_CLOSE(inputfd) < 0) {
224
        ret = -errno;
225
        virReportSystemError(errno,
226 227 228 229 230 231 232
                             _("cannot close file '%s'"),
                             inputvol->target.path);
        goto cleanup;
    }
    inputfd = -1;

cleanup:
233
    VIR_FORCE_CLOSE(inputfd);
234

235
    VIR_FREE(zerobuf);
236 237
    VIR_FREE(buf);

238 239 240
    return ret;
}

241
static int
242
virStorageBackendCreateBlockFrom(virConnectPtr conn ATTRIBUTE_UNUSED,
243
                                 virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
244 245
                                 virStorageVolDefPtr vol,
                                 virStorageVolDefPtr inputvol,
E
Eric Blake 已提交
246
                                 unsigned int flags)
247 248 249 250
{
    int fd = -1;
    int ret = -1;
    unsigned long long remain;
251 252 253
    struct stat st;
    gid_t gid;
    uid_t uid;
254

255 256 257 258 259 260 261 262
    virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, -1);

    if (flags & VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("metadata preallocation is not supported for block "
                         "volumes"));
        goto cleanup;
    }
E
Eric Blake 已提交
263

264
    if ((fd = open(vol->target.path, O_RDWR)) < 0) {
265
        virReportSystemError(errno,
266 267 268 269 270 271 272 273
                             _("cannot create path '%s'"),
                             vol->target.path);
        goto cleanup;
    }

    remain = vol->allocation;

    if (inputvol) {
274
        int res = virStorageBackendCopyToFD(vol, inputvol,
275
                                            fd, &remain, 0);
276 277 278 279
        if (res < 0)
            goto cleanup;
    }

280
    if (fstat(fd, &st) == -1) {
281
        virReportSystemError(errno, _("stat of '%s' failed"),
282 283 284
                             vol->target.path);
        goto cleanup;
    }
P
Philipp Hahn 已提交
285 286 287
    uid = (vol->target.perms.uid != st.st_uid) ? vol->target.perms.uid : (uid_t) -1;
    gid = (vol->target.perms.gid != st.st_gid) ? vol->target.perms.gid : (gid_t) -1;
    if (((uid != (uid_t) -1) || (gid != (gid_t) -1))
288
        && (fchown(fd, uid, gid) < 0)) {
289
        virReportSystemError(errno,
290
                             _("cannot chown '%s' to (%u, %u)"),
291 292
                             vol->target.path, (unsigned int) uid,
                             (unsigned int) gid);
293 294 295
        goto cleanup;
    }
    if (fchmod(fd, vol->target.perms.mode) < 0) {
296
        virReportSystemError(errno,
297 298 299 300
                             _("cannot set mode of '%s' to %04o"),
                             vol->target.path, vol->target.perms.mode);
        goto cleanup;
    }
301
    if (VIR_CLOSE(fd) < 0) {
302
        virReportSystemError(errno,
303 304 305 306 307 308 309 310
                             _("cannot close file '%s'"),
                             vol->target.path);
        goto cleanup;
    }
    fd = -1;

    ret = 0;
cleanup:
311
    VIR_FORCE_CLOSE(fd);
312 313 314 315

    return ret;
}

E
Eric Blake 已提交
316 317 318 319
static int
createRawFile(int fd, virStorageVolDefPtr vol,
              virStorageVolDefPtr inputvol)
{
320 321
    int ret = 0;
    unsigned long long remain;
322

323 324
    /* Seek to the final size, so the capacity is available upfront
     * for progress reporting */
E
Eric Blake 已提交
325
    if (ftruncate(fd, vol->capacity) < 0) {
326
        ret = -errno;
327
        virReportSystemError(errno,
328
                             _("cannot extend file '%s'"),
E
Eric Blake 已提交
329
                             vol->target.path);
330 331 332
        goto cleanup;
    }

E
Eric Blake 已提交
333
    remain = vol->allocation;
334

E
Eric Blake 已提交
335 336
    if (inputvol) {
        ret = virStorageBackendCopyToFD(vol, inputvol, fd, &remain, 1);
337
        if (ret < 0) {
338
            goto cleanup;
339
        }
340 341 342
    }

    if (remain) {
343 344 345 346 347
        if (safezero(fd, 0, remain) < 0) {
            ret = -errno;
            virReportSystemError(errno, _("cannot fill file '%s'"),
                                 vol->target.path);
            goto cleanup;
348
        }
349 350 351
    }

    if (fsync(fd) < 0) {
352
        ret = -errno;
353
        virReportSystemError(errno, _("cannot sync data to file '%s'"),
E
Eric Blake 已提交
354
                             vol->target.path);
355
        goto cleanup;
356 357
    }

358 359 360 361 362 363 364 365 366
cleanup:
    return ret;
}

int
virStorageBackendCreateRaw(virConnectPtr conn ATTRIBUTE_UNUSED,
                           virStoragePoolObjPtr pool,
                           virStorageVolDefPtr vol,
                           virStorageVolDefPtr inputvol,
E
Eric Blake 已提交
367
                           unsigned int flags)
368 369
{
    int ret = -1;
E
Eric Blake 已提交
370 371 372
    int fd = -1;
    int operation_flags;

373 374 375 376 377 378 379 380
    virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, -1);

    if (flags & VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("metadata preallocation is not supported for raw "
                         "volumes"));
        goto cleanup;
    }
381 382

    if (vol->target.encryption != NULL) {
383 384
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("storage pool does not support encrypted volumes"));
385 386
        goto cleanup;
    }
387

L
Laine Stump 已提交
388
    operation_flags = VIR_FILE_OPEN_FORCE_MODE | VIR_FILE_OPEN_FORCE_OWNER;
E
Eric Blake 已提交
389
    if (pool->def->type == VIR_STORAGE_POOL_NETFS)
L
Laine Stump 已提交
390
        operation_flags |= VIR_FILE_OPEN_FORK;
E
Eric Blake 已提交
391

392 393
    if ((fd = virFileOpenAs(vol->target.path,
                            O_RDWR | O_CREAT | O_EXCL,
L
Laine Stump 已提交
394 395 396
                            vol->target.perms.mode,
                            vol->target.perms.uid,
                            vol->target.perms.gid,
397
                            operation_flags)) < 0) {
E
Eric Blake 已提交
398
        virReportSystemError(-fd,
399
                             _("Failed to create file '%s'"),
E
Eric Blake 已提交
400 401 402 403
                             vol->target.path);
        goto cleanup;
    }

404 405
    if ((ret = createRawFile(fd, vol, inputvol)) < 0)
        /* createRawFile already reported the exact error. */
E
Eric Blake 已提交
406
        ret = -1;
407 408

cleanup:
E
Eric Blake 已提交
409
    VIR_FORCE_CLOSE(fd);
410 411 412
    return ret;
}

413 414 415 416 417 418 419 420 421
static int
virStorageGenerateSecretUUID(virConnectPtr conn,
                             unsigned char *uuid)
{
    unsigned attempt;

    for (attempt = 0; attempt < 65536; attempt++) {
        virSecretPtr tmp;
        if (virUUIDGenerate(uuid) < 0) {
422 423
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("unable to generate uuid"));
424 425
            return -1;
        }
426
        tmp = conn->secretDriver->secretLookupByUUID(conn, uuid);
427 428 429 430 431 432
        if (tmp == NULL)
            return 0;

        virSecretFree(tmp);
    }

433 434
    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                   _("too many conflicts when generating an uuid"));
435 436 437 438

    return -1;
}

439 440 441 442 443 444 445 446 447
static int
virStorageGenerateQcowEncryption(virConnectPtr conn,
                                 virStorageVolDefPtr vol)
{
    virSecretDefPtr def = NULL;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    virStorageEncryptionPtr enc;
    virStorageEncryptionSecretPtr enc_secret = NULL;
    virSecretPtr secret = NULL;
448
    char *xml;
449 450 451
    unsigned char value[VIR_STORAGE_QCOW_PASSPHRASE_SIZE];
    int ret = -1;

452
    if (conn->secretDriver == NULL ||
453 454 455
        conn->secretDriver->secretLookupByUUID == NULL ||
        conn->secretDriver->secretDefineXML == NULL ||
        conn->secretDriver->secretSetValue == NULL) {
456 457
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("secret storage not supported"));
458 459 460 461 462
        goto cleanup;
    }

    enc = vol->target.encryption;
    if (enc->nsecrets != 0) {
463 464
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("secrets already defined"));
465 466 467 468 469
        goto cleanup;
    }

    if (VIR_ALLOC(enc_secret) < 0 || VIR_REALLOC_N(enc->secrets, 1) < 0 ||
        VIR_ALLOC(def) < 0) {
470
        virReportOOMError();
471 472 473
        goto cleanup;
    }

474
    def->ephemeral = false;
475
    def->private = false;
476
    if (virStorageGenerateSecretUUID(conn, def->uuid) < 0)
477
        goto cleanup;
478

479
    def->usage_type = VIR_SECRET_USAGE_TYPE_VOLUME;
480
    if (VIR_STRDUP(def->usage.volume, vol->target.path) < 0)
481
        goto cleanup;
482
    xml = virSecretDefFormat(def);
483 484 485 486 487
    virSecretDefFree(def);
    def = NULL;
    if (xml == NULL)
        goto cleanup;

488
    secret = conn->secretDriver->secretDefineXML(conn, xml, 0);
489 490 491 492 493 494
    if (secret == NULL) {
        VIR_FREE(xml);
        goto cleanup;
    }
    VIR_FREE(xml);

495
    if (virStorageGenerateQcowPassphrase(value) < 0)
496 497
        goto cleanup;

498
    if (conn->secretDriver->secretSetValue(secret, value, sizeof(value), 0) < 0)
499 500 501
        goto cleanup;

    enc_secret->type = VIR_STORAGE_ENCRYPTION_SECRET_TYPE_PASSPHRASE;
502
    memcpy(enc_secret->uuid, secret->uuid, VIR_UUID_BUFLEN);
503 504 505 506 507 508 509 510 511
    enc->format = VIR_STORAGE_ENCRYPTION_FORMAT_QCOW;
    enc->secrets[0] = enc_secret; /* Space for secrets[0] allocated above */
    enc_secret = NULL;
    enc->nsecrets = 1;

    ret = 0;

cleanup:
    if (secret != NULL) {
512
        if (ret != 0 &&
513 514
            conn->secretDriver->secretUndefine != NULL)
            conn->secretDriver->secretUndefine(secret);
515 516
        virSecretFree(secret);
    }
517
    virBufferFreeAndReset(&buf);
518 519 520 521 522
    virSecretDefFree(def);
    VIR_FREE(enc_secret);
    return ret;
}

523 524 525 526 527
static int
virStorageBackendCreateExecCommand(virStoragePoolObjPtr pool,
                                   virStorageVolDefPtr vol,
                                   virCommandPtr cmd)
{
528 529 530
    struct stat st;
    gid_t gid;
    uid_t uid;
531
    bool filecreated = false;
532 533

    if ((pool->def->type == VIR_STORAGE_POOL_NETFS)
534
        && (((getuid() == 0)
P
Philipp Hahn 已提交
535
             && (vol->target.perms.uid != (uid_t) -1)
536
             && (vol->target.perms.uid != 0))
P
Philipp Hahn 已提交
537
            || ((vol->target.perms.gid != (gid_t) -1)
538
                && (vol->target.perms.gid != getgid())))) {
539

540 541
        virCommandSetUID(cmd, vol->target.perms.uid);
        virCommandSetGID(cmd, vol->target.perms.gid);
542 543

        if (virCommandRun(cmd, NULL) == 0) {
544 545
            /* command was successfully run, check if the file was created */
            if (stat(vol->target.path, &st) >=0)
546
                filecreated = true;
547 548
        }
    }
549

550 551 552
    /* don't change uid/gid if we retry */
    virCommandSetUID(cmd, -1);
    virCommandSetGID(cmd, -1);
553

554
    if (!filecreated) {
555
        if (virCommandRun(cmd, NULL) < 0) {
556 557 558
            return -1;
        }
        if (stat(vol->target.path, &st) < 0) {
559
            virReportSystemError(errno,
560
                                 _("failed to create %s"), vol->target.path);
561 562 563 564
            return -1;
        }
    }

P
Philipp Hahn 已提交
565 566 567
    uid = (vol->target.perms.uid != st.st_uid) ? vol->target.perms.uid : (uid_t) -1;
    gid = (vol->target.perms.gid != st.st_gid) ? vol->target.perms.gid : (gid_t) -1;
    if (((uid != (uid_t) -1) || (gid != (gid_t) -1))
568
        && (chown(vol->target.path, uid, gid) < 0)) {
569
        virReportSystemError(errno,
570
                             _("cannot chown %s to (%u, %u)"),
571 572
                             vol->target.path, (unsigned int) uid,
                             (unsigned int) gid);
573 574 575
        return -1;
    }
    if (chmod(vol->target.path, vol->target.perms.mode) < 0) {
576
        virReportSystemError(errno,
577 578 579 580 581 582 583
                             _("cannot set mode of '%s' to %04o"),
                             vol->target.path, vol->target.perms.mode);
        return -1;
    }
    return 0;
}

584 585 586 587 588 589
enum {
    QEMU_IMG_BACKING_FORMAT_NONE = 0,
    QEMU_IMG_BACKING_FORMAT_FLAG,
    QEMU_IMG_BACKING_FORMAT_OPTIONS,
};

590 591
static int
virStorageBackendQEMUImgBackingFormat(const char *qemuimg)
592 593 594 595 596 597
{
    char *help = NULL;
    char *start;
    char *end;
    char *tmp;
    int ret = -1;
598
    int exitstatus;
599
    virCommandPtr cmd = virCommandNewArgList(qemuimg, "-h", NULL);
600

601 602 603
    virCommandAddEnvString(cmd, "LC_ALL=C");
    virCommandSetOutputBuffer(cmd, &help);
    virCommandClearCaps(cmd);
604

605 606 607
    /* qemuimg doesn't return zero exit status on -h,
     * therefore we need to provide pointer for storing
     * exit status, although we don't parse it any later */
608
    if (virCommandRun(cmd, &exitstatus) < 0)
609 610
        goto cleanup;

611 612
    if ((start = strstr(help, " create ")) == NULL ||
        (end = strstr(start, "\n")) == NULL) {
613 614 615
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unable to parse qemu-img output '%s'"),
                       help);
616 617
        goto cleanup;
    }
618 619
    if (((tmp = strstr(start, "-F fmt")) && tmp < end) ||
        ((tmp = strstr(start, "-F backing_fmt")) && tmp < end))
620 621 622 623 624 625 626
        ret = QEMU_IMG_BACKING_FORMAT_FLAG;
    else if ((tmp = strstr(start, "[-o options]")) && tmp < end)
        ret = QEMU_IMG_BACKING_FORMAT_OPTIONS;
    else
        ret = QEMU_IMG_BACKING_FORMAT_NONE;

cleanup:
627
    virCommandFree(cmd);
628 629 630 631
    VIR_FREE(help);
    return ret;
}

632 633 634 635
static int
virStorageBackendCreateQemuImgOpts(char **opts,
                                   const char *backingType,
                                   bool encryption,
636 637 638 639
                                   bool preallocate,
                                   int format,
                                   const char *compat,
                                   virBitmapPtr features)
640 641
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
642 643 644
    bool b;
    int i;

645 646 647 648 649 650 651
    if (backingType)
        virBufferAsprintf(&buf, "backing_fmt=%s,", backingType);
    if (encryption)
        virBufferAddLit(&buf, "encryption=on,");
    if (preallocate)
        virBufferAddLit(&buf, "preallocation=metadata,");

652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678
    if (compat)
        virBufferAsprintf(&buf, "compat=%s,", compat);
    if (features && format == VIR_STORAGE_FILE_QCOW2) {
        for (i = 0; i < VIR_STORAGE_FILE_FEATURE_LAST; i++) {
            ignore_value(virBitmapGetBit(features, i, &b));
            if (b) {
                switch ((enum virStorageFileFeature) i) {
                case VIR_STORAGE_FILE_FEATURE_LAZY_REFCOUNTS:
                    if (STREQ_NULLABLE(compat, "0.10")) {
                        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                                       _("Feature %s not supported with compat"
                                         " level %s"),
                                       virStorageFileFeatureTypeToString(i),
                                       compat);
                        goto error;
                    }
                    break;
                case VIR_STORAGE_FILE_FEATURE_NONE:
                case VIR_STORAGE_FILE_FEATURE_LAST:
                    ;
                }
                virBufferAsprintf(&buf, "%s,",
                                  virStorageFileFeatureTypeToString(i));
            }
        }
    }

679 680
    virBufferTrim(&buf, ",", -1);

681 682
    if (virBufferError(&buf))
        goto no_memory;
683 684 685

    *opts = virBufferContentAndReset(&buf);
    return 0;
686 687 688 689 690 691

no_memory:
    virReportOOMError();
error:
    virBufferFreeAndReset(&buf);
    return -1;
692 693
}

694 695 696 697 698 699 700 701
virCommandPtr
virStorageBackendCreateQemuImgCmd(virConnectPtr conn,
                                  virStoragePoolObjPtr pool,
                                  virStorageVolDefPtr vol,
                                  virStorageVolDefPtr inputvol,
                                  unsigned int flags,
                                  const char *create_tool,
                                  int imgformat)
702
{
703 704
    virCommandPtr cmd = NULL;
    bool do_encryption = (vol->target.encryption != NULL);
705
    unsigned long long int size_arg;
706 707 708 709 710
    bool preallocate = !!(flags & VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA);
    const char *type;
    const char *backingType = NULL;
    const char *inputPath = NULL;
    const char *inputType = NULL;
711 712 713
    char *opts = NULL;
    bool convert = false;
    bool backing = false;
714

715 716
    virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, NULL);

717 718 719 720
    /* Treat output block devices as 'raw' format */
    type = virStorageFileFormatTypeToString(vol->type == VIR_STORAGE_VOL_BLOCK ?
                                            VIR_STORAGE_FILE_RAW :
                                            vol->target.format);
721

722
    if (!type) {
723 724 725
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unknown storage vol type %d"),
                       vol->target.format);
726
        return NULL;
727
    }
728

729 730 731
    if (preallocate && vol->target.format != VIR_STORAGE_FILE_QCOW2) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("metadata preallocation only available with qcow2"));
732
        return NULL;
733
    }
734 735 736 737 738 739 740 741 742 743
    if (vol->target.compat && vol->target.format != VIR_STORAGE_FILE_QCOW2) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("compatibility option only available with qcow2"));
        return NULL;
    }
    if (vol->target.features && vol->target.format != VIR_STORAGE_FILE_QCOW2) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("format features only available with qcow2"));
        return NULL;
    }
744

745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764
    if (inputvol) {
        if (!(inputPath = inputvol->target.path)) {
            virReportError(VIR_ERR_INVALID_ARG, "%s",
                           _("missing input volume target path"));
            return NULL;
        }

        inputType = virStorageFileFormatTypeToString(inputvol->type == VIR_STORAGE_VOL_BLOCK ?
                                                     VIR_STORAGE_FILE_RAW :
                                                     inputvol->target.format);

        if (!inputType) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unknown storage vol type %d"),
                           inputvol->target.format);
            return NULL;
        }

    }

765
    if (vol->backingStore.path) {
766 767
        int accessRetCode = -1;
        char *absolutePath = NULL;
768

769 770
        backingType = virStorageFileFormatTypeToString(vol->backingStore.format);

771 772 773 774
        if (preallocate) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("metadata preallocation conflicts with backing"
                             " store"));
775
            return NULL;
776 777
        }

778 779 780 781 782
        /* XXX: Not strictly required: qemu-img has an option a different
         * backing store, not really sure what use it serves though, and it
         * may cause issues with lvm. Untested essentially.
         */
        if (inputvol &&
783 784 785
            STRNEQ_NULLABLE(inputvol->backingStore.path, vol->backingStore.path)) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("a different backing store cannot be specified."));
786
            return NULL;
787 788 789
        }

        if (backingType == NULL) {
790 791 792
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unknown storage vol backing store type %d"),
                           vol->backingStore.format);
793
            return NULL;
794
        }
795 796 797 798 799 800 801 802

        /* Convert relative backing store paths to absolute paths for access
         * validation.
         */
        if ('/' != *(vol->backingStore.path) &&
            virAsprintf(&absolutePath, "%s/%s", pool->def->target.path,
                        vol->backingStore.path) < 0) {
            virReportOOMError();
803
            return NULL;
804 805 806 807 808
        }
        accessRetCode = access(absolutePath ? absolutePath
                               : vol->backingStore.path, R_OK);
        VIR_FREE(absolutePath);
        if (accessRetCode != 0) {
809
            virReportSystemError(errno,
810 811
                                 _("inaccessible backing store volume %s"),
                                 vol->backingStore.path);
812
            return NULL;
813 814 815
        }
    }

816
    if (do_encryption) {
817 818
        virStorageEncryptionPtr enc;

819 820
        if (vol->target.format != VIR_STORAGE_FILE_QCOW &&
            vol->target.format != VIR_STORAGE_FILE_QCOW2) {
821 822 823
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("qcow volume encryption unsupported with "
                             "volume format %s"), type);
824
            return NULL;
825
        }
826 827 828
        enc = vol->target.encryption;
        if (enc->format != VIR_STORAGE_ENCRYPTION_FORMAT_QCOW &&
            enc->format != VIR_STORAGE_ENCRYPTION_FORMAT_DEFAULT) {
829 830 831
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("unsupported volume encryption format %d"),
                           vol->target.encryption->format);
832
            return NULL;
833
        }
834
        if (enc->nsecrets > 1) {
835 836
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("too many secrets for qcow encryption"));
837
            return NULL;
838
        }
839 840 841
        if (enc->format == VIR_STORAGE_ENCRYPTION_FORMAT_DEFAULT ||
            enc->nsecrets == 0) {
            if (virStorageGenerateQcowEncryption(conn, vol) < 0)
842
                return NULL;
843
        }
844 845
    }

846
    /* Size in KB */
847
    size_arg = VIR_DIV_UP(vol->capacity, 1024);
848

849 850
    cmd = virCommandNew(create_tool);

851 852
    convert = !!inputvol;
    backing = !inputvol && vol->backingStore.path;
853

854 855 856
    if (convert)
        virCommandAddArgList(cmd, "convert", "-f", inputType, "-O", type, NULL);
    else
857
        virCommandAddArgList(cmd, "create", "-f", type, NULL);
858

859 860 861 862 863 864
    if (backing)
        virCommandAddArgList(cmd, "-b", vol->backingStore.path, NULL);

    if (imgformat == QEMU_IMG_BACKING_FORMAT_OPTIONS) {
        if (virStorageBackendCreateQemuImgOpts(&opts,
                                               backing ? backingType : NULL,
865 866 867 868
                                               do_encryption, preallocate,
                                               vol->target.format,
                                               vol->target.compat,
                                               vol->target.features) < 0)
869 870 871 872 873 874 875 876 877 878 879
            return NULL;
        if (opts)
            virCommandAddArgList(cmd, "-o", opts, NULL);
        VIR_FREE(opts);
    } else {
        if (backing) {
            if (imgformat == QEMU_IMG_BACKING_FORMAT_FLAG)
                virCommandAddArgList(cmd, "-F", backingType, NULL);
            else
                VIR_DEBUG("Unable to set backing store format for %s with %s",
                          vol->target.path, create_tool);
880
        }
881 882
        if (do_encryption)
            virCommandAddArg(cmd, "-e");
883
    }
884

885 886 887 888 889 890
    if (convert)
        virCommandAddArg(cmd, inputPath);
    virCommandAddArg(cmd, vol->target.path);
    if (!convert)
        virCommandAddArgFormat(cmd, "%lluK", size_arg);

891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927
    return cmd;
}

static int
virStorageBackendCreateQemuImg(virConnectPtr conn,
                               virStoragePoolObjPtr pool,
                               virStorageVolDefPtr vol,
                               virStorageVolDefPtr inputvol,
                               unsigned int flags)
{
    int ret = -1;
    const char *create_tool;
    int imgformat;
    virCommandPtr cmd;

    virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, -1);

    /* KVM is usually ahead of qemu on features, so try that first */
    create_tool = virFindFileInPath("kvm-img");
    if (!create_tool)
        create_tool = virFindFileInPath("qemu-img");

    if (!create_tool) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("unable to find kvm-img or qemu-img"));
        return -1;
    }

    imgformat = virStorageBackendQEMUImgBackingFormat(create_tool);
    if (imgformat < 0)
        goto cleanup;

    cmd = virStorageBackendCreateQemuImgCmd(conn, pool, vol, inputvol, flags,
                                            create_tool, imgformat);
    if (!cmd)
        goto cleanup;

928
    ret = virStorageBackendCreateExecCommand(pool, vol, cmd);
929 930

    virCommandFree(cmd);
931
cleanup:
932
    VIR_FREE(create_tool);
933
    return ret;
934 935 936 937 938 939 940
}

/*
 * Xen removed the fully-functional qemu-img, and replaced it
 * with a partially functional qcow-create. Go figure ??!?
 */
static int
941
virStorageBackendCreateQcowCreate(virConnectPtr conn ATTRIBUTE_UNUSED,
942
                                  virStoragePoolObjPtr pool,
943
                                  virStorageVolDefPtr vol,
944
                                  virStorageVolDefPtr inputvol,
E
Eric Blake 已提交
945
                                  unsigned int flags)
946
{
947
    int ret;
E
Eric Blake 已提交
948
    char *size;
949
    virCommandPtr cmd;
950

951 952 953 954 955 956 957 958
    virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, -1);

    if (flags & VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("metadata preallocation is not supported with "
                         "qcow-create"));
        return -1;
    }
E
Eric Blake 已提交
959

960
    if (inputvol) {
961 962
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("cannot copy from volume with qcow-create"));
963 964 965
        return -1;
    }

966
    if (vol->target.format != VIR_STORAGE_FILE_QCOW2) {
967 968 969
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unsupported storage vol type %d"),
                       vol->target.format);
970 971 972
        return -1;
    }
    if (vol->backingStore.path != NULL) {
973 974 975
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("copy-on-write image not supported with "
                         "qcow-create"));
976 977
        return -1;
    }
978
    if (vol->target.encryption != NULL) {
979 980 981
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       "%s", _("encrypted volumes not supported with "
                               "qcow-create"));
982 983
        return -1;
    }
984 985

    /* Size in MB - yes different units to qemu-img :-( */
986 987
    if (virAsprintf(&size, "%llu",
                    VIR_DIV_UP(vol->capacity, (1024 * 1024))) < 0) {
E
Eric Blake 已提交
988 989 990
        virReportOOMError();
        return -1;
    }
991

992
    cmd = virCommandNewArgList("qcow-create", size, vol->target.path, NULL);
993

994 995
    ret = virStorageBackendCreateExecCommand(pool, vol, cmd);
    virCommandFree(cmd);
E
Eric Blake 已提交
996
    VIR_FREE(size);
997

998
    return ret;
999 1000
}

1001
virStorageBackendBuildVolFrom
1002
virStorageBackendFSImageToolTypeToFunc(int tool_type)
1003 1004 1005 1006 1007 1008 1009 1010
{
    switch (tool_type) {
    case TOOL_KVM_IMG:
    case TOOL_QEMU_IMG:
        return virStorageBackendCreateQemuImg;
    case TOOL_QCOW_CREATE:
        return virStorageBackendCreateQcowCreate;
    default:
1011 1012 1013
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Unknown file create tool type '%d'."),
                       tool_type);
1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040
    }

    return NULL;
}

int
virStorageBackendFindFSImageTool(char **tool)
{
    int tool_type = -1;
    char *tmp = NULL;

    if ((tmp = virFindFileInPath("kvm-img")) != NULL) {
        tool_type = TOOL_KVM_IMG;
    } else if ((tmp = virFindFileInPath("qemu-img")) != NULL) {
        tool_type = TOOL_QEMU_IMG;
    } else if ((tmp = virFindFileInPath("qcow-create")) != NULL) {
        tool_type = TOOL_QCOW_CREATE;
    }

    if (tool)
        *tool = tmp;
    else
        VIR_FREE(tmp);

    return tool_type;
}

1041
virStorageBackendBuildVolFrom
1042
virStorageBackendGetBuildVolFromFunction(virStorageVolDefPtr vol,
1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053
                                         virStorageVolDefPtr inputvol)
{
    int tool_type;

    if (!inputvol)
        return NULL;

    /* If either volume is a non-raw file vol, we need to use an external
     * tool for converting
     */
    if ((vol->type == VIR_STORAGE_VOL_FILE &&
1054
         vol->target.format != VIR_STORAGE_FILE_RAW) ||
1055
        (inputvol->type == VIR_STORAGE_VOL_FILE &&
1056
         inputvol->target.format != VIR_STORAGE_FILE_RAW)) {
1057

D
Daniel P. Berrange 已提交
1058
        if ((tool_type = virStorageBackendFindFSImageTool(NULL)) < 0) {
1059 1060 1061
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("creation of non-raw file images is "
                             "not supported without qemu-img."));
1062 1063 1064
            return NULL;
        }

1065
        return virStorageBackendFSImageToolTypeToFunc(tool_type);
1066 1067
    }

1068 1069 1070 1071
    if (vol->type == VIR_STORAGE_VOL_BLOCK)
        return virStorageBackendCreateBlockFrom;
    else
        return virStorageBackendCreateRaw;
1072
}
1073

1074

1075
virStorageBackendPtr
1076 1077
virStorageBackendForType(int type)
{
1078
    unsigned int i;
1079
    for (i = 0; backends[i]; i++)
1080 1081 1082
        if (backends[i]->type == type)
            return backends[i];

1083 1084
    virReportError(VIR_ERR_INTERNAL_ERROR,
                   _("missing backend for pool type %d"), type);
1085 1086 1087 1088
    return NULL;
}


1089 1090 1091
/*
 * Allows caller to silently ignore files with improper mode
 *
1092 1093
 * Returns -1 on error, -2 if file mode is unexpected or the
 * volume is a dangling symbolic link.
1094
 */
1095
int
1096
virStorageBackendVolOpenCheckMode(const char *path, unsigned int flags)
1097
{
1098 1099
    int fd, mode = 0;
    struct stat sb;
1100
    char *base = last_component(path);
1101

1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116
    if (lstat(path, &sb) < 0) {
        virReportSystemError(errno,
                             _("cannot stat file '%s'"),
                             path);
        return -1;
    }

    if (S_ISFIFO(sb.st_mode)) {
        VIR_WARN("ignoring FIFO '%s'", path);
        return -2;
    } else if (S_ISSOCK(sb.st_mode)) {
        VIR_WARN("ignoring socket '%s'", path);
        return -2;
    }

1117
    if ((fd = open(path, O_RDONLY|O_NONBLOCK|O_NOCTTY)) < 0) {
1118
        if ((errno == ENOENT || errno == ELOOP) &&
1119
            S_ISLNK(sb.st_mode)) {
1120 1121 1122 1123
            VIR_WARN("ignoring dangling symlink '%s'", path);
            return -2;
        }

1124
        virReportSystemError(errno,
1125
                             _("cannot open volume '%s'"),
1126
                             path);
1127 1128 1129
        return -1;
    }

1130 1131 1132 1133 1134 1135 1136 1137
    if (fstat(fd, &sb) < 0) {
        virReportSystemError(errno,
                             _("cannot stat file '%s'"),
                             path);
        VIR_FORCE_CLOSE(fd);
        return -1;
    }

1138 1139 1140 1141 1142 1143
    if (S_ISREG(sb.st_mode))
        mode = VIR_STORAGE_VOL_OPEN_REG;
    else if (S_ISCHR(sb.st_mode))
        mode = VIR_STORAGE_VOL_OPEN_CHAR;
    else if (S_ISBLK(sb.st_mode))
        mode = VIR_STORAGE_VOL_OPEN_BLOCK;
1144 1145 1146 1147 1148 1149 1150 1151 1152 1153
    else if (S_ISDIR(sb.st_mode)) {
        mode = VIR_STORAGE_VOL_OPEN_DIR;

        if (STREQ(base, ".") ||
            STREQ(base, "..")) {
            VIR_FORCE_CLOSE(fd);
            VIR_INFO("Skipping special dir '%s'", base);
            return -2;
        }
    }
1154 1155

    if (!(mode & flags)) {
1156
        VIR_FORCE_CLOSE(fd);
1157
        VIR_INFO("Skipping volume '%s'", path);
1158 1159

        if (mode & VIR_STORAGE_VOL_OPEN_ERROR) {
1160 1161
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unexpected storage mode for '%s'"), path);
1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179
            return -1;
        }

        return -2;
    }

    return fd;
}

int virStorageBackendVolOpen(const char *path)
{
    return virStorageBackendVolOpenCheckMode(path,
                                             VIR_STORAGE_VOL_OPEN_DEFAULT);
}

int
virStorageBackendUpdateVolTargetInfo(virStorageVolTargetPtr target,
                                     unsigned long long *allocation,
1180 1181
                                     unsigned long long *capacity,
                                     unsigned int openflags)
1182 1183 1184
{
    int ret, fd;

1185 1186
    if ((ret = virStorageBackendVolOpenCheckMode(target->path,
                                                 openflags)) < 0)
1187 1188 1189
        return ret;

    fd = ret;
1190
    ret = virStorageBackendUpdateVolTargetInfoFD(target,
1191 1192 1193
                                                 fd,
                                                 allocation,
                                                 capacity);
1194

1195
    VIR_FORCE_CLOSE(fd);
1196 1197 1198 1199

    return ret;
}

1200
int
1201 1202 1203
virStorageBackendUpdateVolInfoFlags(virStorageVolDefPtr vol,
                                    int withCapacity,
                                    unsigned int openflags)
1204 1205 1206
{
    int ret;

1207
    if ((ret = virStorageBackendUpdateVolTargetInfo(&vol->target,
1208 1209 1210
                                    &vol->allocation,
                                    withCapacity ? &vol->capacity : NULL,
                                    openflags)) < 0)
1211 1212 1213
        return ret;

    if (vol->backingStore.path &&
1214
        (ret = virStorageBackendUpdateVolTargetInfo(&vol->backingStore,
1215 1216
                                            NULL, NULL,
                                            VIR_STORAGE_VOL_OPEN_DEFAULT)) < 0)
1217 1218 1219 1220 1221
        return ret;

    return 0;
}

1222 1223 1224 1225 1226 1227 1228
int virStorageBackendUpdateVolInfo(virStorageVolDefPtr vol,
                                   int withCapacity)
{
    return virStorageBackendUpdateVolInfoFlags(vol, withCapacity,
                                               VIR_STORAGE_VOL_OPEN_DEFAULT);
}

1229 1230 1231 1232
/*
 * virStorageBackendUpdateVolTargetInfoFD:
 * @conn: connection to report errors on
 * @target: target definition ptr of volume to update
1233
 * @fd: fd of storage volume to update, via virStorageBackendOpenVol*
1234 1235 1236
 * @allocation: If not NULL, updated allocation information will be stored
 * @capacity: If not NULL, updated capacity info will be stored
 *
1237
 * Returns 0 for success, -1 on a legitimate error condition.
1238
 */
1239
int
1240
virStorageBackendUpdateVolTargetInfoFD(virStorageVolTargetPtr target,
1241 1242 1243
                                       int fd,
                                       unsigned long long *allocation,
                                       unsigned long long *capacity)
1244 1245
{
    struct stat sb;
1246
#if WITH_SELINUX
1247 1248 1249 1250
    security_context_t filecon = NULL;
#endif

    if (fstat(fd, &sb) < 0) {
1251
        virReportSystemError(errno,
1252
                             _("cannot stat file '%s'"),
1253
                             target->path);
1254 1255 1256
        return -1;
    }

1257 1258
    if (allocation) {
        if (S_ISREG(sb.st_mode)) {
1259
#ifndef WIN32
1260
            *allocation = (unsigned long long)sb.st_blocks *
1261
                          (unsigned long long)DEV_BSIZE;
D
Daniel P. Berrange 已提交
1262
#else
1263
            *allocation = sb.st_size;
D
Daniel P. Berrange 已提交
1264
#endif
1265 1266 1267 1268 1269
            /* Regular files may be sparse, so logical size (capacity) is not same
             * as actual allocation above
             */
            if (capacity)
                *capacity = sb.st_size;
1270 1271 1272 1273 1274
        } else if (S_ISDIR(sb.st_mode)) {
            *allocation = 0;
            if (capacity)
                *capacity = 0;

1275 1276
        } else {
            off_t end;
E
Eric Blake 已提交
1277
            /* XXX this is POSIX compliant, but doesn't work for CHAR files,
1278 1279 1280 1281 1282 1283
             * only BLOCK. There is a Linux specific ioctl() for getting
             * size of both CHAR / BLOCK devices we should check for in
             * configure
             */
            end = lseek(fd, 0, SEEK_END);
            if (end == (off_t)-1) {
1284
                virReportSystemError(errno,
1285 1286 1287 1288 1289 1290 1291
                                     _("cannot seek to end of file '%s'"),
                                     target->path);
                return -1;
            }
            *allocation = end;
            if (capacity)
                *capacity = end;
1292 1293 1294
        }
    }

1295 1296 1297
    target->perms.mode = sb.st_mode & S_IRWXUGO;
    target->perms.uid = sb.st_uid;
    target->perms.gid = sb.st_gid;
1298

1299 1300 1301 1302 1303 1304 1305 1306 1307
    if (!target->timestamps && VIR_ALLOC(target->timestamps) < 0) {
        virReportOOMError();
        return -1;
    }
    target->timestamps->atime = get_stat_atime(&sb);
    target->timestamps->btime = get_stat_birthtime(&sb);
    target->timestamps->ctime = get_stat_ctime(&sb);
    target->timestamps->mtime = get_stat_mtime(&sb);

1308
    VIR_FREE(target->perms.label);
1309

1310
#if WITH_SELINUX
1311
    /* XXX: make this a security driver call */
M
Martin Kletzander 已提交
1312
    if (fgetfilecon_raw(fd, &filecon) == -1) {
1313
        if (errno != ENODATA && errno != ENOTSUP) {
1314
            virReportSystemError(errno,
1315
                                 _("cannot get file context of '%s'"),
1316
                                 target->path);
1317 1318
            return -1;
        } else {
1319
            target->perms.label = NULL;
1320 1321
        }
    } else {
1322 1323
        if (VIR_STRDUP(target->perms.label, filecon) < 0) {
            freecon(filecon);
1324 1325
            return -1;
        }
1326
        freecon(filecon);
1327 1328
    }
#else
1329
    target->perms.label = NULL;
1330 1331 1332 1333 1334
#endif

    return 0;
}

D
Dave Allan 已提交
1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369

struct diskType {
    int part_table_type;
    unsigned short offset;
    unsigned short length;
    unsigned long long magic;
};


static struct diskType const disk_types[] = {
    { VIR_STORAGE_POOL_DISK_LVM2, 0x218, 8, 0x31303020324D564CULL },
    { VIR_STORAGE_POOL_DISK_GPT,  0x200, 8, 0x5452415020494645ULL },
    { VIR_STORAGE_POOL_DISK_DVH,  0x0,   4, 0x41A9E50BULL },
    { VIR_STORAGE_POOL_DISK_MAC,  0x0,   2, 0x5245ULL },
    { VIR_STORAGE_POOL_DISK_BSD,  0x40,  4, 0x82564557ULL },
    { VIR_STORAGE_POOL_DISK_SUN,  0x1fc, 2, 0xBEDAULL },
    /*
     * NOTE: pc98 is funky; the actual signature is 0x55AA (just like dos), so
     * we can't use that.  At the moment I'm relying on the "dummy" IPL
     * bootloader data that comes from parted.  Luckily, the chances of running
     * into a pc98 machine running libvirt are approximately nil.
     */
    /*{ 0x1fe, 2, 0xAA55UL },*/
    { VIR_STORAGE_POOL_DISK_PC98, 0x0,   8, 0x314C5049000000CBULL },
    /*
     * NOTE: the order is important here; some other disk types (like GPT and
     * and PC98) also have 0x55AA at this offset.  For that reason, the DOS
     * one must be the last one.
     */
    { VIR_STORAGE_POOL_DISK_DOS,  0x1fe, 2, 0xAA55ULL },
    { -1,                         0x0,   0, 0x0ULL },
};


int
1370 1371
virStorageBackendDetectBlockVolFormatFD(virStorageVolTargetPtr target,
                                        int fd)
D
Dave Allan 已提交
1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382
{
    int i;
    off_t start;
    unsigned char buffer[1024];
    ssize_t bytes;

    /* make sure to set the target format "unknown" to begin with */
    target->format = VIR_STORAGE_POOL_DISK_UNKNOWN;

    start = lseek(fd, 0, SEEK_SET);
    if (start < 0) {
1383
        virReportSystemError(errno,
D
Dave Allan 已提交
1384 1385 1386 1387 1388 1389
                             _("cannot seek to beginning of file '%s'"),
                             target->path);
        return -1;
    }
    bytes = saferead(fd, buffer, sizeof(buffer));
    if (bytes < 0) {
1390
        virReportSystemError(errno,
D
Dave Allan 已提交
1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409
                             _("cannot read beginning of file '%s'"),
                             target->path);
        return -1;
    }

    for (i = 0; disk_types[i].part_table_type != -1; i++) {
        if (disk_types[i].offset + disk_types[i].length > bytes)
            continue;
        if (memcmp(buffer+disk_types[i].offset, &disk_types[i].magic,
            disk_types[i].length) == 0) {
            target->format = disk_types[i].part_table_type;
            break;
        }
    }

    return 0;
}


1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421
/*
 * Given a volume path directly in /dev/XXX, iterate over the
 * entries in the directory pool->def->target.path and find the
 * first symlink pointing to the volume path.
 *
 * If, the target.path is /dev/, then return the original volume
 * path.
 *
 * If no symlink is found, then return the original volume path
 *
 * Typically target.path is one of the /dev/disk/by-XXX dirs
 * with stable paths.
1422
 *
1423
 * If 'loop' is true, we use a timeout loop to give dynamic paths
1424
 * a change to appear.
1425 1426
 */
char *
1427
virStorageBackendStablePath(virStoragePoolObjPtr pool,
1428
                            const char *devpath,
1429
                            bool loop)
1430 1431 1432
{
    DIR *dh;
    struct dirent *dent;
1433
    char *stablepath;
1434
    int opentries = 0;
1435
    int retry = 0;
1436 1437 1438 1439 1440

    /* Short circuit if pool has no target, or if its /dev */
    if (pool->def->target.path == NULL ||
        STREQ(pool->def->target.path, "/dev") ||
        STREQ(pool->def->target.path, "/dev/"))
1441
        goto ret_strdup;
1442

1443
    /* Skip whole thing for a pool which isn't in /dev
1444
     * so we don't mess filesystem/dir based pools
1445 1446 1447 1448
     */
    if (!STRPREFIX(pool->def->target.path, "/dev"))
        goto ret_strdup;

1449 1450 1451 1452
    /* Logical pools are under /dev but already have stable paths */
    if (pool->def->type == VIR_STORAGE_POOL_LOGICAL)
        goto ret_strdup;

1453 1454 1455
    /* We loop here because /dev/disk/by-{id,path} may not have existed
     * before we started this operation, so we have to give it some time to
     * get created.
1456
     */
1457
 reopen:
1458
    if ((dh = opendir(pool->def->target.path)) == NULL) {
1459
        opentries++;
1460
        if (loop && errno == ENOENT && opentries < 50) {
1461 1462 1463
            usleep(100 * 1000);
            goto reopen;
        }
1464
        virReportSystemError(errno,
1465 1466
                             _("cannot read dir '%s'"),
                             pool->def->target.path);
1467 1468 1469
        return NULL;
    }

1470 1471 1472
    /* The pool is pointing somewhere like /dev/disk/by-path
     * or /dev/disk/by-id, so we need to check all symlinks in
     * the target directory and figure out which one points
1473 1474
     * to this device node.
     *
1475
     * And it might need some time till the stable path shows
1476
     * up, so add timeout to retry here.
1477
     */
1478
 retry:
1479 1480 1481 1482
    while ((dent = readdir(dh)) != NULL) {
        if (dent->d_name[0] == '.')
            continue;

1483 1484 1485
        if (virAsprintf(&stablepath, "%s/%s",
                        pool->def->target.path,
                        dent->d_name) == -1) {
1486
            virReportOOMError();
1487 1488 1489 1490 1491 1492 1493 1494 1495
            closedir(dh);
            return NULL;
        }

        if (virFileLinkPointsTo(stablepath, devpath)) {
            closedir(dh);
            return stablepath;
        }

1496
        VIR_FREE(stablepath);
1497 1498
    }

1499
    if (loop && ++retry < 100) {
1500 1501 1502 1503
        usleep(100 * 1000);
        goto retry;
    }

1504 1505
    closedir(dh);

1506
 ret_strdup:
1507 1508 1509
    /* Couldn't find any matching stable link so give back
     * the original non-stable dev path
     */
1510

1511
    ignore_value(VIR_STRDUP(stablepath, devpath));
1512 1513

    return stablepath;
1514 1515
}

D
Daniel P. Berrange 已提交
1516

1517
#ifndef WIN32
1518 1519 1520 1521
/*
 * Run an external program.
 *
 * Read its output and apply a series of regexes to each line
R
Richard W.M. Jones 已提交
1522
 * When the entire set of regexes has matched consecutively
1523 1524 1525
 * then run a callback passing in all the matches
 */
int
1526
virStorageBackendRunProgRegex(virStoragePoolObjPtr pool,
1527
                              virCommandPtr cmd,
1528 1529 1530 1531
                              int nregex,
                              const char **regex,
                              int *nvars,
                              virStorageBackendListVolRegexFunc func,
1532
                              void *data, const char *prefix)
1533
{
1534
    int fd = -1, err, ret = -1;
1535 1536 1537 1538 1539 1540 1541 1542 1543
    FILE *list = NULL;
    regex_t *reg;
    regmatch_t *vars = NULL;
    char line[1024];
    int maxReg = 0, i, j;
    int totgroups = 0, ngroup = 0, maxvars = 0;
    char **groups;

    /* Compile all regular expressions */
1544
    if (VIR_ALLOC_N(reg, nregex) < 0) {
1545
        virReportOOMError();
1546 1547 1548
        return -1;
    }

1549
    for (i = 0; i < nregex; i++) {
1550 1551 1552 1553
        err = regcomp(&reg[i], regex[i], REG_EXTENDED);
        if (err != 0) {
            char error[100];
            regerror(err, &reg[i], error, sizeof(error));
1554 1555
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to compile regex %s"), error);
1556
            for (j = 0; j <= i; j++)
1557
                regfree(&reg[j]);
1558
            VIR_FREE(reg);
1559 1560 1561 1562 1563 1564 1565 1566 1567 1568
            return -1;
        }

        totgroups += nvars[i];
        if (nvars[i] > maxvars)
            maxvars = nvars[i];

    }

    /* Storage for matched variables */
1569
    if (VIR_ALLOC_N(groups, totgroups) < 0) {
1570
        virReportOOMError();
1571 1572
        goto cleanup;
    }
1573
    if (VIR_ALLOC_N(vars, maxvars+1) < 0) {
1574
        virReportOOMError();
1575 1576 1577
        goto cleanup;
    }

1578 1579
    virCommandSetOutputFD(cmd, &fd);
    if (virCommandRunAsync(cmd, NULL) < 0) {
1580 1581 1582
        goto cleanup;
    }

1583
    if ((list = VIR_FDOPEN(fd, "r")) == NULL) {
1584 1585
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("cannot read fd"));
1586 1587 1588 1589
        goto cleanup;
    }

    while (fgets(line, sizeof(line), list) != NULL) {
1590
        char *p = NULL;
1591 1592 1593 1594 1595
        /* Strip trailing newline */
        int len = strlen(line);
        if (len && line[len-1] == '\n')
            line[len-1] = '\0';

1596 1597 1598 1599 1600 1601
        /* ignore any command prefix */
        if (prefix)
            p = STRSKIP(line, prefix);
        if (!p)
            p = line;

1602
        for (i = 0; i <= maxReg && i < nregex; i++) {
1603
            if (regexec(&reg[i], p, nvars[i]+1, vars, 0) == 0) {
1604 1605 1606 1607 1608 1609
                maxReg++;

                if (i == 0)
                    ngroup = 0;

                /* NULL terminate each captured group in the line */
1610
                for (j = 0; j < nvars[i]; j++) {
1611
                    /* NB vars[0] is the full pattern, so we offset j by 1 */
1612
                    p[vars[j+1].rm_eo] = '\0';
1613
                    if (VIR_STRDUP(groups[ngroup++], p + vars[j+1].rm_so) < 0)
1614 1615 1616 1617 1618
                        goto cleanup;
                }

                /* We're matching on the last regex, so callback time */
                if (i == (nregex-1)) {
1619
                    if (((*func)(pool, groups, data)) < 0)
1620 1621 1622
                        goto cleanup;

                    /* Release matches & restart to matching the first regex */
1623
                    for (j = 0; j < totgroups; j++)
1624
                        VIR_FREE(groups[j]);
1625 1626 1627 1628 1629 1630 1631
                    maxReg = 0;
                    ngroup = 0;
                }
            }
        }
    }

1632
    ret = virCommandWait(cmd, NULL);
1633
cleanup:
1634
    if (groups) {
1635
        for (j = 0; j < totgroups; j++)
1636 1637
            VIR_FREE(groups[j]);
        VIR_FREE(groups);
1638
    }
1639
    VIR_FREE(vars);
1640

1641
    for (i = 0; i < nregex; i++)
1642 1643
        regfree(&reg[i]);

1644
    VIR_FREE(reg);
1645

1646 1647
    VIR_FORCE_FCLOSE(list);
    VIR_FORCE_CLOSE(fd);
1648

1649
    return ret;
1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663
}

/*
 * Run an external program and read from its standard output
 * a stream of tokens from IN_STREAM, applying FUNC to
 * each successive sequence of N_COLUMNS tokens.
 * If FUNC returns < 0, stop processing input and return -1.
 * Return -1 if N_COLUMNS == 0.
 * Return -1 upon memory allocation error.
 * If the number of input tokens is not a multiple of N_COLUMNS,
 * then the final FUNC call will specify a number smaller than N_COLUMNS.
 * If there are no input tokens (empty input), call FUNC with N_COLUMNS == 0.
 */
int
1664
virStorageBackendRunProgNul(virStoragePoolObjPtr pool,
1665
                            virCommandPtr cmd,
1666 1667 1668 1669 1670
                            size_t n_columns,
                            virStorageBackendListVolNulFunc func,
                            void *data)
{
    size_t n_tok = 0;
1671
    int fd = -1;
1672 1673
    FILE *fp = NULL;
    char **v;
1674
    int ret = -1;
1675 1676 1677 1678 1679
    int i;

    if (n_columns == 0)
        return -1;

1680
    if (VIR_ALLOC_N(v, n_columns) < 0) {
1681
        virReportOOMError();
1682 1683 1684 1685 1686
        return -1;
    }
    for (i = 0; i < n_columns; i++)
        v[i] = NULL;

1687 1688
    virCommandSetOutputFD(cmd, &fd);
    if (virCommandRunAsync(cmd, NULL) < 0) {
1689 1690 1691
        goto cleanup;
    }

1692
    if ((fp = VIR_FDOPEN(fd, "r")) == NULL) {
1693 1694
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("cannot open file using fd"));
1695 1696 1697 1698 1699 1700 1701 1702
        goto cleanup;
    }

    while (1) {
        char *buf = NULL;
        size_t buf_len = 0;
        /* Be careful: even when it returns -1,
           this use of getdelim allocates memory.  */
1703
        ssize_t tok_len = getdelim(&buf, &buf_len, 0, fp);
1704 1705 1706 1707
        v[n_tok] = buf;
        if (tok_len < 0) {
            /* Maybe EOF, maybe an error.
               If n_tok > 0, then we know it's an error.  */
1708
            if (n_tok && func(pool, n_tok, v, data) < 0)
1709 1710 1711 1712 1713
                goto cleanup;
            break;
        }
        ++n_tok;
        if (n_tok == n_columns) {
1714
            if (func(pool, n_tok, v, data) < 0)
1715 1716 1717
                goto cleanup;
            n_tok = 0;
            for (i = 0; i < n_columns; i++) {
1718
                VIR_FREE(v[i]);
1719 1720 1721 1722
            }
        }
    }

1723 1724 1725
    if (feof(fp) < 0) {
        virReportSystemError(errno, "%s",
                             _("read error on pipe"));
1726 1727
        goto cleanup;
    }
1728

1729
    ret = virCommandWait(cmd, NULL);
1730 1731
 cleanup:
    for (i = 0; i < n_columns; i++)
1732 1733
        VIR_FREE(v[i]);
    VIR_FREE(v);
1734

1735 1736
    VIR_FORCE_FCLOSE(fp);
    VIR_FORCE_CLOSE(fd);
1737

1738
    return ret;
1739
}
D
Daniel P. Berrange 已提交
1740

1741
#else /* WIN32 */
D
Daniel P. Berrange 已提交
1742 1743 1744 1745 1746 1747 1748 1749 1750

int
virStorageBackendRunProgRegex(virConnectPtr conn,
                              virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
                              const char *const*prog ATTRIBUTE_UNUSED,
                              int nregex ATTRIBUTE_UNUSED,
                              const char **regex ATTRIBUTE_UNUSED,
                              int *nvars ATTRIBUTE_UNUSED,
                              virStorageBackendListVolRegexFunc func ATTRIBUTE_UNUSED,
1751
                              void *data ATTRIBUTE_UNUSED)
D
Daniel P. Berrange 已提交
1752
{
1753 1754
    virReportError(VIR_ERR_INTERNAL_ERROR,
                   _("%s not implemented on Win32"), __FUNCTION__);
D
Daniel P. Berrange 已提交
1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765
    return -1;
}

int
virStorageBackendRunProgNul(virConnectPtr conn,
                            virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
                            const char **prog ATTRIBUTE_UNUSED,
                            size_t n_columns ATTRIBUTE_UNUSED,
                            virStorageBackendListVolNulFunc func ATTRIBUTE_UNUSED,
                            void *data ATTRIBUTE_UNUSED)
{
1766 1767
    virReportError(VIR_ERR_INTERNAL_ERROR,
                   _("%s not implemented on Win32"), __FUNCTION__);
D
Daniel P. Berrange 已提交
1768 1769
    return -1;
}
1770
#endif /* WIN32 */