From nobody Thu May 16 01:02:08 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) client-ip=216.205.24.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1607961375; cv=none; d=zohomail.com; s=zohoarc; b=feJyVAw30xUqB8mzF7aW1PBckEUUsVssQuZaFZNUEYelEbkXeSAv2Q2jjIHLw5bdg229i4Et0PGZ7Nkmshs4bTmWeifPsPKehsjcLTTttezFmgdUNC43TJXF3l8A626rEBJmHVE+Y+T4p357ICgOflly1kaCmsHNg/Do+kDzUCo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1607961375; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=RaPMPzkry3kAg5Me7gf0Ezi4HSr54Gr4FtfebKV5s/w=; b=Fc7v3kKRVyxPcLEyxdtSSWRKisiB56buBnoOhC3znzWlriJbwabKLIZX/N8P4YjYO3h9x9Z921oUchJnnzkDH3dBlidR6NVZGHa11ZSQItplSyVBnaPGrR4jngpejibo6qkMoITgCyNUugJWx4gY22TlL0ntzB+0Lm4DzItimvE= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by mx.zohomail.com with SMTPS id 1607961375865902.9638405035118; Mon, 14 Dec 2020 07:56:15 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-491-QZGs1-_1PnWKDu2tWgBuxQ-1; Mon, 14 Dec 2020 10:56:11 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id C3ABC1005513; Mon, 14 Dec 2020 15:56:04 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 9EF0C36FA; Mon, 14 Dec 2020 15:56:04 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 526101809CA6; Mon, 14 Dec 2020 15:56:04 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 0BEFtieb028494 for ; Mon, 14 Dec 2020 10:55:44 -0500 Received: by smtp.corp.redhat.com (Postfix) id 393FB17B77; Mon, 14 Dec 2020 15:55:44 +0000 (UTC) Received: from antique-work.lan (unknown [10.40.194.243]) by smtp.corp.redhat.com (Postfix) with ESMTP id A95915D6D5 for ; Mon, 14 Dec 2020 15:55:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1607961373; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=RaPMPzkry3kAg5Me7gf0Ezi4HSr54Gr4FtfebKV5s/w=; b=S9enPArsuv50kvN+dS7YL7gZC2Xqz930SFkc2ah67+7fJwYSTCuOtr7QK3aHdPYE/Sd8JE QJVPOYe0aJAaGMmXLwiV0fixoFy58xOI+syuUl6q8EXhbQlNvdCM3q2CJVVbmhSci2y3dk L4wSd0EieFOGCYHZeFwXdOGSyp3yc74= X-MC-Unique: QZGs1-_1PnWKDu2tWgBuxQ-1 From: Pavel Hrdina To: libvir-list@redhat.com Subject: [libvirt PATCH 01/17] util: remove unused virStorageGenerateQcowPassphrase Date: Mon, 14 Dec 2020 16:55:21 +0100 Message-Id: In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-loop: libvir-list@redhat.com X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=libvir-list-bounces@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" The last user was removed by commit <40f0e0348dfc84f28a500e262c4953b0d3b44fa0>. Signed-off-by: Pavel Hrdina Reviewed-by: Peter Krempa --- src/libvirt_private.syms | 1 - src/util/virstorageencryption.c | 34 --------------------------------- src/util/virstorageencryption.h | 2 -- 3 files changed, 37 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index d0e548b0a3..8e1d101a97 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -3117,7 +3117,6 @@ virSocketAddrSetPort; virStorageEncryptionFormat; virStorageEncryptionFree; virStorageEncryptionParseNode; -virStorageGenerateQcowPassphrase; =20 =20 # util/virstoragefile.h diff --git a/src/util/virstorageencryption.c b/src/util/virstorageencryptio= n.c index a330b79637..c893f0babe 100644 --- a/src/util/virstorageencryption.c +++ b/src/util/virstorageencryption.c @@ -364,37 +364,3 @@ virStorageEncryptionFormat(virBufferPtr buf, =20 return 0; } - -int -virStorageGenerateQcowPassphrase(unsigned char *dest) -{ - int fd; - size_t i; - - /* A qcow passphrase is up to 16 bytes, with any data following a NUL - ignored. Prohibit control and non-ASCII characters to avoid possib= le - unpleasant surprises with the qemu monitor input mechanism. */ - fd =3D open("/dev/urandom", O_RDONLY); - if (fd < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Cannot open /dev/urandom")); - return -1; - } - i =3D 0; - while (i < VIR_STORAGE_QCOW_PASSPHRASE_SIZE) { - ssize_t r; - - while ((r =3D read(fd, dest + i, 1)) =3D=3D -1 && errno =3D=3D EIN= TR) - ; - if (r <=3D 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Cannot read from /dev/urandom")); - VIR_FORCE_CLOSE(fd); - return -1; - } - if (dest[i] >=3D 0x20 && dest[i] <=3D 0x7E) - i++; /* Got an acceptable character */ - } - VIR_FORCE_CLOSE(fd); - return 0; -} diff --git a/src/util/virstorageencryption.h b/src/util/virstorageencryptio= n.h index 05a7bffdfc..352dd373d6 100644 --- a/src/util/virstorageencryption.h +++ b/src/util/virstorageencryption.h @@ -90,5 +90,3 @@ int virStorageEncryptionFormat(virBufferPtr buf, enum { VIR_STORAGE_QCOW_PASSPHRASE_SIZE =3D 16 }; - -int virStorageGenerateQcowPassphrase(unsigned char *dest); --=20 2.28.0 From nobody Thu May 16 01:02:08 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) client-ip=216.205.24.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1607961381; cv=none; d=zohomail.com; s=zohoarc; b=HznjdpH+xXtAhOMWF3NwcGvi/ckZtFxUTBC8QObPMgwRMOL8R6uBhZsPH3Q00QWwkwAcoET1bqVIOGkglY8VSzQfvvbw1vpAosstmmbY5KmnbiEO445mV+68kBUtilLUUEYS4svBB/OZUAyZrZtftLLb1BM6jiuQ6RYhP55KSVQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1607961381; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=OX0M3r8uUOSsfxrSejV2zdkfhgYx/jslB7OwP4gZ6pU=; b=iey7g6ssicfTowKma+Vpt1TcqpiK6X/UbKpsP9GKy0r5dbe4+G+W2gOt8dULMd539ZfODbk2OGjrsAM0KjQTXk9Q2BWCzmSFIcd1rfmaCNvaPXb19YJrl1TtwtFd0qiOig+RflZll3Dvf5Oy+21g0q2ziENqF2x39fsR9bqrdCQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by mx.zohomail.com with SMTPS id 1607961380979571.117492124453; Mon, 14 Dec 2020 07:56:20 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-5-EgqzLOluONyyuaIFfMugOw-1; Mon, 14 Dec 2020 10:56:14 -0500 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id CF3848015F5; Mon, 14 Dec 2020 15:56:07 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id A5F5E5D6D5; Mon, 14 Dec 2020 15:56:07 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 6CF705002F; Mon, 14 Dec 2020 15:56:07 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 0BEFtjoD028505 for ; Mon, 14 Dec 2020 10:55:45 -0500 Received: by smtp.corp.redhat.com (Postfix) id 1D31D5D6D5; Mon, 14 Dec 2020 15:55:45 +0000 (UTC) Received: from antique-work.lan (unknown [10.40.194.243]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8D1E162467 for ; Mon, 14 Dec 2020 15:55:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1607961377; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=OX0M3r8uUOSsfxrSejV2zdkfhgYx/jslB7OwP4gZ6pU=; b=AVgye1bG9bBKA8ySrJGWbH8f/MUiqSIDtNLp/XoDzrzTdHDbgyHdZYEpAj5inwFwLlZ5s3 W8jWl8iQeq5OjEJ+Nk9KkrcXHCA855WIZorlB0sciZa9xNXVLSmdTiIj2jfVz9n4v5mv9E Wmg2aT84jYvgEbTEwuIPTLN3Oltpaqo= X-MC-Unique: EgqzLOluONyyuaIFfMugOw-1 From: Pavel Hrdina To: libvir-list@redhat.com Subject: [libvirt PATCH 02/17] virstoragefile: remove unused virStorageFileChainCheckBroken Date: Mon, 14 Dec 2020 16:55:22 +0100 Message-Id: <74705fad75ce31cf5dcf513600e609d5e14a75c7.1607960951.git.phrdina@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-loop: libvir-list@redhat.com X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=libvir-list-bounces@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" The last usage outside of tests was removed by commit <780f8c94ca8b3dee7eb59c1bfbc32f672f965df8>. Signed-off-by: Pavel Hrdina Reviewed-by: Peter Krempa --- src/libvirt_private.syms | 1 - src/util/virstoragefile.c | 33 --------------------------------- src/util/virstoragefile.h | 3 --- tests/virstoragetest.c | 6 ------ 4 files changed, 43 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 8e1d101a97..8f55ba515c 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -3126,7 +3126,6 @@ virStorageAuthDefFree; virStorageAuthDefParse; virStorageFileAccess; virStorageFileCanonicalizePath; -virStorageFileChainGetBroken; virStorageFileChainLookup; virStorageFileChown; virStorageFileCreate; diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c index fac93118fd..119342d296 100644 --- a/src/util/virstoragefile.c +++ b/src/util/virstoragefile.c @@ -1193,39 +1193,6 @@ virStorageFileGetMetadataFromFD(const char *path, } =20 =20 -/** - * virStorageFileChainCheckBroken - * - * If CHAIN is broken, set *brokenFile to the broken file name, - * otherwise set it to NULL. Caller MUST free *brokenFile after use. - * Return 0 on success (including when brokenFile is set), negative on - * error (allocation failure). - */ -int -virStorageFileChainGetBroken(virStorageSourcePtr chain, - char **brokenFile) -{ - virStorageSourcePtr tmp; - - *brokenFile =3D NULL; - - if (!chain) - return 0; - - for (tmp =3D chain; virStorageSourceIsBacking(tmp); tmp =3D tmp->backi= ngStore) { - /* Break when we hit end of chain; report error if we detected - * a missing backing file, infinite loop, or other error */ - if (!tmp->backingStore && tmp->backingStoreRaw) { - *brokenFile =3D g_strdup(tmp->backingStoreRaw); - - return 0; - } - } - - return 0; -} - - /** * virStorageFileResize: * diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h index 87763cf389..cc9bd4875f 100644 --- a/src/util/virstoragefile.h +++ b/src/util/virstoragefile.h @@ -403,9 +403,6 @@ virStorageSourcePtr virStorageFileGetMetadataFromBuf(co= nst char *path, size_t len, int format) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); -int virStorageFileChainGetBroken(virStorageSourcePtr chain, - char **broken_file); - int virStorageFileParseChainIndex(const char *diskTarget, const char *name, unsigned int *chainIndex) diff --git a/tests/virstoragetest.c b/tests/virstoragetest.c index 2e466ecb99..a376154def 100644 --- a/tests/virstoragetest.c +++ b/tests/virstoragetest.c @@ -270,7 +270,6 @@ testStorageChain(const void *args) virStorageSourcePtr elt; size_t i =3D 0; g_autoptr(virStorageSource) meta =3D NULL; - g_autofree char *broken =3D NULL; =20 meta =3D testStorageFileGetMetadata(data->start, data->format, -1, -1); if (!meta) { @@ -289,11 +288,6 @@ testStorageChain(const void *args) return -1; } =20 - if (virStorageFileChainGetBroken(meta, &broken) || broken) { - fprintf(stderr, "chain should not be identified as broken\n"); - return -1; - } - elt =3D meta; while (virStorageSourceIsBacking(elt)) { g_autofree char *expect =3D NULL; --=20 2.28.0 From nobody Thu May 16 01:02:08 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 63.128.21.124 as permitted sender) client-ip=63.128.21.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 63.128.21.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1607961363; cv=none; d=zohomail.com; s=zohoarc; b=fH6auwNPezuaBDeJ8brVPz9QDrGXnsmJyMuGCVNgCRkzHQ4kBE6DaXBBdkQ0Rk+THiFybNtsJp2fnTOV2FpP2y/Gj0Heqp1EeLHuGmNlUG9PzRg8WObp4uudJQyw+arms5AjFdC2DbDBpi+Zwsf/pKKch3iTFfHkUy7jBzec8/0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1607961363; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=IWdc43Vca2QkJqPIggv5mKafD9sn67SbHEgceiBakzY=; b=LXzn7nitlTmBckHbOo/4MBXl/Z29C7diCJEfENxS8DnMpheXKr4VEnD+nUwseAJCKPsegrWACdpmowqfMKOeh7o/rM1YHRJz1NEWA30rKW5x9nREYdx5ppEnCV5ehv/iWZipskFNC/dJ9B3sVLioAsj8lBbusaLPH1WuD2OHJgg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 63.128.21.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [63.128.21.124]) by mx.zohomail.com with SMTPS id 1607961363305938.3471182096691; Mon, 14 Dec 2020 07:56:03 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-292-_PYEn4imN3aOg7IUdWDpWg-1; Mon, 14 Dec 2020 10:55:58 -0500 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 8A98C1936B75; Mon, 14 Dec 2020 15:55:53 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 68ED77047D; Mon, 14 Dec 2020 15:55:53 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 22A7E4E58F; Mon, 14 Dec 2020 15:55:53 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 0BEFtkDW028512 for ; Mon, 14 Dec 2020 10:55:46 -0500 Received: by smtp.corp.redhat.com (Postfix) id 0382662680; Mon, 14 Dec 2020 15:55:46 +0000 (UTC) Received: from antique-work.lan (unknown [10.40.194.243]) by smtp.corp.redhat.com (Postfix) with ESMTP id 735AE62467 for ; Mon, 14 Dec 2020 15:55:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1607961362; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=IWdc43Vca2QkJqPIggv5mKafD9sn67SbHEgceiBakzY=; b=Jg/s3vmqUJ8bsTBuCW9NF3OtnLpSZCbZPWq8H8Vh+URAFfqtoQY0VLB86PCktVx+F7WeP1 LaCwpd0SdGK39mZjQUq13xCtP9Q4aEOonpfjGtajacuvWVkCnnsZsPuoeIEC4xpNn5EPbY GCh7W/z6Yy1I3R0ZddiSlM9pSWnw3hE= X-MC-Unique: _PYEn4imN3aOg7IUdWDpWg-1 From: Pavel Hrdina To: libvir-list@redhat.com Subject: [libvirt PATCH 03/17] util: move virQEMUBuildQemuImgKeySecretOpts into storage Date: Mon, 14 Dec 2020 16:55:23 +0100 Message-Id: In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-loop: libvir-list@redhat.com X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=libvir-list-bounces@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" Function virQEMUBuildQemuImgKeySecretOpts is not used anywhere else so there is no need to have it in util. Signed-off-by: Pavel Hrdina Reviewed-by: Peter Krempa --- src/libvirt_private.syms | 1 - src/storage/storage_util.c | 74 ++++++++++++++++++++++++++++++++++++-- src/util/virqemu.c | 69 ----------------------------------- src/util/virqemu.h | 6 ---- 4 files changed, 72 insertions(+), 78 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 8f55ba515c..aecc5cd654 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2953,7 +2953,6 @@ virQEMUBuildCommandLineJSONArrayNumbered; virQEMUBuildDriveCommandlineFromJSON; virQEMUBuildNetdevCommandlineFromJSON; virQEMUBuildObjectCommandlineFromJSON; -virQEMUBuildQemuImgKeySecretOpts; =20 =20 # util/virrandom.h diff --git a/src/storage/storage_util.c b/src/storage/storage_util.c index cf1f33f177..9b9f8b4f13 100644 --- a/src/storage/storage_util.c +++ b/src/storage/storage_util.c @@ -693,6 +693,74 @@ struct _virStorageBackendQemuImgInfo { }; =20 =20 +/** + * storageBackendBuildQemuImgEncriptionOpts: + * @buf: buffer to build the string into + * @encinfo: pointer to encryption info + * @alias: alias to use + * + * Generate the string for id=3D$alias and any encryption options for + * into the buffer. + * + * Important note, a trailing comma (",") is built into the return since + * it's expected other arguments are appended after the id=3D$alias string. + * So either turn something like: + * + * "key-secret=3D$alias," + * + * or + * "key-secret=3D$alias,cipher-alg=3Dtwofish-256,cipher-mode=3Dcbc, + * hash-alg=3Dsha256,ivgen-alg=3Dplain64,igven-hash-alg=3Dsha256," + * + */ +static void +storageBackendBuildQemuImgEncriptionOpts(virBufferPtr buf, + int format, + virStorageEncryptionInfoDefPtr en= cinfo, + const char *alias) +{ + const char *encprefix; + + if (format =3D=3D VIR_STORAGE_FILE_QCOW2) { + virBufferAddLit(buf, "encrypt.format=3Dluks,"); + encprefix =3D "encrypt."; + } else { + encprefix =3D ""; + } + + virBufferAsprintf(buf, "%skey-secret=3D%s,", encprefix, alias); + + if (!encinfo->cipher_name) + return; + + virBufferAsprintf(buf, "%scipher-alg=3D", encprefix); + virQEMUBuildBufferEscapeComma(buf, encinfo->cipher_name); + virBufferAsprintf(buf, "-%u,", encinfo->cipher_size); + if (encinfo->cipher_mode) { + virBufferAsprintf(buf, "%scipher-mode=3D", encprefix); + virQEMUBuildBufferEscapeComma(buf, encinfo->cipher_mode); + virBufferAddLit(buf, ","); + } + if (encinfo->cipher_hash) { + virBufferAsprintf(buf, "%shash-alg=3D", encprefix); + virQEMUBuildBufferEscapeComma(buf, encinfo->cipher_hash); + virBufferAddLit(buf, ","); + } + if (!encinfo->ivgen_name) + return; + + virBufferAsprintf(buf, "%sivgen-alg=3D", encprefix); + virQEMUBuildBufferEscapeComma(buf, encinfo->ivgen_name); + virBufferAddLit(buf, ","); + + if (encinfo->ivgen_hash) { + virBufferAsprintf(buf, "%sivgen-hash-alg=3D", encprefix); + virQEMUBuildBufferEscapeComma(buf, encinfo->ivgen_hash); + virBufferAddLit(buf, ","); + } +} + + static int storageBackendCreateQemuImgOpts(virStorageEncryptionInfoDefPtr encinfo, char **opts, @@ -704,8 +772,10 @@ storageBackendCreateQemuImgOpts(virStorageEncryptionIn= foDefPtr encinfo, virBufferAsprintf(&buf, "backing_fmt=3D%s,", virStorageFileFormatTypeToString(info->backingFo= rmat)); =20 - if (encinfo) - virQEMUBuildQemuImgKeySecretOpts(&buf, info->format, encinfo, info= ->secretAlias); + if (encinfo) { + storageBackendBuildQemuImgEncriptionOpts(&buf, info->format, encin= fo, + info->secretAlias); + } =20 if (info->preallocate) { if (info->size_arg > info->allocation) diff --git a/src/util/virqemu.c b/src/util/virqemu.c index 5405c9eac9..c4b6e8b3db 100644 --- a/src/util/virqemu.c +++ b/src/util/virqemu.c @@ -28,7 +28,6 @@ #include "virqemu.h" #include "virstring.h" #include "viralloc.h" -#include "virstoragefile.h" =20 #define VIR_FROM_THIS VIR_FROM_NONE =20 @@ -384,71 +383,3 @@ virQEMUBuildBufferEscapeComma(virBufferPtr buf, const = char *str) { virBufferEscape(buf, ',', ",", "%s", str); } - - -/** - * virQEMUBuildQemuImgKeySecretOpts: - * @buf: buffer to build the string into - * @encinfo: pointer to encryption info - * @alias: alias to use - * - * Generate the string for id=3D$alias and any encryption options for - * into the buffer. - * - * Important note, a trailing comma (",") is built into the return since - * it's expected other arguments are appended after the id=3D$alias string. - * So either turn something like: - * - * "key-secret=3D$alias," - * - * or - * "key-secret=3D$alias,cipher-alg=3Dtwofish-256,cipher-mode=3Dcbc, - * hash-alg=3Dsha256,ivgen-alg=3Dplain64,igven-hash-alg=3Dsha256," - * - */ -void -virQEMUBuildQemuImgKeySecretOpts(virBufferPtr buf, - int format, - virStorageEncryptionInfoDefPtr encinfo, - const char *alias) -{ - const char *encprefix; - - if (format =3D=3D VIR_STORAGE_FILE_QCOW2) { - virBufferAddLit(buf, "encrypt.format=3Dluks,"); - encprefix =3D "encrypt."; - } else { - encprefix =3D ""; - } - - virBufferAsprintf(buf, "%skey-secret=3D%s,", encprefix, alias); - - if (!encinfo->cipher_name) - return; - - virBufferAsprintf(buf, "%scipher-alg=3D", encprefix); - virQEMUBuildBufferEscapeComma(buf, encinfo->cipher_name); - virBufferAsprintf(buf, "-%u,", encinfo->cipher_size); - if (encinfo->cipher_mode) { - virBufferAsprintf(buf, "%scipher-mode=3D", encprefix); - virQEMUBuildBufferEscapeComma(buf, encinfo->cipher_mode); - virBufferAddLit(buf, ","); - } - if (encinfo->cipher_hash) { - virBufferAsprintf(buf, "%shash-alg=3D", encprefix); - virQEMUBuildBufferEscapeComma(buf, encinfo->cipher_hash); - virBufferAddLit(buf, ","); - } - if (!encinfo->ivgen_name) - return; - - virBufferAsprintf(buf, "%sivgen-alg=3D", encprefix); - virQEMUBuildBufferEscapeComma(buf, encinfo->ivgen_name); - virBufferAddLit(buf, ","); - - if (encinfo->ivgen_hash) { - virBufferAsprintf(buf, "%sivgen-hash-alg=3D", encprefix); - virQEMUBuildBufferEscapeComma(buf, encinfo->ivgen_hash); - virBufferAddLit(buf, ","); - } -} diff --git a/src/util/virqemu.h b/src/util/virqemu.h index 2b33968158..b81efc765f 100644 --- a/src/util/virqemu.h +++ b/src/util/virqemu.h @@ -25,7 +25,6 @@ #include "internal.h" #include "virbuffer.h" #include "virjson.h" -#include "virstorageencryption.h" =20 typedef int (*virQEMUBuildCommandLineJSONArrayFormatFunc)(const char *key, virJSONValuePtr = array, @@ -59,8 +58,3 @@ int virQEMUBuildObjectCommandlineFromJSON(virBufferPtr bu= f, char *virQEMUBuildDriveCommandlineFromJSON(virJSONValuePtr src); =20 void virQEMUBuildBufferEscapeComma(virBufferPtr buf, const char *str); -void virQEMUBuildQemuImgKeySecretOpts(virBufferPtr buf, - int format, - virStorageEncryptionInfoDefPtr enc, - const char *alias) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4); --=20 2.28.0 From nobody Thu May 16 01:02:08 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 63.128.21.124 as permitted sender) client-ip=63.128.21.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 63.128.21.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1607961556; cv=none; d=zohomail.com; s=zohoarc; b=b0ApGNV1w6peab0SrW6hu7psIA0a5+OB3Xiek8OG76zIB8wRU7+o12+Qe+Vb3vjBazz8u/E8N+Z7xjL4reoKcI8nqKlqciZYwxQtms3PfIj6xplNwGGhcdbognQac74TWmyV3xzsB7uIljA15KBh3q0FXR4p6EXbPAxgu2Q4xP8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1607961556; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=Jrt/nRFjt36pqNuw1DAyddLx2PLIbd6P44CYQnpAgdc=; b=OvXDRGJARwvYR8qZB6LjePMMWpcNwNPl6d4GeBF5yW34EU5l+9xpQMAkjmoGWPZgwSaWodZ+cO8ZYg8iAV5WsJ3ZSKG8WEospesJGgU0Ex2yI+iwBtWDpCW6ThOJ/qjj8O1Rmm7xtMC8zsMg8sw9ssN0rsRG6DbwNzdXmHIWlmg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 63.128.21.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [63.128.21.124]) by mx.zohomail.com with SMTPS id 160796155656698.93280217388565; Mon, 14 Dec 2020 07:59:16 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-12-G-7r9RgIP3uecJ2s0zg91w-1; Mon, 14 Dec 2020 10:56:20 -0500 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id CCEA68015FA; Mon, 14 Dec 2020 15:56:10 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 9A99B62467; Mon, 14 Dec 2020 15:56:10 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 5ECF350032; Mon, 14 Dec 2020 15:56:10 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 0BEFtkNv028525 for ; Mon, 14 Dec 2020 10:55:46 -0500 Received: by smtp.corp.redhat.com (Postfix) id D93866267D; Mon, 14 Dec 2020 15:55:46 +0000 (UTC) Received: from antique-work.lan (unknown [10.40.194.243]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5632362467 for ; Mon, 14 Dec 2020 15:55:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1607961383; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=Jrt/nRFjt36pqNuw1DAyddLx2PLIbd6P44CYQnpAgdc=; b=QLKsNXy7Oe86AyH6TGxQOYtGd4A55QsSehVCgMZ54WGpcKH9gbfzK8Z5wwL8ORSwJgnt3O DMZZyAsZ8piNLOQ0Eir7fwf5B83+YfP71MokDzpNzZ0fZdlsRz9jjEUdOEonlvbmjVKFdj 8cTGBqG5y17BEsAyRLKqA00/ovT5y/0= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1607961555; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=Jrt/nRFjt36pqNuw1DAyddLx2PLIbd6P44CYQnpAgdc=; b=grZIg+jSJvHlqLQ7SDVVCBJkLFdxgFxonceeuDk++nTGCamJM7hZjuqhPz4qTU3ZGokJOc dKKEK9Dp+eotvz9KqiljUHgaoSTFLGoU6S7oJDFgQX9nZSFiQSW41wuDOXfiSqcWzm5Pho AlO1iOIqpWNkA3aCWpqKbnGh71oMVx8= X-MC-Unique: G-7r9RgIP3uecJ2s0zg91w-1 From: Pavel Hrdina To: libvir-list@redhat.com Subject: [libvirt PATCH 04/17] util: move virStorageFileGetLVMKey to locking Date: Mon, 14 Dec 2020 16:55:24 +0100 Message-Id: In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-loop: libvir-list@redhat.com X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=libvir-list-bounces@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) (identity @redhat.com) Content-Type: text/plain; charset="utf-8" The function doesn't take virStorageSource as argument and has nothing in common with virStorageSource or storage file. Signed-off-by: Pavel Hrdina Reviewed-by: Peter Krempa --- src/libvirt_private.syms | 1 - src/locking/lock_driver_lockd.c | 66 ++++++++++++++++++++++++++++++++- src/util/virstoragefile.c | 62 ------------------------------- src/util/virstoragefile.h | 2 - 4 files changed, 65 insertions(+), 66 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index aecc5cd654..d04b8f5e0c 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -3134,7 +3134,6 @@ virStorageFileFeatureTypeToString; virStorageFileFormatTypeFromString; virStorageFileFormatTypeToString; virStorageFileGetBackingStoreStr; -virStorageFileGetLVMKey; virStorageFileGetMetadata; virStorageFileGetMetadataFromBuf; virStorageFileGetMetadataFromFD; diff --git a/src/locking/lock_driver_lockd.c b/src/locking/lock_driver_lock= d.c index 15d9e5f076..b8c2121e78 100644 --- a/src/locking/lock_driver_lockd.c +++ b/src/locking/lock_driver_lockd.c @@ -24,6 +24,7 @@ #include "lock_driver.h" #include "virconf.h" #include "viralloc.h" +#include "vircommand.h" #include "vircrypto.h" #include "virlog.h" #include "viruuid.h" @@ -455,6 +456,69 @@ static int virLockManagerLockDaemonNew(virLockManagerP= tr lock, } =20 =20 +#ifdef LVS +static int virLockManagerGetLVMKey(const char *path, + char **key) +{ + /* + * # lvs --noheadings --unbuffered --nosuffix --options "uuid" LVNAME + * 06UgP5-2rhb-w3Bo-3mdR-WeoL-pytO-SAa2ky + */ + int status; + int ret =3D -1; + g_autoptr(virCommand) cmd =3D NULL; + + cmd =3D virCommandNewArgList(LVS, "--noheadings", + "--unbuffered", "--nosuffix", + "--options", "uuid", path, + NULL + ); + *key =3D NULL; + + /* Run the program and capture its output */ + virCommandSetOutputBuffer(cmd, key); + if (virCommandRun(cmd, &status) < 0) + goto cleanup; + + /* Explicitly check status =3D=3D 0, rather than passing NULL + * to virCommandRun because we don't want to raise an actual + * error in this scenario, just return a NULL key. + */ + + if (status =3D=3D 0 && *key) { + char *nl; + char *tmp =3D *key; + + /* Find first non-space character */ + while (*tmp && g_ascii_isspace(*tmp)) + tmp++; + /* Kill leading spaces */ + if (tmp !=3D *key) + memmove(*key, tmp, strlen(tmp)+1); + + /* Kill trailing newline */ + if ((nl =3D strchr(*key, '\n'))) + *nl =3D '\0'; + } + + ret =3D 0; + + cleanup: + if (*key && STREQ(*key, "")) + VIR_FREE(*key); + + return ret; +} +#else +static int virLockManagerGetLVMKey(const char *path, + char **key G_GNUC_UNUSED) +{ + virReportSystemError(ENOSYS, _("Unable to get LVM key for %s"), path); + return -1; +} +#endif + + static int virLockManagerLockDaemonAddResource(virLockManagerPtr lock, unsigned int type, const char *name, @@ -494,7 +558,7 @@ static int virLockManagerLockDaemonAddResource(virLockM= anagerPtr lock, if (STRPREFIX(name, "/dev") && driver->lvmLockSpaceDir) { VIR_DEBUG("Trying to find an LVM UUID for %s", name); - if (virStorageFileGetLVMKey(name, &newName) < 0) + if (virLockManagerGetLVMKey(name, &newName) < 0) goto cleanup; =20 if (newName) { diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c index 119342d296..bc342cabe3 100644 --- a/src/util/virstoragefile.c +++ b/src/util/virstoragefile.c @@ -1251,68 +1251,6 @@ int virStorageFileIsClusterFS(const char *path) VIR_FILE_SHFS_CEPH); } =20 -#ifdef LVS -int virStorageFileGetLVMKey(const char *path, - char **key) -{ - /* - * # lvs --noheadings --unbuffered --nosuffix --options "uuid" LVNAME - * 06UgP5-2rhb-w3Bo-3mdR-WeoL-pytO-SAa2ky - */ - int status; - int ret =3D -1; - g_autoptr(virCommand) cmd =3D NULL; - - cmd =3D virCommandNewArgList(LVS, "--noheadings", - "--unbuffered", "--nosuffix", - "--options", "uuid", path, - NULL - ); - *key =3D NULL; - - /* Run the program and capture its output */ - virCommandSetOutputBuffer(cmd, key); - if (virCommandRun(cmd, &status) < 0) - goto cleanup; - - /* Explicitly check status =3D=3D 0, rather than passing NULL - * to virCommandRun because we don't want to raise an actual - * error in this scenario, just return a NULL key. - */ - - if (status =3D=3D 0 && *key) { - char *nl; - char *tmp =3D *key; - - /* Find first non-space character */ - while (*tmp && g_ascii_isspace(*tmp)) - tmp++; - /* Kill leading spaces */ - if (tmp !=3D *key) - memmove(*key, tmp, strlen(tmp)+1); - - /* Kill trailing newline */ - if ((nl =3D strchr(*key, '\n'))) - *nl =3D '\0'; - } - - ret =3D 0; - - cleanup: - if (*key && STREQ(*key, "")) - VIR_FREE(*key); - - return ret; -} -#else -int virStorageFileGetLVMKey(const char *path, - char **key G_GNUC_UNUSED) -{ - virReportSystemError(ENOSYS, _("Unable to get LVM key for %s"), path); - return -1; -} -#endif - #ifdef WITH_UDEV /* virStorageFileGetSCSIKey * @path: Path to the SCSI device diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h index cc9bd4875f..31feb22f26 100644 --- a/src/util/virstoragefile.h +++ b/src/util/virstoragefile.h @@ -428,8 +428,6 @@ int virStorageFileIsClusterFS(const char *path); bool virStorageIsFile(const char *path); bool virStorageIsRelative(const char *backing); =20 -int virStorageFileGetLVMKey(const char *path, - char **key); int virStorageFileGetSCSIKey(const char *path, char **key, bool ignoreError); --=20 2.28.0 From nobody Thu May 16 01:02:08 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 63.128.21.124 as permitted sender) client-ip=63.128.21.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 63.128.21.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1607961433; cv=none; d=zohomail.com; s=zohoarc; b=VIY6lUgg+qHHCRRAD3KJlUac8/lwpZLAi+vIc9gIvAZr1i4o9+72ahdGZyRKArZcCtsFvq3nJ/nr6WAmD5vEv5Yll1Scc/puhV0Q65YHJrkJEtH5WyaEU/1Un0aqZDEhuj9ju7PKu9HxeP429iTCK+QUzKtLeETQNHaXjvi2UBM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1607961433; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=hM7JwI0QGd6Chw+I0KcdFF+ZvcMN2vw0pO4DJzpt0c8=; b=fPRo9x7gOMginLpwItsRX5X/V2NU5w59DRuUE0Pb9o+c6WAXzGfOO/e0onPn9gJ58nBVQcnXKF9zuhK4ujF9ENeFOsx8AbI6MMRJf93QVtHdkcsPTOj3feA6ZW9elJJHK9y3xuX5WC7PTnmjZ/wONiXCjVaC3kDvSkBD9aeTtzs= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 63.128.21.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [63.128.21.124]) by mx.zohomail.com with SMTPS id 1607961433721324.9500211644695; Mon, 14 Dec 2020 07:57:13 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-483-x_MJSMaWOXeI_159X5ex-A-1; Mon, 14 Dec 2020 10:56:10 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id F0A11E758; Mon, 14 Dec 2020 15:56:03 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id C3ACD5D9E3; Mon, 14 Dec 2020 15:56:03 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 7E80B1809CA4; Mon, 14 Dec 2020 15:56:03 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 0BEFtlvh028536 for ; Mon, 14 Dec 2020 10:55:47 -0500 Received: by smtp.corp.redhat.com (Postfix) id BB47B62688; Mon, 14 Dec 2020 15:55:47 +0000 (UTC) Received: from antique-work.lan (unknown [10.40.194.243]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3880462467 for ; Mon, 14 Dec 2020 15:55:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1607961429; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=hM7JwI0QGd6Chw+I0KcdFF+ZvcMN2vw0pO4DJzpt0c8=; b=ds2ch5bvjnit1X9gN8/M8JO75R9kBbjzoCu1sciKQecPGihtTRSdHGFx5JxNCgRynEFxiJ 5kJuOgAQWijxl6my/pzNN8Rs5AMKKjn/1PQKLP+1SsSjznfULnmjK+CV+3On3AKeH5cw1G RZaakDYxCRoaGEAvuhwKHgyigyyo0MM= X-MC-Unique: x_MJSMaWOXeI_159X5ex-A-1 From: Pavel Hrdina To: libvir-list@redhat.com Subject: [libvirt PATCH 05/17] util: move virStorageFileCheckCompat into conf Date: Mon, 14 Dec 2020 16:55:25 +0100 Message-Id: In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-loop: libvir-list@redhat.com X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=libvir-list-bounces@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" It is not used anywhere else. Signed-off-by: Pavel Hrdina Reviewed-by: Peter Krempa --- src/conf/storage_conf.c | 23 ++++++++++++++++++++++- src/util/virstoragefile.c | 24 ------------------------ src/util/virstoragefile.h | 2 -- 3 files changed, 22 insertions(+), 27 deletions(-) diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c index 09769e6c79..0c50529ace 100644 --- a/src/conf/storage_conf.c +++ b/src/conf/storage_conf.c @@ -1296,6 +1296,27 @@ virStorageSize(const char *unit, } =20 =20 +static int +virStorageCheckCompat(const char *compat) +{ + unsigned int result; + g_auto(GStrv) version =3D NULL; + + if (!compat) + return 0; + + version =3D virStringSplit(compat, ".", 2); + if (!version || !version[1] || + virStrToLong_ui(version[0], NULL, 10, &result) < 0 || + virStrToLong_ui(version[1], NULL, 10, &result) < 0) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("forbidden characters in 'compat' attribute")); + return -1; + } + return 0; +} + + static virStorageVolDefPtr virStorageVolDefParseXML(virStoragePoolDefPtr pool, xmlXPathContextPtr ctxt, @@ -1424,7 +1445,7 @@ virStorageVolDefParseXML(virStoragePoolDefPtr pool, } =20 def->target.compat =3D virXPathString("string(./target/compat)", ctxt); - if (virStorageFileCheckCompat(def->target.compat) < 0) + if (virStorageCheckCompat(def->target.compat) < 0) return NULL; =20 if (virXPathNode("./target/nocow", ctxt)) diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c index bc342cabe3..d6ff47e4a7 100644 --- a/src/util/virstoragefile.c +++ b/src/util/virstoragefile.c @@ -4410,30 +4410,6 @@ virStorageFileGetRelativeBackingPath(virStorageSourc= ePtr top, } =20 =20 -/* - * virStorageFileCheckCompat - */ -int -virStorageFileCheckCompat(const char *compat) -{ - unsigned int result; - g_auto(GStrv) version =3D NULL; - - if (!compat) - return 0; - - version =3D virStringSplit(compat, ".", 2); - if (!version || !version[1] || - virStrToLong_ui(version[0], NULL, 10, &result) < 0 || - virStrToLong_ui(version[1], NULL, 10, &result) < 0) { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("forbidden characters in 'compat' attribute")); - return -1; - } - return 0; -} - - /** * virStorageSourceIsRelative: * @src: storage source to check diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h index 31feb22f26..ec34f2d899 100644 --- a/src/util/virstoragefile.h +++ b/src/util/virstoragefile.h @@ -513,8 +513,6 @@ int virStorageFileGetRelativeBackingPath(virStorageSour= cePtr from, char **relpath) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); =20 -int virStorageFileCheckCompat(const char *compat); - int virStorageSourceNewFromBackingAbsolute(const char *path, virStorageSourcePtr *src); =20 --=20 2.28.0 From nobody Thu May 16 01:02:08 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) client-ip=216.205.24.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1607961362; cv=none; d=zohomail.com; s=zohoarc; b=QDwGthZhAFlaPk/ykYjXV+K+deWTubh8TNroHM5Kv4BSmiHT4eWFIC04DxrfnTE7zss+LgIE74PW8BIKGsGZoXUfDJYGkh9j/CXX1QH5kwYw3G3sgTV1nlKzeaAruN87LXx63i/VhxSysB4fjGZbEDvSWmeE/zZrGdT4JPNChwo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1607961362; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=XgRv/vRwyiP+OaHQ1HZGusIfkcQoABEOS0OYZa9SxiI=; b=YH6bxhQvuvnu3WQzHTV27NCxWeBZhKo/WGtkcvFPi78p6yfEciYDJjMoKqDKOfhud2yttPKPGPplolsdapCNjgHND0/xDyUOHQ9M9R8AIcdsB2Hjiq4PNoru3Ag13LoWIhuabNZvocd/reCxR4j9rBF54hjevEMhhYMX78s/Dlg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by mx.zohomail.com with SMTPS id 1607961362283653.9331445903616; Mon, 14 Dec 2020 07:56:02 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-95-OVaOFTeeM-ePI7CdVx1_MQ-1; Mon, 14 Dec 2020 10:55:58 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id F09421936B66; Mon, 14 Dec 2020 15:55:51 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id B4D636086F; Mon, 14 Dec 2020 15:55:51 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 2FE0B1809CA0; Mon, 14 Dec 2020 15:55:51 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 0BEFtmNo028545 for ; Mon, 14 Dec 2020 10:55:48 -0500 Received: by smtp.corp.redhat.com (Postfix) id 9ECFA62467; Mon, 14 Dec 2020 15:55:48 +0000 (UTC) Received: from antique-work.lan (unknown [10.40.194.243]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1BA6462690 for ; Mon, 14 Dec 2020 15:55:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1607961361; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=XgRv/vRwyiP+OaHQ1HZGusIfkcQoABEOS0OYZa9SxiI=; b=dy+TMgDS92Q/iG/AJxbC7aB4p1JXgbki0VRDIYXwWhYhHCppzmEnfhLw+0uPPD623zt8bR 9Ob3sAjp4tSsA1bWaV5cGbMstRB85fcXR9YM9IY+leIx+JL7PLCy/8xGBipy5z84bnYJTU kyqvk+3N3lNc1Y2v8bSsWMayxlhUTTY= X-MC-Unique: OVaOFTeeM-ePI7CdVx1_MQ-1 From: Pavel Hrdina To: libvir-list@redhat.com Subject: [libvirt PATCH 06/17] virfile: refactor virFileNBDDeviceAssociate Date: Mon, 14 Dec 2020 16:55:26 +0100 Message-Id: <2469a62f02ecccff769b9e989dcc0d34fdba5799.1607960951.git.phrdina@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-loop: libvir-list@redhat.com X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=libvir-list-bounces@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" The only reason why virstoragefile.h needs to be included in virfile.h is that virFileNBDDeviceAssociate() takes virStorageFileFormat argument. The function doesn't need the enum value as it converts the value to string and uses only that. Change the argument to string which will allow us to remove that include. The extra seemingly unrelated include changes is because all of the added includes where indirectly provided by virfile.h having virstoragefile.h. Signed-off-by: Pavel Hrdina Reviewed-by: Peter Krempa --- src/driver.c | 1 + src/lxc/lxc_controller.c | 4 ++-- src/qemu/qemu_interop_config.c | 1 + src/qemu/qemu_shim.c | 1 + src/storage/parthelper.c | 1 + src/util/virarptable.c | 1 + src/util/vircgroupv1.c | 1 + src/util/vircgroupv2devices.c | 1 + src/util/virfile.c | 8 ++------ src/util/virfile.h | 4 ++-- src/util/virpidfile.c | 1 + src/util/virresctrl.c | 1 + src/util/virsysinfo.c | 1 + src/util/virtpm.c | 1 + tools/virsh-console.c | 1 + tools/virsh-util.c | 1 + 16 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/driver.c b/src/driver.c index 1cacec24ff..e005a89d57 100644 --- a/src/driver.c +++ b/src/driver.c @@ -29,6 +29,7 @@ #include "virfile.h" #include "virlog.h" #include "virmodule.h" +#include "virobject.h" #include "virstring.h" #include "virthread.h" #include "virutil.h" diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index 67e5e63d00..8f166a436a 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -509,7 +509,7 @@ static int virLXCControllerSetupNBDDeviceFS(virDomainFS= DefPtr fs) } =20 if (virFileNBDDeviceAssociate(fs->src->path, - fs->format, + virStorageFileFormatTypeToString(fs->for= mat), fs->readonly, &dev) < 0) return -1; @@ -541,7 +541,7 @@ static int virLXCControllerSetupNBDDeviceDisk(virDomain= DiskDefPtr disk) } =20 if (virFileNBDDeviceAssociate(src, - format, + virStorageFileFormatTypeToString(format), disk->src->readonly, &dev) < 0) return -1; diff --git a/src/qemu/qemu_interop_config.c b/src/qemu/qemu_interop_config.c index c5a5a9c6ec..bcaddda446 100644 --- a/src/qemu/qemu_interop_config.c +++ b/src/qemu/qemu_interop_config.c @@ -24,6 +24,7 @@ #include "configmake.h" #include "viralloc.h" #include "virenum.h" +#include "virerror.h" #include "virfile.h" #include "virhash.h" #include "virlog.h" diff --git a/src/qemu/qemu_shim.c b/src/qemu/qemu_shim.c index ef0ba086b5..18bdc99256 100644 --- a/src/qemu/qemu_shim.c +++ b/src/qemu/qemu_shim.c @@ -27,6 +27,7 @@ #include "virfile.h" #include "virstring.h" #include "virgettext.h" +#include "virthread.h" =20 #define VIR_FROM_THIS VIR_FROM_QEMU =20 diff --git a/src/storage/parthelper.c b/src/storage/parthelper.c index caa2e8fa62..94d588615f 100644 --- a/src/storage/parthelper.c +++ b/src/storage/parthelper.c @@ -40,6 +40,7 @@ #include "virstring.h" #include "virgettext.h" #include "virdevmapper.h" +#include "virerror.h" =20 /* we don't need to include the full internal.h just for this */ #define STREQ(a, b) (strcmp(a, b) =3D=3D 0) diff --git a/src/util/virarptable.c b/src/util/virarptable.c index 01a27c0093..d62de5e3dd 100644 --- a/src/util/virarptable.c +++ b/src/util/virarptable.c @@ -26,6 +26,7 @@ =20 #include "viralloc.h" #include "virarptable.h" +#include "virerror.h" #include "virfile.h" #include "virlog.h" #include "virnetlink.h" diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c index 06849efd38..2b4d625c35 100644 --- a/src/util/vircgroupv1.c +++ b/src/util/vircgroupv1.c @@ -41,6 +41,7 @@ #include "virsystemd.h" #include "virerror.h" #include "viralloc.h" +#include "virthread.h" =20 VIR_LOG_INIT("util.cgroup"); =20 diff --git a/src/util/vircgroupv2devices.c b/src/util/vircgroupv2devices.c index f31244f3c1..71591be4c4 100644 --- a/src/util/vircgroupv2devices.c +++ b/src/util/vircgroupv2devices.c @@ -34,6 +34,7 @@ #include "virbpf.h" #include "vircgroup.h" #include "vircgroupv2devices.h" +#include "virerror.h" #include "virfile.h" #include "virlog.h" =20 diff --git a/src/util/virfile.c b/src/util/virfile.c index f7283fa72f..3f4c6d1d0a 100644 --- a/src/util/virfile.c +++ b/src/util/virfile.c @@ -879,14 +879,13 @@ virFileNBDLoadDriver(void) } =20 int virFileNBDDeviceAssociate(const char *file, - virStorageFileFormat fmt, + const char *fmtstr, bool readonly, char **dev) { g_autofree char *nbddev =3D NULL; g_autofree char *qemunbd =3D NULL; g_autoptr(virCommand) cmd =3D NULL; - const char *fmtstr =3D NULL; =20 if (!virFileNBDLoadDriver()) return -1; @@ -900,9 +899,6 @@ int virFileNBDDeviceAssociate(const char *file, return -1; } =20 - if (fmt > 0) - fmtstr =3D virStorageFileFormatTypeToString(fmt); - cmd =3D virCommandNew(qemunbd); =20 /* Explicitly not trying to cope with old qemu-nbd which @@ -945,7 +941,7 @@ int virFileLoopDeviceAssociate(const char *file, } =20 int virFileNBDDeviceAssociate(const char *file, - virStorageFileFormat fmt G_GNUC_UNUSED, + const char *fmtstr G_GNUC_UNUSED, bool readonly G_GNUC_UNUSED, char **dev G_GNUC_UNUSED) { diff --git a/src/util/virfile.h b/src/util/virfile.h index 32505826ee..28dfe86445 100644 --- a/src/util/virfile.h +++ b/src/util/virfile.h @@ -28,7 +28,7 @@ =20 #include "internal.h" #include "virbitmap.h" -#include "virstoragefile.h" +#include "virenum.h" =20 typedef enum { VIR_FILE_CLOSE_PRESERVE_ERRNO =3D 1 << 0, @@ -143,7 +143,7 @@ int virFileLoopDeviceAssociate(const char *file, char **dev); =20 int virFileNBDDeviceAssociate(const char *file, - virStorageFileFormat fmt, + const char *fmtstr, bool readonly, char **dev); =20 diff --git a/src/util/virpidfile.c b/src/util/virpidfile.c index 895eb83ea9..b4d0059405 100644 --- a/src/util/virpidfile.c +++ b/src/util/virpidfile.c @@ -30,6 +30,7 @@ #include "virpidfile.h" #include "virfile.h" #include "viralloc.h" +#include "virbuffer.h" #include "virutil.h" #include "virlog.h" #include "virerror.h" diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c index d3087b98c1..67a921b44b 100644 --- a/src/util/virresctrl.c +++ b/src/util/virresctrl.c @@ -27,6 +27,7 @@ #define LIBVIRT_VIRRESCTRLPRIV_H_ALLOW #include "virresctrlpriv.h" #include "viralloc.h" +#include "virbuffer.h" #include "virfile.h" #include "virlog.h" #include "virobject.h" diff --git a/src/util/virsysinfo.c b/src/util/virsysinfo.c index 217f842a37..28f7104145 100644 --- a/src/util/virsysinfo.c +++ b/src/util/virsysinfo.c @@ -32,6 +32,7 @@ #include "virlog.h" #include "virfile.h" #include "virstring.h" +#include "virxml.h" =20 #define LIBVIRT_VIRSYSINFOPRIV_H_ALLOW #include "virsysinfopriv.h" diff --git a/src/util/virtpm.c b/src/util/virtpm.c index 0e11674a3c..b41eb00619 100644 --- a/src/util/virtpm.c +++ b/src/util/virtpm.c @@ -31,6 +31,7 @@ #include "virbitmap.h" #include "virjson.h" #include "virlog.h" +#include "virthread.h" =20 #define VIR_FROM_THIS VIR_FROM_TPM =20 diff --git a/tools/virsh-console.c b/tools/virsh-console.c index 2e498a6903..4e9bdb67e1 100644 --- a/tools/virsh-console.c +++ b/tools/virsh-console.c @@ -38,6 +38,7 @@ # include "viralloc.h" # include "virthread.h" # include "virerror.h" +# include "virobject.h" =20 VIR_LOG_INIT("tools.virsh-console"); =20 diff --git a/tools/virsh-util.c b/tools/virsh-util.c index af7ed55348..9f69bad8cc 100644 --- a/tools/virsh-util.c +++ b/tools/virsh-util.c @@ -23,6 +23,7 @@ #include "virfile.h" #include "virstring.h" #include "viralloc.h" +#include "virxml.h" =20 static virDomainPtr virshLookupDomainInternal(vshControl *ctl, --=20 2.28.0 From nobody Thu May 16 01:02:08 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 63.128.21.124 as permitted sender) client-ip=63.128.21.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 63.128.21.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1607961431; cv=none; d=zohomail.com; s=zohoarc; b=CwPH4R/P1HkvWklj9AFyeFSL+962wm7+oREIvirFVATaNTniJD/FYO6eq7JKy9etlfa7ASQweKKdMW6aeoGGMLFcnjau/tgEfD/5CtpVKPEsdOgk0D5pdsWn8s4QcLQ8oBy/V6diNFkkQL4IinbIURXiFy9si2CCaCk+VgI7K9w= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1607961431; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=WevwRHhincN0w7qBUFuYTN2QzfNxa4gYwWerrj3L7RI=; b=TNiDxYr6O/rfZKIEJY44vGjMgOZj5OVj2zNd09fPmJ2dV6XTze1ComXgKaDVQ1RqqE0XyhBl74OP15X8E3jcWRirn3FoYj4q8q2XnTsy0Yvngz9Wi3THVFicThNq7S/4ohZiqBFx1a2o+K3v6Yht33jesCyC6GNPqTJ2Dd1wCw4= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 63.128.21.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [63.128.21.124]) by mx.zohomail.com with SMTPS id 1607961431365579.5796875679044; Mon, 14 Dec 2020 07:57:11 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-31-8RfoHGYdP8CBgklvNlGMJQ-1; Mon, 14 Dec 2020 10:56:09 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id E1D8C801817; Mon, 14 Dec 2020 15:56:03 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id BBE145D9E2; Mon, 14 Dec 2020 15:56:03 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 7D8EE4EA6C; Mon, 14 Dec 2020 15:56:03 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 0BEFtnEL028560 for ; Mon, 14 Dec 2020 10:55:49 -0500 Received: by smtp.corp.redhat.com (Postfix) id 829C017B77; Mon, 14 Dec 2020 15:55:49 +0000 (UTC) Received: from antique-work.lan (unknown [10.40.194.243]) by smtp.corp.redhat.com (Postfix) with ESMTP id F2F295D6D5 for ; Mon, 14 Dec 2020 15:55:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1607961429; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=WevwRHhincN0w7qBUFuYTN2QzfNxa4gYwWerrj3L7RI=; b=N3lDceDFMFlYHIqQCdks52JFs0UxhaVYPyV+KgPLTb/xvL8g9E8Q218qYdYn/OfjFh+RDS 9c3lbvqOVuQVwxKMLEHeYjiR4AXnjPdaQVxiCT9fZ8J9JY9ibvA3bn2YayKHYAbirGX2XP QWHn16kzvO/I3OED4wLpOURvWL9tgJ4= X-MC-Unique: 8RfoHGYdP8CBgklvNlGMJQ-1 From: Pavel Hrdina To: libvir-list@redhat.com Subject: [libvirt PATCH 07/17] virstoragefile: move virStorageFileResize into virfile Date: Mon, 14 Dec 2020 16:55:27 +0100 Message-Id: In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-loop: libvir-list@redhat.com X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=libvir-list-bounces@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" Signed-off-by: Pavel Hrdina Reviewed-by: Peter Krempa --- src/libvirt_private.syms | 2 +- src/storage/storage_util.c | 2 +- src/util/virfile.c | 47 ++++++++++++++++++++++++++++++++++++++ src/util/virfile.h | 4 ++++ src/util/virstoragefile.c | 47 -------------------------------------- src/util/virstoragefile.h | 4 ---- 6 files changed, 53 insertions(+), 53 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index d04b8f5e0c..2d1cb7786d 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2121,6 +2121,7 @@ virFileRelLinkPointsTo; virFileRemove; virFileRemoveLastComponent; virFileRemoveXAttr; +virFileResize; virFileResolveAllLinks; virFileResolveLink; virFileRewrite; @@ -3149,7 +3150,6 @@ virStorageFileParseChainIndex; virStorageFileProbeFormat; virStorageFileRead; virStorageFileReportBrokenChain; -virStorageFileResize; virStorageFileStat; virStorageFileSupportsAccess; virStorageFileSupportsBackingChainTraversal; diff --git a/src/storage/storage_util.c b/src/storage/storage_util.c index 9b9f8b4f13..652f65fce2 100644 --- a/src/storage/storage_util.c +++ b/src/storage/storage_util.c @@ -2408,7 +2408,7 @@ virStorageBackendVolResizeLocal(virStoragePoolObjPtr = pool, VIR_STORAGE_VOL_RESIZE_SHRINK, -1); =20 if (vol->target.format =3D=3D VIR_STORAGE_FILE_RAW && !vol->target.enc= ryption) { - return virStorageFileResize(vol->target.path, capacity, pre_alloca= te); + return virFileResize(vol->target.path, capacity, pre_allocate); } else if (vol->target.format =3D=3D VIR_STORAGE_FILE_RAW && vol->targ= et.encryption) { if (pre_allocate) { virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", diff --git a/src/util/virfile.c b/src/util/virfile.c index 3f4c6d1d0a..6e16780e30 100644 --- a/src/util/virfile.c +++ b/src/util/virfile.c @@ -557,6 +557,53 @@ virFileRewriteStr(const char *path, } =20 =20 +/** + * virFileResize: + * + * Change the capacity of the raw storage file at 'path'. + */ +int +virFileResize(const char *path, + unsigned long long capacity, + bool pre_allocate) +{ + int rc; + VIR_AUTOCLOSE fd =3D -1; + + if ((fd =3D open(path, O_RDWR)) < 0) { + virReportSystemError(errno, _("Unable to open '%s'"), path); + return -1; + } + + if (pre_allocate) { + if ((rc =3D virFileAllocate(fd, 0, capacity)) !=3D 0) { + if (rc =3D=3D -2) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("preallocate is not supported on this pla= tform")); + } else { + virReportSystemError(errno, + _("Failed to pre-allocate space for " + "file '%s'"), path); + } + return -1; + } + } + + if (ftruncate(fd, capacity) < 0) { + virReportSystemError(errno, + _("Failed to truncate file '%s'"), path); + return -1; + } + + if (VIR_CLOSE(fd) < 0) { + virReportSystemError(errno, _("Unable to save '%s'"), path); + return -1; + } + + return 0; +} + + int virFileTouch(const char *path, mode_t mode) { int fd =3D -1; diff --git a/src/util/virfile.h b/src/util/virfile.h index 28dfe86445..45b75a059e 100644 --- a/src/util/virfile.h +++ b/src/util/virfile.h @@ -133,6 +133,10 @@ int virFileRewriteStr(const char *path, mode_t mode, const char *str); =20 +int virFileResize(const char *path, + unsigned long long capacity, + bool pre_allocate); + int virFileTouch(const char *path, mode_t mode); =20 int virFileUpdatePerm(const char *path, diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c index d6ff47e4a7..66694bfcc0 100644 --- a/src/util/virstoragefile.c +++ b/src/util/virstoragefile.c @@ -1193,53 +1193,6 @@ virStorageFileGetMetadataFromFD(const char *path, } =20 =20 -/** - * virStorageFileResize: - * - * Change the capacity of the raw storage file at 'path'. - */ -int -virStorageFileResize(const char *path, - unsigned long long capacity, - bool pre_allocate) -{ - int rc; - VIR_AUTOCLOSE fd =3D -1; - - if ((fd =3D open(path, O_RDWR)) < 0) { - virReportSystemError(errno, _("Unable to open '%s'"), path); - return -1; - } - - if (pre_allocate) { - if ((rc =3D virFileAllocate(fd, 0, capacity)) !=3D 0) { - if (rc =3D=3D -2) { - virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", - _("preallocate is not supported on this pla= tform")); - } else { - virReportSystemError(errno, - _("Failed to pre-allocate space for " - "file '%s'"), path); - } - return -1; - } - } - - if (ftruncate(fd, capacity) < 0) { - virReportSystemError(errno, - _("Failed to truncate file '%s'"), path); - return -1; - } - - if (VIR_CLOSE(fd) < 0) { - virReportSystemError(errno, _("Unable to save '%s'"), path); - return -1; - } - - return 0; -} - - int virStorageFileIsClusterFS(const char *path) { /* These are coherent cluster filesystems known to be safe for diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h index ec34f2d899..94bb889d84 100644 --- a/src/util/virstoragefile.h +++ b/src/util/virstoragefile.h @@ -420,10 +420,6 @@ virStorageSourcePtr virStorageFileChainLookup(virStora= geSourcePtr chain, virStorageSourcePtr *parent) ATTRIBUTE_NONNULL(1); =20 -int virStorageFileResize(const char *path, - unsigned long long capacity, - bool pre_allocate); - int virStorageFileIsClusterFS(const char *path); bool virStorageIsFile(const char *path); bool virStorageIsRelative(const char *backing); --=20 2.28.0 From nobody Thu May 16 01:02:08 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 63.128.21.124 as permitted sender) client-ip=63.128.21.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 63.128.21.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1607961388; cv=none; d=zohomail.com; s=zohoarc; b=AA22rvbWoVlXdGKUZEKQXu++9Sy9CVD8r2kxVOXNXPzO4oxyGToMc9S5Nz1tU/5dbNOgSYTQM9A2c2Md7oFJwFVBfuHgbJlMoLdO5w/yVZFAI4wYb9GwICL3/QI0G5R9riy3YDyooJsl0lVDPo/iu8FMrtwQ1m8l8sARQ/JrzF4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1607961388; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=LIAp760JGve8dI0j0ygpGmOjlnCGyhnWD/IDHTE8Rqc=; b=EiGICkcMcfUyqEnfJqPWyyfWvE9CQSAD3XYmwLtGhDDD7kF8xp5pnVW0JbIUWjQahr8xFBEhCU5CvztwqH0Pt0sqWtjgAQ1C0l14d0ERnuqTNiUseOiIhFWXcZGqtFOAasD5138yC3/VKkaLH8jV6+xUZw0KgXb+izNpfhBhsv0= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 63.128.21.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [63.128.21.124]) by mx.zohomail.com with SMTPS id 1607961388698712.2493164960194; Mon, 14 Dec 2020 07:56:28 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-348-2ttRYRHjO7SIuzxTwjZYTg-1; Mon, 14 Dec 2020 10:56:21 -0500 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 96A921936B7A; Mon, 14 Dec 2020 15:56:13 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 6F3C262467; Mon, 14 Dec 2020 15:56:13 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 30BF31809CAD; Mon, 14 Dec 2020 15:56:13 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 0BEFtoS5028568 for ; Mon, 14 Dec 2020 10:55:50 -0500 Received: by smtp.corp.redhat.com (Postfix) id 64D6717B77; Mon, 14 Dec 2020 15:55:50 +0000 (UTC) Received: from antique-work.lan (unknown [10.40.194.243]) by smtp.corp.redhat.com (Postfix) with ESMTP id D60E65D6D5 for ; Mon, 14 Dec 2020 15:55:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1607961384; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=LIAp760JGve8dI0j0ygpGmOjlnCGyhnWD/IDHTE8Rqc=; b=J4XYgZnD+M22pIwDGCZbdRS8rQ4A4zjJGmELBHoIvyM69YtOOWooUSq9ShbYDBinWSzrNH 5bGeN3+ECdL/2X43gJyAjN8W49RuoweMx5rPYBbqdQvfwg1YttRqYulbQvLi71W/PlSXLS FPQJufd6avagQ/+vhDBfwDSdMy1Wg/Y= X-MC-Unique: 2ttRYRHjO7SIuzxTwjZYTg-1 From: Pavel Hrdina To: libvir-list@redhat.com Subject: [libvirt PATCH 08/17] virstoragefile: move virStorageFileIsClusterFS into virfile Date: Mon, 14 Dec 2020 16:55:28 +0100 Message-Id: <699fa95140f57992834b85055d80003914fa85e4.1607960951.git.phrdina@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-loop: libvir-list@redhat.com X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=libvir-list-bounces@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" Signed-off-by: Pavel Hrdina Reviewed-by: Peter Krempa --- src/libvirt_private.syms | 2 +- src/qemu/qemu_migration.c | 2 +- src/util/virfile.c | 12 ++++++++++++ src/util/virfile.h | 1 + src/util/virstoragefile.c | 11 ----------- src/util/virstoragefile.h | 1 - 6 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 2d1cb7786d..57f3b12000 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2087,6 +2087,7 @@ virFileGetXAttr; virFileGetXAttrQuiet; virFileInData; virFileIsCDROM; +virFileIsClusterFS; virFileIsDir; virFileIsExecutable; virFileIsLink; @@ -3144,7 +3145,6 @@ virStorageFileGetSCSIKey; virStorageFileGetUniqueIdentifier; virStorageFileInit; virStorageFileInitAs; -virStorageFileIsClusterFS; virStorageFileParseBackingStoreStr; virStorageFileParseChainIndex; virStorageFileProbeFormat; diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index fcb33d0364..16c9f18e0a 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -1461,7 +1461,7 @@ qemuMigrationSrcIsSafe(virDomainDefPtr def, } else if (rc =3D=3D 0) { unsafe =3D true; } - if ((rc =3D virStorageFileIsClusterFS(src)) < 0) + if ((rc =3D virFileIsClusterFS(src)) < 0) return false; else if (rc =3D=3D 1) continue; diff --git a/src/util/virfile.c b/src/util/virfile.c index 6e16780e30..3f58b98248 100644 --- a/src/util/virfile.c +++ b/src/util/virfile.c @@ -3709,6 +3709,18 @@ int virFileIsSharedFS(const char *path) } =20 =20 +int virFileIsClusterFS(const char *path) +{ + /* These are coherent cluster filesystems known to be safe for + * migration with cache !=3D none + */ + return virFileIsSharedFSType(path, + VIR_FILE_SHFS_GFS2 | + VIR_FILE_SHFS_OCFS | + VIR_FILE_SHFS_CEPH); +} + + #if defined(__linux__) && defined(WITH_SYS_MOUNT_H) int virFileSetupDev(const char *path, diff --git a/src/util/virfile.h b/src/util/virfile.h index 45b75a059e..733d652ac9 100644 --- a/src/util/virfile.h +++ b/src/util/virfile.h @@ -223,6 +223,7 @@ enum { =20 int virFileIsSharedFSType(const char *path, int fstypes) ATTRIBUTE_NONNULL= (1); int virFileIsSharedFS(const char *path) ATTRIBUTE_NONNULL(1); +int virFileIsClusterFS(const char *path) ATTRIBUTE_NONNULL(1); int virFileIsMountPoint(const char *file) ATTRIBUTE_NONNULL(1); int virFileIsCDROM(const char *path) ATTRIBUTE_NONNULL(1) G_GNUC_WARN_UNUSED_RESULT; diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c index 66694bfcc0..3db85d8b89 100644 --- a/src/util/virstoragefile.c +++ b/src/util/virstoragefile.c @@ -1193,17 +1193,6 @@ virStorageFileGetMetadataFromFD(const char *path, } =20 =20 -int virStorageFileIsClusterFS(const char *path) -{ - /* These are coherent cluster filesystems known to be safe for - * migration with cache !=3D none - */ - return virFileIsSharedFSType(path, - VIR_FILE_SHFS_GFS2 | - VIR_FILE_SHFS_OCFS | - VIR_FILE_SHFS_CEPH); -} - #ifdef WITH_UDEV /* virStorageFileGetSCSIKey * @path: Path to the SCSI device diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h index 94bb889d84..2452b967b2 100644 --- a/src/util/virstoragefile.h +++ b/src/util/virstoragefile.h @@ -420,7 +420,6 @@ virStorageSourcePtr virStorageFileChainLookup(virStorag= eSourcePtr chain, virStorageSourcePtr *parent) ATTRIBUTE_NONNULL(1); =20 -int virStorageFileIsClusterFS(const char *path); bool virStorageIsFile(const char *path); bool virStorageIsRelative(const char *backing); =20 --=20 2.28.0 From nobody Thu May 16 01:02:08 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 63.128.21.124 as permitted sender) client-ip=63.128.21.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 63.128.21.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1607961441; cv=none; d=zohomail.com; s=zohoarc; b=Fu9oHSOvx8lG4M3tunKHHb2p2BQE0XxZabFU2qQPq1S8IOhdcxpSXulgXtj72TOp/Nk0Z5Hh1bcPUo+U/2TPsoOLzYJooRLjxJvikL66WomWXHVoHl9ZZ/fK2fQbDnfZx8GKHmP4GmASpnJ+7O/UyZGgPhCsmhAu6ayneC+N4QY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1607961441; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=Bv3eJuamD0cD6VgH7sGJtmDKoyoALWk0NAHOaVisj5w=; b=TFTsZTaTlRa66u/wKaIGHtLDTD5Ee13Ea0R09b5LUHbW0oJYaf1N8jezA29Y5t2IHMQ3c28ECOHKeZ5WGAjqchErcOQqZ3BISEHFnmq8JvTmajr6dva64mF4LFp8EtPxUlEPQV93lMNeb6/B390s+oq/C27pDxih0+xjlIXSoQw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 63.128.21.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [63.128.21.124]) by mx.zohomail.com with SMTPS id 1607961441622814.8489828117534; Mon, 14 Dec 2020 07:57:21 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-466-T5XDrelVNuOfgyFGRBSDpw-1; Mon, 14 Dec 2020 10:56:22 -0500 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id ADEC3801AAA; Mon, 14 Dec 2020 15:56:16 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 88AFB173EA; Mon, 14 Dec 2020 15:56:16 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 004AB5003C; Mon, 14 Dec 2020 15:56:15 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 0BEFtpIQ028580 for ; Mon, 14 Dec 2020 10:55:51 -0500 Received: by smtp.corp.redhat.com (Postfix) id 46EBA17B77; Mon, 14 Dec 2020 15:55:51 +0000 (UTC) Received: from antique-work.lan (unknown [10.40.194.243]) by smtp.corp.redhat.com (Postfix) with ESMTP id B86165D6D5 for ; Mon, 14 Dec 2020 15:55:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1607961438; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=Bv3eJuamD0cD6VgH7sGJtmDKoyoALWk0NAHOaVisj5w=; b=cTl9aoWPnjljNMMwkm6lKe7fW8PryHAFqLCUhRLRZFgmUpBkCazi7NbF/7q2swy/mcQlgK U/0jMvBFk7vtY8kILOP0rfJzKTjEwwFX0PZ0yHhm8dIgglcp34kgUB7pqn3uqARXisrwSr Qo1iQ1eGneGtwyNjEWbqe3jKnbksUFU= X-MC-Unique: T5XDrelVNuOfgyFGRBSDpw-1 From: Pavel Hrdina To: libvir-list@redhat.com Subject: [libvirt PATCH 09/17] virstoragefile: move virStorageIsFile into virfile Date: Mon, 14 Dec 2020 16:55:29 +0100 Message-Id: In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-loop: libvir-list@redhat.com X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=libvir-list-bounces@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" Signed-off-by: Pavel Hrdina --- src/libvirt_private.syms | 2 +- src/util/virfile.c | 21 +++++++++++++++++++++ src/util/virfile.h | 1 + src/util/virstoragefile.c | 26 +++----------------------- src/util/virstoragefile.h | 1 - 5 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 57f3b12000..0b560dfe45 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2090,6 +2090,7 @@ virFileIsCDROM; virFileIsClusterFS; virFileIsDir; virFileIsExecutable; +virFileIsFile; virFileIsLink; virFileIsMountPoint; virFileIsRegular; @@ -3156,7 +3157,6 @@ virStorageFileSupportsBackingChainTraversal; virStorageFileSupportsCreate; virStorageFileSupportsSecurityDriver; virStorageFileUnlink; -virStorageIsFile; virStorageIsRelative; virStorageNetHostDefClear; virStorageNetHostDefCopy; diff --git a/src/util/virfile.c b/src/util/virfile.c index 3f58b98248..7a7468b202 100644 --- a/src/util/virfile.c +++ b/src/util/virfile.c @@ -1995,6 +1995,27 @@ virFileIsCDROM(const char *path) #endif /* defined(__linux__) */ =20 =20 +bool +virFileIsFile(const char *backing) +{ + char *colon; + char *slash; + + if (!backing) + return false; + + colon =3D strchr(backing, ':'); + slash =3D strchr(backing, '/'); + + /* Reject anything that looks like a protocol (such as nbd: or + * rbd:); if someone really does want a relative file name that + * includes ':', they can always prefix './'. */ + if (colon && (!slash || colon < slash)) + return false; + return true; +} + + #if defined WITH_MNTENT_H && defined WITH_GETMNTENT_R static int virFileGetMountSubtreeImpl(const char *mtabpath, diff --git a/src/util/virfile.h b/src/util/virfile.h index 733d652ac9..dfd3188ff2 100644 --- a/src/util/virfile.h +++ b/src/util/virfile.h @@ -227,6 +227,7 @@ int virFileIsClusterFS(const char *path) ATTRIBUTE_NONN= ULL(1); int virFileIsMountPoint(const char *file) ATTRIBUTE_NONNULL(1); int virFileIsCDROM(const char *path) ATTRIBUTE_NONNULL(1) G_GNUC_WARN_UNUSED_RESULT; +bool virFileIsFile(const char *path); =20 int virFileGetMountSubtree(const char *mtabpath, const char *prefix, diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c index 3db85d8b89..f37802260b 100644 --- a/src/util/virstoragefile.c +++ b/src/util/virstoragefile.c @@ -756,26 +756,6 @@ virStorageFileMatchesVersion(int versionOffset, return false; } =20 -bool -virStorageIsFile(const char *backing) -{ - char *colon; - char *slash; - - if (!backing) - return false; - - colon =3D strchr(backing, ':'); - slash =3D strchr(backing, '/'); - - /* Reject anything that looks like a protocol (such as nbd: or - * rbd:); if someone really does want a relative file name that - * includes ':', they can always prefix './'. */ - if (colon && (!slash || colon < slash)) - return false; - return true; -} - =20 bool virStorageIsRelative(const char *backing) @@ -783,7 +763,7 @@ virStorageIsRelative(const char *backing) if (backing[0] =3D=3D '/') return false; =20 - if (!virStorageIsFile(backing)) + if (!virFileIsFile(backing)) return false; =20 return true; @@ -1450,7 +1430,7 @@ virStorageFileChainLookup(virStorageSourcePtr chain, { virStorageSourcePtr prev; const char *start =3D chain->path; - bool nameIsFile =3D virStorageIsFile(name); + bool nameIsFile =3D virFileIsFile(name); =20 if (!parent) parent =3D &prev; @@ -3794,7 +3774,7 @@ virStorageSourceNewFromBackingAbsolute(const char *pa= th, =20 *src =3D NULL; =20 - if (virStorageIsFile(path)) { + if (virFileIsFile(path)) { def->type =3D VIR_STORAGE_TYPE_FILE; =20 def->path =3D g_strdup(path); diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h index 2452b967b2..2a44a535a1 100644 --- a/src/util/virstoragefile.h +++ b/src/util/virstoragefile.h @@ -420,7 +420,6 @@ virStorageSourcePtr virStorageFileChainLookup(virStorag= eSourcePtr chain, virStorageSourcePtr *parent) ATTRIBUTE_NONNULL(1); =20 -bool virStorageIsFile(const char *path); bool virStorageIsRelative(const char *backing); =20 int virStorageFileGetSCSIKey(const char *path, --=20 2.28.0 From nobody Thu May 16 01:02:08 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) client-ip=216.205.24.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1607961447; cv=none; d=zohomail.com; s=zohoarc; b=kUJOwivBvYWADO5ViAQETfvfHFkrDq0jwXOBNhT/zSvVeb+R/W6UyeNYPxHzKotFDKY972lqIfFc3UhzrN1Tn/dTV3VbW3gTZVxucylWPaBc7PRn2P9LD+oLCLjC3xhzqUrwOIZKcAUuupxfTClNVKF2JisRMqO+gWk0tjOHy9Y= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1607961447; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=ZaQOb9OO9PEu3hgMp6tA+hw9tWVbdch+17yliwUVmuE=; b=hVWCNuv+v/NK6CEfeZ+RoKdzrPd5z2aJ+W5E5eIUtYyxz+w+I1nz2xo1XziLyRZMAsgT02pa4JNSPitScU8PIt9uhegZ35WivJZRnvT4/VZAHv3jKLX2QbWqhtfTSpOcH45gJM4rl61k/2zc7v+nN9MCFIWwUtRAbvLhUcOzI9g= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by mx.zohomail.com with SMTPS id 1607961447172906.461783179588; Mon, 14 Dec 2020 07:57:27 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-520-LlIVLbUxMcmMbQn24FcoDw-1; Mon, 14 Dec 2020 10:56:25 -0500 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 87D74107ACFE; Mon, 14 Dec 2020 15:56:19 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 32551E700; Mon, 14 Dec 2020 15:56:19 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id E95D950040; Mon, 14 Dec 2020 15:56:18 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 0BEFtqb1028593 for ; Mon, 14 Dec 2020 10:55:52 -0500 Received: by smtp.corp.redhat.com (Postfix) id 29F6F17B77; Mon, 14 Dec 2020 15:55:52 +0000 (UTC) Received: from antique-work.lan (unknown [10.40.194.243]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9B81F5D6D5 for ; Mon, 14 Dec 2020 15:55:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1607961444; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=ZaQOb9OO9PEu3hgMp6tA+hw9tWVbdch+17yliwUVmuE=; b=UksZZIgBQiJOI9LtMz8shlaSq4NWS276HYtf7dM8pQBlNDFMPl8qNmgNpSRz85hZsmSjo+ hiM6j0x5OPVsf5MlyygSy5Y8mt4uDvoHKuOVH6blUIomLLqEHZLB0UuQcu6yyQMIvcrn+s G2weoQVl951oNY2gnH2VTGvCsZi1JVM= X-MC-Unique: LlIVLbUxMcmMbQn24FcoDw-1 From: Pavel Hrdina To: libvir-list@redhat.com Subject: [libvirt PATCH 10/17] virstoragefile: move virStorageIsRelative into virfile Date: Mon, 14 Dec 2020 16:55:30 +0100 Message-Id: <1a5a60eb1bdfb0b42fbdb8b8befb71840e106140.1607960951.git.phrdina@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-loop: libvir-list@redhat.com X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=libvir-list-bounces@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" Signed-off-by: Pavel Hrdina --- src/libvirt_private.syms | 2 +- src/qemu/qemu_block.c | 2 +- src/qemu/qemu_snapshot.c | 2 +- src/util/virfile.c | 13 +++++++++++++ src/util/virfile.h | 2 ++ src/util/virstoragefile.c | 15 +-------------- src/util/virstoragefile.h | 2 -- 7 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 0b560dfe45..1bbf567847 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2094,6 +2094,7 @@ virFileIsFile; virFileIsLink; virFileIsMountPoint; virFileIsRegular; +virFileIsRelative; virFileIsSharedFS; virFileIsSharedFSType; virFileLength; @@ -3157,7 +3158,6 @@ virStorageFileSupportsBackingChainTraversal; virStorageFileSupportsCreate; virStorageFileSupportsSecurityDriver; virStorageFileUnlink; -virStorageIsRelative; virStorageNetHostDefClear; virStorageNetHostDefCopy; virStorageNetHostDefFree; diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c index 4640e339c0..0743db4d2c 100644 --- a/src/qemu/qemu_block.c +++ b/src/qemu/qemu_block.c @@ -3357,7 +3357,7 @@ qemuBlockUpdateRelativeBacking(virDomainObjPtr vm, if (rc < 0) return rc; =20 - if (backingStoreStr && virStorageIsRelative(backingStoreStr)) + if (backingStoreStr && virFileIsRelative(backingStoreStr)) n->backingStore->relPath =3D g_steal_pointer(&backingStoreStr); } =20 diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c index 15494c3415..6f64111ca8 100644 --- a/src/qemu/qemu_snapshot.c +++ b/src/qemu/qemu_snapshot.c @@ -1075,7 +1075,7 @@ qemuSnapshotDiskPrepareOne(virDomainObjPtr vm, if (virStorageFileGetBackingStoreStr(dd->src, &backingStor= eStr) < 0) return -1; if (backingStoreStr !=3D NULL) { - if (virStorageIsRelative(backingStoreStr)) + if (virFileIsRelative(backingStoreStr)) dd->relPath =3D g_steal_pointer(&backingStoreStr); } } diff --git a/src/util/virfile.c b/src/util/virfile.c index 7a7468b202..c3f0e7cabc 100644 --- a/src/util/virfile.c +++ b/src/util/virfile.c @@ -2016,6 +2016,19 @@ virFileIsFile(const char *backing) } =20 =20 +bool +virFileIsRelative(const char *path) +{ + if (path[0] =3D=3D '/') + return false; + + if (!virFileIsFile(path)) + return false; + + return true; +} + + #if defined WITH_MNTENT_H && defined WITH_GETMNTENT_R static int virFileGetMountSubtreeImpl(const char *mtabpath, diff --git a/src/util/virfile.h b/src/util/virfile.h index dfd3188ff2..06d9cffd88 100644 --- a/src/util/virfile.h +++ b/src/util/virfile.h @@ -228,6 +228,8 @@ int virFileIsMountPoint(const char *file) ATTRIBUTE_NON= NULL(1); int virFileIsCDROM(const char *path) ATTRIBUTE_NONNULL(1) G_GNUC_WARN_UNUSED_RESULT; bool virFileIsFile(const char *path); +bool virFileIsRelative(const char *path); + =20 int virFileGetMountSubtree(const char *mtabpath, const char *prefix, diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c index f37802260b..6ced28762a 100644 --- a/src/util/virstoragefile.c +++ b/src/util/virstoragefile.c @@ -757,19 +757,6 @@ virStorageFileMatchesVersion(int versionOffset, } =20 =20 -bool -virStorageIsRelative(const char *backing) -{ - if (backing[0] =3D=3D '/') - return false; - - if (!virFileIsFile(backing)) - return false; - - return true; -} - - static int virStorageFileProbeFormatFromBuf(const char *path, char *buf, @@ -3846,7 +3833,7 @@ virStorageSourceNewFromChild(virStorageSourcePtr pare= nt, =20 *child =3D NULL; =20 - if (virStorageIsRelative(parentRaw)) { + if (virFileIsRelative(parentRaw)) { if (!(def =3D virStorageSourceNewFromBackingRelative(parent, paren= tRaw))) return -1; } else { diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h index 2a44a535a1..d39486ad59 100644 --- a/src/util/virstoragefile.h +++ b/src/util/virstoragefile.h @@ -420,8 +420,6 @@ virStorageSourcePtr virStorageFileChainLookup(virStorag= eSourcePtr chain, virStorageSourcePtr *parent) ATTRIBUTE_NONNULL(1); =20 -bool virStorageIsRelative(const char *backing); - int virStorageFileGetSCSIKey(const char *path, char **key, bool ignoreError); --=20 2.28.0 From nobody Thu May 16 01:02:08 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 63.128.21.124 as permitted sender) client-ip=63.128.21.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 63.128.21.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1607961392; cv=none; d=zohomail.com; s=zohoarc; b=Npz5RSC2ePZ/CtwFBwOtFWe5PA+VowjGuV5/RI+qE8l7KUCVakQJNFHqNXM8BfzMeIx3oyT+7QQ9BXaJEAKvYmmYX2pYw8b+JElZlih/geojiKwsl5LZp//aYBCjg2fwwxNZQKvuhig0Zx3FvakmIiGFB/Ulkd7dahuM0aacenI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1607961392; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=buEgVe4Vtdn+QA4XgVVDDIK5lJOklqv/wc4wUYxotLI=; b=Dpcd0CjviiQjyzTABetdt2EIZFje2sm3Ts6Xk9v4/iNlbsDFalcORS74UZ18/gmJ6okDGoVfC3B7VVSZfa9KbV439C1rKFy6NHiX4N4pdkoTKN4GoP6zlSB5LZymu3Z0uPSjHlNF1M+ftD6Tmbe6vkTQDIKpeHnJne4eneLmIBE= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 63.128.21.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [63.128.21.124]) by mx.zohomail.com with SMTPS id 1607961392471354.5923884799463; Mon, 14 Dec 2020 07:56:32 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-22-RlRs-dE9NZG7aw_nxSxbBA-1; Mon, 14 Dec 2020 10:56:27 -0500 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 3129EE75A; Mon, 14 Dec 2020 15:56:22 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 0A5FC10016FE; Mon, 14 Dec 2020 15:56:22 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id C59AA1809CA6; Mon, 14 Dec 2020 15:56:21 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 0BEFtrue028601 for ; Mon, 14 Dec 2020 10:55:53 -0500 Received: by smtp.corp.redhat.com (Postfix) id 38AB25D6D5; Mon, 14 Dec 2020 15:55:53 +0000 (UTC) Received: from antique-work.lan (unknown [10.40.194.243]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7DBD462467 for ; Mon, 14 Dec 2020 15:55:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1607961390; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=buEgVe4Vtdn+QA4XgVVDDIK5lJOklqv/wc4wUYxotLI=; b=TFlzr3M9fkgNhl2UvhG9kKJP30mIcHEh5eFEz95t8VRxxiIvxVkWspxpBAxKx2i4lhnfBd 58BQwjchGLaEXB3IX941hSw05INLupN/vor7Ebmm8wW33cq0NrRXxtYk8Z4JECjLncAn+q ADaYRip5OKkJ8vO2VMtSMSPvO0Hj25k= X-MC-Unique: RlRs-dE9NZG7aw_nxSxbBA-1 From: Pavel Hrdina To: libvir-list@redhat.com Subject: [libvirt PATCH 11/17] virstoragefile: change virStorageSource->drv to void pointer Date: Mon, 14 Dec 2020 16:55:31 +0100 Message-Id: <19329efa29a0ca808d04d241ad166791caa4bc0c.1607960951.git.phrdina@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-loop: libvir-list@redhat.com X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=libvir-list-bounces@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" This will allow following patches to move virStorageSource into conf directory and virStorageDriverData into a new storage_file directory. Signed-off-by: Pavel Hrdina Reviewed-by: Peter Krempa --- src/storage/storage_file_fs.c | 21 +++-- src/storage/storage_file_gluster.c | 31 +++++--- src/util/virstoragefile.c | 118 +++++++++++++++++++++-------- src/util/virstoragefile.h | 5 +- src/util/virstoragefilebackend.h | 2 + 5 files changed, 122 insertions(+), 55 deletions(-) diff --git a/src/storage/storage_file_fs.c b/src/storage/storage_file_fs.c index b379a8ca8e..5a44ef8c2d 100644 --- a/src/storage/storage_file_fs.c +++ b/src/storage/storage_file_fs.c @@ -51,7 +51,8 @@ struct _virStorageFileBackendFsPriv { static void virStorageFileBackendFileDeinit(virStorageSourcePtr src) { - virStorageFileBackendFsPrivPtr priv =3D src->drv->priv; + virStorageDriverDataPtr drv =3D src->drv; + virStorageFileBackendFsPrivPtr priv =3D drv->priv; =20 VIR_DEBUG("deinitializing FS storage file %p (%s:%s)", src, virStorageTypeToString(virStorageSourceGetActualType(src)), @@ -66,16 +67,17 @@ virStorageFileBackendFileDeinit(virStorageSourcePtr src) static int virStorageFileBackendFileInit(virStorageSourcePtr src) { + virStorageDriverDataPtr drv =3D src->drv; virStorageFileBackendFsPrivPtr priv =3D NULL; =20 VIR_DEBUG("initializing FS storage file %p (%s:%s)[%u:%u]", src, virStorageTypeToString(virStorageSourceGetActualType(src)), src->path, - (unsigned int)src->drv->uid, (unsigned int)src->drv->gid); + (unsigned int)drv->uid, (unsigned int)drv->gid); =20 priv =3D g_new0(virStorageFileBackendFsPriv, 1); =20 - src->drv->priv =3D priv; + drv->priv =3D priv; =20 return 0; } @@ -84,10 +86,11 @@ virStorageFileBackendFileInit(virStorageSourcePtr src) static int virStorageFileBackendFileCreate(virStorageSourcePtr src) { + virStorageDriverDataPtr drv =3D src->drv; VIR_AUTOCLOSE fd =3D -1; =20 if ((fd =3D virFileOpenAs(src->path, O_WRONLY | O_TRUNC | O_CREAT, S_I= RUSR | S_IWUSR, - src->drv->uid, src->drv->gid, 0)) < 0) { + drv->uid, drv->gid, 0)) < 0) { errno =3D -fd; return -1; } @@ -117,11 +120,12 @@ virStorageFileBackendFileRead(virStorageSourcePtr src, size_t len, char **buf) { + virStorageDriverDataPtr drv =3D src->drv; ssize_t ret =3D -1; VIR_AUTOCLOSE fd =3D -1; =20 if ((fd =3D virFileOpenAs(src->path, O_RDONLY, 0, - src->drv->uid, src->drv->gid, 0)) < 0) { + drv->uid, drv->gid, 0)) < 0) { virReportSystemError(-fd, _("Failed to open file '%s'"), src->path); return -1; @@ -146,7 +150,8 @@ virStorageFileBackendFileRead(virStorageSourcePtr src, static const char * virStorageFileBackendFileGetUniqueIdentifier(virStorageSourcePtr src) { - virStorageFileBackendFsPrivPtr priv =3D src->drv->priv; + virStorageDriverDataPtr drv =3D src->drv; + virStorageFileBackendFsPrivPtr priv =3D drv->priv; =20 if (!priv->canonpath) { if (!(priv->canonpath =3D virFileCanonicalizePath(src->path))) { @@ -164,8 +169,10 @@ static int virStorageFileBackendFileAccess(virStorageSourcePtr src, int mode) { + virStorageDriverDataPtr drv =3D src->drv; + return virFileAccessibleAs(src->path, mode, - src->drv->uid, src->drv->gid); + drv->uid, drv->gid); } =20 =20 diff --git a/src/storage/storage_file_gluster.c b/src/storage/storage_file_= gluster.c index c84af8a4e8..e26dfdfd99 100644 --- a/src/storage/storage_file_gluster.c +++ b/src/storage/storage_file_gluster.c @@ -46,7 +46,8 @@ struct _virStorageFileBackendGlusterPriv { static void virStorageFileBackendGlusterDeinit(virStorageSourcePtr src) { - virStorageFileBackendGlusterPrivPtr priv =3D src->drv->priv; + virStorageDriverDataPtr drv =3D src->drv; + virStorageFileBackendGlusterPrivPtr priv =3D drv->priv; =20 VIR_DEBUG("deinitializing gluster storage file %p (gluster://%s:%u/%s%= s)", src, src->hosts->name, src->hosts->port, src->volume, src->p= ath); @@ -56,7 +57,7 @@ virStorageFileBackendGlusterDeinit(virStorageSourcePtr sr= c) VIR_FREE(priv->canonpath); =20 VIR_FREE(priv); - src->drv->priv =3D NULL; + drv->priv =3D NULL; } =20 static int @@ -99,6 +100,7 @@ virStorageFileBackendGlusterInitServer(virStorageFileBac= kendGlusterPrivPtr priv, static int virStorageFileBackendGlusterInit(virStorageSourcePtr src) { + virStorageDriverDataPtr drv =3D src->drv; virStorageFileBackendGlusterPrivPtr priv =3D NULL; size_t i; =20 @@ -114,7 +116,7 @@ virStorageFileBackendGlusterInit(virStorageSourcePtr sr= c) VIR_DEBUG("initializing gluster storage file %p " "(priv=3D'%p' volume=3D'%s' path=3D'%s') as [%u:%u]", src, priv, src->volume, src->path, - (unsigned int)src->drv->uid, (unsigned int)src->drv->gid); + (unsigned int)drv->uid, (unsigned int)drv->gid); =20 if (!(priv->vol =3D glfs_new(src->volume))) { virReportOOMError(); @@ -133,7 +135,7 @@ virStorageFileBackendGlusterInit(virStorageSourcePtr sr= c) goto error; } =20 - src->drv->priv =3D priv; + drv->priv =3D priv; =20 return 0; =20 @@ -149,7 +151,8 @@ virStorageFileBackendGlusterInit(virStorageSourcePtr sr= c) static int virStorageFileBackendGlusterCreate(virStorageSourcePtr src) { - virStorageFileBackendGlusterPrivPtr priv =3D src->drv->priv; + virStorageDriverDataPtr drv =3D src->drv; + virStorageFileBackendGlusterPrivPtr priv =3D drv->priv; glfs_fd_t *fd =3D NULL; =20 if (!(fd =3D glfs_creat(priv->vol, src->path, @@ -164,7 +167,8 @@ virStorageFileBackendGlusterCreate(virStorageSourcePtr = src) static int virStorageFileBackendGlusterUnlink(virStorageSourcePtr src) { - virStorageFileBackendGlusterPrivPtr priv =3D src->drv->priv; + virStorageDriverDataPtr drv =3D src->drv; + virStorageFileBackendGlusterPrivPtr priv =3D drv->priv; =20 return glfs_unlink(priv->vol, src->path); } @@ -174,7 +178,8 @@ static int virStorageFileBackendGlusterStat(virStorageSourcePtr src, struct stat *st) { - virStorageFileBackendGlusterPrivPtr priv =3D src->drv->priv; + virStorageDriverDataPtr drv =3D src->drv; + virStorageFileBackendGlusterPrivPtr priv =3D drv->priv; =20 return glfs_stat(priv->vol, src->path, st); } @@ -186,7 +191,8 @@ virStorageFileBackendGlusterRead(virStorageSourcePtr sr= c, size_t len, char **buf) { - virStorageFileBackendGlusterPrivPtr priv =3D src->drv->priv; + virStorageDriverDataPtr drv =3D src->drv; + virStorageFileBackendGlusterPrivPtr priv =3D drv->priv; glfs_fd_t *fd =3D NULL; ssize_t ret =3D -1; char *s; @@ -241,7 +247,8 @@ static int virStorageFileBackendGlusterAccess(virStorageSourcePtr src, int mode) { - virStorageFileBackendGlusterPrivPtr priv =3D src->drv->priv; + virStorageDriverDataPtr drv =3D src->drv; + virStorageFileBackendGlusterPrivPtr priv =3D drv->priv; =20 return glfs_access(priv->vol, src->path, mode); } @@ -294,7 +301,8 @@ virStorageFileBackendGlusterReadlinkCallback(const char= *path, static const char * virStorageFileBackendGlusterGetUniqueIdentifier(virStorageSourcePtr src) { - virStorageFileBackendGlusterPrivPtr priv =3D src->drv->priv; + virStorageDriverDataPtr drv =3D src->drv; + virStorageFileBackendGlusterPrivPtr priv =3D drv->priv; g_autofree char *filePath =3D NULL; =20 if (priv->canonpath) @@ -320,7 +328,8 @@ virStorageFileBackendGlusterChown(const virStorageSourc= e *src, uid_t uid, gid_t gid) { - virStorageFileBackendGlusterPrivPtr priv =3D src->drv->priv; + virStorageDriverDataPtr drv =3D src->drv; + virStorageFileBackendGlusterPrivPtr priv =3D drv->priv; =20 return glfs_chown(priv->vol, src->path, uid, gid); } diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c index 6ced28762a..524204a56c 100644 --- a/src/util/virstoragefile.c +++ b/src/util/virstoragefile.c @@ -4521,7 +4521,8 @@ virStorageFileGetBackendForSupportCheck(const virStor= ageSource *src, } =20 if (src->drv) { - *backend =3D src->drv->backend; + virStorageDriverDataPtr drv =3D src->drv; + *backend =3D drv->backend; return 1; } =20 @@ -4617,12 +4618,16 @@ virStorageFileSupportsCreate(const virStorageSource= *src) void virStorageFileDeinit(virStorageSourcePtr src) { + virStorageDriverDataPtr drv =3D NULL; + if (!virStorageFileIsInitialized(src)) return; =20 - if (src->drv->backend && - src->drv->backend->backendDeinit) - src->drv->backend->backendDeinit(src); + drv =3D src->drv; + + if (drv->backend && + drv->backend->backendDeinit) + drv->backend->backendDeinit(src); =20 VIR_FREE(src->drv); } @@ -4646,26 +4651,28 @@ virStorageFileInitAs(virStorageSourcePtr src, uid_t uid, gid_t gid) { int actualType =3D virStorageSourceGetActualType(src); - src->drv =3D g_new0(virStorageDriverData, 1); + virStorageDriverDataPtr drv =3D g_new0(virStorageDriverData, 1); + + src->drv =3D drv; =20 if (uid =3D=3D (uid_t) -1) - src->drv->uid =3D geteuid(); + drv->uid =3D geteuid(); else - src->drv->uid =3D uid; + drv->uid =3D uid; =20 if (gid =3D=3D (gid_t) -1) - src->drv->gid =3D getegid(); + drv->gid =3D getegid(); else - src->drv->gid =3D gid; + drv->gid =3D gid; =20 if (virStorageFileBackendForType(actualType, src->protocol, true, - &src->drv->backend) < 0) + &drv->backend) < 0) goto error; =20 - if (src->drv->backend->backendInit && - src->drv->backend->backendInit(src) < 0) + if (drv->backend->backendInit && + drv->backend->backendInit(src) < 0) goto error; =20 return 0; @@ -4700,15 +4707,22 @@ virStorageFileInit(virStorageSourcePtr src) int virStorageFileCreate(virStorageSourcePtr src) { + virStorageDriverDataPtr drv =3D NULL; int ret; =20 - if (!virStorageFileIsInitialized(src) || - !src->drv->backend->storageFileCreate) { + if (!virStorageFileIsInitialized(src)) { errno =3D ENOSYS; return -2; } =20 - ret =3D src->drv->backend->storageFileCreate(src); + drv =3D src->drv; + + if (!drv->backend->storageFileCreate) { + errno =3D ENOSYS; + return -2; + } + + ret =3D drv->backend->storageFileCreate(src); =20 VIR_DEBUG("created storage file %p: ret=3D%d, errno=3D%d", src, ret, errno); @@ -4730,15 +4744,22 @@ virStorageFileCreate(virStorageSourcePtr src) int virStorageFileUnlink(virStorageSourcePtr src) { + virStorageDriverDataPtr drv =3D NULL; int ret; =20 - if (!virStorageFileIsInitialized(src) || - !src->drv->backend->storageFileUnlink) { + if (!virStorageFileIsInitialized(src)) { errno =3D ENOSYS; return -2; } =20 - ret =3D src->drv->backend->storageFileUnlink(src); + drv =3D src->drv; + + if (!drv->backend->storageFileUnlink) { + errno =3D ENOSYS; + return -2; + } + + ret =3D drv->backend->storageFileUnlink(src); =20 VIR_DEBUG("unlinked storage file %p: ret=3D%d, errno=3D%d", src, ret, errno); @@ -4760,15 +4781,22 @@ int virStorageFileStat(virStorageSourcePtr src, struct stat *st) { + virStorageDriverDataPtr drv =3D NULL; int ret; =20 - if (!virStorageFileIsInitialized(src) || - !src->drv->backend->storageFileStat) { + if (!virStorageFileIsInitialized(src)) { errno =3D ENOSYS; return -2; } =20 - ret =3D src->drv->backend->storageFileStat(src, st); + drv =3D src->drv; + + if (!drv->backend->storageFileStat) { + errno =3D ENOSYS; + return -2; + } + + ret =3D drv->backend->storageFileStat(src, st); =20 VIR_DEBUG("stat of storage file %p: ret=3D%d, errno=3D%d", src, ret, errno); @@ -4795,6 +4823,7 @@ virStorageFileRead(virStorageSourcePtr src, size_t len, char **buf) { + virStorageDriverDataPtr drv =3D NULL; ssize_t ret; =20 if (!virStorageFileIsInitialized(src)) { @@ -4803,10 +4832,12 @@ virStorageFileRead(virStorageSourcePtr src, return -1; } =20 - if (!src->drv->backend->storageFileRead) + drv =3D src->drv; + + if (!drv->backend->storageFileRead) return -2; =20 - ret =3D src->drv->backend->storageFileRead(src, offset, len, buf); + ret =3D drv->backend->storageFileRead(src, offset, len, buf); =20 VIR_DEBUG("read '%zd' bytes from storage '%p' starting at offset '%zu'= ", ret, src, offset); @@ -4826,13 +4857,17 @@ virStorageFileRead(virStorageSourcePtr src, const char * virStorageFileGetUniqueIdentifier(virStorageSourcePtr src) { + virStorageDriverDataPtr drv =3D NULL; + if (!virStorageFileIsInitialized(src)) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("storage file backend not initialized")); return NULL; } =20 - if (!src->drv->backend->storageFileGetUniqueIdentifier) { + drv =3D src->drv; + + if (!drv->backend->storageFileGetUniqueIdentifier) { virReportError(VIR_ERR_INTERNAL_ERROR, _("unique storage file identifier not implemented f= or " "storage type %s (protocol: %s)'"), @@ -4841,7 +4876,7 @@ virStorageFileGetUniqueIdentifier(virStorageSourcePtr= src) return NULL; } =20 - return src->drv->backend->storageFileGetUniqueIdentifier(src); + return drv->backend->storageFileGetUniqueIdentifier(src); } =20 =20 @@ -4859,13 +4894,21 @@ int virStorageFileAccess(virStorageSourcePtr src, int mode) { - if (!virStorageFileIsInitialized(src) || - !src->drv->backend->storageFileAccess) { + virStorageDriverDataPtr drv =3D NULL; + + if (!virStorageFileIsInitialized(src)) { + errno =3D ENOSYS; + return -2; + } + + drv =3D src->drv; + + if (!drv->backend->storageFileAccess) { errno =3D ENOSYS; return -2; } =20 - return src->drv->backend->storageFileAccess(src, mode); + return drv->backend->storageFileAccess(src, mode); } =20 =20 @@ -4885,8 +4928,16 @@ virStorageFileChown(const virStorageSource *src, uid_t uid, gid_t gid) { - if (!virStorageFileIsInitialized(src) || - !src->drv->backend->storageFileChown) { + virStorageDriverDataPtr drv =3D NULL; + + if (!virStorageFileIsInitialized(src)) { + errno =3D ENOSYS; + return -2; + } + + drv =3D src->drv; + + if (!drv->backend->storageFileChown) { errno =3D ENOSYS; return -2; } @@ -4894,7 +4945,7 @@ virStorageFileChown(const virStorageSource *src, VIR_DEBUG("chown of storage file %p to %u:%u", src, (unsigned int)uid, (unsigned int)gid); =20 - return src->drv->backend->storageFileChown(src, uid, gid); + return drv->backend->storageFileChown(src, uid, gid); } =20 =20 @@ -4914,8 +4965,9 @@ virStorageFileReportBrokenChain(int errcode, virStorageSourcePtr parent) { if (src->drv) { - unsigned int access_user =3D src->drv->uid; - unsigned int access_group =3D src->drv->gid; + virStorageDriverDataPtr drv =3D src->drv; + unsigned int access_user =3D drv->uid; + unsigned int access_group =3D drv->gid; =20 if (src =3D=3D parent) { virReportSystemError(errcode, diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h index d39486ad59..a1e0afb28f 100644 --- a/src/util/virstoragefile.h +++ b/src/util/virstoragefile.h @@ -262,9 +262,6 @@ struct _virStorageSourceSlice { }; =20 =20 -typedef struct _virStorageDriverData virStorageDriverData; -typedef virStorageDriverData *virStorageDriverDataPtr; - typedef struct _virStorageSource virStorageSource; typedef virStorageSource *virStorageSourcePtr; =20 @@ -334,7 +331,7 @@ struct _virStorageSource { virStorageSourcePtr backingStore; =20 /* metadata for storage driver access to remote and local volumes */ - virStorageDriverDataPtr drv; + void *drv; =20 /* metadata about storage image which need separate fields */ /* Relative name by which this image was opened from its parent, or NU= LL diff --git a/src/util/virstoragefilebackend.h b/src/util/virstoragefileback= end.h index c7af77bf8f..43b36e95bc 100644 --- a/src/util/virstoragefilebackend.h +++ b/src/util/virstoragefilebackend.h @@ -28,6 +28,8 @@ typedef struct _virStorageFileBackend virStorageFileBackend; typedef virStorageFileBackend *virStorageFileBackendPtr; =20 +typedef struct _virStorageDriverData virStorageDriverData; +typedef virStorageDriverData *virStorageDriverDataPtr; struct _virStorageDriverData { virStorageFileBackendPtr backend; void *priv; --=20 2.28.0 From nobody Thu May 16 01:02:08 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) client-ip=216.205.24.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1607961473; cv=none; d=zohomail.com; s=zohoarc; b=bPTa53z6trgpJod5rsKKen2slncJiMRtD4ZYOvCbB8xTOxbW4MgHvwIuuKKYZn7robMdZ6mu/rr2LcsyvARYpZhsedY/K1aHGp3/OInlOTgU3qOUhCnKUVXg3xk8puAR99z5cTQWnoFwJ8A0yWK+72njLfS6gvsI9nDnw/2HCrc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1607961473; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=X+rZJqOUVx5xI/qws4PxfKue3xvr9ER2Jp5V7hepboI=; b=H+oJFehtNU0jgfMNxkIBip6PJNluRwup8dpq16iTuE0U7BznENbCtW4XSllKi91/g3o14djRb7SQNSIVt3BzRSHvlWSnpHdl5pJvsYdf1d4ia/RMxzVoeqCmwt+EE2mY8EDcTm/AvxB8vzmO27XDbvdgC7me2/LMpx6PzoWcj4g= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by mx.zohomail.com with SMTPS id 1607961472922637.4329416961156; Mon, 14 Dec 2020 07:57:52 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-344-odn3oszqOwqMBV7Mtn-ZNw-1; Mon, 14 Dec 2020 10:57:20 -0500 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id CD616C280; Mon, 14 Dec 2020 15:56:07 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id A47122BCDF; Mon, 14 Dec 2020 15:56:07 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 68E831809CA8; Mon, 14 Dec 2020 15:56:07 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 0BEFtsOw028607 for ; Mon, 14 Dec 2020 10:55:54 -0500 Received: by smtp.corp.redhat.com (Postfix) id 1B59A17B77; Mon, 14 Dec 2020 15:55:54 +0000 (UTC) Received: from antique-work.lan (unknown [10.40.194.243]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8C79C5D6D5 for ; Mon, 14 Dec 2020 15:55:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1607961469; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=X+rZJqOUVx5xI/qws4PxfKue3xvr9ER2Jp5V7hepboI=; b=dpw6ImlPBS65AXF4LLei4O36tjCdh2iyPIdq/+NbImMIn1iBBUyAgqR+MB0q7mNXegODsf KMxUgt0h8fMNCc7JA77H/ZSjDkmNof87815gJnYRB7lshQuAgneM0JTl2RQOazOtg/UWdN VKnuJ0KWKuOUTdfvcU+V1M5YKSvNHoU= X-MC-Unique: odn3oszqOwqMBV7Mtn-ZNw-1 From: Pavel Hrdina To: libvir-list@redhat.com Subject: [libvirt PATCH 12/17] storage: move storage file sources to separate directory Date: Mon, 14 Dec 2020 16:55:32 +0100 Message-Id: In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-loop: libvir-list@redhat.com X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=libvir-list-bounces@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" Introduce a new storage_file directory where we will keep storage file related code. Signed-off-by: Pavel Hrdina --- po/POTFILES.in | 4 +- src/meson.build | 1 + src/storage/meson.build | 30 +-------------- src/storage_file/meson.build | 38 +++++++++++++++++++ .../storage_file_fs.c | 0 .../storage_file_fs.h | 0 .../storage_file_gluster.c | 0 .../storage_file_gluster.h | 0 8 files changed, 43 insertions(+), 30 deletions(-) create mode 100644 src/storage_file/meson.build rename src/{storage =3D> storage_file}/storage_file_fs.c (100%) rename src/{storage =3D> storage_file}/storage_file_fs.h (100%) rename src/{storage =3D> storage_file}/storage_file_gluster.c (100%) rename src/{storage =3D> storage_file}/storage_file_gluster.h (100%) diff --git a/po/POTFILES.in b/po/POTFILES.in index 14636d4b93..e9fc3991f1 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -222,9 +222,9 @@ @SRCDIR@src/storage/storage_backend_vstorage.c @SRCDIR@src/storage/storage_backend_zfs.c @SRCDIR@src/storage/storage_driver.c -@SRCDIR@src/storage/storage_file_fs.c -@SRCDIR@src/storage/storage_file_gluster.c @SRCDIR@src/storage/storage_util.c +@SRCDIR@src/storage_file/storage_file_fs.c +@SRCDIR@src/storage_file/storage_file_gluster.c @SRCDIR@src/test/test_driver.c @SRCDIR@src/util/iohelper.c @SRCDIR@src/util/viralloc.c diff --git a/src/meson.build b/src/meson.build index 7c478219d6..3aa9498b98 100644 --- a/src/meson.build +++ b/src/meson.build @@ -266,6 +266,7 @@ subdir('nwfilter') subdir('secret') subdir('security') subdir('storage') +subdir('storage_file') =20 subdir('bhyve') subdir('esx') diff --git a/src/storage/meson.build b/src/storage/meson.build index b4cefe9a89..8537359e93 100644 --- a/src/storage/meson.build +++ b/src/storage/meson.build @@ -15,10 +15,6 @@ storage_backend_fs_sources =3D [ 'storage_backend_fs.c', ] =20 -stoarge_file_fs_sources =3D [ - 'storage_file_fs.c', -] - storage_backend_disk_sources =3D [ 'storage_backend_disk.c', ] @@ -31,10 +27,6 @@ storage_backend_gluster_sources =3D [ 'storage_backend_gluster.c', ] =20 -storage_file_gluster_sources =3D [ - 'storage_file_gluster.c', -] - storage_backend_iscsi_sources =3D [ 'storage_backend_iscsi.c', ] @@ -72,7 +64,6 @@ storage_backend_zfs_sources =3D [ ] =20 storage_backend_install_dir =3D libdir / 'libvirt' / 'storage-backend' -storage_file_install_dir =3D libdir / 'libvirt' / 'storage-file' =20 if conf.has('WITH_STORAGE') storage_driver_impl_lib =3D static_library( @@ -109,14 +100,6 @@ if conf.has('WITH_STORAGE') 'install_dir': storage_backend_install_dir, } =20 - virt_modules +=3D { - 'name': 'virt_storage_file_fs', - 'sources': [ - files(stoarge_file_fs_sources), - ], - 'install_dir': storage_file_install_dir, - } - virt_daemons +=3D { 'name': 'virtstoraged', 'c_args': [ @@ -181,17 +164,6 @@ if conf.has('WITH_STORAGE_GLUSTER') ], 'install_dir': storage_backend_install_dir, } - - virt_modules +=3D { - 'name': 'virt_storage_file_gluster', - 'sources': [ - files(storage_file_gluster_sources), - ], - 'deps': [ - glusterfs_dep, - ], - 'install_dir': storage_file_install_dir, - } endif =20 if conf.has('WITH_STORAGE_ISCSI') @@ -303,3 +275,5 @@ if conf.has('WITH_STORAGE_ZFS') 'install_dir': storage_backend_install_dir, } endif + +storage_inc_dir =3D include_directories('.') diff --git a/src/storage_file/meson.build b/src/storage_file/meson.build new file mode 100644 index 0000000000..20eb0176fc --- /dev/null +++ b/src/storage_file/meson.build @@ -0,0 +1,38 @@ +stoarge_file_fs_sources =3D [ + 'storage_file_fs.c', +] + +storage_file_gluster_sources =3D [ + 'storage_file_gluster.c', +] + +storage_file_install_dir =3D libdir / 'libvirt' / 'storage-file' + +if conf.has('WITH_STORAGE') + virt_modules +=3D { + 'name': 'virt_storage_file_fs', + 'sources': [ + files(stoarge_file_fs_sources), + ], + 'include': [ + storage_inc_dir, + ], + 'install_dir': storage_file_install_dir, + } +endif + +if conf.has('WITH_STORAGE_GLUSTER') + virt_modules +=3D { + 'name': 'virt_storage_file_gluster', + 'sources': [ + files(storage_file_gluster_sources), + ], + 'include': [ + storage_inc_dir, + ], + 'deps': [ + glusterfs_dep, + ], + 'install_dir': storage_file_install_dir, + } +endif diff --git a/src/storage/storage_file_fs.c b/src/storage_file/storage_file_= fs.c similarity index 100% rename from src/storage/storage_file_fs.c rename to src/storage_file/storage_file_fs.c diff --git a/src/storage/storage_file_fs.h b/src/storage_file/storage_file_= fs.h similarity index 100% rename from src/storage/storage_file_fs.h rename to src/storage_file/storage_file_fs.h diff --git a/src/storage/storage_file_gluster.c b/src/storage_file/storage_= file_gluster.c similarity index 100% rename from src/storage/storage_file_gluster.c rename to src/storage_file/storage_file_gluster.c diff --git a/src/storage/storage_file_gluster.h b/src/storage_file/storage_= file_gluster.h similarity index 100% rename from src/storage/storage_file_gluster.h rename to src/storage_file/storage_file_gluster.h --=20 2.28.0 From nobody Thu May 16 01:02:08 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 63.128.21.124 as permitted sender) client-ip=63.128.21.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 63.128.21.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1607961441; cv=none; d=zohomail.com; s=zohoarc; b=QG09o32fN46BuoMRJgmfloYgAbS3MCMVQE5Xux8Oky8Lr64vtH4clcczc3/kmsFMV119sRsZegxTrxwkuTV79b3/PWB9ST5ual3h1WzaKD8hrVAP+4qiim2uOUKdBBBcxPapr41F17CmRJ3cZcaRhgpajWBRvVXCx3rH9FZQa2s= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1607961440; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=L/Bd2ZjyviCxIaqN9cHbtP7gyIxIr5EhmGeC9cg4HII=; b=HgaVKSMUcKpW5dMld5WLEjW38PKBl4v3kShV3qKBVnGzwDAmB+Z5LtnWBK3IWamb4c6ftq/bXCzljrfuvlL3rJBRo6G4bxzlVkMUVPtCLdDfhOImbZBkreyjx5uUbvBfpkQMBhgXnRZVf1yc0nddQNL+Xc2XwMt7aa1T5QrzJHo= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 63.128.21.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [63.128.21.124]) by mx.zohomail.com with SMTPS id 1607961439407434.2740649693575; Mon, 14 Dec 2020 07:57:19 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-12-JxDkn7w2MiuMqKy69b8ncg-1; Mon, 14 Dec 2020 10:56:20 -0500 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id D66748015FC; Mon, 14 Dec 2020 15:56:10 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id A1DAE17B77; Mon, 14 Dec 2020 15:56:10 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 6101E50036; Mon, 14 Dec 2020 15:56:10 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 0BEFtt2E028630 for ; Mon, 14 Dec 2020 10:55:55 -0500 Received: by smtp.corp.redhat.com (Postfix) id B215762680; Mon, 14 Dec 2020 15:55:55 +0000 (UTC) Received: from antique-work.lan (unknown [10.40.194.243]) by smtp.corp.redhat.com (Postfix) with ESMTP id 766775D6D5 for ; Mon, 14 Dec 2020 15:55:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1607961434; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=L/Bd2ZjyviCxIaqN9cHbtP7gyIxIr5EhmGeC9cg4HII=; b=KNtrjKbKkl1OqDZdJ07gakg8aPRZqzRFgOkKak51V82D5HOx0w9z434kpHiastED81vcSh W60YcWpM65J3c7QeG78C62Lx2dE8vk1XMhiNF7XMFSqVhQX3Parsh7cazVY8cCeh/juf1A uA7cOeUT/4nV8i8BYK5DCCpKVvqSEc0= X-MC-Unique: JxDkn7w2MiuMqKy69b8ncg-1 From: Pavel Hrdina To: libvir-list@redhat.com Subject: [libvirt PATCH 13/17] util: extract virStorageFile code into storage_file Date: Mon, 14 Dec 2020 16:55:33 +0100 Message-Id: In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-loop: libvir-list@redhat.com X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=libvir-list-bounces@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" Up until now we had a runtime code and XML related code in the same source file inside util directory. This patch takes the runtime part and extracts it into the new storage_file directory. Signed-off-by: Pavel Hrdina --- po/POTFILES.in | 1 + src/libvirt_private.syms | 71 +- src/libxl/meson.build | 1 + src/libxl/xen_xl.c | 1 + src/qemu/meson.build | 1 + src/qemu/qemu_backup.c | 1 + src/qemu/qemu_block.c | 1 + src/qemu/qemu_domain.c | 1 + src/qemu/qemu_driver.c | 1 + src/qemu/qemu_hotplug.c | 1 + src/qemu/qemu_process.c | 1 + src/qemu/qemu_snapshot.c | 1 + src/storage/meson.build | 4 + src/storage/storage_backend_gluster.c | 1 + src/storage/storage_util.c | 1 + src/storage_file/meson.build | 18 + src/storage_file/storage_file.c | 3845 +++++++++++++++++++++++ src/storage_file/storage_file.h | 197 ++ src/storage_file/storage_file_gluster.c | 1 + src/util/virstoragefile.c | 3783 +--------------------- src/util/virstoragefile.h | 118 - tests/meson.build | 4 +- tests/qemublocktest.c | 1 + tests/virstoragetest.c | 1 + 24 files changed, 4120 insertions(+), 3936 deletions(-) create mode 100644 src/storage_file/storage_file.c create mode 100644 src/storage_file/storage_file.h diff --git a/po/POTFILES.in b/po/POTFILES.in index e9fc3991f1..6d6678bd36 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -223,6 +223,7 @@ @SRCDIR@src/storage/storage_backend_zfs.c @SRCDIR@src/storage/storage_driver.c @SRCDIR@src/storage/storage_util.c +@SRCDIR@src/storage_file/storage_file.c @SRCDIR@src/storage_file/storage_file_fs.c @SRCDIR@src/storage_file/storage_file_gluster.c @SRCDIR@src/test/test_driver.c diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 1bbf567847..43be8dd61a 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1618,6 +1618,43 @@ virSecurityManagerVerify; virSecurityXATTRNamespaceDefined; =20 =20 +# storage_file/storage_file.h +virStorageFileAccess; +virStorageFileCanonicalizePath; +virStorageFileChainLookup; +virStorageFileChown; +virStorageFileCreate; +virStorageFileDeinit; +virStorageFileGetBackingStoreStr; +virStorageFileGetMetadata; +virStorageFileGetMetadataFromBuf; +virStorageFileGetMetadataFromFD; +virStorageFileGetRelativeBackingPath; +virStorageFileGetUniqueIdentifier; +virStorageFileInit; +virStorageFileInitAs; +virStorageFileParseBackingStoreStr; +virStorageFileParseChainIndex; +virStorageFileProbeFormat; +virStorageFileRead; +virStorageFileReportBrokenChain; +virStorageFileStat; +virStorageFileSupportsAccess; +virStorageFileSupportsBackingChainTraversal; +virStorageFileSupportsCreate; +virStorageFileSupportsSecurityDriver; +virStorageFileUnlink; +virStorageSourceFindByNodeName; +virStorageSourceNewFromBacking; +virStorageSourceNewFromBackingAbsolute; +virStorageSourceParseRBDColonString; +virStorageSourcePrivateDataFormatRelPath; +virStorageSourcePrivateDataParseRelPath; +virStorageSourceUpdateBackingSizes; +virStorageSourceUpdateCapacity; +virStorageSourceUpdatePhysicalSize; + + # util/glibcompat.h vir_g_canonicalize_filename; vir_g_fsync; @@ -3127,37 +3164,12 @@ virStorageAuthDefCopy; virStorageAuthDefFormat; virStorageAuthDefFree; virStorageAuthDefParse; -virStorageFileAccess; -virStorageFileCanonicalizePath; -virStorageFileChainLookup; -virStorageFileChown; -virStorageFileCreate; -virStorageFileDeinit; virStorageFileFeatureTypeFromString; virStorageFileFeatureTypeToString; virStorageFileFormatTypeFromString; virStorageFileFormatTypeToString; -virStorageFileGetBackingStoreStr; -virStorageFileGetMetadata; -virStorageFileGetMetadataFromBuf; -virStorageFileGetMetadataFromFD; virStorageFileGetNPIVKey; -virStorageFileGetRelativeBackingPath; virStorageFileGetSCSIKey; -virStorageFileGetUniqueIdentifier; -virStorageFileInit; -virStorageFileInitAs; -virStorageFileParseBackingStoreStr; -virStorageFileParseChainIndex; -virStorageFileProbeFormat; -virStorageFileRead; -virStorageFileReportBrokenChain; -virStorageFileStat; -virStorageFileSupportsAccess; -virStorageFileSupportsBackingChainTraversal; -virStorageFileSupportsCreate; -virStorageFileSupportsSecurityDriver; -virStorageFileUnlink; virStorageNetHostDefClear; virStorageNetHostDefCopy; virStorageNetHostDefFree; @@ -3174,7 +3186,6 @@ virStorageSourceChainHasManagedPR; virStorageSourceChainHasNVMe; virStorageSourceClear; virStorageSourceCopy; -virStorageSourceFindByNodeName; virStorageSourceGetActualType; virStorageSourceGetSecurityLabelDef; virStorageSourceHasBacking; @@ -3192,18 +3203,10 @@ virStorageSourceIsSameLocation; virStorageSourceNetCookiesValidate; virStorageSourceNetworkAssignDefaultPorts; virStorageSourceNew; -virStorageSourceNewFromBacking; -virStorageSourceNewFromBackingAbsolute; virStorageSourceNVMeDefFree; -virStorageSourceParseRBDColonString; virStorageSourcePoolDefFree; virStorageSourcePoolModeTypeFromString; virStorageSourcePoolModeTypeToString; -virStorageSourcePrivateDataFormatRelPath; -virStorageSourcePrivateDataParseRelPath; -virStorageSourceUpdateBackingSizes; -virStorageSourceUpdateCapacity; -virStorageSourceUpdatePhysicalSize; virStorageTypeFromString; virStorageTypeToString; =20 diff --git a/src/libxl/meson.build b/src/libxl/meson.build index 3bb6cc5f2e..783af6c667 100644 --- a/src/libxl/meson.build +++ b/src/libxl/meson.build @@ -27,6 +27,7 @@ if conf.has('WITH_LIBXL') include_directories: [ conf_inc_dir, hypervisor_inc_dir, + storage_file_inc_dir, ], ) =20 diff --git a/src/libxl/xen_xl.c b/src/libxl/xen_xl.c index ba0942601f..1f97e6bdd4 100644 --- a/src/libxl/xen_xl.c +++ b/src/libxl/xen_xl.c @@ -30,6 +30,7 @@ #include "viralloc.h" #include "virstring.h" #include "virstoragefile.h" +#include "storage_file.h" #include "xen_xl.h" #include "libxl_capabilities.h" #include "libxl_conf.h" diff --git a/src/qemu/meson.build b/src/qemu/meson.build index 90640b03c6..7ab591d040 100644 --- a/src/qemu/meson.build +++ b/src/qemu/meson.build @@ -104,6 +104,7 @@ if conf.has('WITH_QEMU') include_directories: [ conf_inc_dir, hypervisor_inc_dir, + storage_file_inc_dir, ], ) =20 diff --git a/src/qemu/qemu_backup.c b/src/qemu/qemu_backup.c index b2340eb1cf..bd699ad29f 100644 --- a/src/qemu/qemu_backup.c +++ b/src/qemu/qemu_backup.c @@ -29,6 +29,7 @@ #include "qemu_checkpoint.h" #include "qemu_command.h" =20 +#include "storage_file.h" #include "virerror.h" #include "virlog.h" #include "virbuffer.h" diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c index 0743db4d2c..5444b5f4b7 100644 --- a/src/qemu/qemu_block.c +++ b/src/qemu/qemu_block.c @@ -24,6 +24,7 @@ #include "qemu_alias.h" #include "qemu_security.h" =20 +#include "storage_file.h" #include "viralloc.h" #include "virstring.h" #include "virlog.h" diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index bfb6e23942..ef073e5395 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -52,6 +52,7 @@ #include "virtime.h" #include "virnetdevopenvswitch.h" #include "virstoragefile.h" +#include "storage_file.h" #include "virstring.h" #include "virthreadjob.h" #include "virprocess.h" diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 5f0fb0a55f..00ce56c6b9 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -83,6 +83,7 @@ #include "domain_nwfilter.h" #include "virhook.h" #include "virstoragefile.h" +#include "storage_file.h" #include "virfile.h" #include "virfdstream.h" #include "configmake.h" diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 9b93f256e8..a0727b8b90 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -53,6 +53,7 @@ #include "virnetdevmidonet.h" #include "device_conf.h" #include "virstoragefile.h" +#include "storage_file.h" #include "virstring.h" #include "virtime.h" #include "virqemu.h" diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index bb78967ca3..52f33985cf 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -95,6 +95,7 @@ #include "viridentity.h" #include "virthreadjob.h" #include "virutil.h" +#include "storage_file.h" =20 #define VIR_FROM_THIS VIR_FROM_QEMU =20 diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c index 6f64111ca8..9633c8ab40 100644 --- a/src/qemu/qemu_snapshot.c +++ b/src/qemu/qemu_snapshot.c @@ -41,6 +41,7 @@ #include "virstring.h" #include "virdomainsnapshotobjlist.h" #include "virqemu.h" +#include "storage_file.h" =20 #define VIR_FROM_THIS VIR_FROM_QEMU =20 diff --git a/src/storage/meson.build b/src/storage/meson.build index 8537359e93..153ff6f846 100644 --- a/src/storage/meson.build +++ b/src/storage/meson.build @@ -79,6 +79,7 @@ if conf.has('WITH_STORAGE') ], include_directories: [ conf_inc_dir, + include_directories('../storage_file'), ], ) =20 @@ -162,6 +163,9 @@ if conf.has('WITH_STORAGE_GLUSTER') 'deps': [ glusterfs_dep, ], + 'include': [ + include_directories('../storage_file'), + ], 'install_dir': storage_backend_install_dir, } endif diff --git a/src/storage/storage_backend_gluster.c b/src/storage/storage_ba= ckend_gluster.c index 6c99c270da..671d62bf15 100644 --- a/src/storage/storage_backend_gluster.c +++ b/src/storage/storage_backend_gluster.c @@ -25,6 +25,7 @@ =20 #include "storage_backend_gluster.h" #include "storage_conf.h" +#include "storage_file.h" #include "viralloc.h" #include "virerror.h" #include "virlog.h" diff --git a/src/storage/storage_util.c b/src/storage/storage_util.c index 652f65fce2..a1949a5a24 100644 --- a/src/storage/storage_util.c +++ b/src/storage/storage_util.c @@ -62,6 +62,7 @@ #include "vircrypto.h" #include "viruuid.h" #include "virstoragefile.h" +#include "storage_file.h" #include "storage_util.h" #include "virlog.h" #include "virfile.h" diff --git a/src/storage_file/meson.build b/src/storage_file/meson.build index 20eb0176fc..b25ca63b40 100644 --- a/src/storage_file/meson.build +++ b/src/storage_file/meson.build @@ -1,3 +1,7 @@ +storage_file_sources =3D [ + 'storage_file.c' +] + stoarge_file_fs_sources =3D [ 'storage_file_fs.c', ] @@ -8,6 +12,18 @@ storage_file_gluster_sources =3D [ =20 storage_file_install_dir =3D libdir / 'libvirt' / 'storage-file' =20 +virt_storage_file_lib =3D static_library( + 'virt_storage_file', + [ + storage_file_sources, + ], + dependencies: [ + src_dep, + ], +) + +libvirt_libs +=3D virt_storage_file_lib + if conf.has('WITH_STORAGE') virt_modules +=3D { 'name': 'virt_storage_file_fs', @@ -36,3 +52,5 @@ if conf.has('WITH_STORAGE_GLUSTER') 'install_dir': storage_file_install_dir, } endif + +storage_file_inc_dir =3D include_directories('.') diff --git a/src/storage_file/storage_file.c b/src/storage_file/storage_fil= e.c new file mode 100644 index 0000000000..6bfeb26233 --- /dev/null +++ b/src/storage_file/storage_file.c @@ -0,0 +1,3845 @@ +/* + * storage_file.c: file utility functions for FS storage backend + * + * Copyright (C) 2007-2017 Red Hat, Inc. + * 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 + * License along with this library. If not, see + * . + */ + +#include + +#include +#include + +#include "storage_file.h" +#include "viralloc.h" +#include "virendian.h" +#include "virfile.h" +#include "virhash.h" +#include "virjson.h" +#include "virlog.h" +#include "virstoragefilebackend.h" +#include "virstring.h" +#include "viruri.h" + +#define VIR_FROM_THIS VIR_FROM_STORAGE + +VIR_LOG_INIT("storage_file"); + + +enum lv_endian { + LV_LITTLE_ENDIAN =3D 1, /* 1234 */ + LV_BIG_ENDIAN /* 4321 */ +}; + +enum { + BACKING_STORE_OK, + BACKING_STORE_INVALID, + BACKING_STORE_ERROR, +}; + +#define FILE_TYPE_VERSIONS_LAST 3 + +struct FileEncryptionInfo { + int format; /* Encryption format to assign */ + + int magicOffset; /* Byte offset of the magic */ + const char *magic; /* Optional string of magic */ + + enum lv_endian endian; /* Endianness of file format */ + + int versionOffset; /* Byte offset from start of file + * where we find version number, + * -1 to always fail the version test, + * -2 to always pass the version test */ + int versionSize; /* Size in bytes of version data (0, 2, or 4) */ + int versionNumbers[FILE_TYPE_VERSIONS_LAST]; + /* Version numbers to validate. Zeroes are ignor= ed. */ + + int modeOffset; /* Byte offset of the format native encryption mode */ + char modeValue; /* Value expected at offset */ + + int payloadOffset; /* start offset of the volume data (in 512 byte sec= tors) */ +}; + +struct FileTypeInfo { + int magicOffset; /* Byte offset of the magic */ + const char *magic; /* Optional string of file magic + * to check at head of file */ + enum lv_endian endian; /* Endianness of file format */ + + int versionOffset; /* Byte offset from start of file + * where we find version number, + * -1 to always fail the version test, + * -2 to always pass the version test */ + int versionSize; /* Size in bytes of version data (0, 2, or 4) */ + int versionNumbers[FILE_TYPE_VERSIONS_LAST]; + /* Version numbers to validate. Zeroes are ignor= ed. */ + int sizeOffset; /* Byte offset from start of file + * where we find capacity info, + * -1 to use st_size as capacity */ + int sizeBytes; /* Number of bytes for size field */ + int sizeMultiplier; /* A scaling factor if size is not in bytes */ + /* Store a COW base image path (possibly relativ= e), + * or NULL if there is no COW base image, to RES; + * return BACKING_STORE_* */ + const struct FileEncryptionInfo *cryptInfo; /* Encryption info */ + int (*getBackingStore)(char **res, int *format, + const char *buf, size_t buf_size); + int (*getFeatures)(virBitmapPtr *features, int format, + char *buf, ssize_t len); +}; + + +static int +cowGetBackingStore(char **, + int *, + const char *, + size_t); + +static int +qcowXGetBackingStore(char **, int *, + const char *, + size_t); + +static int +qcow2GetFeatures(virBitmapPtr *features, + int format, + char *buf, + ssize_t len); + +static int +vmdk4GetBackingStore(char **, + int *, + const char *, + size_t); + +static int +qedGetBackingStore(char **, + int *, + const char *, + size_t); + + +#define QCOWX_HDR_VERSION (4) +#define QCOWX_HDR_BACKING_FILE_OFFSET (QCOWX_HDR_VERSION+4) +#define QCOWX_HDR_BACKING_FILE_SIZE (QCOWX_HDR_BACKING_FILE_OFFSET+8) +#define QCOWX_HDR_IMAGE_SIZE (QCOWX_HDR_BACKING_FILE_SIZE+4+4) + +#define QCOW1_HDR_CRYPT (QCOWX_HDR_IMAGE_SIZE+8+1+1+2) +#define QCOW2_HDR_CRYPT (QCOWX_HDR_IMAGE_SIZE+8) + +#define QCOW1_HDR_TOTAL_SIZE (QCOW1_HDR_CRYPT+4+8) +#define QCOW2_HDR_TOTAL_SIZE (QCOW2_HDR_CRYPT+4+4+8+8+4+4+8) + +#define QCOW2_HDR_EXTENSION_END 0 +#define QCOW2_HDR_EXTENSION_BACKING_FORMAT 0xE2792ACA + +#define QCOW2v3_HDR_FEATURES_INCOMPATIBLE (QCOW2_HDR_TOTAL_SIZE) +#define QCOW2v3_HDR_FEATURES_COMPATIBLE (QCOW2v3_HDR_FEATURES_INCOMPATIBLE= +8) +#define QCOW2v3_HDR_FEATURES_AUTOCLEAR (QCOW2v3_HDR_FEATURES_COMPATIBLE+8) + +/* The location of the header size [4 bytes] */ +#define QCOW2v3_HDR_SIZE (QCOW2_HDR_TOTAL_SIZE+8+8+8+4) + +#define QED_HDR_FEATURES_OFFSET (4+4+4+4) +#define QED_HDR_IMAGE_SIZE (QED_HDR_FEATURES_OFFSET+8+8+8+8) +#define QED_HDR_BACKING_FILE_OFFSET (QED_HDR_IMAGE_SIZE+8) +#define QED_HDR_BACKING_FILE_SIZE (QED_HDR_BACKING_FILE_OFFSET+4) +#define QED_F_BACKING_FILE 0x01 +#define QED_F_BACKING_FORMAT_NO_PROBE 0x04 + +#define PLOOP_IMAGE_SIZE_OFFSET 36 +#define PLOOP_SIZE_MULTIPLIER 512 + +#define LUKS_HDR_MAGIC_LEN 6 +#define LUKS_HDR_VERSION_LEN 2 +#define LUKS_HDR_CIPHER_NAME_LEN 32 +#define LUKS_HDR_CIPHER_MODE_LEN 32 +#define LUKS_HDR_HASH_SPEC_LEN 32 +#define LUKS_HDR_PAYLOAD_LEN 4 + +/* Format described by qemu commit id '3e308f20e' */ +#define LUKS_HDR_VERSION_OFFSET LUKS_HDR_MAGIC_LEN +#define LUKS_HDR_PAYLOAD_OFFSET (LUKS_HDR_MAGIC_LEN+\ + LUKS_HDR_VERSION_LEN+\ + LUKS_HDR_CIPHER_NAME_LEN+\ + LUKS_HDR_CIPHER_MODE_LEN+\ + LUKS_HDR_HASH_SPEC_LEN) + + +static struct FileEncryptionInfo const luksEncryptionInfo[] =3D { + { + .format =3D VIR_STORAGE_ENCRYPTION_FORMAT_LUKS, + + /* Magic is 'L','U','K','S', 0xBA, 0xBE */ + .magicOffset =3D 0, + .magic =3D "\x4c\x55\x4b\x53\xba\xbe", + .endian =3D LV_BIG_ENDIAN, + + .versionOffset =3D LUKS_HDR_VERSION_OFFSET, + .versionSize =3D LUKS_HDR_VERSION_LEN, + .versionNumbers =3D {1}, + + .modeOffset =3D -1, + .modeValue =3D -1, + + .payloadOffset =3D LUKS_HDR_PAYLOAD_OFFSET, + }, + { 0 } +}; + + +static struct FileEncryptionInfo const qcow1EncryptionInfo[] =3D { + { + .format =3D VIR_STORAGE_ENCRYPTION_FORMAT_QCOW, + + .magicOffset =3D 0, + .magic =3D NULL, + .endian =3D LV_BIG_ENDIAN, + + .versionOffset =3D -1, + .versionSize =3D 0, + .versionNumbers =3D {}, + + .modeOffset =3D QCOW1_HDR_CRYPT, + .modeValue =3D 1, + + .payloadOffset =3D -1, + }, + { 0 } +}; + + +static struct FileEncryptionInfo const qcow2EncryptionInfo[] =3D { + { + .format =3D VIR_STORAGE_ENCRYPTION_FORMAT_QCOW, + + .magicOffset =3D 0, + .magic =3D NULL, + .endian =3D LV_BIG_ENDIAN, + + .versionOffset =3D -1, + .versionSize =3D 0, + .versionNumbers =3D {}, + + .modeOffset =3D QCOW2_HDR_CRYPT, + .modeValue =3D 1, + + .payloadOffset =3D -1, + }, + { + .format =3D VIR_STORAGE_ENCRYPTION_FORMAT_LUKS, + + .magicOffset =3D 0, + .magic =3D NULL, + .endian =3D LV_BIG_ENDIAN, + + .versionOffset =3D -1, + .versionSize =3D 0, + .versionNumbers =3D {}, + + .modeOffset =3D QCOW2_HDR_CRYPT, + .modeValue =3D 2, + + .payloadOffset =3D -1, + }, + { 0 } +}; + + +static struct FileTypeInfo const fileTypeInfo[] =3D { + [VIR_STORAGE_FILE_NONE] =3D { 0, NULL, LV_LITTLE_ENDIAN, + -1, 0, {0}, 0, 0, 0, NULL, NULL, NULL }, + [VIR_STORAGE_FILE_RAW] =3D { 0, NULL, LV_LITTLE_ENDIAN, + -1, 0, {0}, 0, 0, 0, + luksEncryptionInfo, + NULL, NULL }, + [VIR_STORAGE_FILE_DIR] =3D { 0, NULL, LV_LITTLE_ENDIAN, + -1, 0, {0}, 0, 0, 0, NULL, NULL, NULL }, + [VIR_STORAGE_FILE_BOCHS] =3D { + /*"Bochs Virtual HD Image", */ /* Untested */ + 0, NULL, + LV_LITTLE_ENDIAN, 64, 4, {0x20000}, + 32+16+16+4+4+4+4+4, 8, 1, NULL, NULL, NULL + }, + [VIR_STORAGE_FILE_CLOOP] =3D { + /* #!/bin/sh + #V2.0 Format + modprobe cloop file=3D$0 && mount -r -t iso9660 /dev/cloop $1 + */ /* Untested */ + 0, NULL, + LV_LITTLE_ENDIAN, -1, 0, {0}, + -1, 0, 0, NULL, NULL, NULL + }, + [VIR_STORAGE_FILE_DMG] =3D { + /* XXX QEMU says there's no magic for dmg, + * /usr/share/misc/magic lists double magic (both offsets + * would have to match) but then disables that check. */ + 0, NULL, + 0, -1, 0, {0}, + -1, 0, 0, NULL, NULL, NULL + }, + [VIR_STORAGE_FILE_ISO] =3D { + 32769, "CD001", + LV_LITTLE_ENDIAN, -2, 0, {0}, + -1, 0, 0, NULL, NULL, NULL + }, + [VIR_STORAGE_FILE_VPC] =3D { + 0, "conectix", + LV_BIG_ENDIAN, 12, 4, {0x10000}, + 8 + 4 + 4 + 8 + 4 + 4 + 2 + 2 + 4, 8, 1, NULL, NULL, NULL + }, + /* TODO: add getBackingStore function */ + [VIR_STORAGE_FILE_VDI] =3D { + 64, "\x7f\x10\xda\xbe", + LV_LITTLE_ENDIAN, 68, 4, {0x00010001}, + 64 + 5 * 4 + 256 + 7 * 4, 8, 1, NULL, NULL, NULL}, + + /* Not direct file formats, but used for various drivers */ + [VIR_STORAGE_FILE_FAT] =3D { 0, NULL, LV_LITTLE_ENDIAN, + -1, 0, {0}, 0, 0, 0, NULL, NULL, NULL }, + [VIR_STORAGE_FILE_VHD] =3D { 0, NULL, LV_LITTLE_ENDIAN, + -1, 0, {0}, 0, 0, 0, NULL, NULL, NULL }, + [VIR_STORAGE_FILE_PLOOP] =3D { 0, "WithouFreSpacExt", LV_LITTLE_ENDIAN, + -2, 0, {0}, PLOOP_IMAGE_SIZE_OFFSET, 0, + PLOOP_SIZE_MULTIPLIER, NULL, NULL, NULL }, + + /* All formats with a backing store probe below here */ + [VIR_STORAGE_FILE_COW] =3D { + 0, "OOOM", + LV_BIG_ENDIAN, 4, 4, {2}, + 4+4+1024+4, 8, 1, NULL, cowGetBackingStore, NULL + }, + [VIR_STORAGE_FILE_QCOW] =3D { + 0, "QFI", + LV_BIG_ENDIAN, 4, 4, {1}, + QCOWX_HDR_IMAGE_SIZE, 8, 1, + qcow1EncryptionInfo, + qcowXGetBackingStore, NULL + }, + [VIR_STORAGE_FILE_QCOW2] =3D { + 0, "QFI", + LV_BIG_ENDIAN, 4, 4, {2, 3}, + QCOWX_HDR_IMAGE_SIZE, 8, 1, + qcow2EncryptionInfo, + qcowXGetBackingStore, + qcow2GetFeatures + }, + [VIR_STORAGE_FILE_QED] =3D { + /* https://wiki.qemu.org/Features/QED */ + 0, "QED", + LV_LITTLE_ENDIAN, -2, 0, {0}, + QED_HDR_IMAGE_SIZE, 8, 1, NULL, qedGetBackingStore, NULL + }, + [VIR_STORAGE_FILE_VMDK] =3D { + 0, "KDMV", + LV_LITTLE_ENDIAN, 4, 4, {1, 2, 3}, + 4+4+4, 8, 512, NULL, vmdk4GetBackingStore, NULL + }, +}; +G_STATIC_ASSERT(G_N_ELEMENTS(fileTypeInfo) =3D=3D VIR_STORAGE_FILE_LAST); + + +/* qcow2 compatible features in the order they appear on-disk */ +enum qcow2CompatibleFeature { + QCOW2_COMPATIBLE_FEATURE_LAZY_REFCOUNTS =3D 0, + + QCOW2_COMPATIBLE_FEATURE_LAST +}; + + +/* conversion to virStorageFileFeature */ +static const int qcow2CompatibleFeatureArray[] =3D { + VIR_STORAGE_FILE_FEATURE_LAZY_REFCOUNTS, +}; +G_STATIC_ASSERT(G_N_ELEMENTS(qcow2CompatibleFeatureArray) =3D=3D + QCOW2_COMPATIBLE_FEATURE_LAST); + + +static int +cowGetBackingStore(char **res, + int *format, + const char *buf, + size_t buf_size) +{ +#define COW_FILENAME_MAXLEN 1024 + *res =3D NULL; + *format =3D VIR_STORAGE_FILE_AUTO; + + if (buf_size < 4+4+ COW_FILENAME_MAXLEN) + return BACKING_STORE_INVALID; + if (buf[4+4] =3D=3D '\0') { /* cow_header_v2.backing_file[0] */ + *format =3D VIR_STORAGE_FILE_NONE; + return BACKING_STORE_OK; + } + + *res =3D g_strndup((const char *)buf + 4 + 4, COW_FILENAME_MAXLEN); + return BACKING_STORE_OK; +} + + +static int +qcow2GetExtensions(const char *buf, + size_t buf_size, + int *backingFormat) +{ + size_t offset; + size_t extension_start; + size_t extension_end; + int version =3D virReadBufInt32BE(buf + QCOWX_HDR_VERSION); + + if (version < 2) { + /* QCow1 doesn't have the extensions capability + * used to store backing format */ + return 0; + } + + if (version =3D=3D 2) + extension_start =3D QCOW2_HDR_TOTAL_SIZE; + else + extension_start =3D virReadBufInt32BE(buf + QCOW2v3_HDR_SIZE); + + /* + * Traditionally QCow2 files had a layout of + * + * [header] + * [backingStoreName] + * + * Although the backingStoreName typically followed + * the header immediately, this was not required by + * the format. By specifying a higher byte offset for + * the backing file offset in the header, it was + * possible to leave space between the header and + * start of backingStore. + * + * This hack is now used to store extensions to the + * qcow2 format: + * + * [header] + * [extensions] + * [backingStoreName] + * + * Thus the file region to search for extensions is + * between the end of the header (QCOW2_HDR_TOTAL_SIZE) + * and the start of the backingStoreName (offset) + * + * for qcow2 v3 images, the length of the header + * is stored at QCOW2v3_HDR_SIZE + */ + extension_end =3D virReadBufInt64BE(buf + QCOWX_HDR_BACKING_FILE_OFFSE= T); + if (extension_end > buf_size) + return -1; + + /* + * The extensions take format of + * + * int32: magic + * int32: length + * byte[length]: payload + * + * Unknown extensions can be ignored by skipping + * over "length" bytes in the data stream. + */ + offset =3D extension_start; + while (offset < (buf_size-8) && + offset < (extension_end-8)) { + unsigned int magic =3D virReadBufInt32BE(buf + offset); + unsigned int len =3D virReadBufInt32BE(buf + offset + 4); + + offset +=3D 8; + + if ((offset + len) < offset) + break; + + if ((offset + len) > buf_size) + break; + + switch (magic) { + case QCOW2_HDR_EXTENSION_BACKING_FORMAT: { + g_autofree char *tmp =3D NULL; + if (!backingFormat) + break; + + tmp =3D g_new0(char, len + 1); + memcpy(tmp, buf + offset, len); + tmp[len] =3D '\0'; + + *backingFormat =3D virStorageFileFormatTypeFromString(tmp); + if (*backingFormat <=3D VIR_STORAGE_FILE_NONE) + return -1; + break; + } + + case QCOW2_HDR_EXTENSION_END: + return 0; + } + + offset +=3D len; + } + + return 0; +} + + +static int +qcowXGetBackingStore(char **res, + int *format, + const char *buf, + size_t buf_size) +{ + unsigned long long offset; + unsigned int size; + + *res =3D NULL; + *format =3D VIR_STORAGE_FILE_AUTO; + + if (buf_size < QCOWX_HDR_BACKING_FILE_OFFSET+8+4) + return BACKING_STORE_INVALID; + + offset =3D virReadBufInt64BE(buf + QCOWX_HDR_BACKING_FILE_OFFSET); + if (offset > buf_size) + return BACKING_STORE_INVALID; + + if (offset =3D=3D 0) { + *format =3D VIR_STORAGE_FILE_NONE; + return BACKING_STORE_OK; + } + + size =3D virReadBufInt32BE(buf + QCOWX_HDR_BACKING_FILE_SIZE); + if (size =3D=3D 0) { + *format =3D VIR_STORAGE_FILE_NONE; + return BACKING_STORE_OK; + } + if (size > 1023) + return BACKING_STORE_INVALID; + if (offset + size > buf_size || offset + size < offset) + return BACKING_STORE_INVALID; + *res =3D g_new0(char, size + 1); + memcpy(*res, buf + offset, size); + (*res)[size] =3D '\0'; + + if (qcow2GetExtensions(buf, buf_size, format) < 0) + return BACKING_STORE_INVALID; + + return BACKING_STORE_OK; +} + + +static int +vmdk4GetBackingStore(char **res, + int *format, + const char *buf, + size_t buf_size) +{ + static const char prefix[] =3D "parentFileNameHint=3D\""; + char *start, *end; + size_t len; + g_autofree char *desc =3D NULL; + + desc =3D g_new0(char, VIR_STORAGE_MAX_HEADER); + + *res =3D NULL; + /* + * Technically this should have been VMDK, since + * VMDK spec / VMware impl only support VMDK backed + * by VMDK. QEMU isn't following this though and + * does probing on VMDK backing files, hence we set + * AUTO + */ + *format =3D VIR_STORAGE_FILE_AUTO; + + if (buf_size <=3D 0x200) + return BACKING_STORE_INVALID; + + len =3D buf_size - 0x200; + if (len > VIR_STORAGE_MAX_HEADER) + len =3D VIR_STORAGE_MAX_HEADER; + memcpy(desc, buf + 0x200, len); + desc[len] =3D '\0'; + start =3D strstr(desc, prefix); + if (start =3D=3D NULL) { + *format =3D VIR_STORAGE_FILE_NONE; + return BACKING_STORE_OK; + } + start +=3D strlen(prefix); + end =3D strchr(start, '"'); + if (end =3D=3D NULL) + return BACKING_STORE_INVALID; + + if (end =3D=3D start) { + *format =3D VIR_STORAGE_FILE_NONE; + return BACKING_STORE_OK; + } + *end =3D '\0'; + *res =3D g_strdup(start); + + return BACKING_STORE_OK; +} + + +static int +qedGetBackingStore(char **res, + int *format, + const char *buf, + size_t buf_size) +{ + unsigned long long flags; + unsigned long offset, size; + + *res =3D NULL; + /* Check if this image has a backing file */ + if (buf_size < QED_HDR_FEATURES_OFFSET+8) + return BACKING_STORE_INVALID; + flags =3D virReadBufInt64LE(buf + QED_HDR_FEATURES_OFFSET); + if (!(flags & QED_F_BACKING_FILE)) { + *format =3D VIR_STORAGE_FILE_NONE; + return BACKING_STORE_OK; + } + + /* Parse the backing file */ + if (buf_size < QED_HDR_BACKING_FILE_OFFSET+8) + return BACKING_STORE_INVALID; + offset =3D virReadBufInt32LE(buf + QED_HDR_BACKING_FILE_OFFSET); + if (offset > buf_size) + return BACKING_STORE_INVALID; + size =3D virReadBufInt32LE(buf + QED_HDR_BACKING_FILE_SIZE); + if (size =3D=3D 0) + return BACKING_STORE_OK; + if (offset + size > buf_size || offset + size < offset) + return BACKING_STORE_INVALID; + *res =3D g_new0(char, size + 1); + memcpy(*res, buf + offset, size); + (*res)[size] =3D '\0'; + + if (flags & QED_F_BACKING_FORMAT_NO_PROBE) + *format =3D VIR_STORAGE_FILE_RAW; + else + *format =3D VIR_STORAGE_FILE_AUTO_SAFE; + + return BACKING_STORE_OK; +} + + +static bool +virStorageFileMatchesMagic(int magicOffset, + const char *magic, + char *buf, + size_t buflen) +{ + int mlen; + + if (magic =3D=3D NULL) + return false; + + /* Validate magic data */ + mlen =3D strlen(magic); + if (magicOffset + mlen > buflen) + return false; + + if (memcmp(buf + magicOffset, magic, mlen) !=3D 0) + return false; + + return true; +} + + +static bool +virStorageFileMatchesVersion(int versionOffset, + int versionSize, + const int *versionNumbers, + int endian, + char *buf, + size_t buflen) +{ + int version; + size_t i; + + /* Validate version number info */ + if (versionOffset =3D=3D -1) + return false; + + /* -2 =3D=3D non-versioned file format, so trivially match */ + if (versionOffset =3D=3D -2) + return true; + + /* A positive versionOffset, requires using a valid versionSize */ + if (versionSize !=3D 2 && versionSize !=3D 4) + return false; + + if ((versionOffset + versionSize) > buflen) + return false; + + if (endian =3D=3D LV_LITTLE_ENDIAN) { + if (versionSize =3D=3D 4) + version =3D virReadBufInt32LE(buf + + versionOffset); + else + version =3D virReadBufInt16LE(buf + + versionOffset); + } else { + if (versionSize =3D=3D 4) + version =3D virReadBufInt32BE(buf + + versionOffset); + else + version =3D virReadBufInt16BE(buf + + versionOffset); + } + + for (i =3D 0; + i < FILE_TYPE_VERSIONS_LAST && versionNumbers[i]; + i++) { + VIR_DEBUG("Compare detected version %d vs one of the expected vers= ions %d", + version, versionNumbers[i]); + if (version =3D=3D versionNumbers[i]) + return true; + } + + return false; +} + + +static int +virStorageFileProbeFormatFromBuf(const char *path, + char *buf, + size_t buflen) +{ + int format =3D VIR_STORAGE_FILE_RAW; + size_t i; + int possibleFormat =3D VIR_STORAGE_FILE_RAW; + VIR_DEBUG("path=3D%s, buf=3D%p, buflen=3D%zu", path, buf, buflen); + + /* First check file magic */ + for (i =3D 0; i < VIR_STORAGE_FILE_LAST; i++) { + if (virStorageFileMatchesMagic(fileTypeInfo[i].magicOffset, + fileTypeInfo[i].magic, + buf, buflen)) { + if (!virStorageFileMatchesVersion(fileTypeInfo[i].versionOffse= t, + fileTypeInfo[i].versionSize, + fileTypeInfo[i].versionNumbe= rs, + fileTypeInfo[i].endian, + buf, buflen)) { + possibleFormat =3D i; + continue; + } + format =3D i; + goto cleanup; + } + } + + if (possibleFormat !=3D VIR_STORAGE_FILE_RAW) + VIR_WARN("File %s matches %s magic, but version is wrong. " + "Please report new version to libvir-list@redhat.com", + path, virStorageFileFormatTypeToString(possibleFormat)); + + cleanup: + VIR_DEBUG("format=3D%d", format); + return format; +} + + +static int +qcow2GetFeatures(virBitmapPtr *features, + int format, + char *buf, + ssize_t len) +{ + int version =3D -1; + virBitmapPtr feat =3D NULL; + uint64_t bits; + size_t i; + + version =3D virReadBufInt32BE(buf + fileTypeInfo[format].versionOffset= ); + + if (version =3D=3D 2) + return 0; + + if (len < QCOW2v3_HDR_SIZE) + return -1; + + feat =3D virBitmapNew(VIR_STORAGE_FILE_FEATURE_LAST); + + /* todo: check for incompatible or autoclear features? */ + bits =3D virReadBufInt64BE(buf + QCOW2v3_HDR_FEATURES_COMPATIBLE); + for (i =3D 0; i < QCOW2_COMPATIBLE_FEATURE_LAST; i++) { + if (bits & ((uint64_t) 1 << i)) + ignore_value(virBitmapSetBit(feat, qcow2CompatibleFeatureArray= [i])); + } + + *features =3D feat; + return 0; +} + + +static bool +virStorageFileHasEncryptionFormat(const struct FileEncryptionInfo *info, + char *buf, + size_t len) +{ + if (!info->magic && info->modeOffset =3D=3D -1) + return false; /* Shouldn't happen - expect at least one */ + + if (info->magic) { + if (!virStorageFileMatchesMagic(info->magicOffset, + info->magic, + buf, len)) + return false; + + if (info->versionOffset !=3D -1 && + !virStorageFileMatchesVersion(info->versionOffset, + info->versionSize, + info->versionNumbers, + info->endian, + buf, len)) + return false; + + return true; + } else if (info->modeOffset !=3D -1) { + int crypt_format; + + if (info->modeOffset >=3D len) + return false; + + crypt_format =3D virReadBufInt32BE(buf + info->modeOffset); + if (crypt_format !=3D info->modeValue) + return false; + + return true; + } else { + return false; + } +} + + +static int +virStorageFileGetEncryptionPayloadOffset(const struct FileEncryptionInfo *= info, + char *buf) +{ + int payload_offset =3D -1; + + if (info->payloadOffset !=3D -1) { + if (info->endian =3D=3D LV_LITTLE_ENDIAN) + payload_offset =3D virReadBufInt32LE(buf + info->payloadOffset= ); + else + payload_offset =3D virReadBufInt32BE(buf + info->payloadOffset= ); + } + + return payload_offset; +} + + +/* Given a header in BUF with length LEN, as parsed from the storage file + * assuming it has the given FORMAT, populate information into META + * with information about the file and its backing store. Return format + * of the backing store as BACKING_FORMAT. PATH and FORMAT have to be + * pre-populated in META. + * + * Note that this function may be called repeatedly on @meta, so it must + * clean up any existing allocated memory which would be overwritten. + */ +static int +virStorageFileGetMetadataInternal(virStorageSourcePtr meta, + char *buf, + size_t len) +{ + int format; + size_t i; + + VIR_DEBUG("path=3D%s, buf=3D%p, len=3D%zu, meta->format=3D%d", + meta->path, buf, len, meta->format); + + if (meta->format =3D=3D VIR_STORAGE_FILE_AUTO) + meta->format =3D virStorageFileProbeFormatFromBuf(meta->path, buf,= len); + + if (meta->format <=3D VIR_STORAGE_FILE_NONE || + meta->format >=3D VIR_STORAGE_FILE_LAST) { + virReportSystemError(EINVAL, _("unknown storage file meta->format = %d"), + meta->format); + return -1; + } + + if (fileTypeInfo[meta->format].cryptInfo !=3D NULL) { + for (i =3D 0; fileTypeInfo[meta->format].cryptInfo[i].format !=3D = 0; i++) { + if (virStorageFileHasEncryptionFormat(&fileTypeInfo[meta->form= at].cryptInfo[i], + buf, len)) { + int expt_fmt =3D fileTypeInfo[meta->format].cryptInfo[i].f= ormat; + if (!meta->encryption) { + meta->encryption =3D g_new0(virStorageEncryption, 1); + meta->encryption->format =3D expt_fmt; + } else { + if (meta->encryption->format !=3D expt_fmt) { + virReportError(VIR_ERR_XML_ERROR, + _("encryption format %d doesn't mat= ch " + "expected format %d"), + meta->encryption->format, expt_fmt); + return -1; + } + } + meta->encryption->payload_offset =3D + virStorageFileGetEncryptionPayloadOffset(&fileTypeInfo= [meta->format].cryptInfo[i], buf); + } + } + } + + /* XXX we should consider moving virStorageBackendUpdateVolInfo + * code into this method, for non-magic files + */ + if (!fileTypeInfo[meta->format].magic) + return 0; + + /* Optionally extract capacity from file */ + if (fileTypeInfo[meta->format].sizeOffset !=3D -1) { + if ((fileTypeInfo[meta->format].sizeOffset + 8) > len) + return 0; + + if (fileTypeInfo[meta->format].endian =3D=3D LV_LITTLE_ENDIAN) + meta->capacity =3D virReadBufInt64LE(buf + + fileTypeInfo[meta->format].= sizeOffset); + else + meta->capacity =3D virReadBufInt64BE(buf + + fileTypeInfo[meta->format].= sizeOffset); + /* Avoid unlikely, but theoretically possible overflow */ + if (meta->capacity > (ULLONG_MAX / + fileTypeInfo[meta->format].sizeMultiplier)) + return 0; + meta->capacity *=3D fileTypeInfo[meta->format].sizeMultiplier; + } + + VIR_FREE(meta->backingStoreRaw); + if (fileTypeInfo[meta->format].getBackingStore !=3D NULL) { + int store =3D fileTypeInfo[meta->format].getBackingStore(&meta->ba= ckingStoreRaw, + &format, + buf, len); + meta->backingStoreRawFormat =3D format; + + if (store =3D=3D BACKING_STORE_INVALID) + return 0; + + if (store =3D=3D BACKING_STORE_ERROR) + return -1; + } + + virBitmapFree(meta->features); + meta->features =3D NULL; + if (fileTypeInfo[meta->format].getFeatures !=3D NULL && + fileTypeInfo[meta->format].getFeatures(&meta->features, meta->form= at, buf, len) < 0) + return -1; + + VIR_FREE(meta->compat); + if (meta->format =3D=3D VIR_STORAGE_FILE_QCOW2 && meta->features) + meta->compat =3D g_strdup("1.1"); + + return 0; +} + + +/** + * virStorageFileProbeFormat: + * + * Probe for the format of 'path', returning the detected + * disk format. + * + * Callers are advised never to trust the returned 'format' + * unless it is listed as VIR_STORAGE_FILE_RAW, since a + * malicious guest can turn a raw file into any other non-raw + * format at will. + * + * Best option: Don't use this function + */ +int +virStorageFileProbeFormat(const char *path, + uid_t uid, + gid_t gid) +{ + struct stat sb; + ssize_t len =3D VIR_STORAGE_MAX_HEADER; + VIR_AUTOCLOSE fd =3D -1; + g_autofree char *header =3D NULL; + + if ((fd =3D virFileOpenAs(path, O_RDONLY, 0, uid, gid, 0)) < 0) { + virReportSystemError(-fd, _("Failed to open file '%s'"), path); + return -1; + } + + if (fstat(fd, &sb) < 0) { + virReportSystemError(errno, _("cannot stat file '%s'"), path); + return -1; + } + + /* No header to probe for directories */ + if (S_ISDIR(sb.st_mode)) + return VIR_STORAGE_FILE_DIR; + + if (lseek(fd, 0, SEEK_SET) =3D=3D (off_t)-1) { + virReportSystemError(errno, _("cannot set to start of '%s'"), path= ); + return -1; + } + + if ((len =3D virFileReadHeaderFD(fd, len, &header)) < 0) { + virReportSystemError(errno, _("cannot read header '%s'"), path); + return -1; + } + + return virStorageFileProbeFormatFromBuf(path, header, len); +} + + +static virStorageSourcePtr +virStorageFileMetadataNew(const char *path, + int format) +{ + g_autoptr(virStorageSource) def =3D virStorageSourceNew(); + + def->format =3D format; + def->type =3D VIR_STORAGE_TYPE_FILE; + + def->path =3D g_strdup(path); + + return g_steal_pointer(&def); +} + + +/** + * virStorageFileGetMetadataFromBuf: + * @path: name of file, for error messages + * @buf: header bytes from @path + * @len: length of @buf + * @format: format of the storage file + * + * Extract metadata about the storage volume with the specified image form= at. + * If image format is VIR_STORAGE_FILE_AUTO, it will probe to automatically + * identify the format. Does not recurse. + * + * Callers are advised never to use VIR_STORAGE_FILE_AUTO as a format on a= file + * that might be raw if that file will then be passed to a guest, since a + * malicious guest can turn a raw file into any other non-raw format at wi= ll. + * + * If the 'backingStoreRawFormat' field of the returned structure is + * VIR_STORAGE_FILE_AUTO it indicates the image didn't specify an explicit + * format for its backing store. Callers are advised against probing for t= he + * backing store format in this case. + * + * Caller MUST free the result after use via virObjectUnref. + */ +virStorageSourcePtr +virStorageFileGetMetadataFromBuf(const char *path, + char *buf, + size_t len, + int format) +{ + virStorageSourcePtr ret =3D NULL; + + if (!(ret =3D virStorageFileMetadataNew(path, format))) + return NULL; + + if (virStorageFileGetMetadataInternal(ret, buf, len) < 0) { + virObjectUnref(ret); + return NULL; + } + + return ret; +} + + +/** + * virStorageFileGetMetadataFromFD: + * + * Extract metadata about the storage volume with the specified + * image format. If image format is VIR_STORAGE_FILE_AUTO, it + * will probe to automatically identify the format. Does not recurse. + * + * Callers are advised never to use VIR_STORAGE_FILE_AUTO as a + * format, since a malicious guest can turn a raw file into any + * other non-raw format at will. + * + * Caller MUST free the result after use via virObjectUnref. + */ +virStorageSourcePtr +virStorageFileGetMetadataFromFD(const char *path, + int fd, + int format) + +{ + ssize_t len =3D VIR_STORAGE_MAX_HEADER; + struct stat sb; + g_autofree char *buf =3D NULL; + g_autoptr(virStorageSource) meta =3D NULL; + + if (fstat(fd, &sb) < 0) { + virReportSystemError(errno, + _("cannot stat file '%s'"), path); + return NULL; + } + + if (!(meta =3D virStorageFileMetadataNew(path, format))) + return NULL; + + if (S_ISDIR(sb.st_mode)) { + /* No header to probe for directories, but also no backing file. J= ust + * update the metadata.*/ + meta->type =3D VIR_STORAGE_TYPE_DIR; + meta->format =3D VIR_STORAGE_FILE_DIR; + return g_steal_pointer(&meta); + } + + if (lseek(fd, 0, SEEK_SET) =3D=3D (off_t)-1) { + virReportSystemError(errno, _("cannot seek to start of '%s'"), met= a->path); + return NULL; + } + + if ((len =3D virFileReadHeaderFD(fd, len, &buf)) < 0) { + virReportSystemError(errno, _("cannot read header '%s'"), meta->pa= th); + return NULL; + } + + if (virStorageFileGetMetadataInternal(meta, buf, len) < 0) + return NULL; + + if (S_ISREG(sb.st_mode)) + meta->type =3D VIR_STORAGE_TYPE_FILE; + else if (S_ISBLK(sb.st_mode)) + meta->type =3D VIR_STORAGE_TYPE_BLOCK; + + return g_steal_pointer(&meta); +} + + +/** + * virStorageFileParseBackingStoreStr: + * @str: backing store specifier string to parse + * @target: returns target device portion of the string + * @chainIndex: returns the backing store portion of the string + * + * Parses the backing store specifier string such as vda[1], or sda into + * components and returns them via arguments. If the string did not specif= y an + * index, 0 is assumed. + * + * Returns 0 on success -1 on error + */ +int +virStorageFileParseBackingStoreStr(const char *str, + char **target, + unsigned int *chainIndex) +{ + size_t nstrings; + unsigned int idx =3D 0; + char *suffix; + g_auto(GStrv) strings =3D NULL; + + *chainIndex =3D 0; + + if (!(strings =3D virStringSplitCount(str, "[", 2, &nstrings))) + return -1; + + if (nstrings =3D=3D 2) { + if (virStrToLong_uip(strings[1], &suffix, 10, &idx) < 0 || + STRNEQ(suffix, "]")) + return -1; + } + + if (target) + *target =3D g_strdup(strings[0]); + + *chainIndex =3D idx; + return 0; +} + + +int +virStorageFileParseChainIndex(const char *diskTarget, + const char *name, + unsigned int *chainIndex) +{ + unsigned int idx =3D 0; + g_autofree char *target =3D NULL; + + *chainIndex =3D 0; + + if (!name || !diskTarget) + return 0; + + if (virStorageFileParseBackingStoreStr(name, &target, &idx) < 0) + return 0; + + if (idx =3D=3D 0) + return 0; + + if (STRNEQ(diskTarget, target)) { + virReportError(VIR_ERR_INVALID_ARG, + _("requested target '%s' does not match target '%s'= "), + target, diskTarget); + return -1; + } + + *chainIndex =3D idx; + + return 0; +} + + +/* Given a @chain, look for the backing store @name that is a backing file + * of @startFrom (or any member of @chain if @startFrom is NULL) and return + * that location within the chain. @chain must always point to the top of + * the chain. Pass NULL for @name and 0 for @idx to find the base of the + * chain. Pass nonzero @idx to find the backing source according to its + * position in the backing chain. If @parent is not NULL, set *@parent to + * the preferred name of the parent (or to NULL if @name matches the start + * of the chain). Since the results point within @chain, they must not be + * independently freed. Reports an error and returns NULL if @name is not + * found. + */ +virStorageSourcePtr +virStorageFileChainLookup(virStorageSourcePtr chain, + virStorageSourcePtr startFrom, + const char *name, + unsigned int idx, + virStorageSourcePtr *parent) +{ + virStorageSourcePtr prev; + const char *start =3D chain->path; + bool nameIsFile =3D virFileIsFile(name); + + if (!parent) + parent =3D &prev; + *parent =3D NULL; + + if (startFrom) { + while (virStorageSourceIsBacking(chain) && + chain !=3D startFrom->backingStore) + chain =3D chain->backingStore; + + *parent =3D startFrom; + } + + while (virStorageSourceIsBacking(chain)) { + if (!name && !idx) { + if (!virStorageSourceHasBacking(chain)) + break; + } else if (idx) { + VIR_DEBUG("%u: %s", chain->id, chain->path); + if (idx =3D=3D chain->id) + break; + } else { + if (STREQ_NULLABLE(name, chain->relPath) || + STREQ_NULLABLE(name, chain->path)) + break; + + if (nameIsFile && virStorageSourceIsLocalStorage(chain)) { + g_autofree char *parentDir =3D NULL; + int result; + + if (*parent && virStorageSourceIsLocalStorage(*parent)) + parentDir =3D g_path_get_dirname((*parent)->path); + else + parentDir =3D g_strdup("."); + + result =3D virFileRelLinkPointsTo(parentDir, name, + chain->path); + + if (result < 0) + goto error; + + if (result > 0) + break; + } + } + *parent =3D chain; + chain =3D chain->backingStore; + } + + if (!virStorageSourceIsBacking(chain)) + goto error; + + return chain; + + error: + if (idx) { + virReportError(VIR_ERR_INVALID_ARG, + _("could not find backing store index %u in chain " + "for '%s'"), + idx, NULLSTR(start)); + } else if (name) { + if (startFrom) + virReportError(VIR_ERR_INVALID_ARG, + _("could not find image '%s' beneath '%s' in " + "chain for '%s'"), name, NULLSTR(startFrom->p= ath), + NULLSTR(start)); + else + virReportError(VIR_ERR_INVALID_ARG, + _("could not find image '%s' in chain for '%s'"= ), + name, NULLSTR(start)); + } else { + virReportError(VIR_ERR_INVALID_ARG, + _("could not find base image in chain for '%s'"), + NULLSTR(start)); + } + *parent =3D NULL; + return NULL; +} + + +static virStorageSourcePtr +virStorageSourceNewFromBackingRelative(virStorageSourcePtr parent, + const char *rel) +{ + g_autofree char *dirname =3D NULL; + g_autoptr(virStorageSource) def =3D virStorageSourceNew(); + + /* store relative name */ + def->relPath =3D g_strdup(rel); + + dirname =3D g_path_get_dirname(parent->path); + + if (STRNEQ(dirname, "/")) { + def->path =3D g_strdup_printf("%s/%s", dirname, rel); + } else { + def->path =3D g_strdup_printf("/%s", rel); + } + + if (virStorageSourceGetActualType(parent) =3D=3D VIR_STORAGE_TYPE_NETW= ORK) { + def->type =3D VIR_STORAGE_TYPE_NETWORK; + + /* copy the host network part */ + def->protocol =3D parent->protocol; + if (parent->nhosts) { + if (!(def->hosts =3D virStorageNetHostDefCopy(parent->nhosts, + parent->hosts))) + return NULL; + + def->nhosts =3D parent->nhosts; + } + + def->volume =3D g_strdup(parent->volume); + } else { + /* set the type to _FILE, the caller shall update it to the actual= type */ + def->type =3D VIR_STORAGE_TYPE_FILE; + } + + return g_steal_pointer(&def); +} + + +static int +virStorageSourceParseBackingURI(virStorageSourcePtr src, + const char *uristr) +{ + g_autoptr(virURI) uri =3D NULL; + const char *path =3D NULL; + g_auto(GStrv) scheme =3D NULL; + + if (!(uri =3D virURIParse(uristr))) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("failed to parse backing file location '%s'"), + uristr); + return -1; + } + + src->hosts =3D g_new0(virStorageNetHostDef, 1); + src->nhosts =3D 1; + + if (!(scheme =3D virStringSplit(uri->scheme, "+", 2))) + return -1; + + if (!scheme[0] || + (src->protocol =3D virStorageNetProtocolTypeFromString(scheme[0]))= < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("invalid backing protocol '%s'"), + NULLSTR(scheme[0])); + return -1; + } + + if (scheme[1] && + (src->hosts->transport =3D virStorageNetHostTransportTypeFromStrin= g(scheme[1])) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("invalid protocol transport type '%s'"), + scheme[1]); + return -1; + } + + if (uri->query) { + if (src->protocol =3D=3D VIR_STORAGE_NET_PROTOCOL_HTTP || + src->protocol =3D=3D VIR_STORAGE_NET_PROTOCOL_HTTPS) { + src->query =3D g_strdup(uri->query); + } else { + /* handle socket stored as a query */ + if (STRPREFIX(uri->query, "socket=3D")) + src->hosts->socket =3D g_strdup(STRSKIP(uri->query, "socke= t=3D")); + } + } + + /* uri->path is NULL if the URI does not contain slash after host: + * transport://host:port */ + if (uri->path) + path =3D uri->path; + else + path =3D ""; + + /* possibly skip the leading slash */ + if (path[0] =3D=3D '/') + path++; + + /* NBD allows empty export name (path) */ + if (src->protocol =3D=3D VIR_STORAGE_NET_PROTOCOL_NBD && + path[0] =3D=3D '\0') + path =3D NULL; + + src->path =3D g_strdup(path); + + if (src->protocol =3D=3D VIR_STORAGE_NET_PROTOCOL_GLUSTER) { + char *tmp; + + if (!src->path) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("missing volume name and path for gluster vol= ume")); + return -1; + } + + if (!(tmp =3D strchr(src->path, '/')) || + tmp =3D=3D src->path) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("missing volume name or file name in " + "gluster source path '%s'"), src->path); + return -1; + } + + src->volume =3D src->path; + + src->path =3D g_strdup(tmp + 1); + + tmp[0] =3D '\0'; + } + + src->hosts->port =3D uri->port; + + src->hosts->name =3D g_strdup(uri->server); + + /* Libvirt doesn't handle inline authentication. Make the caller aware= . */ + if (uri->user) + return 1; + + return 0; +} + + +static int +virStorageSourceRBDAddHost(virStorageSourcePtr src, + char *hostport) +{ + char *port; + size_t skip; + g_auto(GStrv) parts =3D NULL; + + if (VIR_EXPAND_N(src->hosts, src->nhosts, 1) < 0) + return -1; + + if ((port =3D strchr(hostport, ']'))) { + /* ipv6, strip brackets */ + hostport +=3D 1; + skip =3D 3; + } else { + port =3D strstr(hostport, "\\:"); + skip =3D 2; + } + + if (port) { + *port =3D '\0'; + port +=3D skip; + if (virStringParsePort(port, &src->hosts[src->nhosts - 1].port) < = 0) + goto error; + } + + parts =3D virStringSplit(hostport, "\\:", 0); + if (!parts) + goto error; + src->hosts[src->nhosts-1].name =3D virStringListJoin((const char **)pa= rts, ":"); + if (!src->hosts[src->nhosts-1].name) + goto error; + + src->hosts[src->nhosts-1].transport =3D VIR_STORAGE_NET_HOST_TRANS_TCP; + src->hosts[src->nhosts-1].socket =3D NULL; + + return 0; + + error: + VIR_FREE(src->hosts[src->nhosts-1].name); + return -1; +} + + +int +virStorageSourceParseRBDColonString(const char *rbdstr, + virStorageSourcePtr src) +{ + char *p, *e, *next; + g_autofree char *options =3D NULL; + g_autoptr(virStorageAuthDef) authdef =3D NULL; + + /* optionally skip the "rbd:" prefix if provided */ + if (STRPREFIX(rbdstr, "rbd:")) + rbdstr +=3D strlen("rbd:"); + + src->path =3D g_strdup(rbdstr); + + p =3D strchr(src->path, ':'); + if (p) { + options =3D g_strdup(p + 1); + *p =3D '\0'; + } + + /* snapshot name */ + if ((p =3D strchr(src->path, '@'))) { + src->snapshot =3D g_strdup(p + 1); + *p =3D '\0'; + } + + /* pool vs. image name */ + if ((p =3D strchr(src->path, '/'))) { + src->volume =3D g_steal_pointer(&src->path); + src->path =3D g_strdup(p + 1); + *p =3D '\0'; + } + + /* options */ + if (!options) + return 0; /* all done */ + + p =3D options; + while (*p) { + /* find : delimiter or end of string */ + for (e =3D p; *e && *e !=3D ':'; ++e) { + if (*e =3D=3D '\\') { + e++; + if (*e =3D=3D '\0') + break; + } + } + if (*e =3D=3D '\0') { + next =3D e; /* last kv pair */ + } else { + next =3D e + 1; + *e =3D '\0'; + } + + if (STRPREFIX(p, "id=3D")) { + /* formulate authdef for src->auth */ + if (src->auth) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("duplicate 'id' found in '%s'"), src->pat= h); + return -1; + } + + authdef =3D g_new0(virStorageAuthDef, 1); + + authdef->username =3D g_strdup(p + strlen("id=3D")); + + authdef->secrettype =3D g_strdup(virSecretUsageTypeToString(VI= R_SECRET_USAGE_TYPE_CEPH)); + src->auth =3D g_steal_pointer(&authdef); + + /* Cannot formulate a secretType (eg, usage or uuid) given + * what is provided. + */ + } + if (STRPREFIX(p, "mon_host=3D")) { + char *h, *sep; + + h =3D p + strlen("mon_host=3D"); + while (h < e) { + for (sep =3D h; sep < e; ++sep) { + if (*sep =3D=3D '\\' && (sep[1] =3D=3D ',' || + sep[1] =3D=3D ';' || + sep[1] =3D=3D ' ')) { + *sep =3D '\0'; + sep +=3D 2; + break; + } + } + + if (virStorageSourceRBDAddHost(src, h) < 0) + return -1; + + h =3D sep; + } + } + + if (STRPREFIX(p, "conf=3D")) + src->configFile =3D g_strdup(p + strlen("conf=3D")); + + p =3D next; + } + return 0; +} + + +static int +virStorageSourceParseNBDColonString(const char *nbdstr, + virStorageSourcePtr src) +{ + g_autofree char *nbd =3D g_strdup(nbdstr); + char *export_name; + char *host_spec; + char *unixpath; + char *port; + + src->hosts =3D g_new0(virStorageNetHostDef, 1); + src->nhosts =3D 1; + + /* We extract the parameters in a similar way qemu does it */ + + /* format: [] denotes optional sections, uppercase are variable strings + * nbd:unix:/PATH/TO/SOCKET[:exportname=3DEXPORTNAME] + * nbd:HOSTNAME:PORT[:exportname=3DEXPORTNAME] + */ + + /* first look for ':exportname=3D' and cut it off */ + if ((export_name =3D strstr(nbd, ":exportname=3D"))) { + src->path =3D g_strdup(export_name + strlen(":exportname=3D")); + export_name[0] =3D '\0'; + } + + /* Verify the prefix and contents. Note that we require a + * "host_spec" part to be present. */ + if (!(host_spec =3D STRSKIP(nbd, "nbd:")) || host_spec[0] =3D=3D '\0') + goto malformed; + + if ((unixpath =3D STRSKIP(host_spec, "unix:"))) { + src->hosts->transport =3D VIR_STORAGE_NET_HOST_TRANS_UNIX; + + if (unixpath[0] =3D=3D '\0') + goto malformed; + + src->hosts->socket =3D g_strdup(unixpath); + } else { + src->hosts->transport =3D VIR_STORAGE_NET_HOST_TRANS_TCP; + + if (host_spec[0] =3D=3D ':') { + /* no host given */ + goto malformed; + } else if (host_spec[0] =3D=3D '[') { + host_spec++; + /* IPv6 addr */ + if (!(port =3D strstr(host_spec, "]:"))) + goto malformed; + + port[0] =3D '\0'; + port +=3D 2; + + if (host_spec[0] =3D=3D '\0') + goto malformed; + } else { + if (!(port =3D strchr(host_spec, ':'))) + goto malformed; + + port[0] =3D '\0'; + port++; + } + + if (virStringParsePort(port, &src->hosts->port) < 0) + return -1; + + src->hosts->name =3D g_strdup(host_spec); + } + + return 0; + + malformed: + virReportError(VIR_ERR_INTERNAL_ERROR, + _("malformed nbd string '%s'"), nbdstr); + return -1; +} + + +static int +virStorageSourceParseBackingColon(virStorageSourcePtr src, + const char *path) +{ + const char *p; + g_autofree char *protocol =3D NULL; + + if (!(p =3D strchr(path, ':'))) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("invalid backing protocol string '%s'"), + path); + return -1; + } + + protocol =3D g_strndup(path, p - path); + + if ((src->protocol =3D virStorageNetProtocolTypeFromString(protocol)) = < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("invalid backing protocol '%s'"), + protocol); + return -1; + } + + switch ((virStorageNetProtocol) src->protocol) { + case VIR_STORAGE_NET_PROTOCOL_NBD: + if (virStorageSourceParseNBDColonString(path, src) < 0) + return -1; + break; + + case VIR_STORAGE_NET_PROTOCOL_RBD: + if (virStorageSourceParseRBDColonString(path, src) < 0) + return -1; + break; + + case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG: + case VIR_STORAGE_NET_PROTOCOL_LAST: + case VIR_STORAGE_NET_PROTOCOL_NONE: + virReportError(VIR_ERR_INTERNAL_ERROR, + _("backing store parser is not implemented for prot= ocol %s"), + protocol); + return -1; + + case VIR_STORAGE_NET_PROTOCOL_HTTP: + case VIR_STORAGE_NET_PROTOCOL_HTTPS: + case VIR_STORAGE_NET_PROTOCOL_FTP: + case VIR_STORAGE_NET_PROTOCOL_FTPS: + case VIR_STORAGE_NET_PROTOCOL_TFTP: + case VIR_STORAGE_NET_PROTOCOL_ISCSI: + case VIR_STORAGE_NET_PROTOCOL_GLUSTER: + case VIR_STORAGE_NET_PROTOCOL_SSH: + case VIR_STORAGE_NET_PROTOCOL_VXHS: + virReportError(VIR_ERR_INTERNAL_ERROR, + _("malformed backing store path for protocol %s"), + protocol); + return -1; + } + + return 0; +} + + +static int +virStorageSourceParseBackingJSONInternal(virStorageSourcePtr src, + virJSONValuePtr json, + const char *jsonstr, + bool allowformat); + + +static int +virStorageSourceParseBackingJSONPath(virStorageSourcePtr src, + virJSONValuePtr json, + const char *jsonstr G_GNUC_UNUSED, + int type) +{ + const char *path; + + if (!(path =3D virJSONValueObjectGetString(json, "filename"))) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("missing 'filename' field in JSON backing volume " + "definition")); + return -1; + } + + src->path =3D g_strdup(path); + + src->type =3D type; + return 0; +} + + +static int +virStorageSourceParseBackingJSONUriStr(virStorageSourcePtr src, + const char *uri, + int protocol) +{ + int rc; + + if ((rc =3D virStorageSourceParseBackingURI(src, uri)) < 0) + return -1; + + if (src->protocol !=3D protocol) { + virReportError(VIR_ERR_INVALID_ARG, + _("expected protocol '%s' but got '%s' in URI JSON = volume " + "definition"), + virStorageNetProtocolTypeToString(protocol), + virStorageNetProtocolTypeToString(src->protocol)); + return -1; + } + + return rc; +} + + +static int +virStorageSourceParseBackingJSONUriCookies(virStorageSourcePtr src, + virJSONValuePtr json, + const char *jsonstr) +{ + const char *cookiestr; + g_auto(GStrv) cookies =3D NULL; + size_t ncookies =3D 0; + size_t i; + + if (!virJSONValueObjectHasKey(json, "cookie")) + return 0; + + if (!(cookiestr =3D virJSONValueObjectGetString(json, "cookie"))) { + virReportError(VIR_ERR_INVALID_ARG, + _("wrong format of 'cookie' field in backing store = definition '%s'"), + jsonstr); + return -1; + } + + if (!(cookies =3D virStringSplitCount(cookiestr, ";", 0, &ncookies))) + return -1; + + src->cookies =3D g_new0(virStorageNetCookieDefPtr, ncookies); + src->ncookies =3D ncookies; + + for (i =3D 0; i < ncookies; i++) { + char *cookiename =3D cookies[i]; + char *cookievalue; + + virSkipSpaces((const char **) &cookiename); + + if (!(cookievalue =3D strchr(cookiename, '=3D'))) { + virReportError(VIR_ERR_INVALID_ARG, + _("malformed http cookie '%s' in backing store = definition '%s'"), + cookies[i], jsonstr); + return -1; + } + + *cookievalue =3D '\0'; + cookievalue++; + + src->cookies[i] =3D g_new0(virStorageNetCookieDef, 1); + src->cookies[i]->name =3D g_strdup(cookiename); + src->cookies[i]->value =3D g_strdup(cookievalue); + } + + return 0; +} + + +static int +virStorageSourceParseBackingJSONUri(virStorageSourcePtr src, + virJSONValuePtr json, + const char *jsonstr, + int protocol) +{ + const char *uri; + + if (!(uri =3D virJSONValueObjectGetString(json, "url"))) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("missing 'url' in JSON backing volume definition"= )); + return -1; + } + + if (protocol =3D=3D VIR_STORAGE_NET_PROTOCOL_HTTPS || + protocol =3D=3D VIR_STORAGE_NET_PROTOCOL_FTPS) { + if (virJSONValueObjectHasKey(json, "sslverify")) { + const char *tmpstr; + bool tmp; + + /* libguestfs still uses undocumented legacy value of 'off' */ + if ((tmpstr =3D virJSONValueObjectGetString(json, "sslverify")= ) && + STREQ(tmpstr, "off")) { + src->sslverify =3D VIR_TRISTATE_BOOL_NO; + } else { + if (virJSONValueObjectGetBoolean(json, "sslverify", &tmp) = < 0) { + virReportError(VIR_ERR_INVALID_ARG, + _("malformed 'sslverify' field in backi= ng store definition '%s'"), + jsonstr); + return -1; + } + + src->sslverify =3D virTristateBoolFromBool(tmp); + } + } + } + + if (protocol =3D=3D VIR_STORAGE_NET_PROTOCOL_HTTPS || + protocol =3D=3D VIR_STORAGE_NET_PROTOCOL_HTTP) { + if (virStorageSourceParseBackingJSONUriCookies(src, json, jsonstr)= < 0) + return -1; + } + + if (virJSONValueObjectHasKey(json, "readahead") && + virJSONValueObjectGetNumberUlong(json, "readahead", &src->readahea= d) < 0) { + virReportError(VIR_ERR_INVALID_ARG, + _("malformed 'readahead' field in backing store def= inition '%s'"), + jsonstr); + return -1; + } + + if (virJSONValueObjectHasKey(json, "timeout") && + virJSONValueObjectGetNumberUlong(json, "timeout", &src->timeout) <= 0) { + virReportError(VIR_ERR_INVALID_ARG, + _("malformed 'timeout' field in backing store defin= ition '%s'"), + jsonstr); + return -1; + } + + return virStorageSourceParseBackingJSONUriStr(src, uri, protocol); +} + + +static int +virStorageSourceParseBackingJSONInetSocketAddress(virStorageNetHostDefPtr = host, + virJSONValuePtr json) +{ + const char *hostname; + const char *port; + + if (!json) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("missing remote server specification in JSON " + "backing volume definition")); + return -1; + } + + hostname =3D virJSONValueObjectGetString(json, "host"); + port =3D virJSONValueObjectGetString(json, "port"); + + if (!hostname) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("missing hostname for tcp backing server in " + "JSON backing volume definition")); + return -1; + } + + host->transport =3D VIR_STORAGE_NET_HOST_TRANS_TCP; + host->name =3D g_strdup(hostname); + + if (virStringParsePort(port, &host->port) < 0) + return -1; + + return 0; +} + + +static int +virStorageSourceParseBackingJSONSocketAddress(virStorageNetHostDefPtr host, + virJSONValuePtr json) +{ + const char *type; + const char *socket; + + if (!json) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("missing remote server specification in JSON " + "backing volume definition")); + return -1; + } + + if (!(type =3D virJSONValueObjectGetString(json, "type"))) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("missing socket address type in " + "JSON backing volume definition")); + return -1; + } + + if (STREQ(type, "tcp") || STREQ(type, "inet")) { + return virStorageSourceParseBackingJSONInetSocketAddress(host, jso= n); + + } else if (STREQ(type, "unix")) { + host->transport =3D VIR_STORAGE_NET_HOST_TRANS_UNIX; + + socket =3D virJSONValueObjectGetString(json, "path"); + + /* check for old spelling for gluster protocol */ + if (!socket) + socket =3D virJSONValueObjectGetString(json, "socket"); + + if (!socket) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("missing socket path for udp backing server i= n " + "JSON backing volume definition")); + return -1; + } + + host->socket =3D g_strdup(socket); + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("backing store protocol '%s' is not yet supported= "), + type); + return -1; + } + + return 0; +} + + +static int +virStorageSourceParseBackingJSONGluster(virStorageSourcePtr src, + virJSONValuePtr json, + const char *jsonstr G_GNUC_UNUSED, + int opaque G_GNUC_UNUSED) +{ + const char *uri =3D virJSONValueObjectGetString(json, "filename"); + const char *volume =3D virJSONValueObjectGetString(json, "volume"); + const char *path =3D virJSONValueObjectGetString(json, "path"); + virJSONValuePtr server =3D virJSONValueObjectGetArray(json, "server"); + size_t nservers; + size_t i; + + /* legacy URI based syntax passed via 'filename' option */ + if (uri) + return virStorageSourceParseBackingJSONUriStr(src, uri, + VIR_STORAGE_NET_PROT= OCOL_GLUSTER); + + if (!volume || !path || !server) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("missing 'volume', 'path' or 'server' attribute i= n " + "JSON backing definition for gluster volume")); + return -1; + } + + src->type =3D VIR_STORAGE_TYPE_NETWORK; + src->protocol =3D VIR_STORAGE_NET_PROTOCOL_GLUSTER; + + src->volume =3D g_strdup(volume); + src->path =3D g_strdup(path); + + nservers =3D virJSONValueArraySize(server); + if (nservers =3D=3D 0) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("at least 1 server is necessary in " + "JSON backing definition for gluster volume")); + + return -1; + } + + src->hosts =3D g_new0(virStorageNetHostDef, nservers); + src->nhosts =3D nservers; + + for (i =3D 0; i < nservers; i++) { + if (virStorageSourceParseBackingJSONSocketAddress(src->hosts + i, + virJSONValueArra= yGet(server, i)) < 0) + return -1; + } + + return 0; +} + + +static int +virStorageSourceParseBackingJSONiSCSI(virStorageSourcePtr src, + virJSONValuePtr json, + const char *jsonstr G_GNUC_UNUSED, + int opaque G_GNUC_UNUSED) +{ + const char *transport =3D virJSONValueObjectGetString(json, "transport= "); + const char *portal =3D virJSONValueObjectGetString(json, "portal"); + const char *target =3D virJSONValueObjectGetString(json, "target"); + const char *lun =3D virJSONValueObjectGetStringOrNumber(json, "lun"); + const char *uri; + char *port; + + /* legacy URI based syntax passed via 'filename' option */ + if ((uri =3D virJSONValueObjectGetString(json, "filename"))) + return virStorageSourceParseBackingJSONUriStr(src, uri, + VIR_STORAGE_NET_PROT= OCOL_ISCSI); + + src->type =3D VIR_STORAGE_TYPE_NETWORK; + src->protocol =3D VIR_STORAGE_NET_PROTOCOL_ISCSI; + + if (!lun) + lun =3D "0"; + + src->hosts =3D g_new0(virStorageNetHostDef, 1); + src->nhosts =3D 1; + + if (STRNEQ_NULLABLE(transport, "tcp")) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("only TCP transport is supported for iSCSI volume= s")); + return -1; + } + + src->hosts->transport =3D VIR_STORAGE_NET_HOST_TRANS_TCP; + + if (!portal) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("missing 'portal' address in iSCSI backing defini= tion")); + return -1; + } + + if (!target) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("missing 'target' in iSCSI backing definition")); + return -1; + } + + src->hosts->name =3D g_strdup(portal); + + if ((port =3D strrchr(src->hosts->name, ':')) && + !strchr(port, ']')) { + if (virStringParsePort(port + 1, &src->hosts->port) < 0) + return -1; + + *port =3D '\0'; + } + + src->path =3D g_strdup_printf("%s/%s", target, lun); + + /* Libvirt doesn't handle inline authentication. Make the caller aware= . */ + if (virJSONValueObjectGetString(json, "user") || + virJSONValueObjectGetString(json, "password")) + return 1; + + return 0; +} + + +static int +virStorageSourceParseBackingJSONNbd(virStorageSourcePtr src, + virJSONValuePtr json, + const char *jsonstr G_GNUC_UNUSED, + int opaque G_GNUC_UNUSED) +{ + const char *path =3D virJSONValueObjectGetString(json, "path"); + const char *host =3D virJSONValueObjectGetString(json, "host"); + const char *port =3D virJSONValueObjectGetString(json, "port"); + const char *export =3D virJSONValueObjectGetString(json, "export"); + virJSONValuePtr server =3D virJSONValueObjectGetObject(json, "server"); + + if (!path && !host && !server) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("missing host specification of NBD server in JSON= " + "backing volume definition")); + return -1; + } + + src->type =3D VIR_STORAGE_TYPE_NETWORK; + src->protocol =3D VIR_STORAGE_NET_PROTOCOL_NBD; + + src->path =3D g_strdup(export); + + src->hosts =3D g_new0(virStorageNetHostDef, 1); + src->nhosts =3D 1; + + if (server) { + if (virStorageSourceParseBackingJSONSocketAddress(src->hosts, serv= er) < 0) + return -1; + } else { + if (path) { + src->hosts[0].transport =3D VIR_STORAGE_NET_HOST_TRANS_UNIX; + src->hosts[0].socket =3D g_strdup(path); + } else { + src->hosts[0].transport =3D VIR_STORAGE_NET_HOST_TRANS_TCP; + src->hosts[0].name =3D g_strdup(host); + + if (virStringParsePort(port, &src->hosts[0].port) < 0) + return -1; + } + } + + return 0; +} + + +static int +virStorageSourceParseBackingJSONSheepdog(virStorageSourcePtr src, + virJSONValuePtr json, + const char *jsonstr G_GNUC_UNUSED, + int opaque G_GNUC_UNUSED) +{ + const char *filename; + const char *vdi =3D virJSONValueObjectGetString(json, "vdi"); + virJSONValuePtr server =3D virJSONValueObjectGetObject(json, "server"); + + /* legacy URI based syntax passed via 'filename' option */ + if ((filename =3D virJSONValueObjectGetString(json, "filename"))) { + if (strstr(filename, "://")) + return virStorageSourceParseBackingJSONUriStr(src, filename, + VIR_STORAGE_NET_= PROTOCOL_SHEEPDOG); + + /* libvirt doesn't implement a parser for the legacy non-URI synta= x */ + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("missing sheepdog URI in JSON backing volume defi= nition")); + return -1; + } + + src->type =3D VIR_STORAGE_TYPE_NETWORK; + src->protocol =3D VIR_STORAGE_NET_PROTOCOL_SHEEPDOG; + + if (!vdi) { + virReportError(VIR_ERR_INVALID_ARG, "%s", _("missing sheepdog vdi = name")); + return -1; + } + + src->path =3D g_strdup(vdi); + + src->hosts =3D g_new0(virStorageNetHostDef, 1); + src->nhosts =3D 1; + + if (virStorageSourceParseBackingJSONSocketAddress(src->hosts, server) = < 0) + return -1; + + return 0; +} + + +static int +virStorageSourceParseBackingJSONSSH(virStorageSourcePtr src, + virJSONValuePtr json, + const char *jsonstr G_GNUC_UNUSED, + int opaque G_GNUC_UNUSED) +{ + const char *path =3D virJSONValueObjectGetString(json, "path"); + const char *host =3D virJSONValueObjectGetString(json, "host"); + const char *port =3D virJSONValueObjectGetString(json, "port"); + const char *user =3D virJSONValueObjectGetString(json, "user"); + const char *host_key_check =3D virJSONValueObjectGetString(json, "host= _key_check"); + virJSONValuePtr server =3D virJSONValueObjectGetObject(json, "server"); + + if (!(host || server) || !path) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("missing host/server or path of SSH JSON backing " + "volume definition")); + return -1; + } + + src->type =3D VIR_STORAGE_TYPE_NETWORK; + src->protocol =3D VIR_STORAGE_NET_PROTOCOL_SSH; + + src->path =3D g_strdup(path); + + src->hosts =3D g_new0(virStorageNetHostDef, 1); + src->nhosts =3D 1; + + if (server) { + if (virStorageSourceParseBackingJSONInetSocketAddress(src->hosts, + server) < 0) + return -1; + } else { + src->hosts[0].transport =3D VIR_STORAGE_NET_HOST_TRANS_TCP; + src->hosts[0].name =3D g_strdup(host); + + if (virStringParsePort(port, &src->hosts[0].port) < 0) + return -1; + } + + /* these two are parsed just to be passed back as we don't model them = yet */ + src->ssh_user =3D g_strdup(user); + if (STREQ_NULLABLE(host_key_check, "no")) + src->ssh_host_key_check_disabled =3D true; + + return 0; +} + + +static int +virStorageSourceParseBackingJSONRBD(virStorageSourcePtr src, + virJSONValuePtr json, + const char *jsonstr G_GNUC_UNUSED, + int opaque G_GNUC_UNUSED) +{ + const char *filename; + const char *pool =3D virJSONValueObjectGetString(json, "pool"); + const char *image =3D virJSONValueObjectGetString(json, "image"); + const char *conf =3D virJSONValueObjectGetString(json, "conf"); + const char *snapshot =3D virJSONValueObjectGetString(json, "snapshot"); + virJSONValuePtr servers =3D virJSONValueObjectGetArray(json, "server"); + size_t nservers; + size_t i; + + src->type =3D VIR_STORAGE_TYPE_NETWORK; + src->protocol =3D VIR_STORAGE_NET_PROTOCOL_RBD; + + /* legacy syntax passed via 'filename' option */ + if ((filename =3D virJSONValueObjectGetString(json, "filename"))) + return virStorageSourceParseRBDColonString(filename, src); + + if (!pool || !image) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("missing pool or image name in ceph backing volum= e " + "JSON specification")); + return -1; + } + + src->volume =3D g_strdup(pool); + src->path =3D g_strdup(image); + src->snapshot =3D g_strdup(snapshot); + src->configFile =3D g_strdup(conf); + + if (servers) { + nservers =3D virJSONValueArraySize(servers); + + src->hosts =3D g_new0(virStorageNetHostDef, nservers); + src->nhosts =3D nservers; + + for (i =3D 0; i < nservers; i++) { + if (virStorageSourceParseBackingJSONInetSocketAddress(src->hos= ts + i, + virJSONV= alueArrayGet(servers, i)) < 0) + return -1; + } + } + + return 0; +} + +static int +virStorageSourceParseBackingJSONRaw(virStorageSourcePtr src, + virJSONValuePtr json, + const char *jsonstr, + int opaque G_GNUC_UNUSED) +{ + bool has_offset =3D virJSONValueObjectHasKey(json, "offset"); + bool has_size =3D virJSONValueObjectHasKey(json, "size"); + virJSONValuePtr file; + + if (has_offset || has_size) { + src->sliceStorage =3D g_new0(virStorageSourceSlice, 1); + + if (has_offset && + virJSONValueObjectGetNumberUlong(json, "offset", &src->sliceSt= orage->offset) < 0) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("malformed 'offset' property of 'raw' driver"= )); + return -1; + } + + if (has_size && + virJSONValueObjectGetNumberUlong(json, "size", &src->sliceStor= age->size) < 0) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("malformed 'size' property of 'raw' driver")); + return -1; + } + } + + /* 'raw' is a format driver so it can have protocol driver children */ + if (!(file =3D virJSONValueObjectGetObject(json, "file"))) { + virReportError(VIR_ERR_INVALID_ARG, + _("JSON backing volume definition '%s' lacks 'file'= object"), + jsonstr); + return -1; + } + + return virStorageSourceParseBackingJSONInternal(src, file, jsonstr, fa= lse); +} + + +static int +virStorageSourceParseBackingJSONVxHS(virStorageSourcePtr src, + virJSONValuePtr json, + const char *jsonstr G_GNUC_UNUSED, + int opaque G_GNUC_UNUSED) +{ + const char *vdisk_id =3D virJSONValueObjectGetString(json, "vdisk-id"); + virJSONValuePtr server =3D virJSONValueObjectGetObject(json, "server"); + + if (!vdisk_id || !server) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("missing 'vdisk-id' or 'server' attribute in " + "JSON backing definition for VxHS volume")); + return -1; + } + + src->type =3D VIR_STORAGE_TYPE_NETWORK; + src->protocol =3D VIR_STORAGE_NET_PROTOCOL_VXHS; + + src->path =3D g_strdup(vdisk_id); + + src->hosts =3D g_new0(virStorageNetHostDef, 1); + src->nhosts =3D 1; + + if (virStorageSourceParseBackingJSONInetSocketAddress(src->hosts, + server) < 0) + return -1; + + return 0; +} + + +static int +virStorageSourceParseBackingJSONNVMe(virStorageSourcePtr src, + virJSONValuePtr json, + const char *jsonstr G_GNUC_UNUSED, + int opaque G_GNUC_UNUSED) +{ + g_autoptr(virStorageSourceNVMeDef) nvme =3D g_new0(virStorageSourceNVM= eDef, 1); + const char *device =3D virJSONValueObjectGetString(json, "device"); + + if (!device || virPCIDeviceAddressParse((char *) device, &nvme->pciAdd= r) < 0) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("missing or malformed 'device' field of 'nvme' st= orage")); + return -1; + } + + if (virJSONValueObjectGetNumberUlong(json, "namespace", &nvme->namespc= ) < 0 || + nvme->namespc =3D=3D 0) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("missing or malformed 'namespace' field of 'nvme'= storage")); + return -1; + } + + src->type =3D VIR_STORAGE_TYPE_NVME; + src->nvme =3D g_steal_pointer(&nvme); + + return 0; +} + + +struct virStorageSourceJSONDriverParser { + const char *drvname; + bool formatdriver; + /** + * The callback gets a pre-allocated storage source @src and the JSON + * object to parse. The callback shall return -1 on error and report e= rror + * 0 on success and 1 in cases when the configuration itself is valid,= but + * can't be converted to libvirt's configuration (e.g. inline authenti= cation + * credentials are present). + */ + int (*func)(virStorageSourcePtr src, virJSONValuePtr json, const char = *jsonstr, int opaque); + int opaque; +}; + +static const struct virStorageSourceJSONDriverParser jsonParsers[] =3D { + {"file", false, virStorageSourceParseBackingJSONPath, VIR_STORAGE_TYPE= _FILE}, + {"host_device", false, virStorageSourceParseBackingJSONPath, VIR_STORA= GE_TYPE_BLOCK}, + {"host_cdrom", false, virStorageSourceParseBackingJSONPath, VIR_STORAG= E_TYPE_BLOCK}, + {"http", false, virStorageSourceParseBackingJSONUri, VIR_STORAGE_NET_P= ROTOCOL_HTTP}, + {"https", false, virStorageSourceParseBackingJSONUri, VIR_STORAGE_NET_= PROTOCOL_HTTPS}, + {"ftp", false, virStorageSourceParseBackingJSONUri, VIR_STORAGE_NET_PR= OTOCOL_FTP}, + {"ftps", false, virStorageSourceParseBackingJSONUri, VIR_STORAGE_NET_P= ROTOCOL_FTPS}, + {"tftp", false, virStorageSourceParseBackingJSONUri, VIR_STORAGE_NET_P= ROTOCOL_TFTP}, + {"gluster", false, virStorageSourceParseBackingJSONGluster, 0}, + {"iscsi", false, virStorageSourceParseBackingJSONiSCSI, 0}, + {"nbd", false, virStorageSourceParseBackingJSONNbd, 0}, + {"sheepdog", false, virStorageSourceParseBackingJSONSheepdog, 0}, + {"ssh", false, virStorageSourceParseBackingJSONSSH, 0}, + {"rbd", false, virStorageSourceParseBackingJSONRBD, 0}, + {"raw", true, virStorageSourceParseBackingJSONRaw, 0}, + {"vxhs", false, virStorageSourceParseBackingJSONVxHS, 0}, + {"nvme", false, virStorageSourceParseBackingJSONNVMe, 0}, +}; + + + +static int +virStorageSourceParseBackingJSONInternal(virStorageSourcePtr src, + virJSONValuePtr json, + const char *jsonstr, + bool allowformat) +{ + const char *drvname; + size_t i; + + if (!(drvname =3D virJSONValueObjectGetString(json, "driver"))) { + virReportError(VIR_ERR_INVALID_ARG, + _("JSON backing volume definition '%s' lacks driver= name"), + jsonstr); + return -1; + } + + for (i =3D 0; i < G_N_ELEMENTS(jsonParsers); i++) { + if (STRNEQ(drvname, jsonParsers[i].drvname)) + continue; + + if (jsonParsers[i].formatdriver && !allowformat) { + virReportError(VIR_ERR_INVALID_ARG, + _("JSON backing volume definition '%s' must not= have nested format drivers"), + jsonstr); + return -1; + } + + return jsonParsers[i].func(src, json, jsonstr, jsonParsers[i].opaq= ue); + } + + virReportError(VIR_ERR_INTERNAL_ERROR, + _("missing parser implementation for JSON backing volum= e " + "driver '%s'"), drvname); + return -1; +} + + +static int +virStorageSourceParseBackingJSON(virStorageSourcePtr src, + const char *json) +{ + g_autoptr(virJSONValue) root =3D NULL; + g_autoptr(virJSONValue) deflattened =3D NULL; + virJSONValuePtr file =3D NULL; + + if (!(root =3D virJSONValueFromString(json))) + return -1; + + if (!(deflattened =3D virJSONValueObjectDeflatten(root))) + return -1; + + /* There are 2 possible syntaxes: + * 1) json:{"file":{"driver":...}} + * 2) json:{"driver":...} + * Remove the 'file' wrapper object in case 1. + */ + if (!virJSONValueObjectHasKey(deflattened, "driver")) + file =3D virJSONValueObjectGetObject(deflattened, "file"); + + if (!file) + file =3D deflattened; + + return virStorageSourceParseBackingJSONInternal(src, file, json, true); +} + + +/** + * virStorageSourceNewFromBackingAbsolute + * @path: string representing absolute location of a storage source + * @src: filled with virStorageSource object representing @path + * + * Returns 0 on success, 1 if we could parse all location data but @path + * specified other data unrepresentable by libvirt (e.g. inline authentica= tion). + * In both cases @src is filled. On error -1 is returned @src is NULL and = an + * error is reported. + */ +int +virStorageSourceNewFromBackingAbsolute(const char *path, + virStorageSourcePtr *src) +{ + const char *json; + const char *dirpath; + int rc =3D 0; + g_autoptr(virStorageSource) def =3D virStorageSourceNew(); + + *src =3D NULL; + + if (virFileIsFile(path)) { + def->type =3D VIR_STORAGE_TYPE_FILE; + + def->path =3D g_strdup(path); + } else { + if ((dirpath =3D STRSKIP(path, "fat:"))) { + def->type =3D VIR_STORAGE_TYPE_DIR; + def->format =3D VIR_STORAGE_FILE_FAT; + def->path =3D g_strdup(dirpath); + *src =3D g_steal_pointer(&def); + return 0; + } + + def->type =3D VIR_STORAGE_TYPE_NETWORK; + + VIR_DEBUG("parsing backing store string: '%s'", path); + + /* handle URI formatted backing stores */ + if ((json =3D STRSKIP(path, "json:"))) + rc =3D virStorageSourceParseBackingJSON(def, json); + else if (strstr(path, "://")) + rc =3D virStorageSourceParseBackingURI(def, path); + else + rc =3D virStorageSourceParseBackingColon(def, path); + + if (rc < 0) + return -1; + + virStorageSourceNetworkAssignDefaultPorts(def); + + /* Some of the legacy parsers parse authentication data since they= are + * also used in other places. For backing store detection the + * authentication data would be invalid anyways, so we clear it */ + if (def->auth) { + virStorageAuthDefFree(def->auth); + def->auth =3D NULL; + } + } + + *src =3D g_steal_pointer(&def); + return rc; +} + + +/** + * virStorageSourceNewFromChild: + * @parent: storage source parent + * @child: returned child/backing store definition + * @parentRaw: raw child string (backingStoreRaw) + * + * Creates a storage source which describes the backing image of @parent a= nd + * fills it into @backing depending on the passed parentRaw (backingStoreR= aw) + * and other data. Note that for local storage this function accesses the = file + * to update the actual type of the child store. + * + * Returns 0 on success, 1 if we could parse all location data but the chi= ld + * store specification contained other data unrepresentable by libvirt (e.= g. + * inline authentication). + * In both cases @src is filled. On error -1 is returned @src is NULL and = an + * error is reported. + */ +static int +virStorageSourceNewFromChild(virStorageSourcePtr parent, + const char *parentRaw, + virStorageSourcePtr *child) +{ + struct stat st; + g_autoptr(virStorageSource) def =3D NULL; + int rc =3D 0; + + *child =3D NULL; + + if (virFileIsRelative(parentRaw)) { + if (!(def =3D virStorageSourceNewFromBackingRelative(parent, paren= tRaw))) + return -1; + } else { + if ((rc =3D virStorageSourceNewFromBackingAbsolute(parentRaw, &def= )) < 0) + return -1; + } + + /* possibly update local type */ + if (def->type =3D=3D VIR_STORAGE_TYPE_FILE) { + if (stat(def->path, &st) =3D=3D 0) { + if (S_ISDIR(st.st_mode)) { + def->type =3D VIR_STORAGE_TYPE_DIR; + def->format =3D VIR_STORAGE_FILE_DIR; + } else if (S_ISBLK(st.st_mode)) { + def->type =3D VIR_STORAGE_TYPE_BLOCK; + } + } + } + + /* copy parent's labelling and other top level stuff */ + if (virStorageSourceInitChainElement(def, parent, true) < 0) + return -1; + + def->detected =3D true; + + *child =3D g_steal_pointer(&def); + return rc; +} + + +int +virStorageSourceNewFromBacking(virStorageSourcePtr parent, + virStorageSourcePtr *backing) +{ + int rc; + + if ((rc =3D virStorageSourceNewFromChild(parent, + parent->backingStoreRaw, + backing)) < 0) + return rc; + + (*backing)->format =3D parent->backingStoreRawFormat; + (*backing)->readonly =3D true; + return rc; +} + + +/** + * @src: disk source definition structure + * @fd: file descriptor + * @sb: stat buffer + * + * Updates src->physical depending on the actual type of storage being use= d. + * To be called for domain storage source reporting as the volume code does + * not set/use the 'type' field for the voldef->source.target + * + * Returns 0 on success, -1 on error. No libvirt errors are reported. + */ +int +virStorageSourceUpdatePhysicalSize(virStorageSourcePtr src, + int fd, + struct stat const *sb) +{ + off_t end; + virStorageType actual_type =3D virStorageSourceGetActualType(src); + + switch (actual_type) { + case VIR_STORAGE_TYPE_FILE: + case VIR_STORAGE_TYPE_NETWORK: + src->physical =3D sb->st_size; + break; + + case VIR_STORAGE_TYPE_BLOCK: + if ((end =3D lseek(fd, 0, SEEK_END)) =3D=3D (off_t) -1) + return -1; + + src->physical =3D end; + break; + + case VIR_STORAGE_TYPE_DIR: + src->physical =3D 0; + break; + + /* We shouldn't get VOLUME, but the switch requires all cases */ + case VIR_STORAGE_TYPE_VOLUME: + case VIR_STORAGE_TYPE_NVME: + case VIR_STORAGE_TYPE_NONE: + case VIR_STORAGE_TYPE_LAST: + return -1; + } + + return 0; +} + + +/** + * @src: disk source definition structure + * @fd: file descriptor + * @sb: stat buffer + * + * Update the capacity, allocation, physical values for the storage @src + * Shared between the domain storage source for an inactive domain and the + * voldef source target as the result is not affected by the 'type' field. + * + * Returns 0 on success, -1 on error. + */ +int +virStorageSourceUpdateBackingSizes(virStorageSourcePtr src, + int fd, + struct stat const *sb) +{ + /* Get info for normal formats */ + if (S_ISREG(sb->st_mode) || fd =3D=3D -1) { +#ifndef WIN32 + src->allocation =3D (unsigned long long)sb->st_blocks * + (unsigned long long)DEV_BSIZE; +#else + src->allocation =3D sb->st_size; +#endif + /* Regular files may be sparse, so logical size (capacity) is not = same + * as actual allocation above + */ + src->capacity =3D sb->st_size; + + /* Allocation tracks when the file is sparse, physical is the + * last offset of the file. */ + src->physical =3D sb->st_size; + } else if (S_ISDIR(sb->st_mode)) { + src->allocation =3D 0; + src->capacity =3D 0; + src->physical =3D 0; + } else if (fd >=3D 0) { + off_t end; + + /* XXX this is POSIX compliant, but doesn't work for CHAR files, + * only BLOCK. There is a Linux specific ioctl() for getting + * size of both CHAR / BLOCK devices we should check for in + * configure + * + * NB. Because we configure with AC_SYS_LARGEFILE, off_t + * should be 64 bits on all platforms. For block devices, we + * have to seek (safe even if someone else is writing) to + * determine physical size, and assume that allocation is the + * same as physical (but can refine that assumption later if + * qemu is still running). + */ + if ((end =3D lseek(fd, 0, SEEK_END)) =3D=3D (off_t)-1) { + virReportSystemError(errno, + _("failed to seek to end of %s"), src->pa= th); + return -1; + } + src->physical =3D end; + src->allocation =3D end; + src->capacity =3D end; + } + + return 0; +} + + +/** + * @src: disk source definition structure + * @buf: buffer to the storage file header + * @len: length of the storage file header + * + * Update the storage @src capacity. + * + * Returns 0 on success, -1 on error. + */ +int +virStorageSourceUpdateCapacity(virStorageSourcePtr src, + char *buf, + ssize_t len) +{ + int format =3D src->format; + g_autoptr(virStorageSource) meta =3D NULL; + + /* Raw files: capacity is physical size. For all other files: if + * the metadata has a capacity, use that, otherwise fall back to + * physical size. */ + if (format =3D=3D VIR_STORAGE_FILE_NONE) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("no disk format for %s was specified"), + src->path); + return -1; + } + + if (format =3D=3D VIR_STORAGE_FILE_RAW && !src->encryption) { + src->capacity =3D src->physical; + } else if ((meta =3D virStorageFileGetMetadataFromBuf(src->path, buf, + len, format))) { + src->capacity =3D meta->capacity ? meta->capacity : src->physical; + if (src->encryption && meta->encryption) + src->encryption->payload_offset =3D meta->encryption->payload_= offset; + } else { + return -1; + } + + if (src->encryption && src->encryption->payload_offset !=3D -1) + src->capacity -=3D src->encryption->payload_offset * 512; + + return 0; +} + + +static char * +virStorageFileCanonicalizeFormatPath(char **components, + size_t ncomponents, + bool beginSlash, + bool beginDoubleSlash) +{ + g_auto(virBuffer) buf =3D VIR_BUFFER_INITIALIZER; + size_t i; + char *ret =3D NULL; + + if (beginSlash) + virBufferAddLit(&buf, "/"); + + if (beginDoubleSlash) + virBufferAddLit(&buf, "/"); + + for (i =3D 0; i < ncomponents; i++) { + if (i !=3D 0) + virBufferAddLit(&buf, "/"); + + virBufferAdd(&buf, components[i], -1); + } + + /* if the output string is empty just return an empty string */ + if (!(ret =3D virBufferContentAndReset(&buf))) + ret =3D g_strdup(""); + + return ret; +} + + +static int +virStorageFileCanonicalizeInjectSymlink(const char *path, + size_t at, + char ***components, + size_t *ncomponents) +{ + char **tmp =3D NULL; + char **next; + size_t ntmp =3D 0; + int ret =3D -1; + + if (!(tmp =3D virStringSplitCount(path, "/", 0, &ntmp))) + goto cleanup; + + /* prepend */ + for (next =3D tmp; *next; next++) { + if (VIR_INSERT_ELEMENT(*components, at, *ncomponents, *next) < 0) + goto cleanup; + + at++; + } + + ret =3D 0; + + cleanup: + virStringListFreeCount(tmp, ntmp); + return ret; +} + + +char * +virStorageFileCanonicalizePath(const char *path, + virStorageFileSimplifyPathReadlinkCallback = cb, + void *cbdata) +{ + GHashTable *cycle =3D NULL; + bool beginSlash =3D false; + bool beginDoubleSlash =3D false; + char **components =3D NULL; + size_t ncomponents =3D 0; + size_t i =3D 0; + size_t j =3D 0; + int rc; + char *ret =3D NULL; + g_autofree char *linkpath =3D NULL; + g_autofree char *currentpath =3D NULL; + + if (path[0] =3D=3D '/') { + beginSlash =3D true; + + if (path[1] =3D=3D '/' && path[2] !=3D '/') + beginDoubleSlash =3D true; + } + + if (!(cycle =3D virHashNew(NULL))) + goto cleanup; + + if (!(components =3D virStringSplitCount(path, "/", 0, &ncomponents))) + goto cleanup; + + j =3D 0; + while (j < ncomponents) { + /* skip slashes */ + if (STREQ(components[j], "")) { + VIR_FREE(components[j]); + VIR_DELETE_ELEMENT(components, j, ncomponents); + continue; + } + j++; + } + + while (i < ncomponents) { + /* skip '.'s unless it's the last one remaining */ + if (STREQ(components[i], ".") && + (beginSlash || ncomponents > 1)) { + VIR_FREE(components[i]); + VIR_DELETE_ELEMENT(components, i, ncomponents); + continue; + } + + /* resolve changes to parent directory */ + if (STREQ(components[i], "..")) { + if (!beginSlash && + (i =3D=3D 0 || STREQ(components[i - 1], ".."))) { + i++; + continue; + } + + VIR_FREE(components[i]); + VIR_DELETE_ELEMENT(components, i, ncomponents); + + if (i !=3D 0) { + VIR_FREE(components[i - 1]); + VIR_DELETE_ELEMENT(components, i - 1, ncomponents); + i--; + } + + continue; + } + + /* check if the actual path isn't resulting into a symlink */ + if (!(currentpath =3D virStorageFileCanonicalizeFormatPath(compone= nts, + i + 1, + beginSlas= h, + beginDoub= leSlash))) + goto cleanup; + + if ((rc =3D cb(currentpath, &linkpath, cbdata)) < 0) + goto cleanup; + + if (rc =3D=3D 0) { + if (virHashLookup(cycle, currentpath)) { + virReportSystemError(ELOOP, + _("Failed to canonicalize path '%s'")= , path); + goto cleanup; + } + + if (virHashAddEntry(cycle, currentpath, (void *) 1) < 0) + goto cleanup; + + if (linkpath[0] =3D=3D '/') { + /* kill everything from the beginning including the actual= component */ + i++; + while (i--) { + VIR_FREE(components[0]); + VIR_DELETE_ELEMENT(components, 0, ncomponents); + } + beginSlash =3D true; + + if (linkpath[1] =3D=3D '/' && linkpath[2] !=3D '/') + beginDoubleSlash =3D true; + else + beginDoubleSlash =3D false; + + i =3D 0; + } else { + VIR_FREE(components[i]); + VIR_DELETE_ELEMENT(components, i, ncomponents); + } + + if (virStorageFileCanonicalizeInjectSymlink(linkpath, + i, + &components, + &ncomponents) < 0) + goto cleanup; + + j =3D 0; + while (j < ncomponents) { + /* skip slashes */ + if (STREQ(components[j], "")) { + VIR_FREE(components[j]); + VIR_DELETE_ELEMENT(components, j, ncomponents); + continue; + } + j++; + } + + VIR_FREE(linkpath); + VIR_FREE(currentpath); + + continue; + } + + VIR_FREE(currentpath); + + i++; + } + + ret =3D virStorageFileCanonicalizeFormatPath(components, ncomponents, + beginSlash, beginDoubleSlas= h); + + cleanup: + virHashFree(cycle); + virStringListFreeCount(components, ncomponents); + + return ret; +} + + +/** + * virStorageFileRemoveLastPathComponent: + * + * @path: Path string to remove the last component from + * + * Removes the last path component of a path. This function is designed to= be + * called on file paths only (no trailing slashes in @path). Caller is + * responsible to free the returned string. + */ +static char * +virStorageFileRemoveLastPathComponent(const char *path) +{ + char *ret; + + ret =3D g_strdup(NULLSTR_EMPTY(path)); + + virFileRemoveLastComponent(ret); + + return ret; +} + + +/* + * virStorageFileGetRelativeBackingPath: + * + * Resolve relative path to be written to the overlay of @top image when + * collapsing the backing chain between @top and @base. + * + * Returns 0 on success; 1 if backing chain isn't relative and -1 on error. + */ +int +virStorageFileGetRelativeBackingPath(virStorageSourcePtr top, + virStorageSourcePtr base, + char **relpath) +{ + virStorageSourcePtr next; + g_autofree char *tmp =3D NULL; + g_autofree char *path =3D NULL; + + *relpath =3D NULL; + + for (next =3D top; virStorageSourceIsBacking(next); next =3D next->bac= kingStore) { + if (!next->relPath) + return 1; + + if (!(tmp =3D virStorageFileRemoveLastPathComponent(path))) + return -1; + + VIR_FREE(path); + + path =3D g_strdup_printf("%s%s", tmp, next->relPath); + + VIR_FREE(tmp); + + if (next =3D=3D base) + break; + } + + if (next !=3D base) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to resolve relative backing name: " + "base image is not in backing chain")); + return -1; + } + + *relpath =3D g_steal_pointer(&path); + return 0; +} + + +/** + * virStorageSourceFindByNodeName: + * @top: backing chain top + * @nodeName: node name to find in backing chain + * + * Looks up the given storage source in the backing chain and returns the + * pointer to it. + * On failure NULL is returned and no error is reported. + */ +virStorageSourcePtr +virStorageSourceFindByNodeName(virStorageSourcePtr top, + const char *nodeName) +{ + virStorageSourcePtr tmp; + + for (tmp =3D top; virStorageSourceIsBacking(tmp); tmp =3D tmp->backing= Store) { + if ((tmp->nodeformat && STREQ(tmp->nodeformat, nodeName)) || + (tmp->nodestorage && STREQ(tmp->nodestorage, nodeName))) + return tmp; + } + + return NULL; +} + + +int +virStorageSourcePrivateDataParseRelPath(xmlXPathContextPtr ctxt, + virStorageSourcePtr src) +{ + src->relPath =3D virXPathString("string(./relPath)", ctxt); + return 0; +} + + +int +virStorageSourcePrivateDataFormatRelPath(virStorageSourcePtr src, + virBufferPtr buf) +{ + if (src->relPath) + virBufferEscapeString(buf, "%s\n", src->relPath= ); + + return 0; +} + + +static bool +virStorageFileIsInitialized(const virStorageSource *src) +{ + return src && src->drv; +} + + +/** + * virStorageFileGetBackendForSupportCheck: + * @src: storage source to check support for + * @backend: pointer to the storage backend for @src if it's supported + * + * Returns 0 if @src is not supported by any storage backend currently lin= ked + * 1 if it is supported and -1 on error with an error reported. + */ +static int +virStorageFileGetBackendForSupportCheck(const virStorageSource *src, + virStorageFileBackendPtr *backend) +{ + int actualType; + + + if (!src) { + *backend =3D NULL; + return 0; + } + + if (src->drv) { + virStorageDriverDataPtr drv =3D src->drv; + *backend =3D drv->backend; + return 1; + } + + actualType =3D virStorageSourceGetActualType(src); + + if (virStorageFileBackendForType(actualType, src->protocol, false, bac= kend) < 0) + return -1; + + if (!*backend) + return 0; + + return 1; +} + + +int +virStorageFileSupportsBackingChainTraversal(const virStorageSource *src) +{ + virStorageFileBackendPtr backend; + int rv; + + if ((rv =3D virStorageFileGetBackendForSupportCheck(src, &backend)) < = 1) + return rv; + + return backend->storageFileGetUniqueIdentifier && + backend->storageFileRead && + backend->storageFileAccess ? 1 : 0; +} + + +/** + * virStorageFileSupportsSecurityDriver: + * + * @src: a storage file structure + * + * Check if a storage file supports operations needed by the security + * driver to perform labelling + */ +int +virStorageFileSupportsSecurityDriver(const virStorageSource *src) +{ + virStorageFileBackendPtr backend; + int rv; + + if ((rv =3D virStorageFileGetBackendForSupportCheck(src, &backend)) < = 1) + return rv; + + return backend->storageFileChown ? 1 : 0; +} + + +/** + * virStorageFileSupportsAccess: + * + * @src: a storage file structure + * + * Check if a storage file supports checking if the storage source is acce= ssible + * for the given vm. + */ +int +virStorageFileSupportsAccess(const virStorageSource *src) +{ + virStorageFileBackendPtr backend; + int rv; + + if ((rv =3D virStorageFileGetBackendForSupportCheck(src, &backend)) < = 1) + return rv; + + return backend->storageFileAccess ? 1 : 0; +} + + +/** + * virStorageFileSupportsCreate: + * @src: a storage file structure + * + * Check if the storage driver supports creating storage described by @src + * via virStorageFileCreate. + */ +int +virStorageFileSupportsCreate(const virStorageSource *src) +{ + virStorageFileBackendPtr backend; + int rv; + + if ((rv =3D virStorageFileGetBackendForSupportCheck(src, &backend)) < = 1) + return rv; + + return backend->storageFileCreate ? 1 : 0; +} + + +void +virStorageFileDeinit(virStorageSourcePtr src) +{ + virStorageDriverDataPtr drv =3D NULL; + + if (!virStorageFileIsInitialized(src)) + return; + + drv =3D src->drv; + + if (drv->backend && + drv->backend->backendDeinit) + drv->backend->backendDeinit(src); + + VIR_FREE(src->drv); +} + + +/** + * virStorageFileInitAs: + * + * @src: storage source definition + * @uid: uid used to access the file, or -1 for current uid + * @gid: gid used to access the file, or -1 for current gid + * + * Initialize a storage source to be used with storage driver. Use the pro= vided + * uid and gid if possible for the operations. + * + * Returns 0 if the storage file was successfully initialized, -1 if the + * initialization failed. Libvirt error is reported. + */ +int +virStorageFileInitAs(virStorageSourcePtr src, + uid_t uid, + gid_t gid) +{ + int actualType =3D virStorageSourceGetActualType(src); + virStorageDriverDataPtr drv =3D g_new0(virStorageDriverData, 1); + + src->drv =3D drv; + + if (uid =3D=3D (uid_t) -1) + drv->uid =3D geteuid(); + else + drv->uid =3D uid; + + if (gid =3D=3D (gid_t) -1) + drv->gid =3D getegid(); + else + drv->gid =3D gid; + + if (virStorageFileBackendForType(actualType, + src->protocol, + true, + &drv->backend) < 0) + goto error; + + if (drv->backend->backendInit && + drv->backend->backendInit(src) < 0) + goto error; + + return 0; + + error: + VIR_FREE(src->drv); + return -1; +} + + +/** + * virStorageFileInit: + * + * See virStorageFileInitAs. The file is initialized to be accessed by the + * current user. + */ +int +virStorageFileInit(virStorageSourcePtr src) +{ + return virStorageFileInitAs(src, -1, -1); +} + + +/** + * virStorageFileCreate: Creates an empty storage file via storage driver + * + * @src: file structure pointing to the file + * + * Returns 0 on success, -2 if the function isn't supported by the backend, + * -1 on other failure. Errno is set in case of failure. + */ +int +virStorageFileCreate(virStorageSourcePtr src) +{ + virStorageDriverDataPtr drv =3D NULL; + int ret; + + if (!virStorageFileIsInitialized(src)) { + errno =3D ENOSYS; + return -2; + } + + drv =3D src->drv; + + if (!drv->backend->storageFileCreate) { + errno =3D ENOSYS; + return -2; + } + + ret =3D drv->backend->storageFileCreate(src); + + VIR_DEBUG("created storage file %p: ret=3D%d, errno=3D%d", + src, ret, errno); + + return ret; +} + + +/** + * virStorageFileUnlink: Unlink storage file via storage driver + * + * @src: file structure pointing to the file + * + * Unlinks the file described by the @file structure. + * + * Returns 0 on success, -2 if the function isn't supported by the backend, + * -1 on other failure. Errno is set in case of failure. + */ +int +virStorageFileUnlink(virStorageSourcePtr src) +{ + virStorageDriverDataPtr drv =3D NULL; + int ret; + + if (!virStorageFileIsInitialized(src)) { + errno =3D ENOSYS; + return -2; + } + + drv =3D src->drv; + + if (!drv->backend->storageFileUnlink) { + errno =3D ENOSYS; + return -2; + } + + ret =3D drv->backend->storageFileUnlink(src); + + VIR_DEBUG("unlinked storage file %p: ret=3D%d, errno=3D%d", + src, ret, errno); + + return ret; +} + + +/** + * virStorageFileStat: returns stat struct of a file via storage driver + * + * @src: file structure pointing to the file + * @stat: stat structure to return data + * + * Returns 0 on success, -2 if the function isn't supported by the backend, + * -1 on other failure. Errno is set in case of failure. +*/ +int +virStorageFileStat(virStorageSourcePtr src, + struct stat *st) +{ + virStorageDriverDataPtr drv =3D NULL; + int ret; + + if (!virStorageFileIsInitialized(src)) { + errno =3D ENOSYS; + return -2; + } + + drv =3D src->drv; + + if (!drv->backend->storageFileStat) { + errno =3D ENOSYS; + return -2; + } + + ret =3D drv->backend->storageFileStat(src, st); + + VIR_DEBUG("stat of storage file %p: ret=3D%d, errno=3D%d", + src, ret, errno); + + return ret; +} + + +/** + * virStorageFileRead: read bytes from a file into a buffer + * + * @src: file structure pointing to the file + * @offset: number of bytes to skip in the storage file + * @len: maximum number of bytes read from the storage file + * @buf: buffer to read the data into. (buffer shall be freed by caller) + * + * Returns the count of bytes read on success and -1 on failure, -2 if the + * function isn't supported by the backend. + * Libvirt error is reported on failure. + */ +ssize_t +virStorageFileRead(virStorageSourcePtr src, + size_t offset, + size_t len, + char **buf) +{ + virStorageDriverDataPtr drv =3D NULL; + ssize_t ret; + + if (!virStorageFileIsInitialized(src)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("storage file backend not initialized")); + return -1; + } + + drv =3D src->drv; + + if (!drv->backend->storageFileRead) + return -2; + + ret =3D drv->backend->storageFileRead(src, offset, len, buf); + + VIR_DEBUG("read '%zd' bytes from storage '%p' starting at offset '%zu'= ", + ret, src, offset); + + return ret; +} + + +/* + * virStorageFileGetUniqueIdentifier: Get a unique string describing the v= olume + * + * @src: file structure pointing to the file + * + * Returns a string uniquely describing a single volume (canonical path). + * The string shall not be freed and is valid until the storage file is + * deinitialized. Returns NULL on error and sets a libvirt error code */ +const char * +virStorageFileGetUniqueIdentifier(virStorageSourcePtr src) +{ + virStorageDriverDataPtr drv =3D NULL; + + if (!virStorageFileIsInitialized(src)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("storage file backend not initialized")); + return NULL; + } + + drv =3D src->drv; + + if (!drv->backend->storageFileGetUniqueIdentifier) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("unique storage file identifier not implemented f= or " + "storage type %s (protocol: %s)'"), + virStorageTypeToString(src->type), + virStorageNetProtocolTypeToString(src->protocol)); + return NULL; + } + + return drv->backend->storageFileGetUniqueIdentifier(src); +} + + +/** + * virStorageFileAccess: Check accessibility of a storage file + * + * @src: storage file to check access permissions + * @mode: accessibility check options (see man 2 access) + * + * Returns 0 on success, -1 on error and sets errno. No libvirt + * error is reported. Returns -2 if the operation isn't supported + * by libvirt storage backend. + */ +int +virStorageFileAccess(virStorageSourcePtr src, + int mode) +{ + virStorageDriverDataPtr drv =3D NULL; + + if (!virStorageFileIsInitialized(src)) { + errno =3D ENOSYS; + return -2; + } + + drv =3D src->drv; + + if (!drv->backend->storageFileAccess) { + errno =3D ENOSYS; + return -2; + } + + return drv->backend->storageFileAccess(src, mode); +} + + +/** + * virStorageFileChown: Change owner of a storage file + * + * @src: storage file to change owner of + * @uid: new owner id + * @gid: new group id + * + * Returns 0 on success, -1 on error and sets errno. No libvirt + * error is reported. Returns -2 if the operation isn't supported + * by libvirt storage backend. + */ +int +virStorageFileChown(const virStorageSource *src, + uid_t uid, + gid_t gid) +{ + virStorageDriverDataPtr drv =3D NULL; + + if (!virStorageFileIsInitialized(src)) { + errno =3D ENOSYS; + return -2; + } + + drv =3D src->drv; + + if (!drv->backend->storageFileChown) { + errno =3D ENOSYS; + return -2; + } + + VIR_DEBUG("chown of storage file %p to %u:%u", + src, (unsigned int)uid, (unsigned int)gid); + + return drv->backend->storageFileChown(src, uid, gid); +} + + +/** + * virStorageFileReportBrokenChain: + * + * @errcode: errno when accessing @src + * @src: inaccessible file in the backing chain of @parent + * @parent: root virStorageSource being checked + * + * Reports the correct error message if @src is missing in the backing cha= in + * for @parent. + */ +void +virStorageFileReportBrokenChain(int errcode, + virStorageSourcePtr src, + virStorageSourcePtr parent) +{ + if (src->drv) { + virStorageDriverDataPtr drv =3D src->drv; + unsigned int access_user =3D drv->uid; + unsigned int access_group =3D drv->gid; + + if (src =3D=3D parent) { + virReportSystemError(errcode, + _("Cannot access storage file '%s' " + "(as uid:%u, gid:%u)"), + src->path, access_user, access_group); + } else { + virReportSystemError(errcode, + _("Cannot access backing file '%s' " + "of storage file '%s' (as uid:%u, gid:%= u)"), + src->path, parent->path, access_user, acc= ess_group); + } + } else { + if (src =3D=3D parent) { + virReportSystemError(errcode, + _("Cannot access storage file '%s'"), + src->path); + } else { + virReportSystemError(errcode, + _("Cannot access backing file '%s' " + "of storage file '%s'"), + src->path, parent->path); + } + } +} + + +static int +virStorageFileGetMetadataRecurseReadHeader(virStorageSourcePtr src, + virStorageSourcePtr parent, + uid_t uid, + gid_t gid, + char **buf, + size_t *headerLen, + GHashTable *cycle) +{ + int ret =3D -1; + const char *uniqueName; + ssize_t len; + + if (virStorageFileInitAs(src, uid, gid) < 0) + return -1; + + if (virStorageFileAccess(src, F_OK) < 0) { + virStorageFileReportBrokenChain(errno, src, parent); + goto cleanup; + } + + if (!(uniqueName =3D virStorageFileGetUniqueIdentifier(src))) + goto cleanup; + + if (virHashHasEntry(cycle, uniqueName)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("backing store for %s (%s) is self-referential"), + NULLSTR(src->path), uniqueName); + goto cleanup; + } + + if (virHashAddEntry(cycle, uniqueName, NULL) < 0) + goto cleanup; + + if ((len =3D virStorageFileRead(src, 0, VIR_STORAGE_MAX_HEADER, buf)) = < 0) + goto cleanup; + + *headerLen =3D len; + ret =3D 0; + + cleanup: + virStorageFileDeinit(src); + return ret; +} + + +/* Recursive workhorse for virStorageFileGetMetadata. */ +static int +virStorageFileGetMetadataRecurse(virStorageSourcePtr src, + virStorageSourcePtr parent, + uid_t uid, gid_t gid, + bool report_broken, + GHashTable *cycle, + unsigned int depth) +{ + virStorageFileFormat orig_format =3D src->format; + size_t headerLen; + int rv; + g_autofree char *buf =3D NULL; + g_autoptr(virStorageSource) backingStore =3D NULL; + + VIR_DEBUG("path=3D%s format=3D%d uid=3D%u gid=3D%u", + NULLSTR(src->path), src->format, + (unsigned int)uid, (unsigned int)gid); + + if (src->format =3D=3D VIR_STORAGE_FILE_AUTO_SAFE) + src->format =3D VIR_STORAGE_FILE_AUTO; + + /* exit if we can't load information about the current image */ + rv =3D virStorageFileSupportsBackingChainTraversal(src); + if (rv <=3D 0) { + if (orig_format =3D=3D VIR_STORAGE_FILE_AUTO) + return -2; + + return rv; + } + + if (virStorageFileGetMetadataRecurseReadHeader(src, parent, uid, gid, + &buf, &headerLen, cycle= ) < 0) + return -1; + + if (virStorageFileGetMetadataInternal(src, buf, headerLen) < 0) + return -1; + + /* If we probed the format we MUST ensure that nothing else than the c= urrent + * image is considered for security labelling and/or recursion. */ + if (orig_format =3D=3D VIR_STORAGE_FILE_AUTO) { + if (src->backingStoreRaw) { + src->format =3D VIR_STORAGE_FILE_RAW; + VIR_FREE(src->backingStoreRaw); + return -2; + } + } + + if (src->backingStoreRaw) { + if ((rv =3D virStorageSourceNewFromBacking(src, &backingStore)) < = 0) + return -1; + + /* the backing file would not be usable for VM usage */ + if (rv =3D=3D 1) + return 0; + + if ((rv =3D virStorageFileGetMetadataRecurse(backingStore, parent, + uid, gid, + report_broken, + cycle, depth + 1)) < 0)= { + if (!report_broken) + return 0; + + if (rv =3D=3D -2) { + virReportError(VIR_ERR_OPERATION_INVALID, + _("format of backing image '%s' of image '%= s' was not specified in the image metadata " + "(See https://libvirt.org/kbase/backing_c= hains.html for troubleshooting)"), + src->backingStoreRaw, NULLSTR(src->path)); + } + + return -1; + } + + backingStore->id =3D depth; + src->backingStore =3D g_steal_pointer(&backingStore); + } else { + /* add terminator */ + src->backingStore =3D virStorageSourceNew(); + } + + return 0; +} + + +/** + * virStorageFileGetMetadata: + * + * Extract metadata about the storage volume with the specified + * image format. If image format is VIR_STORAGE_FILE_AUTO, it + * will probe to automatically identify the format. Recurses through + * the entire chain. + * + * Open files using UID and GID (or pass -1 for the current user/group). + * Treat any backing files without explicit type as raw, unless ALLOW_PROB= E. + * + * Callers are advised never to use VIR_STORAGE_FILE_AUTO as a + * format, since a malicious guest can turn a raw file into any + * other non-raw format at will. + * + * If @report_broken is true, the whole function fails with a possibly sane + * error instead of just returning a broken chain. Note that the inability= for + * libvirt to traverse a given source is not considered an error. + * + * Caller MUST free result after use via virObjectUnref. + */ +int +virStorageFileGetMetadata(virStorageSourcePtr src, + uid_t uid, gid_t gid, + bool report_broken) +{ + GHashTable *cycle =3D NULL; + virStorageType actualType =3D virStorageSourceGetActualType(src); + int ret =3D -1; + + VIR_DEBUG("path=3D%s format=3D%d uid=3D%u gid=3D%u report_broken=3D%d", + src->path, src->format, (unsigned int)uid, (unsigned int)gid, + report_broken); + + if (!(cycle =3D virHashNew(NULL))) + return -1; + + if (src->format <=3D VIR_STORAGE_FILE_NONE) { + if (actualType =3D=3D VIR_STORAGE_TYPE_DIR) + src->format =3D VIR_STORAGE_FILE_DIR; + else + src->format =3D VIR_STORAGE_FILE_RAW; + } + + ret =3D virStorageFileGetMetadataRecurse(src, src, uid, gid, + report_broken, cycle, 1); + + virHashFree(cycle); + return ret; +} + + +/** + * virStorageFileGetBackingStoreStr: + * @src: storage object + * + * Extracts the backing store string as stored in the storage volume descr= ibed + * by @src and returns it to the user. Caller is responsible for freeing i= t. + * In case when the string can't be retrieved or does not exist NULL is + * returned. + */ +int +virStorageFileGetBackingStoreStr(virStorageSourcePtr src, + char **backing) +{ + ssize_t headerLen; + int rv; + g_autofree char *buf =3D NULL; + g_autoptr(virStorageSource) tmp =3D NULL; + + *backing =3D NULL; + + /* exit if we can't load information about the current image */ + if (!virStorageFileSupportsBackingChainTraversal(src)) + return 0; + + rv =3D virStorageFileAccess(src, F_OK); + if (rv =3D=3D -2) + return 0; + if (rv < 0) { + virStorageFileReportBrokenChain(errno, src, src); + return -1; + } + + if ((headerLen =3D virStorageFileRead(src, 0, VIR_STORAGE_MAX_HEADER, + &buf)) < 0) { + if (headerLen =3D=3D -2) + return 0; + return -1; + } + + if (!(tmp =3D virStorageSourceCopy(src, false))) + return -1; + + if (virStorageFileGetMetadataInternal(tmp, buf, headerLen) < 0) + return -1; + + *backing =3D g_steal_pointer(&tmp->backingStoreRaw); + return 0; +} diff --git a/src/storage_file/storage_file.h b/src/storage_file/storage_fil= e.h new file mode 100644 index 0000000000..8afedc35b3 --- /dev/null +++ b/src/storage_file/storage_file.h @@ -0,0 +1,197 @@ +/* + * storage_file.h: file utility functions for FS storage backend + * + * Copyright (C) 2007-2009, 2012-2016 Red Hat, Inc. + * 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 + * License along with this library. If not, see + * . + */ + +#pragma once + +#include "virstoragefile.h" + + +/* Minimum header size required to probe all known formats with + * virStorageFileProbeFormat, or obtain metadata from a known format. + * Rounded to multiple of 512 (ISO has a 5-byte magic at offset + * 32769). Some formats can be probed with fewer bytes. Although + * some formats theoretically permit metadata that can rely on offsets + * beyond this size, in practice that doesn't matter. */ +#define VIR_STORAGE_MAX_HEADER 0x8200 + +#ifndef DEV_BSIZE +# define DEV_BSIZE 512 +#endif + +int +virStorageFileProbeFormat(const char *path, + uid_t uid, + gid_t gid); + +virStorageSourcePtr +virStorageFileGetMetadataFromFD(const char *path, + int fd, + int format); + +virStorageSourcePtr +virStorageFileGetMetadataFromBuf(const char *path, + char *buf, + size_t len, + int format) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); + +int +virStorageFileParseChainIndex(const char *diskTarget, + const char *name, + unsigned int *chainIndex) + ATTRIBUTE_NONNULL(3); + +int +virStorageFileParseBackingStoreStr(const char *str, + char **target, + unsigned int *chainIndex) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3); + +virStorageSourcePtr +virStorageFileChainLookup(virStorageSourcePtr chain, + virStorageSourcePtr startFrom, + const char *name, + unsigned int idx, + virStorageSourcePtr *parent) + ATTRIBUTE_NONNULL(1); + +int +virStorageSourceUpdatePhysicalSize(virStorageSourcePtr src, + int fd, + struct stat const *sb); +int +virStorageSourceUpdateBackingSizes(virStorageSourcePtr src, + int fd, + struct stat const *sb); + +int +virStorageSourceUpdateCapacity(virStorageSourcePtr src, + char *buf, + ssize_t len); + +int +virStorageSourceNewFromBacking(virStorageSourcePtr parent, + virStorageSourcePtr *backing); + +int +virStorageSourceParseRBDColonString(const char *rbdstr, + virStorageSourcePtr src) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); + +typedef int +(*virStorageFileSimplifyPathReadlinkCallback)(const char *path, + char **link, + void *data); + +char * +virStorageFileCanonicalizePath(const char *path, + virStorageFileSimplifyPathReadlinkCallback = cb, + void *cbdata); + +int +virStorageFileGetRelativeBackingPath(virStorageSourcePtr from, + virStorageSourcePtr to, + char **relpath) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); + +int +virStorageSourceNewFromBackingAbsolute(const char *path, + virStorageSourcePtr *src); + +virStorageSourcePtr +virStorageSourceFindByNodeName(virStorageSourcePtr top, + const char *nodeName) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); + +int +virStorageSourcePrivateDataParseRelPath(xmlXPathContextPtr ctxt, + virStorageSourcePtr src); + +int +virStorageSourcePrivateDataFormatRelPath(virStorageSourcePtr src, + virBufferPtr buf); + +int +virStorageFileInit(virStorageSourcePtr src); + +int +virStorageFileInitAs(virStorageSourcePtr src, + uid_t uid, + gid_t gid); + +void +virStorageFileDeinit(virStorageSourcePtr src); + +int +virStorageFileCreate(virStorageSourcePtr src); + +int +virStorageFileUnlink(virStorageSourcePtr src); + +int +virStorageFileStat(virStorageSourcePtr src, + struct stat *stat); + +ssize_t +virStorageFileRead(virStorageSourcePtr src, + size_t offset, + size_t len, + char **buf); + +const char * +virStorageFileGetUniqueIdentifier(virStorageSourcePtr src); + +int +virStorageFileAccess(virStorageSourcePtr src, + int mode); + +int +virStorageFileChown(const virStorageSource *src, + uid_t uid, + gid_t gid); + +int +virStorageFileSupportsSecurityDriver(const virStorageSource *src); + +int +virStorageFileSupportsAccess(const virStorageSource *src); + +int +virStorageFileSupportsCreate(const virStorageSource *src); + +int +virStorageFileSupportsBackingChainTraversal(const virStorageSource *src); + +int +virStorageFileGetMetadata(virStorageSourcePtr src, + uid_t uid, gid_t gid, + bool report_broken) + ATTRIBUTE_NONNULL(1); + +int +virStorageFileGetBackingStoreStr(virStorageSourcePtr src, + char **backing) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); + +void +virStorageFileReportBrokenChain(int errcode, + virStorageSourcePtr src, + virStorageSourcePtr parent); diff --git a/src/storage_file/storage_file_gluster.c b/src/storage_file/sto= rage_file_gluster.c index e26dfdfd99..599afada2c 100644 --- a/src/storage_file/storage_file_gluster.c +++ b/src/storage_file/storage_file_gluster.c @@ -23,6 +23,7 @@ =20 #include =20 +#include "storage_file.h" #include "storage_file_gluster.h" #include "viralloc.h" #include "virerror.h" diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c index 524204a56c..3489934546 100644 --- a/src/util/virstoragefile.c +++ b/src/util/virstoragefile.c @@ -20,26 +20,17 @@ */ =20 #include -#include "virstoragefilebackend.h" +#include "virstoragefile.h" =20 -#include -#include #include "viralloc.h" #include "virxml.h" -#include "viruuid.h" #include "virerror.h" #include "virlog.h" -#include "virfile.h" #include "vircommand.h" -#include "virhash.h" -#include "virendian.h" #include "virstring.h" -#include "viruri.h" #include "virbuffer.h" -#include "virjson.h" #include "virstorageencryption.h" #include "virsecret.h" -#include "virutil.h" =20 #define VIR_FROM_THIS VIR_FROM_STORAGE =20 @@ -111,1054 +102,6 @@ VIR_ENUM_IMPL(virStorageAuth, "none", "chap", "ceph", ); =20 -enum lv_endian { - LV_LITTLE_ENDIAN =3D 1, /* 1234 */ - LV_BIG_ENDIAN /* 4321 */ -}; - -enum { - BACKING_STORE_OK, - BACKING_STORE_INVALID, - BACKING_STORE_ERROR, -}; - -#define FILE_TYPE_VERSIONS_LAST 3 - -struct FileEncryptionInfo { - int format; /* Encryption format to assign */ - - int magicOffset; /* Byte offset of the magic */ - const char *magic; /* Optional string of magic */ - - enum lv_endian endian; /* Endianness of file format */ - - int versionOffset; /* Byte offset from start of file - * where we find version number, - * -1 to always fail the version test, - * -2 to always pass the version test */ - int versionSize; /* Size in bytes of version data (0, 2, or 4) */ - int versionNumbers[FILE_TYPE_VERSIONS_LAST]; - /* Version numbers to validate. Zeroes are ignor= ed. */ - - int modeOffset; /* Byte offset of the format native encryption mode */ - char modeValue; /* Value expected at offset */ - - int payloadOffset; /* start offset of the volume data (in 512 byte sec= tors) */ -}; - -struct FileTypeInfo { - int magicOffset; /* Byte offset of the magic */ - const char *magic; /* Optional string of file magic - * to check at head of file */ - enum lv_endian endian; /* Endianness of file format */ - - int versionOffset; /* Byte offset from start of file - * where we find version number, - * -1 to always fail the version test, - * -2 to always pass the version test */ - int versionSize; /* Size in bytes of version data (0, 2, or 4) */ - int versionNumbers[FILE_TYPE_VERSIONS_LAST]; - /* Version numbers to validate. Zeroes are ignor= ed. */ - int sizeOffset; /* Byte offset from start of file - * where we find capacity info, - * -1 to use st_size as capacity */ - int sizeBytes; /* Number of bytes for size field */ - int sizeMultiplier; /* A scaling factor if size is not in bytes */ - /* Store a COW base image path (possibly relativ= e), - * or NULL if there is no COW base image, to RES; - * return BACKING_STORE_* */ - const struct FileEncryptionInfo *cryptInfo; /* Encryption info */ - int (*getBackingStore)(char **res, int *format, - const char *buf, size_t buf_size); - int (*getFeatures)(virBitmapPtr *features, int format, - char *buf, ssize_t len); -}; - - -static int cowGetBackingStore(char **, int *, - const char *, size_t); -static int qcowXGetBackingStore(char **, int *, - const char *, size_t); -static int qcow2GetFeatures(virBitmapPtr *features, int format, - char *buf, ssize_t len); -static int vmdk4GetBackingStore(char **, int *, - const char *, size_t); -static int -qedGetBackingStore(char **, int *, const char *, size_t); - -#define QCOWX_HDR_VERSION (4) -#define QCOWX_HDR_BACKING_FILE_OFFSET (QCOWX_HDR_VERSION+4) -#define QCOWX_HDR_BACKING_FILE_SIZE (QCOWX_HDR_BACKING_FILE_OFFSET+8) -#define QCOWX_HDR_IMAGE_SIZE (QCOWX_HDR_BACKING_FILE_SIZE+4+4) - -#define QCOW1_HDR_CRYPT (QCOWX_HDR_IMAGE_SIZE+8+1+1+2) -#define QCOW2_HDR_CRYPT (QCOWX_HDR_IMAGE_SIZE+8) - -#define QCOW1_HDR_TOTAL_SIZE (QCOW1_HDR_CRYPT+4+8) -#define QCOW2_HDR_TOTAL_SIZE (QCOW2_HDR_CRYPT+4+4+8+8+4+4+8) - -#define QCOW2_HDR_EXTENSION_END 0 -#define QCOW2_HDR_EXTENSION_BACKING_FORMAT 0xE2792ACA - -#define QCOW2v3_HDR_FEATURES_INCOMPATIBLE (QCOW2_HDR_TOTAL_SIZE) -#define QCOW2v3_HDR_FEATURES_COMPATIBLE (QCOW2v3_HDR_FEATURES_INCOMPATIBLE= +8) -#define QCOW2v3_HDR_FEATURES_AUTOCLEAR (QCOW2v3_HDR_FEATURES_COMPATIBLE+8) - -/* The location of the header size [4 bytes] */ -#define QCOW2v3_HDR_SIZE (QCOW2_HDR_TOTAL_SIZE+8+8+8+4) - -#define QED_HDR_FEATURES_OFFSET (4+4+4+4) -#define QED_HDR_IMAGE_SIZE (QED_HDR_FEATURES_OFFSET+8+8+8+8) -#define QED_HDR_BACKING_FILE_OFFSET (QED_HDR_IMAGE_SIZE+8) -#define QED_HDR_BACKING_FILE_SIZE (QED_HDR_BACKING_FILE_OFFSET+4) -#define QED_F_BACKING_FILE 0x01 -#define QED_F_BACKING_FORMAT_NO_PROBE 0x04 - -#define PLOOP_IMAGE_SIZE_OFFSET 36 -#define PLOOP_SIZE_MULTIPLIER 512 - -#define LUKS_HDR_MAGIC_LEN 6 -#define LUKS_HDR_VERSION_LEN 2 -#define LUKS_HDR_CIPHER_NAME_LEN 32 -#define LUKS_HDR_CIPHER_MODE_LEN 32 -#define LUKS_HDR_HASH_SPEC_LEN 32 -#define LUKS_HDR_PAYLOAD_LEN 4 - -/* Format described by qemu commit id '3e308f20e' */ -#define LUKS_HDR_VERSION_OFFSET LUKS_HDR_MAGIC_LEN -#define LUKS_HDR_PAYLOAD_OFFSET (LUKS_HDR_MAGIC_LEN+\ - LUKS_HDR_VERSION_LEN+\ - LUKS_HDR_CIPHER_NAME_LEN+\ - LUKS_HDR_CIPHER_MODE_LEN+\ - LUKS_HDR_HASH_SPEC_LEN) - -static struct FileEncryptionInfo const luksEncryptionInfo[] =3D { - { - .format =3D VIR_STORAGE_ENCRYPTION_FORMAT_LUKS, - - /* Magic is 'L','U','K','S', 0xBA, 0xBE */ - .magicOffset =3D 0, - .magic =3D "\x4c\x55\x4b\x53\xba\xbe", - .endian =3D LV_BIG_ENDIAN, - - .versionOffset =3D LUKS_HDR_VERSION_OFFSET, - .versionSize =3D LUKS_HDR_VERSION_LEN, - .versionNumbers =3D {1}, - - .modeOffset =3D -1, - .modeValue =3D -1, - - .payloadOffset =3D LUKS_HDR_PAYLOAD_OFFSET, - }, - { 0 } -}; - -static struct FileEncryptionInfo const qcow1EncryptionInfo[] =3D { - { - .format =3D VIR_STORAGE_ENCRYPTION_FORMAT_QCOW, - - .magicOffset =3D 0, - .magic =3D NULL, - .endian =3D LV_BIG_ENDIAN, - - .versionOffset =3D -1, - .versionSize =3D 0, - .versionNumbers =3D {}, - - .modeOffset =3D QCOW1_HDR_CRYPT, - .modeValue =3D 1, - - .payloadOffset =3D -1, - }, - { 0 } -}; - -static struct FileEncryptionInfo const qcow2EncryptionInfo[] =3D { - { - .format =3D VIR_STORAGE_ENCRYPTION_FORMAT_QCOW, - - .magicOffset =3D 0, - .magic =3D NULL, - .endian =3D LV_BIG_ENDIAN, - - .versionOffset =3D -1, - .versionSize =3D 0, - .versionNumbers =3D {}, - - .modeOffset =3D QCOW2_HDR_CRYPT, - .modeValue =3D 1, - - .payloadOffset =3D -1, - }, - { - .format =3D VIR_STORAGE_ENCRYPTION_FORMAT_LUKS, - - .magicOffset =3D 0, - .magic =3D NULL, - .endian =3D LV_BIG_ENDIAN, - - .versionOffset =3D -1, - .versionSize =3D 0, - .versionNumbers =3D {}, - - .modeOffset =3D QCOW2_HDR_CRYPT, - .modeValue =3D 2, - - .payloadOffset =3D -1, - }, - { 0 } -}; - -static struct FileTypeInfo const fileTypeInfo[] =3D { - [VIR_STORAGE_FILE_NONE] =3D { 0, NULL, LV_LITTLE_ENDIAN, - -1, 0, {0}, 0, 0, 0, NULL, NULL, NULL }, - [VIR_STORAGE_FILE_RAW] =3D { 0, NULL, LV_LITTLE_ENDIAN, - -1, 0, {0}, 0, 0, 0, - luksEncryptionInfo, - NULL, NULL }, - [VIR_STORAGE_FILE_DIR] =3D { 0, NULL, LV_LITTLE_ENDIAN, - -1, 0, {0}, 0, 0, 0, NULL, NULL, NULL }, - [VIR_STORAGE_FILE_BOCHS] =3D { - /*"Bochs Virtual HD Image", */ /* Untested */ - 0, NULL, - LV_LITTLE_ENDIAN, 64, 4, {0x20000}, - 32+16+16+4+4+4+4+4, 8, 1, NULL, NULL, NULL - }, - [VIR_STORAGE_FILE_CLOOP] =3D { - /* #!/bin/sh - #V2.0 Format - modprobe cloop file=3D$0 && mount -r -t iso9660 /dev/cloop $1 - */ /* Untested */ - 0, NULL, - LV_LITTLE_ENDIAN, -1, 0, {0}, - -1, 0, 0, NULL, NULL, NULL - }, - [VIR_STORAGE_FILE_DMG] =3D { - /* XXX QEMU says there's no magic for dmg, - * /usr/share/misc/magic lists double magic (both offsets - * would have to match) but then disables that check. */ - 0, NULL, - 0, -1, 0, {0}, - -1, 0, 0, NULL, NULL, NULL - }, - [VIR_STORAGE_FILE_ISO] =3D { - 32769, "CD001", - LV_LITTLE_ENDIAN, -2, 0, {0}, - -1, 0, 0, NULL, NULL, NULL - }, - [VIR_STORAGE_FILE_VPC] =3D { - 0, "conectix", - LV_BIG_ENDIAN, 12, 4, {0x10000}, - 8 + 4 + 4 + 8 + 4 + 4 + 2 + 2 + 4, 8, 1, NULL, NULL, NULL - }, - /* TODO: add getBackingStore function */ - [VIR_STORAGE_FILE_VDI] =3D { - 64, "\x7f\x10\xda\xbe", - LV_LITTLE_ENDIAN, 68, 4, {0x00010001}, - 64 + 5 * 4 + 256 + 7 * 4, 8, 1, NULL, NULL, NULL}, - - /* Not direct file formats, but used for various drivers */ - [VIR_STORAGE_FILE_FAT] =3D { 0, NULL, LV_LITTLE_ENDIAN, - -1, 0, {0}, 0, 0, 0, NULL, NULL, NULL }, - [VIR_STORAGE_FILE_VHD] =3D { 0, NULL, LV_LITTLE_ENDIAN, - -1, 0, {0}, 0, 0, 0, NULL, NULL, NULL }, - [VIR_STORAGE_FILE_PLOOP] =3D { 0, "WithouFreSpacExt", LV_LITTLE_ENDIAN, - -2, 0, {0}, PLOOP_IMAGE_SIZE_OFFSET, 0, - PLOOP_SIZE_MULTIPLIER, NULL, NULL, NULL }, - - /* All formats with a backing store probe below here */ - [VIR_STORAGE_FILE_COW] =3D { - 0, "OOOM", - LV_BIG_ENDIAN, 4, 4, {2}, - 4+4+1024+4, 8, 1, NULL, cowGetBackingStore, NULL - }, - [VIR_STORAGE_FILE_QCOW] =3D { - 0, "QFI", - LV_BIG_ENDIAN, 4, 4, {1}, - QCOWX_HDR_IMAGE_SIZE, 8, 1, - qcow1EncryptionInfo, - qcowXGetBackingStore, NULL - }, - [VIR_STORAGE_FILE_QCOW2] =3D { - 0, "QFI", - LV_BIG_ENDIAN, 4, 4, {2, 3}, - QCOWX_HDR_IMAGE_SIZE, 8, 1, - qcow2EncryptionInfo, - qcowXGetBackingStore, - qcow2GetFeatures - }, - [VIR_STORAGE_FILE_QED] =3D { - /* https://wiki.qemu.org/Features/QED */ - 0, "QED", - LV_LITTLE_ENDIAN, -2, 0, {0}, - QED_HDR_IMAGE_SIZE, 8, 1, NULL, qedGetBackingStore, NULL - }, - [VIR_STORAGE_FILE_VMDK] =3D { - 0, "KDMV", - LV_LITTLE_ENDIAN, 4, 4, {1, 2, 3}, - 4+4+4, 8, 512, NULL, vmdk4GetBackingStore, NULL - }, -}; -G_STATIC_ASSERT(G_N_ELEMENTS(fileTypeInfo) =3D=3D VIR_STORAGE_FILE_LAST); - - -/* qcow2 compatible features in the order they appear on-disk */ -enum qcow2CompatibleFeature { - QCOW2_COMPATIBLE_FEATURE_LAZY_REFCOUNTS =3D 0, - - QCOW2_COMPATIBLE_FEATURE_LAST -}; - -/* conversion to virStorageFileFeature */ -static const int qcow2CompatibleFeatureArray[] =3D { - VIR_STORAGE_FILE_FEATURE_LAZY_REFCOUNTS, -}; -G_STATIC_ASSERT(G_N_ELEMENTS(qcow2CompatibleFeatureArray) =3D=3D - QCOW2_COMPATIBLE_FEATURE_LAST); - -static int -cowGetBackingStore(char **res, - int *format, - const char *buf, - size_t buf_size) -{ -#define COW_FILENAME_MAXLEN 1024 - *res =3D NULL; - *format =3D VIR_STORAGE_FILE_AUTO; - - if (buf_size < 4+4+ COW_FILENAME_MAXLEN) - return BACKING_STORE_INVALID; - if (buf[4+4] =3D=3D '\0') { /* cow_header_v2.backing_file[0] */ - *format =3D VIR_STORAGE_FILE_NONE; - return BACKING_STORE_OK; - } - - *res =3D g_strndup((const char *)buf + 4 + 4, COW_FILENAME_MAXLEN); - return BACKING_STORE_OK; -} - - -static int -qcow2GetExtensions(const char *buf, - size_t buf_size, - int *backingFormat) -{ - size_t offset; - size_t extension_start; - size_t extension_end; - int version =3D virReadBufInt32BE(buf + QCOWX_HDR_VERSION); - - if (version < 2) { - /* QCow1 doesn't have the extensions capability - * used to store backing format */ - return 0; - } - - if (version =3D=3D 2) - extension_start =3D QCOW2_HDR_TOTAL_SIZE; - else - extension_start =3D virReadBufInt32BE(buf + QCOW2v3_HDR_SIZE); - - /* - * Traditionally QCow2 files had a layout of - * - * [header] - * [backingStoreName] - * - * Although the backingStoreName typically followed - * the header immediately, this was not required by - * the format. By specifying a higher byte offset for - * the backing file offset in the header, it was - * possible to leave space between the header and - * start of backingStore. - * - * This hack is now used to store extensions to the - * qcow2 format: - * - * [header] - * [extensions] - * [backingStoreName] - * - * Thus the file region to search for extensions is - * between the end of the header (QCOW2_HDR_TOTAL_SIZE) - * and the start of the backingStoreName (offset) - * - * for qcow2 v3 images, the length of the header - * is stored at QCOW2v3_HDR_SIZE - */ - extension_end =3D virReadBufInt64BE(buf + QCOWX_HDR_BACKING_FILE_OFFSE= T); - if (extension_end > buf_size) - return -1; - - /* - * The extensions take format of - * - * int32: magic - * int32: length - * byte[length]: payload - * - * Unknown extensions can be ignored by skipping - * over "length" bytes in the data stream. - */ - offset =3D extension_start; - while (offset < (buf_size-8) && - offset < (extension_end-8)) { - unsigned int magic =3D virReadBufInt32BE(buf + offset); - unsigned int len =3D virReadBufInt32BE(buf + offset + 4); - - offset +=3D 8; - - if ((offset + len) < offset) - break; - - if ((offset + len) > buf_size) - break; - - switch (magic) { - case QCOW2_HDR_EXTENSION_BACKING_FORMAT: { - g_autofree char *tmp =3D NULL; - if (!backingFormat) - break; - - tmp =3D g_new0(char, len + 1); - memcpy(tmp, buf + offset, len); - tmp[len] =3D '\0'; - - *backingFormat =3D virStorageFileFormatTypeFromString(tmp); - if (*backingFormat <=3D VIR_STORAGE_FILE_NONE) - return -1; - break; - } - - case QCOW2_HDR_EXTENSION_END: - return 0; - } - - offset +=3D len; - } - - return 0; -} - - -static int -qcowXGetBackingStore(char **res, - int *format, - const char *buf, - size_t buf_size) -{ - unsigned long long offset; - unsigned int size; - - *res =3D NULL; - *format =3D VIR_STORAGE_FILE_AUTO; - - if (buf_size < QCOWX_HDR_BACKING_FILE_OFFSET+8+4) - return BACKING_STORE_INVALID; - - offset =3D virReadBufInt64BE(buf + QCOWX_HDR_BACKING_FILE_OFFSET); - if (offset > buf_size) - return BACKING_STORE_INVALID; - - if (offset =3D=3D 0) { - *format =3D VIR_STORAGE_FILE_NONE; - return BACKING_STORE_OK; - } - - size =3D virReadBufInt32BE(buf + QCOWX_HDR_BACKING_FILE_SIZE); - if (size =3D=3D 0) { - *format =3D VIR_STORAGE_FILE_NONE; - return BACKING_STORE_OK; - } - if (size > 1023) - return BACKING_STORE_INVALID; - if (offset + size > buf_size || offset + size < offset) - return BACKING_STORE_INVALID; - *res =3D g_new0(char, size + 1); - memcpy(*res, buf + offset, size); - (*res)[size] =3D '\0'; - - if (qcow2GetExtensions(buf, buf_size, format) < 0) - return BACKING_STORE_INVALID; - - return BACKING_STORE_OK; -} - - -static int -vmdk4GetBackingStore(char **res, - int *format, - const char *buf, - size_t buf_size) -{ - static const char prefix[] =3D "parentFileNameHint=3D\""; - char *start, *end; - size_t len; - g_autofree char *desc =3D NULL; - - desc =3D g_new0(char, VIR_STORAGE_MAX_HEADER); - - *res =3D NULL; - /* - * Technically this should have been VMDK, since - * VMDK spec / VMware impl only support VMDK backed - * by VMDK. QEMU isn't following this though and - * does probing on VMDK backing files, hence we set - * AUTO - */ - *format =3D VIR_STORAGE_FILE_AUTO; - - if (buf_size <=3D 0x200) - return BACKING_STORE_INVALID; - - len =3D buf_size - 0x200; - if (len > VIR_STORAGE_MAX_HEADER) - len =3D VIR_STORAGE_MAX_HEADER; - memcpy(desc, buf + 0x200, len); - desc[len] =3D '\0'; - start =3D strstr(desc, prefix); - if (start =3D=3D NULL) { - *format =3D VIR_STORAGE_FILE_NONE; - return BACKING_STORE_OK; - } - start +=3D strlen(prefix); - end =3D strchr(start, '"'); - if (end =3D=3D NULL) - return BACKING_STORE_INVALID; - - if (end =3D=3D start) { - *format =3D VIR_STORAGE_FILE_NONE; - return BACKING_STORE_OK; - } - *end =3D '\0'; - *res =3D g_strdup(start); - - return BACKING_STORE_OK; -} - -static int -qedGetBackingStore(char **res, - int *format, - const char *buf, - size_t buf_size) -{ - unsigned long long flags; - unsigned long offset, size; - - *res =3D NULL; - /* Check if this image has a backing file */ - if (buf_size < QED_HDR_FEATURES_OFFSET+8) - return BACKING_STORE_INVALID; - flags =3D virReadBufInt64LE(buf + QED_HDR_FEATURES_OFFSET); - if (!(flags & QED_F_BACKING_FILE)) { - *format =3D VIR_STORAGE_FILE_NONE; - return BACKING_STORE_OK; - } - - /* Parse the backing file */ - if (buf_size < QED_HDR_BACKING_FILE_OFFSET+8) - return BACKING_STORE_INVALID; - offset =3D virReadBufInt32LE(buf + QED_HDR_BACKING_FILE_OFFSET); - if (offset > buf_size) - return BACKING_STORE_INVALID; - size =3D virReadBufInt32LE(buf + QED_HDR_BACKING_FILE_SIZE); - if (size =3D=3D 0) - return BACKING_STORE_OK; - if (offset + size > buf_size || offset + size < offset) - return BACKING_STORE_INVALID; - *res =3D g_new0(char, size + 1); - memcpy(*res, buf + offset, size); - (*res)[size] =3D '\0'; - - if (flags & QED_F_BACKING_FORMAT_NO_PROBE) - *format =3D VIR_STORAGE_FILE_RAW; - else - *format =3D VIR_STORAGE_FILE_AUTO_SAFE; - - return BACKING_STORE_OK; -} - - -static bool -virStorageFileMatchesMagic(int magicOffset, - const char *magic, - char *buf, - size_t buflen) -{ - int mlen; - - if (magic =3D=3D NULL) - return false; - - /* Validate magic data */ - mlen =3D strlen(magic); - if (magicOffset + mlen > buflen) - return false; - - if (memcmp(buf + magicOffset, magic, mlen) !=3D 0) - return false; - - return true; -} - - -static bool -virStorageFileMatchesVersion(int versionOffset, - int versionSize, - const int *versionNumbers, - int endian, - char *buf, - size_t buflen) -{ - int version; - size_t i; - - /* Validate version number info */ - if (versionOffset =3D=3D -1) - return false; - - /* -2 =3D=3D non-versioned file format, so trivially match */ - if (versionOffset =3D=3D -2) - return true; - - /* A positive versionOffset, requires using a valid versionSize */ - if (versionSize !=3D 2 && versionSize !=3D 4) - return false; - - if ((versionOffset + versionSize) > buflen) - return false; - - if (endian =3D=3D LV_LITTLE_ENDIAN) { - if (versionSize =3D=3D 4) - version =3D virReadBufInt32LE(buf + - versionOffset); - else - version =3D virReadBufInt16LE(buf + - versionOffset); - } else { - if (versionSize =3D=3D 4) - version =3D virReadBufInt32BE(buf + - versionOffset); - else - version =3D virReadBufInt16BE(buf + - versionOffset); - } - - for (i =3D 0; - i < FILE_TYPE_VERSIONS_LAST && versionNumbers[i]; - i++) { - VIR_DEBUG("Compare detected version %d vs one of the expected vers= ions %d", - version, versionNumbers[i]); - if (version =3D=3D versionNumbers[i]) - return true; - } - - return false; -} - - -static int -virStorageFileProbeFormatFromBuf(const char *path, - char *buf, - size_t buflen) -{ - int format =3D VIR_STORAGE_FILE_RAW; - size_t i; - int possibleFormat =3D VIR_STORAGE_FILE_RAW; - VIR_DEBUG("path=3D%s, buf=3D%p, buflen=3D%zu", path, buf, buflen); - - /* First check file magic */ - for (i =3D 0; i < VIR_STORAGE_FILE_LAST; i++) { - if (virStorageFileMatchesMagic(fileTypeInfo[i].magicOffset, - fileTypeInfo[i].magic, - buf, buflen)) { - if (!virStorageFileMatchesVersion(fileTypeInfo[i].versionOffse= t, - fileTypeInfo[i].versionSize, - fileTypeInfo[i].versionNumbe= rs, - fileTypeInfo[i].endian, - buf, buflen)) { - possibleFormat =3D i; - continue; - } - format =3D i; - goto cleanup; - } - } - - if (possibleFormat !=3D VIR_STORAGE_FILE_RAW) - VIR_WARN("File %s matches %s magic, but version is wrong. " - "Please report new version to libvir-list@redhat.com", - path, virStorageFileFormatTypeToString(possibleFormat)); - - cleanup: - VIR_DEBUG("format=3D%d", format); - return format; -} - - -static int -qcow2GetFeatures(virBitmapPtr *features, - int format, - char *buf, - ssize_t len) -{ - int version =3D -1; - virBitmapPtr feat =3D NULL; - uint64_t bits; - size_t i; - - version =3D virReadBufInt32BE(buf + fileTypeInfo[format].versionOffset= ); - - if (version =3D=3D 2) - return 0; - - if (len < QCOW2v3_HDR_SIZE) - return -1; - - feat =3D virBitmapNew(VIR_STORAGE_FILE_FEATURE_LAST); - - /* todo: check for incompatible or autoclear features? */ - bits =3D virReadBufInt64BE(buf + QCOW2v3_HDR_FEATURES_COMPATIBLE); - for (i =3D 0; i < QCOW2_COMPATIBLE_FEATURE_LAST; i++) { - if (bits & ((uint64_t) 1 << i)) - ignore_value(virBitmapSetBit(feat, qcow2CompatibleFeatureArray= [i])); - } - - *features =3D feat; - return 0; -} - - -static bool -virStorageFileHasEncryptionFormat(const struct FileEncryptionInfo *info, - char *buf, - size_t len) -{ - if (!info->magic && info->modeOffset =3D=3D -1) - return false; /* Shouldn't happen - expect at least one */ - - if (info->magic) { - if (!virStorageFileMatchesMagic(info->magicOffset, - info->magic, - buf, len)) - return false; - - if (info->versionOffset !=3D -1 && - !virStorageFileMatchesVersion(info->versionOffset, - info->versionSize, - info->versionNumbers, - info->endian, - buf, len)) - return false; - - return true; - } else if (info->modeOffset !=3D -1) { - int crypt_format; - - if (info->modeOffset >=3D len) - return false; - - crypt_format =3D virReadBufInt32BE(buf + info->modeOffset); - if (crypt_format !=3D info->modeValue) - return false; - - return true; - } else { - return false; - } -} - - -static int -virStorageFileGetEncryptionPayloadOffset(const struct FileEncryptionInfo *= info, - char *buf) -{ - int payload_offset =3D -1; - - if (info->payloadOffset !=3D -1) { - if (info->endian =3D=3D LV_LITTLE_ENDIAN) - payload_offset =3D virReadBufInt32LE(buf + info->payloadOffset= ); - else - payload_offset =3D virReadBufInt32BE(buf + info->payloadOffset= ); - } - - return payload_offset; -} - - -/* Given a header in BUF with length LEN, as parsed from the storage file - * assuming it has the given FORMAT, populate information into META - * with information about the file and its backing store. Return format - * of the backing store as BACKING_FORMAT. PATH and FORMAT have to be - * pre-populated in META. - * - * Note that this function may be called repeatedly on @meta, so it must - * clean up any existing allocated memory which would be overwritten. - */ -static int -virStorageFileGetMetadataInternal(virStorageSourcePtr meta, - char *buf, - size_t len) -{ - int format; - size_t i; - - VIR_DEBUG("path=3D%s, buf=3D%p, len=3D%zu, meta->format=3D%d", - meta->path, buf, len, meta->format); - - if (meta->format =3D=3D VIR_STORAGE_FILE_AUTO) - meta->format =3D virStorageFileProbeFormatFromBuf(meta->path, buf,= len); - - if (meta->format <=3D VIR_STORAGE_FILE_NONE || - meta->format >=3D VIR_STORAGE_FILE_LAST) { - virReportSystemError(EINVAL, _("unknown storage file meta->format = %d"), - meta->format); - return -1; - } - - if (fileTypeInfo[meta->format].cryptInfo !=3D NULL) { - for (i =3D 0; fileTypeInfo[meta->format].cryptInfo[i].format !=3D = 0; i++) { - if (virStorageFileHasEncryptionFormat(&fileTypeInfo[meta->form= at].cryptInfo[i], - buf, len)) { - int expt_fmt =3D fileTypeInfo[meta->format].cryptInfo[i].f= ormat; - if (!meta->encryption) { - meta->encryption =3D g_new0(virStorageEncryption, 1); - meta->encryption->format =3D expt_fmt; - } else { - if (meta->encryption->format !=3D expt_fmt) { - virReportError(VIR_ERR_XML_ERROR, - _("encryption format %d doesn't mat= ch " - "expected format %d"), - meta->encryption->format, expt_fmt); - return -1; - } - } - meta->encryption->payload_offset =3D - virStorageFileGetEncryptionPayloadOffset(&fileTypeInfo= [meta->format].cryptInfo[i], buf); - } - } - } - - /* XXX we should consider moving virStorageBackendUpdateVolInfo - * code into this method, for non-magic files - */ - if (!fileTypeInfo[meta->format].magic) - return 0; - - /* Optionally extract capacity from file */ - if (fileTypeInfo[meta->format].sizeOffset !=3D -1) { - if ((fileTypeInfo[meta->format].sizeOffset + 8) > len) - return 0; - - if (fileTypeInfo[meta->format].endian =3D=3D LV_LITTLE_ENDIAN) - meta->capacity =3D virReadBufInt64LE(buf + - fileTypeInfo[meta->format].= sizeOffset); - else - meta->capacity =3D virReadBufInt64BE(buf + - fileTypeInfo[meta->format].= sizeOffset); - /* Avoid unlikely, but theoretically possible overflow */ - if (meta->capacity > (ULLONG_MAX / - fileTypeInfo[meta->format].sizeMultiplier)) - return 0; - meta->capacity *=3D fileTypeInfo[meta->format].sizeMultiplier; - } - - VIR_FREE(meta->backingStoreRaw); - if (fileTypeInfo[meta->format].getBackingStore !=3D NULL) { - int store =3D fileTypeInfo[meta->format].getBackingStore(&meta->ba= ckingStoreRaw, - &format, - buf, len); - meta->backingStoreRawFormat =3D format; - - if (store =3D=3D BACKING_STORE_INVALID) - return 0; - - if (store =3D=3D BACKING_STORE_ERROR) - return -1; - } - - virBitmapFree(meta->features); - meta->features =3D NULL; - if (fileTypeInfo[meta->format].getFeatures !=3D NULL && - fileTypeInfo[meta->format].getFeatures(&meta->features, meta->form= at, buf, len) < 0) - return -1; - - VIR_FREE(meta->compat); - if (meta->format =3D=3D VIR_STORAGE_FILE_QCOW2 && meta->features) - meta->compat =3D g_strdup("1.1"); - - return 0; -} - - -/** - * virStorageFileProbeFormat: - * - * Probe for the format of 'path', returning the detected - * disk format. - * - * Callers are advised never to trust the returned 'format' - * unless it is listed as VIR_STORAGE_FILE_RAW, since a - * malicious guest can turn a raw file into any other non-raw - * format at will. - * - * Best option: Don't use this function - */ -int -virStorageFileProbeFormat(const char *path, uid_t uid, gid_t gid) -{ - struct stat sb; - ssize_t len =3D VIR_STORAGE_MAX_HEADER; - VIR_AUTOCLOSE fd =3D -1; - g_autofree char *header =3D NULL; - - if ((fd =3D virFileOpenAs(path, O_RDONLY, 0, uid, gid, 0)) < 0) { - virReportSystemError(-fd, _("Failed to open file '%s'"), path); - return -1; - } - - if (fstat(fd, &sb) < 0) { - virReportSystemError(errno, _("cannot stat file '%s'"), path); - return -1; - } - - /* No header to probe for directories */ - if (S_ISDIR(sb.st_mode)) - return VIR_STORAGE_FILE_DIR; - - if (lseek(fd, 0, SEEK_SET) =3D=3D (off_t)-1) { - virReportSystemError(errno, _("cannot set to start of '%s'"), path= ); - return -1; - } - - if ((len =3D virFileReadHeaderFD(fd, len, &header)) < 0) { - virReportSystemError(errno, _("cannot read header '%s'"), path); - return -1; - } - - return virStorageFileProbeFormatFromBuf(path, header, len); -} - - -static virStorageSourcePtr -virStorageFileMetadataNew(const char *path, - int format) -{ - g_autoptr(virStorageSource) def =3D virStorageSourceNew(); - - def->format =3D format; - def->type =3D VIR_STORAGE_TYPE_FILE; - - def->path =3D g_strdup(path); - - return g_steal_pointer(&def); -} - - -/** - * virStorageFileGetMetadataFromBuf: - * @path: name of file, for error messages - * @buf: header bytes from @path - * @len: length of @buf - * @format: format of the storage file - * - * Extract metadata about the storage volume with the specified image form= at. - * If image format is VIR_STORAGE_FILE_AUTO, it will probe to automatically - * identify the format. Does not recurse. - * - * Callers are advised never to use VIR_STORAGE_FILE_AUTO as a format on a= file - * that might be raw if that file will then be passed to a guest, since a - * malicious guest can turn a raw file into any other non-raw format at wi= ll. - * - * If the 'backingStoreRawFormat' field of the returned structure is - * VIR_STORAGE_FILE_AUTO it indicates the image didn't specify an explicit - * format for its backing store. Callers are advised against probing for t= he - * backing store format in this case. - * - * Caller MUST free the result after use via virObjectUnref. - */ -virStorageSourcePtr -virStorageFileGetMetadataFromBuf(const char *path, - char *buf, - size_t len, - int format) -{ - virStorageSourcePtr ret =3D NULL; - - if (!(ret =3D virStorageFileMetadataNew(path, format))) - return NULL; - - if (virStorageFileGetMetadataInternal(ret, buf, len) < 0) { - virObjectUnref(ret); - return NULL; - } - - return ret; -} - - -/** - * virStorageFileGetMetadataFromFD: - * - * Extract metadata about the storage volume with the specified - * image format. If image format is VIR_STORAGE_FILE_AUTO, it - * will probe to automatically identify the format. Does not recurse. - * - * Callers are advised never to use VIR_STORAGE_FILE_AUTO as a - * format, since a malicious guest can turn a raw file into any - * other non-raw format at will. - * - * Caller MUST free the result after use via virObjectUnref. - */ -virStorageSourcePtr -virStorageFileGetMetadataFromFD(const char *path, - int fd, - int format) - -{ - ssize_t len =3D VIR_STORAGE_MAX_HEADER; - struct stat sb; - g_autofree char *buf =3D NULL; - g_autoptr(virStorageSource) meta =3D NULL; - - if (fstat(fd, &sb) < 0) { - virReportSystemError(errno, - _("cannot stat file '%s'"), path); - return NULL; - } - - if (!(meta =3D virStorageFileMetadataNew(path, format))) - return NULL; - - if (S_ISDIR(sb.st_mode)) { - /* No header to probe for directories, but also no backing file. J= ust - * update the metadata.*/ - meta->type =3D VIR_STORAGE_TYPE_DIR; - meta->format =3D VIR_STORAGE_FILE_DIR; - return g_steal_pointer(&meta); - } - - if (lseek(fd, 0, SEEK_SET) =3D=3D (off_t)-1) { - virReportSystemError(errno, _("cannot seek to start of '%s'"), met= a->path); - return NULL; - } - - if ((len =3D virFileReadHeaderFD(fd, len, &buf)) < 0) { - virReportSystemError(errno, _("cannot read header '%s'"), meta->pa= th); - return NULL; - } - - if (virStorageFileGetMetadataInternal(meta, buf, len) < 0) - return NULL; - - if (S_ISREG(sb.st_mode)) - meta->type =3D VIR_STORAGE_TYPE_FILE; - else if (S_ISBLK(sb.st_mode)) - meta->type =3D VIR_STORAGE_TYPE_BLOCK; - - return g_steal_pointer(&meta); -} - =20 #ifdef WITH_UDEV /* virStorageFileGetSCSIKey @@ -1297,78 +240,6 @@ int virStorageFileGetNPIVKey(const char *path G_GNUC_= UNUSED, } #endif =20 -/** - * virStorageFileParseBackingStoreStr: - * @str: backing store specifier string to parse - * @target: returns target device portion of the string - * @chainIndex: returns the backing store portion of the string - * - * Parses the backing store specifier string such as vda[1], or sda into - * components and returns them via arguments. If the string did not specif= y an - * index, 0 is assumed. - * - * Returns 0 on success -1 on error - */ -int -virStorageFileParseBackingStoreStr(const char *str, - char **target, - unsigned int *chainIndex) -{ - size_t nstrings; - unsigned int idx =3D 0; - char *suffix; - g_auto(GStrv) strings =3D NULL; - - *chainIndex =3D 0; - - if (!(strings =3D virStringSplitCount(str, "[", 2, &nstrings))) - return -1; - - if (nstrings =3D=3D 2) { - if (virStrToLong_uip(strings[1], &suffix, 10, &idx) < 0 || - STRNEQ(suffix, "]")) - return -1; - } - - if (target) - *target =3D g_strdup(strings[0]); - - *chainIndex =3D idx; - return 0; -} - - -int -virStorageFileParseChainIndex(const char *diskTarget, - const char *name, - unsigned int *chainIndex) -{ - unsigned int idx =3D 0; - g_autofree char *target =3D NULL; - - *chainIndex =3D 0; - - if (!name || !diskTarget) - return 0; - - if (virStorageFileParseBackingStoreStr(name, &target, &idx) < 0) - return 0; - - if (idx =3D=3D 0) - return 0; - - if (STRNEQ(diskTarget, target)) { - virReportError(VIR_ERR_INVALID_ARG, - _("requested target '%s' does not match target '%s'= "), - target, diskTarget); - return -1; - } - - *chainIndex =3D idx; - - return 0; -} - =20 /** * virStorageSourceIsBacking: @@ -1397,107 +268,6 @@ virStorageSourceHasBacking(const virStorageSource *s= rc) } =20 =20 -/* Given a @chain, look for the backing store @name that is a backing file - * of @startFrom (or any member of @chain if @startFrom is NULL) and return - * that location within the chain. @chain must always point to the top of - * the chain. Pass NULL for @name and 0 for @idx to find the base of the - * chain. Pass nonzero @idx to find the backing source according to its - * position in the backing chain. If @parent is not NULL, set *@parent to - * the preferred name of the parent (or to NULL if @name matches the start - * of the chain). Since the results point within @chain, they must not be - * independently freed. Reports an error and returns NULL if @name is not - * found. - */ -virStorageSourcePtr -virStorageFileChainLookup(virStorageSourcePtr chain, - virStorageSourcePtr startFrom, - const char *name, - unsigned int idx, - virStorageSourcePtr *parent) -{ - virStorageSourcePtr prev; - const char *start =3D chain->path; - bool nameIsFile =3D virFileIsFile(name); - - if (!parent) - parent =3D &prev; - *parent =3D NULL; - - if (startFrom) { - while (virStorageSourceIsBacking(chain) && - chain !=3D startFrom->backingStore) - chain =3D chain->backingStore; - - *parent =3D startFrom; - } - - while (virStorageSourceIsBacking(chain)) { - if (!name && !idx) { - if (!virStorageSourceHasBacking(chain)) - break; - } else if (idx) { - VIR_DEBUG("%u: %s", chain->id, chain->path); - if (idx =3D=3D chain->id) - break; - } else { - if (STREQ_NULLABLE(name, chain->relPath) || - STREQ_NULLABLE(name, chain->path)) - break; - - if (nameIsFile && virStorageSourceIsLocalStorage(chain)) { - g_autofree char *parentDir =3D NULL; - int result; - - if (*parent && virStorageSourceIsLocalStorage(*parent)) - parentDir =3D g_path_get_dirname((*parent)->path); - else - parentDir =3D g_strdup("."); - - result =3D virFileRelLinkPointsTo(parentDir, name, - chain->path); - - if (result < 0) - goto error; - - if (result > 0) - break; - } - } - *parent =3D chain; - chain =3D chain->backingStore; - } - - if (!virStorageSourceIsBacking(chain)) - goto error; - - return chain; - - error: - if (idx) { - virReportError(VIR_ERR_INVALID_ARG, - _("could not find backing store index %u in chain " - "for '%s'"), - idx, NULLSTR(start)); - } else if (name) { - if (startFrom) - virReportError(VIR_ERR_INVALID_ARG, - _("could not find image '%s' beneath '%s' in " - "chain for '%s'"), name, NULLSTR(startFrom->p= ath), - NULLSTR(start)); - else - virReportError(VIR_ERR_INVALID_ARG, - _("could not find image '%s' in chain for '%s'"= ), - name, NULLSTR(start)); - } else { - virReportError(VIR_ERR_INVALID_ARG, - _("could not find base image in chain for '%s'"), - NULLSTR(start)); - } - *parent =3D NULL; - return NULL; -} - - void virStorageNetHostDefClear(virStorageNetHostDefPtr def) { @@ -2545,1780 +1315,6 @@ virStorageSourceNew(void) } =20 =20 -static virStorageSourcePtr -virStorageSourceNewFromBackingRelative(virStorageSourcePtr parent, - const char *rel) -{ - g_autofree char *dirname =3D NULL; - g_autoptr(virStorageSource) def =3D virStorageSourceNew(); - - /* store relative name */ - def->relPath =3D g_strdup(rel); - - dirname =3D g_path_get_dirname(parent->path); - - if (STRNEQ(dirname, "/")) { - def->path =3D g_strdup_printf("%s/%s", dirname, rel); - } else { - def->path =3D g_strdup_printf("/%s", rel); - } - - if (virStorageSourceGetActualType(parent) =3D=3D VIR_STORAGE_TYPE_NETW= ORK) { - def->type =3D VIR_STORAGE_TYPE_NETWORK; - - /* copy the host network part */ - def->protocol =3D parent->protocol; - if (parent->nhosts) { - if (!(def->hosts =3D virStorageNetHostDefCopy(parent->nhosts, - parent->hosts))) - return NULL; - - def->nhosts =3D parent->nhosts; - } - - def->volume =3D g_strdup(parent->volume); - } else { - /* set the type to _FILE, the caller shall update it to the actual= type */ - def->type =3D VIR_STORAGE_TYPE_FILE; - } - - return g_steal_pointer(&def); -} - - -static int -virStorageSourceParseBackingURI(virStorageSourcePtr src, - const char *uristr) -{ - g_autoptr(virURI) uri =3D NULL; - const char *path =3D NULL; - g_auto(GStrv) scheme =3D NULL; - - if (!(uri =3D virURIParse(uristr))) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("failed to parse backing file location '%s'"), - uristr); - return -1; - } - - src->hosts =3D g_new0(virStorageNetHostDef, 1); - src->nhosts =3D 1; - - if (!(scheme =3D virStringSplit(uri->scheme, "+", 2))) - return -1; - - if (!scheme[0] || - (src->protocol =3D virStorageNetProtocolTypeFromString(scheme[0]))= < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("invalid backing protocol '%s'"), - NULLSTR(scheme[0])); - return -1; - } - - if (scheme[1] && - (src->hosts->transport =3D virStorageNetHostTransportTypeFromStrin= g(scheme[1])) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("invalid protocol transport type '%s'"), - scheme[1]); - return -1; - } - - if (uri->query) { - if (src->protocol =3D=3D VIR_STORAGE_NET_PROTOCOL_HTTP || - src->protocol =3D=3D VIR_STORAGE_NET_PROTOCOL_HTTPS) { - src->query =3D g_strdup(uri->query); - } else { - /* handle socket stored as a query */ - if (STRPREFIX(uri->query, "socket=3D")) - src->hosts->socket =3D g_strdup(STRSKIP(uri->query, "socke= t=3D")); - } - } - - /* uri->path is NULL if the URI does not contain slash after host: - * transport://host:port */ - if (uri->path) - path =3D uri->path; - else - path =3D ""; - - /* possibly skip the leading slash */ - if (path[0] =3D=3D '/') - path++; - - /* NBD allows empty export name (path) */ - if (src->protocol =3D=3D VIR_STORAGE_NET_PROTOCOL_NBD && - path[0] =3D=3D '\0') - path =3D NULL; - - src->path =3D g_strdup(path); - - if (src->protocol =3D=3D VIR_STORAGE_NET_PROTOCOL_GLUSTER) { - char *tmp; - - if (!src->path) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("missing volume name and path for gluster vol= ume")); - return -1; - } - - if (!(tmp =3D strchr(src->path, '/')) || - tmp =3D=3D src->path) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("missing volume name or file name in " - "gluster source path '%s'"), src->path); - return -1; - } - - src->volume =3D src->path; - - src->path =3D g_strdup(tmp + 1); - - tmp[0] =3D '\0'; - } - - src->hosts->port =3D uri->port; - - src->hosts->name =3D g_strdup(uri->server); - - /* Libvirt doesn't handle inline authentication. Make the caller aware= . */ - if (uri->user) - return 1; - - return 0; -} - - -static int -virStorageSourceRBDAddHost(virStorageSourcePtr src, - char *hostport) -{ - char *port; - size_t skip; - g_auto(GStrv) parts =3D NULL; - - if (VIR_EXPAND_N(src->hosts, src->nhosts, 1) < 0) - return -1; - - if ((port =3D strchr(hostport, ']'))) { - /* ipv6, strip brackets */ - hostport +=3D 1; - skip =3D 3; - } else { - port =3D strstr(hostport, "\\:"); - skip =3D 2; - } - - if (port) { - *port =3D '\0'; - port +=3D skip; - if (virStringParsePort(port, &src->hosts[src->nhosts - 1].port) < = 0) - goto error; - } - - parts =3D virStringSplit(hostport, "\\:", 0); - if (!parts) - goto error; - src->hosts[src->nhosts-1].name =3D virStringListJoin((const char **)pa= rts, ":"); - if (!src->hosts[src->nhosts-1].name) - goto error; - - src->hosts[src->nhosts-1].transport =3D VIR_STORAGE_NET_HOST_TRANS_TCP; - src->hosts[src->nhosts-1].socket =3D NULL; - - return 0; - - error: - VIR_FREE(src->hosts[src->nhosts-1].name); - return -1; -} - - -int -virStorageSourceParseRBDColonString(const char *rbdstr, - virStorageSourcePtr src) -{ - char *p, *e, *next; - g_autofree char *options =3D NULL; - g_autoptr(virStorageAuthDef) authdef =3D NULL; - - /* optionally skip the "rbd:" prefix if provided */ - if (STRPREFIX(rbdstr, "rbd:")) - rbdstr +=3D strlen("rbd:"); - - src->path =3D g_strdup(rbdstr); - - p =3D strchr(src->path, ':'); - if (p) { - options =3D g_strdup(p + 1); - *p =3D '\0'; - } - - /* snapshot name */ - if ((p =3D strchr(src->path, '@'))) { - src->snapshot =3D g_strdup(p + 1); - *p =3D '\0'; - } - - /* pool vs. image name */ - if ((p =3D strchr(src->path, '/'))) { - src->volume =3D g_steal_pointer(&src->path); - src->path =3D g_strdup(p + 1); - *p =3D '\0'; - } - - /* options */ - if (!options) - return 0; /* all done */ - - p =3D options; - while (*p) { - /* find : delimiter or end of string */ - for (e =3D p; *e && *e !=3D ':'; ++e) { - if (*e =3D=3D '\\') { - e++; - if (*e =3D=3D '\0') - break; - } - } - if (*e =3D=3D '\0') { - next =3D e; /* last kv pair */ - } else { - next =3D e + 1; - *e =3D '\0'; - } - - if (STRPREFIX(p, "id=3D")) { - /* formulate authdef for src->auth */ - if (src->auth) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("duplicate 'id' found in '%s'"), src->pat= h); - return -1; - } - - authdef =3D g_new0(virStorageAuthDef, 1); - - authdef->username =3D g_strdup(p + strlen("id=3D")); - - authdef->secrettype =3D g_strdup(virSecretUsageTypeToString(VI= R_SECRET_USAGE_TYPE_CEPH)); - src->auth =3D g_steal_pointer(&authdef); - - /* Cannot formulate a secretType (eg, usage or uuid) given - * what is provided. - */ - } - if (STRPREFIX(p, "mon_host=3D")) { - char *h, *sep; - - h =3D p + strlen("mon_host=3D"); - while (h < e) { - for (sep =3D h; sep < e; ++sep) { - if (*sep =3D=3D '\\' && (sep[1] =3D=3D ',' || - sep[1] =3D=3D ';' || - sep[1] =3D=3D ' ')) { - *sep =3D '\0'; - sep +=3D 2; - break; - } - } - - if (virStorageSourceRBDAddHost(src, h) < 0) - return -1; - - h =3D sep; - } - } - - if (STRPREFIX(p, "conf=3D")) - src->configFile =3D g_strdup(p + strlen("conf=3D")); - - p =3D next; - } - return 0; -} - - -static int -virStorageSourceParseNBDColonString(const char *nbdstr, - virStorageSourcePtr src) -{ - g_autofree char *nbd =3D g_strdup(nbdstr); - char *export_name; - char *host_spec; - char *unixpath; - char *port; - - src->hosts =3D g_new0(virStorageNetHostDef, 1); - src->nhosts =3D 1; - - /* We extract the parameters in a similar way qemu does it */ - - /* format: [] denotes optional sections, uppercase are variable strings - * nbd:unix:/PATH/TO/SOCKET[:exportname=3DEXPORTNAME] - * nbd:HOSTNAME:PORT[:exportname=3DEXPORTNAME] - */ - - /* first look for ':exportname=3D' and cut it off */ - if ((export_name =3D strstr(nbd, ":exportname=3D"))) { - src->path =3D g_strdup(export_name + strlen(":exportname=3D")); - export_name[0] =3D '\0'; - } - - /* Verify the prefix and contents. Note that we require a - * "host_spec" part to be present. */ - if (!(host_spec =3D STRSKIP(nbd, "nbd:")) || host_spec[0] =3D=3D '\0') - goto malformed; - - if ((unixpath =3D STRSKIP(host_spec, "unix:"))) { - src->hosts->transport =3D VIR_STORAGE_NET_HOST_TRANS_UNIX; - - if (unixpath[0] =3D=3D '\0') - goto malformed; - - src->hosts->socket =3D g_strdup(unixpath); - } else { - src->hosts->transport =3D VIR_STORAGE_NET_HOST_TRANS_TCP; - - if (host_spec[0] =3D=3D ':') { - /* no host given */ - goto malformed; - } else if (host_spec[0] =3D=3D '[') { - host_spec++; - /* IPv6 addr */ - if (!(port =3D strstr(host_spec, "]:"))) - goto malformed; - - port[0] =3D '\0'; - port +=3D 2; - - if (host_spec[0] =3D=3D '\0') - goto malformed; - } else { - if (!(port =3D strchr(host_spec, ':'))) - goto malformed; - - port[0] =3D '\0'; - port++; - } - - if (virStringParsePort(port, &src->hosts->port) < 0) - return -1; - - src->hosts->name =3D g_strdup(host_spec); - } - - return 0; - - malformed: - virReportError(VIR_ERR_INTERNAL_ERROR, - _("malformed nbd string '%s'"), nbdstr); - return -1; -} - - -static int -virStorageSourceParseBackingColon(virStorageSourcePtr src, - const char *path) -{ - const char *p; - g_autofree char *protocol =3D NULL; - - if (!(p =3D strchr(path, ':'))) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("invalid backing protocol string '%s'"), - path); - return -1; - } - - protocol =3D g_strndup(path, p - path); - - if ((src->protocol =3D virStorageNetProtocolTypeFromString(protocol)) = < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("invalid backing protocol '%s'"), - protocol); - return -1; - } - - switch ((virStorageNetProtocol) src->protocol) { - case VIR_STORAGE_NET_PROTOCOL_NBD: - if (virStorageSourceParseNBDColonString(path, src) < 0) - return -1; - break; - - case VIR_STORAGE_NET_PROTOCOL_RBD: - if (virStorageSourceParseRBDColonString(path, src) < 0) - return -1; - break; - - case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG: - case VIR_STORAGE_NET_PROTOCOL_LAST: - case VIR_STORAGE_NET_PROTOCOL_NONE: - virReportError(VIR_ERR_INTERNAL_ERROR, - _("backing store parser is not implemented for prot= ocol %s"), - protocol); - return -1; - - case VIR_STORAGE_NET_PROTOCOL_HTTP: - case VIR_STORAGE_NET_PROTOCOL_HTTPS: - case VIR_STORAGE_NET_PROTOCOL_FTP: - case VIR_STORAGE_NET_PROTOCOL_FTPS: - case VIR_STORAGE_NET_PROTOCOL_TFTP: - case VIR_STORAGE_NET_PROTOCOL_ISCSI: - case VIR_STORAGE_NET_PROTOCOL_GLUSTER: - case VIR_STORAGE_NET_PROTOCOL_SSH: - case VIR_STORAGE_NET_PROTOCOL_VXHS: - virReportError(VIR_ERR_INTERNAL_ERROR, - _("malformed backing store path for protocol %s"), - protocol); - return -1; - } - - return 0; -} - - -static int -virStorageSourceParseBackingJSONInternal(virStorageSourcePtr src, - virJSONValuePtr json, - const char *jsonstr, - bool allowformat); - - -static int -virStorageSourceParseBackingJSONPath(virStorageSourcePtr src, - virJSONValuePtr json, - const char *jsonstr G_GNUC_UNUSED, - int type) -{ - const char *path; - - if (!(path =3D virJSONValueObjectGetString(json, "filename"))) { - virReportError(VIR_ERR_INVALID_ARG, "%s", - _("missing 'filename' field in JSON backing volume " - "definition")); - return -1; - } - - src->path =3D g_strdup(path); - - src->type =3D type; - return 0; -} - - -static int -virStorageSourceParseBackingJSONUriStr(virStorageSourcePtr src, - const char *uri, - int protocol) -{ - int rc; - - if ((rc =3D virStorageSourceParseBackingURI(src, uri)) < 0) - return -1; - - if (src->protocol !=3D protocol) { - virReportError(VIR_ERR_INVALID_ARG, - _("expected protocol '%s' but got '%s' in URI JSON = volume " - "definition"), - virStorageNetProtocolTypeToString(protocol), - virStorageNetProtocolTypeToString(src->protocol)); - return -1; - } - - return rc; -} - - -static int -virStorageSourceParseBackingJSONUriCookies(virStorageSourcePtr src, - virJSONValuePtr json, - const char *jsonstr) -{ - const char *cookiestr; - g_auto(GStrv) cookies =3D NULL; - size_t ncookies =3D 0; - size_t i; - - if (!virJSONValueObjectHasKey(json, "cookie")) - return 0; - - if (!(cookiestr =3D virJSONValueObjectGetString(json, "cookie"))) { - virReportError(VIR_ERR_INVALID_ARG, - _("wrong format of 'cookie' field in backing store = definition '%s'"), - jsonstr); - return -1; - } - - if (!(cookies =3D virStringSplitCount(cookiestr, ";", 0, &ncookies))) - return -1; - - src->cookies =3D g_new0(virStorageNetCookieDefPtr, ncookies); - src->ncookies =3D ncookies; - - for (i =3D 0; i < ncookies; i++) { - char *cookiename =3D cookies[i]; - char *cookievalue; - - virSkipSpaces((const char **) &cookiename); - - if (!(cookievalue =3D strchr(cookiename, '=3D'))) { - virReportError(VIR_ERR_INVALID_ARG, - _("malformed http cookie '%s' in backing store = definition '%s'"), - cookies[i], jsonstr); - return -1; - } - - *cookievalue =3D '\0'; - cookievalue++; - - src->cookies[i] =3D g_new0(virStorageNetCookieDef, 1); - src->cookies[i]->name =3D g_strdup(cookiename); - src->cookies[i]->value =3D g_strdup(cookievalue); - } - - return 0; -} - - -static int -virStorageSourceParseBackingJSONUri(virStorageSourcePtr src, - virJSONValuePtr json, - const char *jsonstr, - int protocol) -{ - const char *uri; - - if (!(uri =3D virJSONValueObjectGetString(json, "url"))) { - virReportError(VIR_ERR_INVALID_ARG, "%s", - _("missing 'url' in JSON backing volume definition"= )); - return -1; - } - - if (protocol =3D=3D VIR_STORAGE_NET_PROTOCOL_HTTPS || - protocol =3D=3D VIR_STORAGE_NET_PROTOCOL_FTPS) { - if (virJSONValueObjectHasKey(json, "sslverify")) { - const char *tmpstr; - bool tmp; - - /* libguestfs still uses undocumented legacy value of 'off' */ - if ((tmpstr =3D virJSONValueObjectGetString(json, "sslverify")= ) && - STREQ(tmpstr, "off")) { - src->sslverify =3D VIR_TRISTATE_BOOL_NO; - } else { - if (virJSONValueObjectGetBoolean(json, "sslverify", &tmp) = < 0) { - virReportError(VIR_ERR_INVALID_ARG, - _("malformed 'sslverify' field in backi= ng store definition '%s'"), - jsonstr); - return -1; - } - - src->sslverify =3D virTristateBoolFromBool(tmp); - } - } - } - - if (protocol =3D=3D VIR_STORAGE_NET_PROTOCOL_HTTPS || - protocol =3D=3D VIR_STORAGE_NET_PROTOCOL_HTTP) { - if (virStorageSourceParseBackingJSONUriCookies(src, json, jsonstr)= < 0) - return -1; - } - - if (virJSONValueObjectHasKey(json, "readahead") && - virJSONValueObjectGetNumberUlong(json, "readahead", &src->readahea= d) < 0) { - virReportError(VIR_ERR_INVALID_ARG, - _("malformed 'readahead' field in backing store def= inition '%s'"), - jsonstr); - return -1; - } - - if (virJSONValueObjectHasKey(json, "timeout") && - virJSONValueObjectGetNumberUlong(json, "timeout", &src->timeout) <= 0) { - virReportError(VIR_ERR_INVALID_ARG, - _("malformed 'timeout' field in backing store defin= ition '%s'"), - jsonstr); - return -1; - } - - return virStorageSourceParseBackingJSONUriStr(src, uri, protocol); -} - - -static int -virStorageSourceParseBackingJSONInetSocketAddress(virStorageNetHostDefPtr = host, - virJSONValuePtr json) -{ - const char *hostname; - const char *port; - - if (!json) { - virReportError(VIR_ERR_INVALID_ARG, "%s", - _("missing remote server specification in JSON " - "backing volume definition")); - return -1; - } - - hostname =3D virJSONValueObjectGetString(json, "host"); - port =3D virJSONValueObjectGetString(json, "port"); - - if (!hostname) { - virReportError(VIR_ERR_INVALID_ARG, "%s", - _("missing hostname for tcp backing server in " - "JSON backing volume definition")); - return -1; - } - - host->transport =3D VIR_STORAGE_NET_HOST_TRANS_TCP; - host->name =3D g_strdup(hostname); - - if (virStringParsePort(port, &host->port) < 0) - return -1; - - return 0; -} - - -static int -virStorageSourceParseBackingJSONSocketAddress(virStorageNetHostDefPtr host, - virJSONValuePtr json) -{ - const char *type; - const char *socket; - - if (!json) { - virReportError(VIR_ERR_INVALID_ARG, "%s", - _("missing remote server specification in JSON " - "backing volume definition")); - return -1; - } - - if (!(type =3D virJSONValueObjectGetString(json, "type"))) { - virReportError(VIR_ERR_INVALID_ARG, "%s", - _("missing socket address type in " - "JSON backing volume definition")); - return -1; - } - - if (STREQ(type, "tcp") || STREQ(type, "inet")) { - return virStorageSourceParseBackingJSONInetSocketAddress(host, jso= n); - - } else if (STREQ(type, "unix")) { - host->transport =3D VIR_STORAGE_NET_HOST_TRANS_UNIX; - - socket =3D virJSONValueObjectGetString(json, "path"); - - /* check for old spelling for gluster protocol */ - if (!socket) - socket =3D virJSONValueObjectGetString(json, "socket"); - - if (!socket) { - virReportError(VIR_ERR_INVALID_ARG, "%s", - _("missing socket path for udp backing server i= n " - "JSON backing volume definition")); - return -1; - } - - host->socket =3D g_strdup(socket); - } else { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("backing store protocol '%s' is not yet supported= "), - type); - return -1; - } - - return 0; -} - - -static int -virStorageSourceParseBackingJSONGluster(virStorageSourcePtr src, - virJSONValuePtr json, - const char *jsonstr G_GNUC_UNUSED, - int opaque G_GNUC_UNUSED) -{ - const char *uri =3D virJSONValueObjectGetString(json, "filename"); - const char *volume =3D virJSONValueObjectGetString(json, "volume"); - const char *path =3D virJSONValueObjectGetString(json, "path"); - virJSONValuePtr server =3D virJSONValueObjectGetArray(json, "server"); - size_t nservers; - size_t i; - - /* legacy URI based syntax passed via 'filename' option */ - if (uri) - return virStorageSourceParseBackingJSONUriStr(src, uri, - VIR_STORAGE_NET_PROT= OCOL_GLUSTER); - - if (!volume || !path || !server) { - virReportError(VIR_ERR_INVALID_ARG, "%s", - _("missing 'volume', 'path' or 'server' attribute i= n " - "JSON backing definition for gluster volume")); - return -1; - } - - src->type =3D VIR_STORAGE_TYPE_NETWORK; - src->protocol =3D VIR_STORAGE_NET_PROTOCOL_GLUSTER; - - src->volume =3D g_strdup(volume); - src->path =3D g_strdup(path); - - nservers =3D virJSONValueArraySize(server); - if (nservers =3D=3D 0) { - virReportError(VIR_ERR_INVALID_ARG, "%s", - _("at least 1 server is necessary in " - "JSON backing definition for gluster volume")); - - return -1; - } - - src->hosts =3D g_new0(virStorageNetHostDef, nservers); - src->nhosts =3D nservers; - - for (i =3D 0; i < nservers; i++) { - if (virStorageSourceParseBackingJSONSocketAddress(src->hosts + i, - virJSONValueArra= yGet(server, i)) < 0) - return -1; - } - - return 0; -} - - -static int -virStorageSourceParseBackingJSONiSCSI(virStorageSourcePtr src, - virJSONValuePtr json, - const char *jsonstr G_GNUC_UNUSED, - int opaque G_GNUC_UNUSED) -{ - const char *transport =3D virJSONValueObjectGetString(json, "transport= "); - const char *portal =3D virJSONValueObjectGetString(json, "portal"); - const char *target =3D virJSONValueObjectGetString(json, "target"); - const char *lun =3D virJSONValueObjectGetStringOrNumber(json, "lun"); - const char *uri; - char *port; - - /* legacy URI based syntax passed via 'filename' option */ - if ((uri =3D virJSONValueObjectGetString(json, "filename"))) - return virStorageSourceParseBackingJSONUriStr(src, uri, - VIR_STORAGE_NET_PROT= OCOL_ISCSI); - - src->type =3D VIR_STORAGE_TYPE_NETWORK; - src->protocol =3D VIR_STORAGE_NET_PROTOCOL_ISCSI; - - if (!lun) - lun =3D "0"; - - src->hosts =3D g_new0(virStorageNetHostDef, 1); - src->nhosts =3D 1; - - if (STRNEQ_NULLABLE(transport, "tcp")) { - virReportError(VIR_ERR_INVALID_ARG, "%s", - _("only TCP transport is supported for iSCSI volume= s")); - return -1; - } - - src->hosts->transport =3D VIR_STORAGE_NET_HOST_TRANS_TCP; - - if (!portal) { - virReportError(VIR_ERR_INVALID_ARG, "%s", - _("missing 'portal' address in iSCSI backing defini= tion")); - return -1; - } - - if (!target) { - virReportError(VIR_ERR_INVALID_ARG, "%s", - _("missing 'target' in iSCSI backing definition")); - return -1; - } - - src->hosts->name =3D g_strdup(portal); - - if ((port =3D strrchr(src->hosts->name, ':')) && - !strchr(port, ']')) { - if (virStringParsePort(port + 1, &src->hosts->port) < 0) - return -1; - - *port =3D '\0'; - } - - src->path =3D g_strdup_printf("%s/%s", target, lun); - - /* Libvirt doesn't handle inline authentication. Make the caller aware= . */ - if (virJSONValueObjectGetString(json, "user") || - virJSONValueObjectGetString(json, "password")) - return 1; - - return 0; -} - - -static int -virStorageSourceParseBackingJSONNbd(virStorageSourcePtr src, - virJSONValuePtr json, - const char *jsonstr G_GNUC_UNUSED, - int opaque G_GNUC_UNUSED) -{ - const char *path =3D virJSONValueObjectGetString(json, "path"); - const char *host =3D virJSONValueObjectGetString(json, "host"); - const char *port =3D virJSONValueObjectGetString(json, "port"); - const char *export =3D virJSONValueObjectGetString(json, "export"); - virJSONValuePtr server =3D virJSONValueObjectGetObject(json, "server"); - - if (!path && !host && !server) { - virReportError(VIR_ERR_INVALID_ARG, "%s", - _("missing host specification of NBD server in JSON= " - "backing volume definition")); - return -1; - } - - src->type =3D VIR_STORAGE_TYPE_NETWORK; - src->protocol =3D VIR_STORAGE_NET_PROTOCOL_NBD; - - src->path =3D g_strdup(export); - - src->hosts =3D g_new0(virStorageNetHostDef, 1); - src->nhosts =3D 1; - - if (server) { - if (virStorageSourceParseBackingJSONSocketAddress(src->hosts, serv= er) < 0) - return -1; - } else { - if (path) { - src->hosts[0].transport =3D VIR_STORAGE_NET_HOST_TRANS_UNIX; - src->hosts[0].socket =3D g_strdup(path); - } else { - src->hosts[0].transport =3D VIR_STORAGE_NET_HOST_TRANS_TCP; - src->hosts[0].name =3D g_strdup(host); - - if (virStringParsePort(port, &src->hosts[0].port) < 0) - return -1; - } - } - - return 0; -} - - -static int -virStorageSourceParseBackingJSONSheepdog(virStorageSourcePtr src, - virJSONValuePtr json, - const char *jsonstr G_GNUC_UNUSED, - int opaque G_GNUC_UNUSED) -{ - const char *filename; - const char *vdi =3D virJSONValueObjectGetString(json, "vdi"); - virJSONValuePtr server =3D virJSONValueObjectGetObject(json, "server"); - - /* legacy URI based syntax passed via 'filename' option */ - if ((filename =3D virJSONValueObjectGetString(json, "filename"))) { - if (strstr(filename, "://")) - return virStorageSourceParseBackingJSONUriStr(src, filename, - VIR_STORAGE_NET_= PROTOCOL_SHEEPDOG); - - /* libvirt doesn't implement a parser for the legacy non-URI synta= x */ - virReportError(VIR_ERR_INVALID_ARG, "%s", - _("missing sheepdog URI in JSON backing volume defi= nition")); - return -1; - } - - src->type =3D VIR_STORAGE_TYPE_NETWORK; - src->protocol =3D VIR_STORAGE_NET_PROTOCOL_SHEEPDOG; - - if (!vdi) { - virReportError(VIR_ERR_INVALID_ARG, "%s", _("missing sheepdog vdi = name")); - return -1; - } - - src->path =3D g_strdup(vdi); - - src->hosts =3D g_new0(virStorageNetHostDef, 1); - src->nhosts =3D 1; - - if (virStorageSourceParseBackingJSONSocketAddress(src->hosts, server) = < 0) - return -1; - - return 0; -} - - -static int -virStorageSourceParseBackingJSONSSH(virStorageSourcePtr src, - virJSONValuePtr json, - const char *jsonstr G_GNUC_UNUSED, - int opaque G_GNUC_UNUSED) -{ - const char *path =3D virJSONValueObjectGetString(json, "path"); - const char *host =3D virJSONValueObjectGetString(json, "host"); - const char *port =3D virJSONValueObjectGetString(json, "port"); - const char *user =3D virJSONValueObjectGetString(json, "user"); - const char *host_key_check =3D virJSONValueObjectGetString(json, "host= _key_check"); - virJSONValuePtr server =3D virJSONValueObjectGetObject(json, "server"); - - if (!(host || server) || !path) { - virReportError(VIR_ERR_INVALID_ARG, "%s", - _("missing host/server or path of SSH JSON backing " - "volume definition")); - return -1; - } - - src->type =3D VIR_STORAGE_TYPE_NETWORK; - src->protocol =3D VIR_STORAGE_NET_PROTOCOL_SSH; - - src->path =3D g_strdup(path); - - src->hosts =3D g_new0(virStorageNetHostDef, 1); - src->nhosts =3D 1; - - if (server) { - if (virStorageSourceParseBackingJSONInetSocketAddress(src->hosts, - server) < 0) - return -1; - } else { - src->hosts[0].transport =3D VIR_STORAGE_NET_HOST_TRANS_TCP; - src->hosts[0].name =3D g_strdup(host); - - if (virStringParsePort(port, &src->hosts[0].port) < 0) - return -1; - } - - /* these two are parsed just to be passed back as we don't model them = yet */ - src->ssh_user =3D g_strdup(user); - if (STREQ_NULLABLE(host_key_check, "no")) - src->ssh_host_key_check_disabled =3D true; - - return 0; -} - - -static int -virStorageSourceParseBackingJSONRBD(virStorageSourcePtr src, - virJSONValuePtr json, - const char *jsonstr G_GNUC_UNUSED, - int opaque G_GNUC_UNUSED) -{ - const char *filename; - const char *pool =3D virJSONValueObjectGetString(json, "pool"); - const char *image =3D virJSONValueObjectGetString(json, "image"); - const char *conf =3D virJSONValueObjectGetString(json, "conf"); - const char *snapshot =3D virJSONValueObjectGetString(json, "snapshot"); - virJSONValuePtr servers =3D virJSONValueObjectGetArray(json, "server"); - size_t nservers; - size_t i; - - src->type =3D VIR_STORAGE_TYPE_NETWORK; - src->protocol =3D VIR_STORAGE_NET_PROTOCOL_RBD; - - /* legacy syntax passed via 'filename' option */ - if ((filename =3D virJSONValueObjectGetString(json, "filename"))) - return virStorageSourceParseRBDColonString(filename, src); - - if (!pool || !image) { - virReportError(VIR_ERR_INVALID_ARG, "%s", - _("missing pool or image name in ceph backing volum= e " - "JSON specification")); - return -1; - } - - src->volume =3D g_strdup(pool); - src->path =3D g_strdup(image); - src->snapshot =3D g_strdup(snapshot); - src->configFile =3D g_strdup(conf); - - if (servers) { - nservers =3D virJSONValueArraySize(servers); - - src->hosts =3D g_new0(virStorageNetHostDef, nservers); - src->nhosts =3D nservers; - - for (i =3D 0; i < nservers; i++) { - if (virStorageSourceParseBackingJSONInetSocketAddress(src->hos= ts + i, - virJSONV= alueArrayGet(servers, i)) < 0) - return -1; - } - } - - return 0; -} - -static int -virStorageSourceParseBackingJSONRaw(virStorageSourcePtr src, - virJSONValuePtr json, - const char *jsonstr, - int opaque G_GNUC_UNUSED) -{ - bool has_offset =3D virJSONValueObjectHasKey(json, "offset"); - bool has_size =3D virJSONValueObjectHasKey(json, "size"); - virJSONValuePtr file; - - if (has_offset || has_size) { - src->sliceStorage =3D g_new0(virStorageSourceSlice, 1); - - if (has_offset && - virJSONValueObjectGetNumberUlong(json, "offset", &src->sliceSt= orage->offset) < 0) { - virReportError(VIR_ERR_INVALID_ARG, "%s", - _("malformed 'offset' property of 'raw' driver"= )); - return -1; - } - - if (has_size && - virJSONValueObjectGetNumberUlong(json, "size", &src->sliceStor= age->size) < 0) { - virReportError(VIR_ERR_INVALID_ARG, "%s", - _("malformed 'size' property of 'raw' driver")); - return -1; - } - } - - /* 'raw' is a format driver so it can have protocol driver children */ - if (!(file =3D virJSONValueObjectGetObject(json, "file"))) { - virReportError(VIR_ERR_INVALID_ARG, - _("JSON backing volume definition '%s' lacks 'file'= object"), - jsonstr); - return -1; - } - - return virStorageSourceParseBackingJSONInternal(src, file, jsonstr, fa= lse); -} - - -static int -virStorageSourceParseBackingJSONVxHS(virStorageSourcePtr src, - virJSONValuePtr json, - const char *jsonstr G_GNUC_UNUSED, - int opaque G_GNUC_UNUSED) -{ - const char *vdisk_id =3D virJSONValueObjectGetString(json, "vdisk-id"); - virJSONValuePtr server =3D virJSONValueObjectGetObject(json, "server"); - - if (!vdisk_id || !server) { - virReportError(VIR_ERR_INVALID_ARG, "%s", - _("missing 'vdisk-id' or 'server' attribute in " - "JSON backing definition for VxHS volume")); - return -1; - } - - src->type =3D VIR_STORAGE_TYPE_NETWORK; - src->protocol =3D VIR_STORAGE_NET_PROTOCOL_VXHS; - - src->path =3D g_strdup(vdisk_id); - - src->hosts =3D g_new0(virStorageNetHostDef, 1); - src->nhosts =3D 1; - - if (virStorageSourceParseBackingJSONInetSocketAddress(src->hosts, - server) < 0) - return -1; - - return 0; -} - - -static int -virStorageSourceParseBackingJSONNVMe(virStorageSourcePtr src, - virJSONValuePtr json, - const char *jsonstr G_GNUC_UNUSED, - int opaque G_GNUC_UNUSED) -{ - g_autoptr(virStorageSourceNVMeDef) nvme =3D g_new0(virStorageSourceNVM= eDef, 1); - const char *device =3D virJSONValueObjectGetString(json, "device"); - - if (!device || virPCIDeviceAddressParse((char *) device, &nvme->pciAdd= r) < 0) { - virReportError(VIR_ERR_INVALID_ARG, "%s", - _("missing or malformed 'device' field of 'nvme' st= orage")); - return -1; - } - - if (virJSONValueObjectGetNumberUlong(json, "namespace", &nvme->namespc= ) < 0 || - nvme->namespc =3D=3D 0) { - virReportError(VIR_ERR_INVALID_ARG, "%s", - _("missing or malformed 'namespace' field of 'nvme'= storage")); - return -1; - } - - src->type =3D VIR_STORAGE_TYPE_NVME; - src->nvme =3D g_steal_pointer(&nvme); - - return 0; -} - - -struct virStorageSourceJSONDriverParser { - const char *drvname; - bool formatdriver; - /** - * The callback gets a pre-allocated storage source @src and the JSON - * object to parse. The callback shall return -1 on error and report e= rror - * 0 on success and 1 in cases when the configuration itself is valid,= but - * can't be converted to libvirt's configuration (e.g. inline authenti= cation - * credentials are present). - */ - int (*func)(virStorageSourcePtr src, virJSONValuePtr json, const char = *jsonstr, int opaque); - int opaque; -}; - -static const struct virStorageSourceJSONDriverParser jsonParsers[] =3D { - {"file", false, virStorageSourceParseBackingJSONPath, VIR_STORAGE_TYPE= _FILE}, - {"host_device", false, virStorageSourceParseBackingJSONPath, VIR_STORA= GE_TYPE_BLOCK}, - {"host_cdrom", false, virStorageSourceParseBackingJSONPath, VIR_STORAG= E_TYPE_BLOCK}, - {"http", false, virStorageSourceParseBackingJSONUri, VIR_STORAGE_NET_P= ROTOCOL_HTTP}, - {"https", false, virStorageSourceParseBackingJSONUri, VIR_STORAGE_NET_= PROTOCOL_HTTPS}, - {"ftp", false, virStorageSourceParseBackingJSONUri, VIR_STORAGE_NET_PR= OTOCOL_FTP}, - {"ftps", false, virStorageSourceParseBackingJSONUri, VIR_STORAGE_NET_P= ROTOCOL_FTPS}, - {"tftp", false, virStorageSourceParseBackingJSONUri, VIR_STORAGE_NET_P= ROTOCOL_TFTP}, - {"gluster", false, virStorageSourceParseBackingJSONGluster, 0}, - {"iscsi", false, virStorageSourceParseBackingJSONiSCSI, 0}, - {"nbd", false, virStorageSourceParseBackingJSONNbd, 0}, - {"sheepdog", false, virStorageSourceParseBackingJSONSheepdog, 0}, - {"ssh", false, virStorageSourceParseBackingJSONSSH, 0}, - {"rbd", false, virStorageSourceParseBackingJSONRBD, 0}, - {"raw", true, virStorageSourceParseBackingJSONRaw, 0}, - {"vxhs", false, virStorageSourceParseBackingJSONVxHS, 0}, - {"nvme", false, virStorageSourceParseBackingJSONNVMe, 0}, -}; - - - -static int -virStorageSourceParseBackingJSONInternal(virStorageSourcePtr src, - virJSONValuePtr json, - const char *jsonstr, - bool allowformat) -{ - const char *drvname; - size_t i; - - if (!(drvname =3D virJSONValueObjectGetString(json, "driver"))) { - virReportError(VIR_ERR_INVALID_ARG, - _("JSON backing volume definition '%s' lacks driver= name"), - jsonstr); - return -1; - } - - for (i =3D 0; i < G_N_ELEMENTS(jsonParsers); i++) { - if (STRNEQ(drvname, jsonParsers[i].drvname)) - continue; - - if (jsonParsers[i].formatdriver && !allowformat) { - virReportError(VIR_ERR_INVALID_ARG, - _("JSON backing volume definition '%s' must not= have nested format drivers"), - jsonstr); - return -1; - } - - return jsonParsers[i].func(src, json, jsonstr, jsonParsers[i].opaq= ue); - } - - virReportError(VIR_ERR_INTERNAL_ERROR, - _("missing parser implementation for JSON backing volum= e " - "driver '%s'"), drvname); - return -1; -} - - -static int -virStorageSourceParseBackingJSON(virStorageSourcePtr src, - const char *json) -{ - g_autoptr(virJSONValue) root =3D NULL; - g_autoptr(virJSONValue) deflattened =3D NULL; - virJSONValuePtr file =3D NULL; - - if (!(root =3D virJSONValueFromString(json))) - return -1; - - if (!(deflattened =3D virJSONValueObjectDeflatten(root))) - return -1; - - /* There are 2 possible syntaxes: - * 1) json:{"file":{"driver":...}} - * 2) json:{"driver":...} - * Remove the 'file' wrapper object in case 1. - */ - if (!virJSONValueObjectHasKey(deflattened, "driver")) - file =3D virJSONValueObjectGetObject(deflattened, "file"); - - if (!file) - file =3D deflattened; - - return virStorageSourceParseBackingJSONInternal(src, file, json, true); -} - - -/** - * virStorageSourceNewFromBackingAbsolute - * @path: string representing absolute location of a storage source - * @src: filled with virStorageSource object representing @path - * - * Returns 0 on success, 1 if we could parse all location data but @path - * specified other data unrepresentable by libvirt (e.g. inline authentica= tion). - * In both cases @src is filled. On error -1 is returned @src is NULL and = an - * error is reported. - */ -int -virStorageSourceNewFromBackingAbsolute(const char *path, - virStorageSourcePtr *src) -{ - const char *json; - const char *dirpath; - int rc =3D 0; - g_autoptr(virStorageSource) def =3D virStorageSourceNew(); - - *src =3D NULL; - - if (virFileIsFile(path)) { - def->type =3D VIR_STORAGE_TYPE_FILE; - - def->path =3D g_strdup(path); - } else { - if ((dirpath =3D STRSKIP(path, "fat:"))) { - def->type =3D VIR_STORAGE_TYPE_DIR; - def->format =3D VIR_STORAGE_FILE_FAT; - def->path =3D g_strdup(dirpath); - *src =3D g_steal_pointer(&def); - return 0; - } - - def->type =3D VIR_STORAGE_TYPE_NETWORK; - - VIR_DEBUG("parsing backing store string: '%s'", path); - - /* handle URI formatted backing stores */ - if ((json =3D STRSKIP(path, "json:"))) - rc =3D virStorageSourceParseBackingJSON(def, json); - else if (strstr(path, "://")) - rc =3D virStorageSourceParseBackingURI(def, path); - else - rc =3D virStorageSourceParseBackingColon(def, path); - - if (rc < 0) - return -1; - - virStorageSourceNetworkAssignDefaultPorts(def); - - /* Some of the legacy parsers parse authentication data since they= are - * also used in other places. For backing store detection the - * authentication data would be invalid anyways, so we clear it */ - if (def->auth) { - virStorageAuthDefFree(def->auth); - def->auth =3D NULL; - } - } - - *src =3D g_steal_pointer(&def); - return rc; -} - - -/** - * virStorageSourceNewFromChild: - * @parent: storage source parent - * @child: returned child/backing store definition - * @parentRaw: raw child string (backingStoreRaw) - * - * Creates a storage source which describes the backing image of @parent a= nd - * fills it into @backing depending on the passed parentRaw (backingStoreR= aw) - * and other data. Note that for local storage this function accesses the = file - * to update the actual type of the child store. - * - * Returns 0 on success, 1 if we could parse all location data but the chi= ld - * store specification contained other data unrepresentable by libvirt (e.= g. - * inline authentication). - * In both cases @src is filled. On error -1 is returned @src is NULL and = an - * error is reported. - */ -static int -virStorageSourceNewFromChild(virStorageSourcePtr parent, - const char *parentRaw, - virStorageSourcePtr *child) -{ - struct stat st; - g_autoptr(virStorageSource) def =3D NULL; - int rc =3D 0; - - *child =3D NULL; - - if (virFileIsRelative(parentRaw)) { - if (!(def =3D virStorageSourceNewFromBackingRelative(parent, paren= tRaw))) - return -1; - } else { - if ((rc =3D virStorageSourceNewFromBackingAbsolute(parentRaw, &def= )) < 0) - return -1; - } - - /* possibly update local type */ - if (def->type =3D=3D VIR_STORAGE_TYPE_FILE) { - if (stat(def->path, &st) =3D=3D 0) { - if (S_ISDIR(st.st_mode)) { - def->type =3D VIR_STORAGE_TYPE_DIR; - def->format =3D VIR_STORAGE_FILE_DIR; - } else if (S_ISBLK(st.st_mode)) { - def->type =3D VIR_STORAGE_TYPE_BLOCK; - } - } - } - - /* copy parent's labelling and other top level stuff */ - if (virStorageSourceInitChainElement(def, parent, true) < 0) - return -1; - - def->detected =3D true; - - *child =3D g_steal_pointer(&def); - return rc; -} - - -int -virStorageSourceNewFromBacking(virStorageSourcePtr parent, - virStorageSourcePtr *backing) -{ - int rc; - - if ((rc =3D virStorageSourceNewFromChild(parent, - parent->backingStoreRaw, - backing)) < 0) - return rc; - - (*backing)->format =3D parent->backingStoreRawFormat; - (*backing)->readonly =3D true; - return rc; -} - - -/** - * @src: disk source definition structure - * @fd: file descriptor - * @sb: stat buffer - * - * Updates src->physical depending on the actual type of storage being use= d. - * To be called for domain storage source reporting as the volume code does - * not set/use the 'type' field for the voldef->source.target - * - * Returns 0 on success, -1 on error. No libvirt errors are reported. - */ -int -virStorageSourceUpdatePhysicalSize(virStorageSourcePtr src, - int fd, - struct stat const *sb) -{ - off_t end; - virStorageType actual_type =3D virStorageSourceGetActualType(src); - - switch (actual_type) { - case VIR_STORAGE_TYPE_FILE: - case VIR_STORAGE_TYPE_NETWORK: - src->physical =3D sb->st_size; - break; - - case VIR_STORAGE_TYPE_BLOCK: - if ((end =3D lseek(fd, 0, SEEK_END)) =3D=3D (off_t) -1) - return -1; - - src->physical =3D end; - break; - - case VIR_STORAGE_TYPE_DIR: - src->physical =3D 0; - break; - - /* We shouldn't get VOLUME, but the switch requires all cases */ - case VIR_STORAGE_TYPE_VOLUME: - case VIR_STORAGE_TYPE_NVME: - case VIR_STORAGE_TYPE_NONE: - case VIR_STORAGE_TYPE_LAST: - return -1; - } - - return 0; -} - - -/** - * @src: disk source definition structure - * @fd: file descriptor - * @sb: stat buffer - * - * Update the capacity, allocation, physical values for the storage @src - * Shared between the domain storage source for an inactive domain and the - * voldef source target as the result is not affected by the 'type' field. - * - * Returns 0 on success, -1 on error. - */ -int -virStorageSourceUpdateBackingSizes(virStorageSourcePtr src, - int fd, - struct stat const *sb) -{ - /* Get info for normal formats */ - if (S_ISREG(sb->st_mode) || fd =3D=3D -1) { -#ifndef WIN32 - src->allocation =3D (unsigned long long)sb->st_blocks * - (unsigned long long)DEV_BSIZE; -#else - src->allocation =3D sb->st_size; -#endif - /* Regular files may be sparse, so logical size (capacity) is not = same - * as actual allocation above - */ - src->capacity =3D sb->st_size; - - /* Allocation tracks when the file is sparse, physical is the - * last offset of the file. */ - src->physical =3D sb->st_size; - } else if (S_ISDIR(sb->st_mode)) { - src->allocation =3D 0; - src->capacity =3D 0; - src->physical =3D 0; - } else if (fd >=3D 0) { - off_t end; - - /* XXX this is POSIX compliant, but doesn't work for CHAR files, - * only BLOCK. There is a Linux specific ioctl() for getting - * size of both CHAR / BLOCK devices we should check for in - * configure - * - * NB. Because we configure with AC_SYS_LARGEFILE, off_t - * should be 64 bits on all platforms. For block devices, we - * have to seek (safe even if someone else is writing) to - * determine physical size, and assume that allocation is the - * same as physical (but can refine that assumption later if - * qemu is still running). - */ - if ((end =3D lseek(fd, 0, SEEK_END)) =3D=3D (off_t)-1) { - virReportSystemError(errno, - _("failed to seek to end of %s"), src->pa= th); - return -1; - } - src->physical =3D end; - src->allocation =3D end; - src->capacity =3D end; - } - - return 0; -} - - -/** - * @src: disk source definition structure - * @buf: buffer to the storage file header - * @len: length of the storage file header - * - * Update the storage @src capacity. - * - * Returns 0 on success, -1 on error. - */ -int -virStorageSourceUpdateCapacity(virStorageSourcePtr src, - char *buf, - ssize_t len) -{ - int format =3D src->format; - g_autoptr(virStorageSource) meta =3D NULL; - - /* Raw files: capacity is physical size. For all other files: if - * the metadata has a capacity, use that, otherwise fall back to - * physical size. */ - if (format =3D=3D VIR_STORAGE_FILE_NONE) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("no disk format for %s was specified"), - src->path); - return -1; - } - - if (format =3D=3D VIR_STORAGE_FILE_RAW && !src->encryption) { - src->capacity =3D src->physical; - } else if ((meta =3D virStorageFileGetMetadataFromBuf(src->path, buf, - len, format))) { - src->capacity =3D meta->capacity ? meta->capacity : src->physical; - if (src->encryption && meta->encryption) - src->encryption->payload_offset =3D meta->encryption->payload_= offset; - } else { - return -1; - } - - if (src->encryption && src->encryption->payload_offset !=3D -1) - src->capacity -=3D src->encryption->payload_offset * 512; - - return 0; -} - - -static char * -virStorageFileCanonicalizeFormatPath(char **components, - size_t ncomponents, - bool beginSlash, - bool beginDoubleSlash) -{ - g_auto(virBuffer) buf =3D VIR_BUFFER_INITIALIZER; - size_t i; - char *ret =3D NULL; - - if (beginSlash) - virBufferAddLit(&buf, "/"); - - if (beginDoubleSlash) - virBufferAddLit(&buf, "/"); - - for (i =3D 0; i < ncomponents; i++) { - if (i !=3D 0) - virBufferAddLit(&buf, "/"); - - virBufferAdd(&buf, components[i], -1); - } - - /* if the output string is empty just return an empty string */ - if (!(ret =3D virBufferContentAndReset(&buf))) - ret =3D g_strdup(""); - - return ret; -} - - -static int -virStorageFileCanonicalizeInjectSymlink(const char *path, - size_t at, - char ***components, - size_t *ncomponents) -{ - char **tmp =3D NULL; - char **next; - size_t ntmp =3D 0; - int ret =3D -1; - - if (!(tmp =3D virStringSplitCount(path, "/", 0, &ntmp))) - goto cleanup; - - /* prepend */ - for (next =3D tmp; *next; next++) { - if (VIR_INSERT_ELEMENT(*components, at, *ncomponents, *next) < 0) - goto cleanup; - - at++; - } - - ret =3D 0; - - cleanup: - virStringListFreeCount(tmp, ntmp); - return ret; -} - - -char * -virStorageFileCanonicalizePath(const char *path, - virStorageFileSimplifyPathReadlinkCallback = cb, - void *cbdata) -{ - GHashTable *cycle =3D NULL; - bool beginSlash =3D false; - bool beginDoubleSlash =3D false; - char **components =3D NULL; - size_t ncomponents =3D 0; - size_t i =3D 0; - size_t j =3D 0; - int rc; - char *ret =3D NULL; - g_autofree char *linkpath =3D NULL; - g_autofree char *currentpath =3D NULL; - - if (path[0] =3D=3D '/') { - beginSlash =3D true; - - if (path[1] =3D=3D '/' && path[2] !=3D '/') - beginDoubleSlash =3D true; - } - - if (!(cycle =3D virHashNew(NULL))) - goto cleanup; - - if (!(components =3D virStringSplitCount(path, "/", 0, &ncomponents))) - goto cleanup; - - j =3D 0; - while (j < ncomponents) { - /* skip slashes */ - if (STREQ(components[j], "")) { - VIR_FREE(components[j]); - VIR_DELETE_ELEMENT(components, j, ncomponents); - continue; - } - j++; - } - - while (i < ncomponents) { - /* skip '.'s unless it's the last one remaining */ - if (STREQ(components[i], ".") && - (beginSlash || ncomponents > 1)) { - VIR_FREE(components[i]); - VIR_DELETE_ELEMENT(components, i, ncomponents); - continue; - } - - /* resolve changes to parent directory */ - if (STREQ(components[i], "..")) { - if (!beginSlash && - (i =3D=3D 0 || STREQ(components[i - 1], ".."))) { - i++; - continue; - } - - VIR_FREE(components[i]); - VIR_DELETE_ELEMENT(components, i, ncomponents); - - if (i !=3D 0) { - VIR_FREE(components[i - 1]); - VIR_DELETE_ELEMENT(components, i - 1, ncomponents); - i--; - } - - continue; - } - - /* check if the actual path isn't resulting into a symlink */ - if (!(currentpath =3D virStorageFileCanonicalizeFormatPath(compone= nts, - i + 1, - beginSlas= h, - beginDoub= leSlash))) - goto cleanup; - - if ((rc =3D cb(currentpath, &linkpath, cbdata)) < 0) - goto cleanup; - - if (rc =3D=3D 0) { - if (virHashLookup(cycle, currentpath)) { - virReportSystemError(ELOOP, - _("Failed to canonicalize path '%s'")= , path); - goto cleanup; - } - - if (virHashAddEntry(cycle, currentpath, (void *) 1) < 0) - goto cleanup; - - if (linkpath[0] =3D=3D '/') { - /* kill everything from the beginning including the actual= component */ - i++; - while (i--) { - VIR_FREE(components[0]); - VIR_DELETE_ELEMENT(components, 0, ncomponents); - } - beginSlash =3D true; - - if (linkpath[1] =3D=3D '/' && linkpath[2] !=3D '/') - beginDoubleSlash =3D true; - else - beginDoubleSlash =3D false; - - i =3D 0; - } else { - VIR_FREE(components[i]); - VIR_DELETE_ELEMENT(components, i, ncomponents); - } - - if (virStorageFileCanonicalizeInjectSymlink(linkpath, - i, - &components, - &ncomponents) < 0) - goto cleanup; - - j =3D 0; - while (j < ncomponents) { - /* skip slashes */ - if (STREQ(components[j], "")) { - VIR_FREE(components[j]); - VIR_DELETE_ELEMENT(components, j, ncomponents); - continue; - } - j++; - } - - VIR_FREE(linkpath); - VIR_FREE(currentpath); - - continue; - } - - VIR_FREE(currentpath); - - i++; - } - - ret =3D virStorageFileCanonicalizeFormatPath(components, ncomponents, - beginSlash, beginDoubleSlas= h); - - cleanup: - virHashFree(cycle); - virStringListFreeCount(components, ncomponents); - - return ret; -} - - -/** - * virStorageFileRemoveLastPathComponent: - * - * @path: Path string to remove the last component from - * - * Removes the last path component of a path. This function is designed to= be - * called on file paths only (no trailing slashes in @path). Caller is - * responsible to free the returned string. - */ -static char * -virStorageFileRemoveLastPathComponent(const char *path) -{ - char *ret; - - ret =3D g_strdup(NULLSTR_EMPTY(path)); - - virFileRemoveLastComponent(ret); - - return ret; -} - - -/* - * virStorageFileGetRelativeBackingPath: - * - * Resolve relative path to be written to the overlay of @top image when - * collapsing the backing chain between @top and @base. - * - * Returns 0 on success; 1 if backing chain isn't relative and -1 on error. - */ -int -virStorageFileGetRelativeBackingPath(virStorageSourcePtr top, - virStorageSourcePtr base, - char **relpath) -{ - virStorageSourcePtr next; - g_autofree char *tmp =3D NULL; - g_autofree char *path =3D NULL; - - *relpath =3D NULL; - - for (next =3D top; virStorageSourceIsBacking(next); next =3D next->bac= kingStore) { - if (!next->relPath) - return 1; - - if (!(tmp =3D virStorageFileRemoveLastPathComponent(path))) - return -1; - - VIR_FREE(path); - - path =3D g_strdup_printf("%s%s", tmp, next->relPath); - - VIR_FREE(tmp); - - if (next =3D=3D base) - break; - } - - if (next !=3D base) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("failed to resolve relative backing name: " - "base image is not in backing chain")); - return -1; - } - - *relpath =3D g_steal_pointer(&path); - return 0; -} - - /** * virStorageSourceIsRelative: * @src: storage source to check @@ -4351,31 +1347,6 @@ virStorageSourceIsRelative(virStorageSourcePtr src) } =20 =20 -/** - * virStorageSourceFindByNodeName: - * @top: backing chain top - * @nodeName: node name to find in backing chain - * - * Looks up the given storage source in the backing chain and returns the - * pointer to it. - * On failure NULL is returned and no error is reported. - */ -virStorageSourcePtr -virStorageSourceFindByNodeName(virStorageSourcePtr top, - const char *nodeName) -{ - virStorageSourcePtr tmp; - - for (tmp =3D top; virStorageSourceIsBacking(tmp); tmp =3D tmp->backing= Store) { - if ((tmp->nodeformat && STREQ(tmp->nodeformat, nodeName)) || - (tmp->nodestorage && STREQ(tmp->nodestorage, nodeName))) - return tmp; - } - - return NULL; -} - - static unsigned int virStorageSourceNetworkDefaultPort(virStorageNetProtocol protocol) { @@ -4439,25 +1410,6 @@ virStorageSourceNetworkAssignDefaultPorts(virStorage= SourcePtr src) } =20 =20 -int -virStorageSourcePrivateDataParseRelPath(xmlXPathContextPtr ctxt, - virStorageSourcePtr src) -{ - src->relPath =3D virXPathString("string(./relPath)", ctxt); - return 0; -} - - -int -virStorageSourcePrivateDataFormatRelPath(virStorageSourcePtr src, - virBufferPtr buf) -{ - if (src->relPath) - virBufferEscapeString(buf, "%s\n", src->relPath= ); - - return 0; -} - void virStorageSourceInitiatorParseXML(xmlXPathContextPtr ctxt, virStorageSourceInitiatorDefPtr initiato= r) @@ -4492,736 +1444,3 @@ virStorageSourceInitiatorClear(virStorageSourceInit= iatorDefPtr initiator) { VIR_FREE(initiator->iqn); } - -static bool -virStorageFileIsInitialized(const virStorageSource *src) -{ - return src && src->drv; -} - - -/** - * virStorageFileGetBackendForSupportCheck: - * @src: storage source to check support for - * @backend: pointer to the storage backend for @src if it's supported - * - * Returns 0 if @src is not supported by any storage backend currently lin= ked - * 1 if it is supported and -1 on error with an error reported. - */ -static int -virStorageFileGetBackendForSupportCheck(const virStorageSource *src, - virStorageFileBackendPtr *backend) -{ - int actualType; - - - if (!src) { - *backend =3D NULL; - return 0; - } - - if (src->drv) { - virStorageDriverDataPtr drv =3D src->drv; - *backend =3D drv->backend; - return 1; - } - - actualType =3D virStorageSourceGetActualType(src); - - if (virStorageFileBackendForType(actualType, src->protocol, false, bac= kend) < 0) - return -1; - - if (!*backend) - return 0; - - return 1; -} - - -int -virStorageFileSupportsBackingChainTraversal(const virStorageSource *src) -{ - virStorageFileBackendPtr backend; - int rv; - - if ((rv =3D virStorageFileGetBackendForSupportCheck(src, &backend)) < = 1) - return rv; - - return backend->storageFileGetUniqueIdentifier && - backend->storageFileRead && - backend->storageFileAccess ? 1 : 0; -} - - -/** - * virStorageFileSupportsSecurityDriver: - * - * @src: a storage file structure - * - * Check if a storage file supports operations needed by the security - * driver to perform labelling - */ -int -virStorageFileSupportsSecurityDriver(const virStorageSource *src) -{ - virStorageFileBackendPtr backend; - int rv; - - if ((rv =3D virStorageFileGetBackendForSupportCheck(src, &backend)) < = 1) - return rv; - - return backend->storageFileChown ? 1 : 0; -} - - -/** - * virStorageFileSupportsAccess: - * - * @src: a storage file structure - * - * Check if a storage file supports checking if the storage source is acce= ssible - * for the given vm. - */ -int -virStorageFileSupportsAccess(const virStorageSource *src) -{ - virStorageFileBackendPtr backend; - int rv; - - if ((rv =3D virStorageFileGetBackendForSupportCheck(src, &backend)) < = 1) - return rv; - - return backend->storageFileAccess ? 1 : 0; -} - - -/** - * virStorageFileSupportsCreate: - * @src: a storage file structure - * - * Check if the storage driver supports creating storage described by @src - * via virStorageFileCreate. - */ -int -virStorageFileSupportsCreate(const virStorageSource *src) -{ - virStorageFileBackendPtr backend; - int rv; - - if ((rv =3D virStorageFileGetBackendForSupportCheck(src, &backend)) < = 1) - return rv; - - return backend->storageFileCreate ? 1 : 0; -} - - -void -virStorageFileDeinit(virStorageSourcePtr src) -{ - virStorageDriverDataPtr drv =3D NULL; - - if (!virStorageFileIsInitialized(src)) - return; - - drv =3D src->drv; - - if (drv->backend && - drv->backend->backendDeinit) - drv->backend->backendDeinit(src); - - VIR_FREE(src->drv); -} - - -/** - * virStorageFileInitAs: - * - * @src: storage source definition - * @uid: uid used to access the file, or -1 for current uid - * @gid: gid used to access the file, or -1 for current gid - * - * Initialize a storage source to be used with storage driver. Use the pro= vided - * uid and gid if possible for the operations. - * - * Returns 0 if the storage file was successfully initialized, -1 if the - * initialization failed. Libvirt error is reported. - */ -int -virStorageFileInitAs(virStorageSourcePtr src, - uid_t uid, gid_t gid) -{ - int actualType =3D virStorageSourceGetActualType(src); - virStorageDriverDataPtr drv =3D g_new0(virStorageDriverData, 1); - - src->drv =3D drv; - - if (uid =3D=3D (uid_t) -1) - drv->uid =3D geteuid(); - else - drv->uid =3D uid; - - if (gid =3D=3D (gid_t) -1) - drv->gid =3D getegid(); - else - drv->gid =3D gid; - - if (virStorageFileBackendForType(actualType, - src->protocol, - true, - &drv->backend) < 0) - goto error; - - if (drv->backend->backendInit && - drv->backend->backendInit(src) < 0) - goto error; - - return 0; - - error: - VIR_FREE(src->drv); - return -1; -} - - -/** - * virStorageFileInit: - * - * See virStorageFileInitAs. The file is initialized to be accessed by the - * current user. - */ -int -virStorageFileInit(virStorageSourcePtr src) -{ - return virStorageFileInitAs(src, -1, -1); -} - - -/** - * virStorageFileCreate: Creates an empty storage file via storage driver - * - * @src: file structure pointing to the file - * - * Returns 0 on success, -2 if the function isn't supported by the backend, - * -1 on other failure. Errno is set in case of failure. - */ -int -virStorageFileCreate(virStorageSourcePtr src) -{ - virStorageDriverDataPtr drv =3D NULL; - int ret; - - if (!virStorageFileIsInitialized(src)) { - errno =3D ENOSYS; - return -2; - } - - drv =3D src->drv; - - if (!drv->backend->storageFileCreate) { - errno =3D ENOSYS; - return -2; - } - - ret =3D drv->backend->storageFileCreate(src); - - VIR_DEBUG("created storage file %p: ret=3D%d, errno=3D%d", - src, ret, errno); - - return ret; -} - - -/** - * virStorageFileUnlink: Unlink storage file via storage driver - * - * @src: file structure pointing to the file - * - * Unlinks the file described by the @file structure. - * - * Returns 0 on success, -2 if the function isn't supported by the backend, - * -1 on other failure. Errno is set in case of failure. - */ -int -virStorageFileUnlink(virStorageSourcePtr src) -{ - virStorageDriverDataPtr drv =3D NULL; - int ret; - - if (!virStorageFileIsInitialized(src)) { - errno =3D ENOSYS; - return -2; - } - - drv =3D src->drv; - - if (!drv->backend->storageFileUnlink) { - errno =3D ENOSYS; - return -2; - } - - ret =3D drv->backend->storageFileUnlink(src); - - VIR_DEBUG("unlinked storage file %p: ret=3D%d, errno=3D%d", - src, ret, errno); - - return ret; -} - - -/** - * virStorageFileStat: returns stat struct of a file via storage driver - * - * @src: file structure pointing to the file - * @stat: stat structure to return data - * - * Returns 0 on success, -2 if the function isn't supported by the backend, - * -1 on other failure. Errno is set in case of failure. -*/ -int -virStorageFileStat(virStorageSourcePtr src, - struct stat *st) -{ - virStorageDriverDataPtr drv =3D NULL; - int ret; - - if (!virStorageFileIsInitialized(src)) { - errno =3D ENOSYS; - return -2; - } - - drv =3D src->drv; - - if (!drv->backend->storageFileStat) { - errno =3D ENOSYS; - return -2; - } - - ret =3D drv->backend->storageFileStat(src, st); - - VIR_DEBUG("stat of storage file %p: ret=3D%d, errno=3D%d", - src, ret, errno); - - return ret; -} - - -/** - * virStorageFileRead: read bytes from a file into a buffer - * - * @src: file structure pointing to the file - * @offset: number of bytes to skip in the storage file - * @len: maximum number of bytes read from the storage file - * @buf: buffer to read the data into. (buffer shall be freed by caller) - * - * Returns the count of bytes read on success and -1 on failure, -2 if the - * function isn't supported by the backend. - * Libvirt error is reported on failure. - */ -ssize_t -virStorageFileRead(virStorageSourcePtr src, - size_t offset, - size_t len, - char **buf) -{ - virStorageDriverDataPtr drv =3D NULL; - ssize_t ret; - - if (!virStorageFileIsInitialized(src)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("storage file backend not initialized")); - return -1; - } - - drv =3D src->drv; - - if (!drv->backend->storageFileRead) - return -2; - - ret =3D drv->backend->storageFileRead(src, offset, len, buf); - - VIR_DEBUG("read '%zd' bytes from storage '%p' starting at offset '%zu'= ", - ret, src, offset); - - return ret; -} - - -/* - * virStorageFileGetUniqueIdentifier: Get a unique string describing the v= olume - * - * @src: file structure pointing to the file - * - * Returns a string uniquely describing a single volume (canonical path). - * The string shall not be freed and is valid until the storage file is - * deinitialized. Returns NULL on error and sets a libvirt error code */ -const char * -virStorageFileGetUniqueIdentifier(virStorageSourcePtr src) -{ - virStorageDriverDataPtr drv =3D NULL; - - if (!virStorageFileIsInitialized(src)) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("storage file backend not initialized")); - return NULL; - } - - drv =3D src->drv; - - if (!drv->backend->storageFileGetUniqueIdentifier) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("unique storage file identifier not implemented f= or " - "storage type %s (protocol: %s)'"), - virStorageTypeToString(src->type), - virStorageNetProtocolTypeToString(src->protocol)); - return NULL; - } - - return drv->backend->storageFileGetUniqueIdentifier(src); -} - - -/** - * virStorageFileAccess: Check accessibility of a storage file - * - * @src: storage file to check access permissions - * @mode: accessibility check options (see man 2 access) - * - * Returns 0 on success, -1 on error and sets errno. No libvirt - * error is reported. Returns -2 if the operation isn't supported - * by libvirt storage backend. - */ -int -virStorageFileAccess(virStorageSourcePtr src, - int mode) -{ - virStorageDriverDataPtr drv =3D NULL; - - if (!virStorageFileIsInitialized(src)) { - errno =3D ENOSYS; - return -2; - } - - drv =3D src->drv; - - if (!drv->backend->storageFileAccess) { - errno =3D ENOSYS; - return -2; - } - - return drv->backend->storageFileAccess(src, mode); -} - - -/** - * virStorageFileChown: Change owner of a storage file - * - * @src: storage file to change owner of - * @uid: new owner id - * @gid: new group id - * - * Returns 0 on success, -1 on error and sets errno. No libvirt - * error is reported. Returns -2 if the operation isn't supported - * by libvirt storage backend. - */ -int -virStorageFileChown(const virStorageSource *src, - uid_t uid, - gid_t gid) -{ - virStorageDriverDataPtr drv =3D NULL; - - if (!virStorageFileIsInitialized(src)) { - errno =3D ENOSYS; - return -2; - } - - drv =3D src->drv; - - if (!drv->backend->storageFileChown) { - errno =3D ENOSYS; - return -2; - } - - VIR_DEBUG("chown of storage file %p to %u:%u", - src, (unsigned int)uid, (unsigned int)gid); - - return drv->backend->storageFileChown(src, uid, gid); -} - - -/** - * virStorageFileReportBrokenChain: - * - * @errcode: errno when accessing @src - * @src: inaccessible file in the backing chain of @parent - * @parent: root virStorageSource being checked - * - * Reports the correct error message if @src is missing in the backing cha= in - * for @parent. - */ -void -virStorageFileReportBrokenChain(int errcode, - virStorageSourcePtr src, - virStorageSourcePtr parent) -{ - if (src->drv) { - virStorageDriverDataPtr drv =3D src->drv; - unsigned int access_user =3D drv->uid; - unsigned int access_group =3D drv->gid; - - if (src =3D=3D parent) { - virReportSystemError(errcode, - _("Cannot access storage file '%s' " - "(as uid:%u, gid:%u)"), - src->path, access_user, access_group); - } else { - virReportSystemError(errcode, - _("Cannot access backing file '%s' " - "of storage file '%s' (as uid:%u, gid:%= u)"), - src->path, parent->path, access_user, acc= ess_group); - } - } else { - if (src =3D=3D parent) { - virReportSystemError(errcode, - _("Cannot access storage file '%s'"), - src->path); - } else { - virReportSystemError(errcode, - _("Cannot access backing file '%s' " - "of storage file '%s'"), - src->path, parent->path); - } - } -} - - -static int -virStorageFileGetMetadataRecurseReadHeader(virStorageSourcePtr src, - virStorageSourcePtr parent, - uid_t uid, - gid_t gid, - char **buf, - size_t *headerLen, - GHashTable *cycle) -{ - int ret =3D -1; - const char *uniqueName; - ssize_t len; - - if (virStorageFileInitAs(src, uid, gid) < 0) - return -1; - - if (virStorageFileAccess(src, F_OK) < 0) { - virStorageFileReportBrokenChain(errno, src, parent); - goto cleanup; - } - - if (!(uniqueName =3D virStorageFileGetUniqueIdentifier(src))) - goto cleanup; - - if (virHashHasEntry(cycle, uniqueName)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("backing store for %s (%s) is self-referential"), - NULLSTR(src->path), uniqueName); - goto cleanup; - } - - if (virHashAddEntry(cycle, uniqueName, NULL) < 0) - goto cleanup; - - if ((len =3D virStorageFileRead(src, 0, VIR_STORAGE_MAX_HEADER, buf)) = < 0) - goto cleanup; - - *headerLen =3D len; - ret =3D 0; - - cleanup: - virStorageFileDeinit(src); - return ret; -} - - -/* Recursive workhorse for virStorageFileGetMetadata. */ -static int -virStorageFileGetMetadataRecurse(virStorageSourcePtr src, - virStorageSourcePtr parent, - uid_t uid, gid_t gid, - bool report_broken, - GHashTable *cycle, - unsigned int depth) -{ - virStorageFileFormat orig_format =3D src->format; - size_t headerLen; - int rv; - g_autofree char *buf =3D NULL; - g_autoptr(virStorageSource) backingStore =3D NULL; - - VIR_DEBUG("path=3D%s format=3D%d uid=3D%u gid=3D%u", - NULLSTR(src->path), src->format, - (unsigned int)uid, (unsigned int)gid); - - if (src->format =3D=3D VIR_STORAGE_FILE_AUTO_SAFE) - src->format =3D VIR_STORAGE_FILE_AUTO; - - /* exit if we can't load information about the current image */ - rv =3D virStorageFileSupportsBackingChainTraversal(src); - if (rv <=3D 0) { - if (orig_format =3D=3D VIR_STORAGE_FILE_AUTO) - return -2; - - return rv; - } - - if (virStorageFileGetMetadataRecurseReadHeader(src, parent, uid, gid, - &buf, &headerLen, cycle= ) < 0) - return -1; - - if (virStorageFileGetMetadataInternal(src, buf, headerLen) < 0) - return -1; - - /* If we probed the format we MUST ensure that nothing else than the c= urrent - * image is considered for security labelling and/or recursion. */ - if (orig_format =3D=3D VIR_STORAGE_FILE_AUTO) { - if (src->backingStoreRaw) { - src->format =3D VIR_STORAGE_FILE_RAW; - VIR_FREE(src->backingStoreRaw); - return -2; - } - } - - if (src->backingStoreRaw) { - if ((rv =3D virStorageSourceNewFromBacking(src, &backingStore)) < = 0) - return -1; - - /* the backing file would not be usable for VM usage */ - if (rv =3D=3D 1) - return 0; - - if ((rv =3D virStorageFileGetMetadataRecurse(backingStore, parent, - uid, gid, - report_broken, - cycle, depth + 1)) < 0)= { - if (!report_broken) - return 0; - - if (rv =3D=3D -2) { - virReportError(VIR_ERR_OPERATION_INVALID, - _("format of backing image '%s' of image '%= s' was not specified in the image metadata " - "(See https://libvirt.org/kbase/backing_c= hains.html for troubleshooting)"), - src->backingStoreRaw, NULLSTR(src->path)); - } - - return -1; - } - - backingStore->id =3D depth; - src->backingStore =3D g_steal_pointer(&backingStore); - } else { - /* add terminator */ - src->backingStore =3D virStorageSourceNew(); - } - - return 0; -} - - -/** - * virStorageFileGetMetadata: - * - * Extract metadata about the storage volume with the specified - * image format. If image format is VIR_STORAGE_FILE_AUTO, it - * will probe to automatically identify the format. Recurses through - * the entire chain. - * - * Open files using UID and GID (or pass -1 for the current user/group). - * Treat any backing files without explicit type as raw, unless ALLOW_PROB= E. - * - * Callers are advised never to use VIR_STORAGE_FILE_AUTO as a - * format, since a malicious guest can turn a raw file into any - * other non-raw format at will. - * - * If @report_broken is true, the whole function fails with a possibly sane - * error instead of just returning a broken chain. Note that the inability= for - * libvirt to traverse a given source is not considered an error. - * - * Caller MUST free result after use via virObjectUnref. - */ -int -virStorageFileGetMetadata(virStorageSourcePtr src, - uid_t uid, gid_t gid, - bool report_broken) -{ - GHashTable *cycle =3D NULL; - virStorageType actualType =3D virStorageSourceGetActualType(src); - int ret =3D -1; - - VIR_DEBUG("path=3D%s format=3D%d uid=3D%u gid=3D%u report_broken=3D%d", - src->path, src->format, (unsigned int)uid, (unsigned int)gid, - report_broken); - - if (!(cycle =3D virHashNew(NULL))) - return -1; - - if (src->format <=3D VIR_STORAGE_FILE_NONE) { - if (actualType =3D=3D VIR_STORAGE_TYPE_DIR) - src->format =3D VIR_STORAGE_FILE_DIR; - else - src->format =3D VIR_STORAGE_FILE_RAW; - } - - ret =3D virStorageFileGetMetadataRecurse(src, src, uid, gid, - report_broken, cycle, 1); - - virHashFree(cycle); - return ret; -} - - -/** - * virStorageFileGetBackingStoreStr: - * @src: storage object - * - * Extracts the backing store string as stored in the storage volume descr= ibed - * by @src and returns it to the user. Caller is responsible for freeing i= t. - * In case when the string can't be retrieved or does not exist NULL is - * returned. - */ -int -virStorageFileGetBackingStoreStr(virStorageSourcePtr src, - char **backing) -{ - ssize_t headerLen; - int rv; - g_autofree char *buf =3D NULL; - g_autoptr(virStorageSource) tmp =3D NULL; - - *backing =3D NULL; - - /* exit if we can't load information about the current image */ - if (!virStorageFileSupportsBackingChainTraversal(src)) - return 0; - - rv =3D virStorageFileAccess(src, F_OK); - if (rv =3D=3D -2) - return 0; - if (rv < 0) { - virStorageFileReportBrokenChain(errno, src, src); - return -1; - } - - if ((headerLen =3D virStorageFileRead(src, 0, VIR_STORAGE_MAX_HEADER, - &buf)) < 0) { - if (headerLen =3D=3D -2) - return 0; - return -1; - } - - if (!(tmp =3D virStorageSourceCopy(src, false))) - return -1; - - if (virStorageFileGetMetadataInternal(tmp, buf, headerLen) < 0) - return -1; - - *backing =3D g_steal_pointer(&tmp->backingStoreRaw); - return 0; -} diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h index a1e0afb28f..557e7da81e 100644 --- a/src/util/virstoragefile.h +++ b/src/util/virstoragefile.h @@ -21,8 +21,6 @@ =20 #pragma once =20 -#include - #include "virbitmap.h" #include "virobject.h" #include "virseclabel.h" @@ -31,14 +29,6 @@ #include "virenum.h" #include "virpci.h" =20 -/* Minimum header size required to probe all known formats with - * virStorageFileProbeFormat, or obtain metadata from a known format. - * Rounded to multiple of 512 (ISO has a 5-byte magic at offset - * 32769). Some formats can be probed with fewer bytes. Although - * some formats theoretically permit metadata that can rely on offsets - * beyond this size, in practice that doesn't matter. */ -#define VIR_STORAGE_MAX_HEADER 0x8200 - =20 /* Types of disk backends (host resource). Comparable to the public * virStorageVolType, except we have an undetermined state, don't have @@ -386,37 +376,6 @@ struct _virStorageSource { G_DEFINE_AUTOPTR_CLEANUP_FUNC(virStorageSource, virObjectUnref); =20 =20 -#ifndef DEV_BSIZE -# define DEV_BSIZE 512 -#endif - -int virStorageFileProbeFormat(const char *path, uid_t uid, gid_t gid); - -virStorageSourcePtr virStorageFileGetMetadataFromFD(const char *path, - int fd, - int format); -virStorageSourcePtr virStorageFileGetMetadataFromBuf(const char *path, - char *buf, - size_t len, - int format) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); -int virStorageFileParseChainIndex(const char *diskTarget, - const char *name, - unsigned int *chainIndex) - ATTRIBUTE_NONNULL(3); - -int virStorageFileParseBackingStoreStr(const char *str, - char **target, - unsigned int *chainIndex) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3); - -virStorageSourcePtr virStorageFileChainLookup(virStorageSourcePtr chain, - virStorageSourcePtr startFro= m, - const char *name, - unsigned int idx, - virStorageSourcePtr *parent) - ATTRIBUTE_NONNULL(1); - int virStorageFileGetSCSIKey(const char *path, char **key, bool ignoreError); @@ -454,7 +413,6 @@ void virStorageNetHostDefClear(virStorageNetHostDefPtr = def); void virStorageNetHostDefFree(size_t nhosts, virStorageNetHostDefPtr hosts= ); virStorageNetHostDefPtr virStorageNetHostDefCopy(size_t nhosts, virStorageNetHostDefPtr h= osts); - int virStorageSourceInitChainElement(virStorageSourcePtr newelem, virStorageSourcePtr old, bool force); @@ -466,15 +424,6 @@ bool virStorageSourceIsEmpty(virStorageSourcePtr src); bool virStorageSourceIsBlockLocal(const virStorageSource *src); virStorageSourcePtr virStorageSourceNew(void); void virStorageSourceBackingStoreClear(virStorageSourcePtr def); -int virStorageSourceUpdatePhysicalSize(virStorageSourcePtr src, - int fd, struct stat const *sb); -int virStorageSourceUpdateBackingSizes(virStorageSourcePtr src, - int fd, struct stat const *sb); -int virStorageSourceUpdateCapacity(virStorageSourcePtr src, - char *buf, ssize_t len); - -int virStorageSourceNewFromBacking(virStorageSourcePtr parent, - virStorageSourcePtr *backing); =20 int virStorageSourceNetCookiesValidate(virStorageSourcePtr src); =20 @@ -485,33 +434,8 @@ bool virStorageSourceIsSameLocation(virStorageSourcePt= r a, virStorageSourcePtr b) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); =20 -int virStorageSourceParseRBDColonString(const char *rbdstr, - virStorageSourcePtr src) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); - -typedef int -(*virStorageFileSimplifyPathReadlinkCallback)(const char *path, - char **link, - void *data); -char *virStorageFileCanonicalizePath(const char *path, - virStorageFileSimplifyPathReadlinkCal= lback cb, - void *cbdata); - -int virStorageFileGetRelativeBackingPath(virStorageSourcePtr from, - virStorageSourcePtr to, - char **relpath) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); - -int virStorageSourceNewFromBackingAbsolute(const char *path, - virStorageSourcePtr *src); - bool virStorageSourceIsRelative(virStorageSourcePtr src); =20 -virStorageSourcePtr -virStorageSourceFindByNodeName(virStorageSourcePtr top, - const char *nodeName) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); - void virStorageSourceNetworkAssignDefaultPorts(virStorageSourcePtr src) ATTRIBUTE_NONNULL(1); @@ -522,13 +446,6 @@ bool virStorageSourceHasBacking(const virStorageSource *src); =20 =20 -int -virStorageSourcePrivateDataParseRelPath(xmlXPathContextPtr ctxt, - virStorageSourcePtr src); -int -virStorageSourcePrivateDataFormatRelPath(virStorageSourcePtr src, - virBufferPtr buf); - void virStorageSourceInitiatorParseXML(xmlXPathContextPtr ctxt, virStorageSourceInitiatorDefPtr initiato= r); @@ -544,39 +461,4 @@ virStorageSourceInitiatorCopy(virStorageSourceInitiato= rDefPtr dest, void virStorageSourceInitiatorClear(virStorageSourceInitiatorDefPtr initiator); =20 -int virStorageFileInit(virStorageSourcePtr src); -int virStorageFileInitAs(virStorageSourcePtr src, - uid_t uid, gid_t gid); -void virStorageFileDeinit(virStorageSourcePtr src); - -int virStorageFileCreate(virStorageSourcePtr src); -int virStorageFileUnlink(virStorageSourcePtr src); -int virStorageFileStat(virStorageSourcePtr src, - struct stat *stat); -ssize_t virStorageFileRead(virStorageSourcePtr src, - size_t offset, - size_t len, - char **buf); -const char *virStorageFileGetUniqueIdentifier(virStorageSourcePtr src); -int virStorageFileAccess(virStorageSourcePtr src, int mode); -int virStorageFileChown(const virStorageSource *src, uid_t uid, gid_t gid); - -int virStorageFileSupportsSecurityDriver(const virStorageSource *src); -int virStorageFileSupportsAccess(const virStorageSource *src); -int virStorageFileSupportsCreate(const virStorageSource *src); -int virStorageFileSupportsBackingChainTraversal(const virStorageSource *sr= c); - -int virStorageFileGetMetadata(virStorageSourcePtr src, - uid_t uid, gid_t gid, - bool report_broken) - ATTRIBUTE_NONNULL(1); - -int virStorageFileGetBackingStoreStr(virStorageSourcePtr src, - char **backing) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); - -void virStorageFileReportBrokenChain(int errcode, - virStorageSourcePtr src, - virStorageSourcePtr parent); - G_DEFINE_AUTOPTR_CLEANUP_FUNC(virStorageAuthDef, virStorageAuthDefFree); diff --git a/tests/meson.build b/tests/meson.build index f1d91ca50d..ce5b625b43 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -442,7 +442,7 @@ endif if conf.has('WITH_QEMU') tests +=3D [ { 'name': 'qemuagenttest', 'link_with': [ test_qemu_driver_lib, test_u= tils_qemu_monitor_lib ], 'link_whole': [ test_utils_qemu_lib ] }, - { 'name': 'qemublocktest', 'link_with': [ test_qemu_driver_lib, test_u= tils_qemu_monitor_lib ], 'link_whole': [ test_utils_qemu_lib ] }, + { 'name': 'qemublocktest', 'include': [ storage_file_inc_dir ], 'link_= with': [ test_qemu_driver_lib, test_utils_qemu_monitor_lib ], 'link_whole':= [ test_utils_qemu_lib ] }, { 'name': 'qemucapabilitiestest', 'link_with': [ test_qemu_driver_lib,= test_utils_qemu_monitor_lib ], 'link_whole': [ test_utils_qemu_lib ] }, { 'name': 'qemucaps2xmltest', 'link_with': [ test_qemu_driver_lib ], '= link_whole': [ test_utils_qemu_lib ] }, { 'name': 'qemucommandutiltest', 'link_with': [ test_qemu_driver_lib, = test_utils_qemu_monitor_lib ], 'link_whole': [ test_utils_qemu_lib ] }, @@ -509,7 +509,7 @@ endif =20 if conf.has('WITH_STORAGE_FS') tests +=3D [ - { 'name': 'virstoragetest', 'link_with': [ storage_driver_impl_lib ] }, + { 'name': 'virstoragetest', 'include': [ storage_file_inc_dir ], 'link= _with': [ storage_driver_impl_lib ] }, ] endif =20 diff --git a/tests/qemublocktest.c b/tests/qemublocktest.c index f86e9fd552..ee57449868 100644 --- a/tests/qemublocktest.c +++ b/tests/qemublocktest.c @@ -21,6 +21,7 @@ #include "testutilsqemu.h" #include "testutilsqemuschema.h" #include "virstoragefile.h" +#include "storage_file.h" #include "virstring.h" #include "virlog.h" #include "qemu/qemu_block.h" diff --git a/tests/virstoragetest.c b/tests/virstoragetest.c index a376154def..59c03255d4 100644 --- a/tests/virstoragetest.c +++ b/tests/virstoragetest.c @@ -20,6 +20,7 @@ =20 #include =20 +#include "storage_file.h" #include "testutils.h" #include "vircommand.h" #include "virerror.h" --=20 2.28.0 From nobody Thu May 16 01:02:08 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 63.128.21.124 as permitted sender) client-ip=63.128.21.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 63.128.21.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1607961394; cv=none; d=zohomail.com; s=zohoarc; b=PE4K3DffFXSal4S6fu/XC/wCzp5EPWg3GbTNCW7lg7Q2IrJG1Pbhj4gE+qjeUyOtd/NkQITMuVvIXLyIaYzM2X4ZsbnbIPP93h8V5v6JMkLoU47LDp9tG9hMgLLBKcsqvPmGAH+9fSWT1WESwyeRMpttsQT1AHYGISBRBwNqn2c= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1607961394; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=DteIZ/91v/K7Dr1Bf3OgkmgD6XfB9gMb7EF8zW8BJls=; b=GnFM2tVMpHnFy4NLVTdgxmL647OzezFFor4v9NLK9xcmBXeo8rzS+MkaproAZjDaCIYKhr7jd6pGx8k6DJGv5dLybpLZcvopd5PZdS1YMn9b7549soTYISZwfFGCrLoTtVdxyPIJU6aGc4WUf9ZCuGmwxShKWmaw2KH/aFosyw0= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 63.128.21.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [63.128.21.124]) by mx.zohomail.com with SMTPS id 1607961394886511.32726463946756; Mon, 14 Dec 2020 07:56:34 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-386-XggrzdiNP3qwW4YdhQR65g-1; Mon, 14 Dec 2020 10:56:31 -0500 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 96C67800D53; Mon, 14 Dec 2020 15:56:25 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 6DA5762680; Mon, 14 Dec 2020 15:56:25 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 351D54A7C6; Mon, 14 Dec 2020 15:56:25 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 0BEFtuQq028642 for ; Mon, 14 Dec 2020 10:55:56 -0500 Received: by smtp.corp.redhat.com (Postfix) id 972AD5D6D5; Mon, 14 Dec 2020 15:55:56 +0000 (UTC) Received: from antique-work.lan (unknown [10.40.194.243]) by smtp.corp.redhat.com (Postfix) with ESMTP id 11EE317B77 for ; Mon, 14 Dec 2020 15:55:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1607961393; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=DteIZ/91v/K7Dr1Bf3OgkmgD6XfB9gMb7EF8zW8BJls=; b=Iw6J9RnHZdh8BNpLqR35+01Y1q0ayj/nwgghwrrk/ZCqpBkNDl4QwxBB2YcgIiuMMddiGX T/W/xckztLUmsVBwI0JPuVkcDQe/c8N7qOzecKRPxXpjrQvB0MjSijqFU1dYGJBld1HXtt zfQtz+0kpIc65QQYbHlrVkIOozRjFPQ= X-MC-Unique: XggrzdiNP3qwW4YdhQR65g-1 From: Pavel Hrdina To: libvir-list@redhat.com Subject: [libvirt PATCH 14/17] util: move virStorageFileBackend code into storage_file Date: Mon, 14 Dec 2020 16:55:34 +0100 Message-Id: <90a501b4f1de99c6e7fff4adf05b2ca8f41df433.1607960951.git.phrdina@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-loop: libvir-list@redhat.com X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=libvir-list-bounces@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" It's used only by storage file code so it doesn't make sense to have it in util directory. Signed-off-by: Pavel Hrdina --- po/POTFILES.in | 2 +- src/libvirt_private.syms | 8 ++++---- src/storage_file/meson.build | 3 ++- src/storage_file/storage_file.c | 2 +- .../storage_file_backend.c} | 4 ++-- .../storage_file_backend.h} | 2 +- src/storage_file/storage_file_fs.c | 2 +- src/storage_file/storage_file_gluster.c | 2 +- src/util/meson.build | 1 - 9 files changed, 13 insertions(+), 13 deletions(-) rename src/{util/virstoragefilebackend.c =3D> storage_file/storage_file_ba= ckend.c} (97%) rename src/{util/virstoragefilebackend.h =3D> storage_file/storage_file_ba= ckend.h} (97%) diff --git a/po/POTFILES.in b/po/POTFILES.in index 6d6678bd36..d3a0f85d91 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -224,6 +224,7 @@ @SRCDIR@src/storage/storage_driver.c @SRCDIR@src/storage/storage_util.c @SRCDIR@src/storage_file/storage_file.c +@SRCDIR@src/storage_file/storage_file_backend.c @SRCDIR@src/storage_file/storage_file_fs.c @SRCDIR@src/storage_file/storage_file_gluster.c @SRCDIR@src/test/test_driver.c @@ -306,7 +307,6 @@ @SRCDIR@src/util/virsocketaddr.c @SRCDIR@src/util/virstorageencryption.c @SRCDIR@src/util/virstoragefile.c -@SRCDIR@src/util/virstoragefilebackend.c @SRCDIR@src/util/virstring.c @SRCDIR@src/util/virsysinfo.c @SRCDIR@src/util/virsystemd.c diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 43be8dd61a..fe6683f728 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1655,6 +1655,10 @@ virStorageSourceUpdateCapacity; virStorageSourceUpdatePhysicalSize; =20 =20 +# storage_file/storage_file_backend.h +virStorageFileBackendRegister; + + # util/glibcompat.h vir_g_canonicalize_filename; vir_g_fsync; @@ -3211,10 +3215,6 @@ virStorageTypeFromString; virStorageTypeToString; =20 =20 -# util/virstoragefilebackend.h -virStorageFileBackendRegister; - - # util/virstring.h virSkipSpaces; virSkipSpacesAndBackslash; diff --git a/src/storage_file/meson.build b/src/storage_file/meson.build index b25ca63b40..4d85d16929 100644 --- a/src/storage_file/meson.build +++ b/src/storage_file/meson.build @@ -1,5 +1,6 @@ storage_file_sources =3D [ - 'storage_file.c' + 'storage_file.c', + 'storage_file_backend.c', ] =20 stoarge_file_fs_sources =3D [ diff --git a/src/storage_file/storage_file.c b/src/storage_file/storage_fil= e.c index 6bfeb26233..e5b2f68420 100644 --- a/src/storage_file/storage_file.c +++ b/src/storage_file/storage_file.c @@ -25,13 +25,13 @@ #include =20 #include "storage_file.h" +#include "storage_file_backend.h" #include "viralloc.h" #include "virendian.h" #include "virfile.h" #include "virhash.h" #include "virjson.h" #include "virlog.h" -#include "virstoragefilebackend.h" #include "virstring.h" #include "viruri.h" =20 diff --git a/src/util/virstoragefilebackend.c b/src/storage_file/storage_fi= le_backend.c similarity index 97% rename from src/util/virstoragefilebackend.c rename to src/storage_file/storage_file_backend.c index 55c62b0212..6e4b2f408b 100644 --- a/src/util/virstoragefilebackend.c +++ b/src/storage_file/storage_file_backend.c @@ -1,5 +1,5 @@ /* - * virstoragefilebackend.c: internal storage source backend contract + * storage_file_backend.c: internal storage source backend contract * * Copyright (C) 2007-2018 Red Hat, Inc. * Copyright (C) 2007-2008 Daniel P. Berrange @@ -27,7 +27,7 @@ #include "virerror.h" #include "viralloc.h" #include "internal.h" -#include "virstoragefilebackend.h" +#include "storage_file_backend.h" #include "virlog.h" #include "virmodule.h" #include "virfile.h" diff --git a/src/util/virstoragefilebackend.h b/src/storage_file/storage_fi= le_backend.h similarity index 97% rename from src/util/virstoragefilebackend.h rename to src/storage_file/storage_file_backend.h index 43b36e95bc..ad0f66212c 100644 --- a/src/util/virstoragefilebackend.h +++ b/src/storage_file/storage_file_backend.h @@ -1,5 +1,5 @@ /* - * virstoragefilebackend.h: internal storage source backend contract + * storage_file_backend.h: internal storage source backend contract * * Copyright (C) 2007-2018 Red Hat, Inc. * diff --git a/src/storage_file/storage_file_fs.c b/src/storage_file/storage_= file_fs.c index 5a44ef8c2d..1cc9233512 100644 --- a/src/storage_file/storage_file_fs.c +++ b/src/storage_file/storage_file_fs.c @@ -25,9 +25,9 @@ #include =20 #include "virerror.h" +#include "storage_file_backend.h" #include "storage_file_fs.h" #include "storage_util.h" -#include "virstoragefilebackend.h" #include "vircommand.h" #include "viralloc.h" #include "virfile.h" diff --git a/src/storage_file/storage_file_gluster.c b/src/storage_file/sto= rage_file_gluster.c index 599afada2c..786b39b6de 100644 --- a/src/storage_file/storage_file_gluster.c +++ b/src/storage_file/storage_file_gluster.c @@ -24,11 +24,11 @@ #include =20 #include "storage_file.h" +#include "storage_file_backend.h" #include "storage_file_gluster.h" #include "viralloc.h" #include "virerror.h" #include "virlog.h" -#include "virstoragefilebackend.h" #include "virstring.h" =20 #define VIR_FROM_THIS VIR_FROM_STORAGE diff --git a/src/util/meson.build b/src/util/meson.build index 395e70fd38..b510f0ebe9 100644 --- a/src/util/meson.build +++ b/src/util/meson.build @@ -90,7 +90,6 @@ util_sources =3D [ 'virsocketaddr.c', 'virstorageencryption.c', 'virstoragefile.c', - 'virstoragefilebackend.c', 'virstring.c', 'virsysinfo.c', 'virsystemd.c', --=20 2.28.0 From nobody Thu May 16 01:02:08 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) client-ip=216.205.24.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1607961444; cv=none; d=zohomail.com; s=zohoarc; b=mdVBD9+xtUWJ5i0RftLvwwWGuZEBE7ftV2lU97kj8PARyxk53JTl5ZgowbSS/EOaE3YrGP0qDh8vMgdOVwmfpjeqReHtUwGK8B9ej4NAHnqh2CeUYnUug9W4/vacViX9MfVIYYeWyMmgcHbiqVuc5nxhv9PCNsz1TbD/1NcsFaQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1607961444; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=Rx6zhLcD1h7BlzQUcnx0CJ0QZk9ksi1Ns5AXBQOGI6o=; b=Ted3IAV030hTrYH5WNwTMJp4l3zscdlIEE+gPQTYC/Rw2N78YZkROWwMX7hQoyawT0LBO9T+WvVeT1LUlAhX9SWk8Cyz4utSw1lCZUJA14Ds1oDeIqLVeHzi0yViqSBctcIioBMVlIJdePPRQALFp7ySyoFkYRFmcnw4S6JAhwQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by mx.zohomail.com with SMTPS id 16079614418341022.2092738744254; Mon, 14 Dec 2020 07:57:21 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-517-WJ_UvI2-NK-XFQestURsbA-1; Mon, 14 Dec 2020 10:56:21 -0500 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 9F8491075649; Mon, 14 Dec 2020 15:56:07 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 6F9A22BCEC; Mon, 14 Dec 2020 15:56:07 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 3616D5002D; Mon, 14 Dec 2020 15:56:07 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 0BEFtv0Y028648 for ; Mon, 14 Dec 2020 10:55:57 -0500 Received: by smtp.corp.redhat.com (Postfix) id 8077017B77; Mon, 14 Dec 2020 15:55:57 +0000 (UTC) Received: from antique-work.lan (unknown [10.40.194.243]) by smtp.corp.redhat.com (Postfix) with ESMTP id EDCED5D6D5 for ; Mon, 14 Dec 2020 15:55:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1607961439; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=Rx6zhLcD1h7BlzQUcnx0CJ0QZk9ksi1Ns5AXBQOGI6o=; b=aBq2+Dhpjf5OU0dKMfelczwyZ34e4NAO8PMusUNtJJQq6pUz6v3pj7mOzAuEyvAl0VJDMG ifaJEAozCmm2bpWhDKonNhSdF+PzKfNMvuodquVjKjRF1p7TDCiQHHfEaj/462cvytmrVQ kF2mHY4yDlLzmyRkOEGtGqFUdPS+iX4= X-MC-Unique: WJ_UvI2-NK-XFQestURsbA-1 From: Pavel Hrdina To: libvir-list@redhat.com Subject: [libvirt PATCH 15/17] util: move virStorageSource code into conf Date: Mon, 14 Dec 2020 16:55:35 +0100 Message-Id: <534dc0b61db00a06decf68063ade7ebcdb714267.1607960951.git.phrdina@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-loop: libvir-list@redhat.com X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=libvir-list-bounces@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" The code handles XML bits and internal definition and should be in conf directory. Signed-off-by: Pavel Hrdina --- po/POTFILES.in | 1 + src/conf/backup_conf.c | 2 +- src/conf/checkpoint_conf.c | 2 +- src/conf/domain_conf.c | 2 +- src/conf/domain_conf.h | 4 +- src/conf/meson.build | 1 + src/conf/snapshot_conf.c | 2 +- src/conf/storage_conf.c | 2 +- src/conf/storage_conf.h | 2 +- src/conf/storage_source.c | 1316 +++++++++++++++++++++++ src/conf/storage_source.h | 518 +++++++++ src/esx/esx_storage_backend_iscsi.c | 2 +- src/esx/esx_storage_backend_vmfs.c | 2 +- src/libvirt_private.syms | 97 +- src/locking/lock_driver_lockd.c | 1 + src/qemu/qemu_backup.c | 2 +- src/qemu/qemu_blockjob.c | 2 +- src/qemu/qemu_command.c | 2 +- src/qemu/qemu_domain.c | 2 +- src/qemu/qemu_driver.c | 2 +- src/qemu/qemu_hotplug.c | 2 +- src/qemu/qemu_migration.c | 2 +- src/qemu/qemu_process.h | 2 +- src/storage/storage_backend.c | 2 +- src/storage/storage_util.c | 1 + src/storage_file/meson.build | 3 + src/storage_file/storage_file.h | 2 +- src/storage_file/storage_file_backend.h | 2 +- src/util/virstoragefile.c | 1281 ---------------------- src/util/virstoragefile.h | 436 +------- 30 files changed, 1913 insertions(+), 1784 deletions(-) create mode 100644 src/conf/storage_source.c create mode 100644 src/conf/storage_source.h diff --git a/po/POTFILES.in b/po/POTFILES.in index d3a0f85d91..135198820a 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -43,6 +43,7 @@ @SRCDIR@src/conf/snapshot_conf.c @SRCDIR@src/conf/storage_adapter_conf.c @SRCDIR@src/conf/storage_conf.c +@SRCDIR@src/conf/storage_source.c @SRCDIR@src/conf/virchrdev.c @SRCDIR@src/conf/virdomainmomentobjlist.c @SRCDIR@src/conf/virdomainobjlist.c diff --git a/src/conf/backup_conf.c b/src/conf/backup_conf.c index 90ffcc51d1..7d4c466a9e 100644 --- a/src/conf/backup_conf.c +++ b/src/conf/backup_conf.c @@ -26,7 +26,7 @@ #include "virlog.h" #include "viralloc.h" #include "backup_conf.h" -#include "virstoragefile.h" +#include "storage_source.h" #include "virfile.h" #include "virerror.h" #include "virxml.h" diff --git a/src/conf/checkpoint_conf.c b/src/conf/checkpoint_conf.c index 7edc7daa12..7b8e53ca75 100644 --- a/src/conf/checkpoint_conf.c +++ b/src/conf/checkpoint_conf.c @@ -30,7 +30,7 @@ #include "virlog.h" #include "viralloc.h" #include "checkpoint_conf.h" -#include "virstoragefile.h" +#include "storage_source.h" #include "viruuid.h" #include "virfile.h" #include "virerror.h" diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 26c48ef38c..e1fc61073e 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -43,7 +43,7 @@ #include "nwfilter_conf.h" #include "virnetworkportdef.h" #include "storage_conf.h" -#include "virstoragefile.h" +#include "storage_source.h" #include "virfile.h" #include "virbitmap.h" #include "secret_conf.h" diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index ce8ed48a04..5c95317501 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -48,7 +48,7 @@ #include "virobject.h" #include "device_conf.h" #include "virbitmap.h" -#include "virstoragefile.h" +#include "storage_source.h" #include "virseclabel.h" #include "virprocess.h" #include "virgic.h" @@ -359,7 +359,7 @@ struct _virDomainHostdevDef { =20 =20 /* Types of disk frontend (guest view). For backends (host view), see - * virStorageType in util/virstoragefile.h */ + * virStorageType in util/storage_source.h */ typedef enum { VIR_DOMAIN_DISK_DEVICE_DISK, VIR_DOMAIN_DISK_DEVICE_CDROM, diff --git a/src/conf/meson.build b/src/conf/meson.build index 8ddcc9968d..12efaf56cc 100644 --- a/src/conf/meson.build +++ b/src/conf/meson.build @@ -54,6 +54,7 @@ storage_conf_sources =3D [ 'storage_adapter_conf.c', 'storage_capabilities.c', 'storage_conf.c', + 'storage_source.c', 'virstorageobj.c', ] =20 diff --git a/src/conf/snapshot_conf.c b/src/conf/snapshot_conf.c index f896fd1cf2..2abb14b4f6 100644 --- a/src/conf/snapshot_conf.c +++ b/src/conf/snapshot_conf.c @@ -38,7 +38,7 @@ #include "nwfilter_conf.h" #include "secret_conf.h" #include "snapshot_conf.h" -#include "virstoragefile.h" +#include "storage_source.h" #include "viruuid.h" #include "virfile.h" #include "virerror.h" diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c index 0c50529ace..fa11d965cd 100644 --- a/src/conf/storage_conf.c +++ b/src/conf/storage_conf.c @@ -31,7 +31,7 @@ #include "node_device_conf.h" #include "storage_adapter_conf.h" #include "storage_conf.h" -#include "virstoragefile.h" +#include "storage_source.h" =20 #include "virxml.h" #include "viruuid.h" diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h index ffd406e093..47f2bf602d 100644 --- a/src/conf/storage_conf.h +++ b/src/conf/storage_conf.h @@ -23,7 +23,7 @@ =20 #include "internal.h" #include "virstorageencryption.h" -#include "virstoragefile.h" +#include "storage_source.h" #include "virbitmap.h" #include "virthread.h" #include "device_conf.h" diff --git a/src/conf/storage_source.c b/src/conf/storage_source.c new file mode 100644 index 0000000000..271dbc06c0 --- /dev/null +++ b/src/conf/storage_source.c @@ -0,0 +1,1316 @@ +/* + * storage_source.c: file utility functions for FS storage backend + * + * Copyright (C) 2007-2017 Red Hat, Inc. + * 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 + * License along with this library. If not, see + * . + */ + +#include + +#include "storage_source.h" + +#include "viralloc.h" +#include "virbuffer.h" +#include "virerror.h" +#include "virlog.h" +#include "virstring.h" + +#define VIR_FROM_THIS VIR_FROM_STORAGE + +VIR_LOG_INIT("conf.storage_source"); + + +static virClassPtr virStorageSourceClass; + + +VIR_ENUM_IMPL(virStorage, + VIR_STORAGE_TYPE_LAST, + "none", + "file", + "block", + "dir", + "network", + "volume", + "nvme", +); + + +VIR_ENUM_IMPL(virStorageFileFormat, + VIR_STORAGE_FILE_LAST, + "none", + "raw", "dir", "bochs", + "cloop", "dmg", "iso", + "vpc", "vdi", + /* Not direct file formats, but used for various drivers */ + "fat", "vhd", "ploop", + /* Formats with backing file below here */ + "cow", "qcow", "qcow2", "qed", "vmdk", +); + + +VIR_ENUM_IMPL(virStorageFileFeature, + VIR_STORAGE_FILE_FEATURE_LAST, + "lazy_refcounts", +); + + +VIR_ENUM_IMPL(virStorageNetProtocol, + VIR_STORAGE_NET_PROTOCOL_LAST, + "none", + "nbd", + "rbd", + "sheepdog", + "gluster", + "iscsi", + "http", + "https", + "ftp", + "ftps", + "tftp", + "ssh", + "vxhs", +); + + +VIR_ENUM_IMPL(virStorageNetHostTransport, + VIR_STORAGE_NET_HOST_TRANS_LAST, + "tcp", + "unix", + "rdma", +); + + +VIR_ENUM_IMPL(virStorageSourcePoolMode, + VIR_STORAGE_SOURCE_POOL_MODE_LAST, + "default", + "host", + "direct", +); + + +VIR_ENUM_IMPL(virStorageAuth, + VIR_STORAGE_AUTH_TYPE_LAST, + "none", "chap", "ceph", +); + + +/** + * virStorageSourceIsBacking: + * @src: storage source + * + * Returns true if @src is a eligible backing store structure. Useful + * for iterators. + */ +bool +virStorageSourceIsBacking(const virStorageSource *src) +{ + return src && src->type !=3D VIR_STORAGE_TYPE_NONE; +} + +/** + * virStorageSourceHasBacking: + * @src: storage source + * + * Returns true if @src has backing store/chain. + */ +bool +virStorageSourceHasBacking(const virStorageSource *src) +{ + return virStorageSourceIsBacking(src) && src->backingStore && + src->backingStore->type !=3D VIR_STORAGE_TYPE_NONE; +} + + +void +virStorageNetHostDefClear(virStorageNetHostDefPtr def) +{ + if (!def) + return; + + VIR_FREE(def->name); + VIR_FREE(def->socket); +} + + +void +virStorageNetHostDefFree(size_t nhosts, + virStorageNetHostDefPtr hosts) +{ + size_t i; + + if (!hosts) + return; + + for (i =3D 0; i < nhosts; i++) + virStorageNetHostDefClear(&hosts[i]); + + VIR_FREE(hosts); +} + + +static void +virStoragePermsFree(virStoragePermsPtr def) +{ + if (!def) + return; + + VIR_FREE(def->label); + VIR_FREE(def); +} + + +virStorageNetHostDefPtr +virStorageNetHostDefCopy(size_t nhosts, + virStorageNetHostDefPtr hosts) +{ + virStorageNetHostDefPtr ret =3D NULL; + size_t i; + + ret =3D g_new0(virStorageNetHostDef, nhosts); + + for (i =3D 0; i < nhosts; i++) { + virStorageNetHostDefPtr src =3D &hosts[i]; + virStorageNetHostDefPtr dst =3D &ret[i]; + + dst->transport =3D src->transport; + dst->port =3D src->port; + + dst->name =3D g_strdup(src->name); + dst->socket =3D g_strdup(src->socket); + } + + return ret; +} + + +void +virStorageAuthDefFree(virStorageAuthDefPtr authdef) +{ + if (!authdef) + return; + + VIR_FREE(authdef->username); + VIR_FREE(authdef->secrettype); + virSecretLookupDefClear(&authdef->seclookupdef); + VIR_FREE(authdef); +} + + +virStorageAuthDefPtr +virStorageAuthDefCopy(const virStorageAuthDef *src) +{ + g_autoptr(virStorageAuthDef) authdef =3D NULL; + + authdef =3D g_new0(virStorageAuthDef, 1); + + authdef->username =3D g_strdup(src->username); + /* Not present for storage pool, but used for disk source */ + authdef->secrettype =3D g_strdup(src->secrettype); + authdef->authType =3D src->authType; + + virSecretLookupDefCopy(&authdef->seclookupdef, &src->seclookupdef); + + return g_steal_pointer(&authdef); +} + + +virStorageAuthDefPtr +virStorageAuthDefParse(xmlNodePtr node, + xmlXPathContextPtr ctxt) +{ + VIR_XPATH_NODE_AUTORESTORE(ctxt) + virStorageAuthDefPtr ret =3D NULL; + xmlNodePtr secretnode =3D NULL; + g_autoptr(virStorageAuthDef) authdef =3D NULL; + g_autofree char *authtype =3D NULL; + + ctxt->node =3D node; + + authdef =3D g_new0(virStorageAuthDef, 1); + + if (!(authdef->username =3D virXPathString("string(./@username)", ctxt= ))) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("missing username for auth")); + goto cleanup; + } + + authdef->authType =3D VIR_STORAGE_AUTH_TYPE_NONE; + authtype =3D virXPathString("string(./@type)", ctxt); + if (authtype) { + /* Used by the storage pool instead of the secret type field + * to define whether chap or ceph being used + */ + if ((authdef->authType =3D virStorageAuthTypeFromString(authtype))= < 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown auth type '%s'"), authtype); + goto cleanup; + } + } + + if (!(secretnode =3D virXPathNode("./secret ", ctxt))) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Missing element in auth")); + goto cleanup; + } + + /* Used by the domain disk xml parsing in order to ensure the + * secrettype =3D virXMLPropString(secretnode, "type"); + + if (virSecretLookupParseSecret(secretnode, &authdef->seclookupdef) < 0) + goto cleanup; + + ret =3D g_steal_pointer(&authdef); + + cleanup: + + return ret; +} + + +void +virStorageAuthDefFormat(virBufferPtr buf, + virStorageAuthDefPtr authdef) +{ + if (authdef->authType =3D=3D VIR_STORAGE_AUTH_TYPE_NONE) { + virBufferEscapeString(buf, "\n", authdef->us= ername); + } else { + virBufferAsprintf(buf, "authType)); + virBufferEscapeString(buf, "username=3D'%s'>\n", authdef->username= ); + } + + virBufferAdjustIndent(buf, 2); + virSecretLookupFormatSecret(buf, authdef->secrettype, + &authdef->seclookupdef); + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "\n"); +} + + +void +virStoragePRDefFree(virStoragePRDefPtr prd) +{ + if (!prd) + return; + + VIR_FREE(prd->path); + VIR_FREE(prd->mgralias); + VIR_FREE(prd); +} + + +virStoragePRDefPtr +virStoragePRDefParseXML(xmlXPathContextPtr ctxt) +{ + virStoragePRDefPtr prd; + virStoragePRDefPtr ret =3D NULL; + g_autofree char *managed =3D NULL; + g_autofree char *type =3D NULL; + g_autofree char *path =3D NULL; + g_autofree char *mode =3D NULL; + + prd =3D g_new0(virStoragePRDef, 1); + + if (!(managed =3D virXPathString("string(./@managed)", ctxt))) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("missing @managed attribute for ")= ); + goto cleanup; + } + + if ((prd->managed =3D virTristateBoolTypeFromString(managed)) <=3D 0) { + virReportError(VIR_ERR_XML_ERROR, + _("invalid value for 'managed': %s"), managed); + goto cleanup; + } + + type =3D virXPathString("string(./source[1]/@type)", ctxt); + path =3D virXPathString("string(./source[1]/@path)", ctxt); + mode =3D virXPathString("string(./source[1]/@mode)", ctxt); + + if (prd->managed =3D=3D VIR_TRISTATE_BOOL_NO || type || path || mode) { + if (!type) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("missing connection type for "= )); + goto cleanup; + } + + if (!path) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("missing path for ")); + goto cleanup; + } + + if (!mode) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("missing connection mode for "= )); + goto cleanup; + } + } + + if (type && STRNEQ(type, "unix")) { + virReportError(VIR_ERR_XML_ERROR, + _("unsupported connection type for := %s"), + type); + goto cleanup; + } + + if (mode && STRNEQ(mode, "client")) { + virReportError(VIR_ERR_XML_ERROR, + _("unsupported connection mode for := %s"), + mode); + goto cleanup; + } + + prd->path =3D g_steal_pointer(&path); + ret =3D g_steal_pointer(&prd); + + cleanup: + virStoragePRDefFree(prd); + return ret; +} + + +void +virStoragePRDefFormat(virBufferPtr buf, + virStoragePRDefPtr prd, + bool migratable) +{ + virBufferAsprintf(buf, "managed)); + if (prd->path && + (prd->managed =3D=3D VIR_TRISTATE_BOOL_NO || !migratable)) { + virBufferAddLit(buf, ">\n"); + virBufferAdjustIndent(buf, 2); + virBufferAddLit(buf, "path); + virBufferAddLit(buf, " mode=3D'client'/>\n"); + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "\n"); + } else { + virBufferAddLit(buf, "/>\n"); + } +} + + +bool +virStoragePRDefIsEqual(virStoragePRDefPtr a, + virStoragePRDefPtr b) +{ + if (!a && !b) + return true; + + if (!a || !b) + return false; + + if (a->managed !=3D b->managed || + STRNEQ_NULLABLE(a->path, b->path)) + return false; + + return true; +} + + +bool +virStoragePRDefIsManaged(virStoragePRDefPtr prd) +{ + return prd && prd->managed =3D=3D VIR_TRISTATE_BOOL_YES; +} + + +bool +virStorageSourceChainHasManagedPR(virStorageSourcePtr src) +{ + virStorageSourcePtr n; + + for (n =3D src; virStorageSourceIsBacking(n); n =3D n->backingStore) { + if (virStoragePRDefIsManaged(n->pr)) + return true; + } + + return false; +} + + +static virStoragePRDefPtr +virStoragePRDefCopy(virStoragePRDefPtr src) +{ + virStoragePRDefPtr copy =3D NULL; + virStoragePRDefPtr ret =3D NULL; + + copy =3D g_new0(virStoragePRDef, 1); + + copy->managed =3D src->managed; + + copy->path =3D g_strdup(src->path); + copy->mgralias =3D g_strdup(src->mgralias); + + ret =3D g_steal_pointer(©); + + virStoragePRDefFree(copy); + return ret; +} + + +static virStorageSourceNVMeDefPtr +virStorageSourceNVMeDefCopy(const virStorageSourceNVMeDef *src) +{ + virStorageSourceNVMeDefPtr ret =3D NULL; + + ret =3D g_new0(virStorageSourceNVMeDef, 1); + + ret->namespc =3D src->namespc; + ret->managed =3D src->managed; + virPCIDeviceAddressCopy(&ret->pciAddr, &src->pciAddr); + return ret; +} + + +static bool +virStorageSourceNVMeDefIsEqual(const virStorageSourceNVMeDef *a, + const virStorageSourceNVMeDef *b) +{ + if (!a && !b) + return true; + + if (!a || !b) + return false; + + if (a->namespc !=3D b->namespc || + a->managed !=3D b->managed || + !virPCIDeviceAddressEqual(&a->pciAddr, &b->pciAddr)) + return false; + + return true; +} + + +void +virStorageSourceNVMeDefFree(virStorageSourceNVMeDefPtr def) +{ + if (!def) + return; + + VIR_FREE(def); +} + + +bool +virStorageSourceChainHasNVMe(const virStorageSource *src) +{ + const virStorageSource *n; + + for (n =3D src; virStorageSourceIsBacking(n); n =3D n->backingStore) { + if (n->type =3D=3D VIR_STORAGE_TYPE_NVME) + return true; + } + + return false; +} + + +virSecurityDeviceLabelDefPtr +virStorageSourceGetSecurityLabelDef(virStorageSourcePtr src, + const char *model) +{ + size_t i; + + for (i =3D 0; i < src->nseclabels; i++) { + if (STREQ_NULLABLE(src->seclabels[i]->model, model)) + return src->seclabels[i]; + } + + return NULL; +} + + +static void +virStorageSourceSeclabelsClear(virStorageSourcePtr def) +{ + size_t i; + + if (def->seclabels) { + for (i =3D 0; i < def->nseclabels; i++) + virSecurityDeviceLabelDefFree(def->seclabels[i]); + VIR_FREE(def->seclabels); + } +} + + +static int +virStorageSourceSeclabelsCopy(virStorageSourcePtr to, + const virStorageSource *from) +{ + size_t i; + + if (from->nseclabels =3D=3D 0) + return 0; + + to->seclabels =3D g_new0(virSecurityDeviceLabelDefPtr, from->nseclabel= s); + to->nseclabels =3D from->nseclabels; + + for (i =3D 0; i < to->nseclabels; i++) { + if (!(to->seclabels[i] =3D virSecurityDeviceLabelDefCopy(from->sec= labels[i]))) + goto error; + } + + return 0; + + error: + virStorageSourceSeclabelsClear(to); + return -1; +} + + +void +virStorageNetCookieDefFree(virStorageNetCookieDefPtr def) +{ + if (!def) + return; + + g_free(def->name); + g_free(def->value); + + g_free(def); +} + + +static void +virStorageSourceNetCookiesClear(virStorageSourcePtr src) +{ + size_t i; + + if (!src || !src->cookies) + return; + + for (i =3D 0; i < src->ncookies; i++) + virStorageNetCookieDefFree(src->cookies[i]); + + g_clear_pointer(&src->cookies, g_free); + src->ncookies =3D 0; +} + + +static void +virStorageSourceNetCookiesCopy(virStorageSourcePtr to, + const virStorageSource *from) +{ + size_t i; + + if (from->ncookies =3D=3D 0) + return; + + to->cookies =3D g_new0(virStorageNetCookieDefPtr, from->ncookies); + to->ncookies =3D from->ncookies; + + for (i =3D 0; i < from->ncookies; i++) { + to->cookies[i]->name =3D g_strdup(from->cookies[i]->name); + to->cookies[i]->value =3D g_strdup(from->cookies[i]->value); + } +} + + +/* see https://tools.ietf.org/html/rfc6265#section-4.1.1 */ +static const char virStorageSourceCookieValueInvalidChars[] =3D + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" + " \",;\\"; + +/* in addition cookie name can't contain these */ +static const char virStorageSourceCookieNameInvalidChars[] =3D + "()<>@:/[]?=3D{}"; + +static int +virStorageSourceNetCookieValidate(virStorageNetCookieDefPtr def) +{ + g_autofree char *val =3D g_strdup(def->value); + const char *checkval =3D val; + size_t len =3D strlen(val); + + /* name must have at least 1 character */ + if (*(def->name) =3D=3D '\0') { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("cookie name must not be empty")); + return -1; + } + + /* check invalid characters in name */ + if (virStringHasChars(def->name, virStorageSourceCookieValueInvalidCha= rs) || + virStringHasChars(def->name, virStorageSourceCookieNameInvalidChar= s)) { + virReportError(VIR_ERR_XML_ERROR, + _("cookie name '%s' contains invalid characters"), + def->name); + return -1; + } + + /* check for optional quotes around the cookie value string */ + if (val[0] =3D=3D '"') { + if (val[len - 1] !=3D '"') { + virReportError(VIR_ERR_XML_ERROR, + _("value of cookie '%s' contains invalid charac= ters"), + def->name); + return -1; + } + + val[len - 1] =3D '\0'; + checkval++; + } + + /* check invalid characters in value */ + if (virStringHasChars(checkval, virStorageSourceCookieValueInvalidChar= s)) { + virReportError(VIR_ERR_XML_ERROR, + _("value of cookie '%s' contains invalid characters= "), + def->name); + return -1; + } + + return 0; +} + + +int +virStorageSourceNetCookiesValidate(virStorageSourcePtr src) +{ + size_t i; + size_t j; + + for (i =3D 0; i < src->ncookies; i++) { + if (virStorageSourceNetCookieValidate(src->cookies[i]) < 0) + return -1; + + for (j =3D i + 1; j < src->ncookies; j++) { + if (STREQ(src->cookies[i]->name, src->cookies[j]->name)) { + virReportError(VIR_ERR_XML_ERROR, _("duplicate cookie '%s'= "), + src->cookies[i]->name); + return -1; + } + } + } + + return 0; +} + + +static virStorageTimestampsPtr +virStorageTimestampsCopy(const virStorageTimestamps *src) +{ + virStorageTimestampsPtr ret; + + ret =3D g_new0(virStorageTimestamps, 1); + + memcpy(ret, src, sizeof(*src)); + + return ret; +} + + +static virStoragePermsPtr +virStoragePermsCopy(const virStoragePerms *src) +{ + virStoragePermsPtr ret; + + ret =3D g_new0(virStoragePerms, 1); + + ret->mode =3D src->mode; + ret->uid =3D src->uid; + ret->gid =3D src->gid; + + ret->label =3D g_strdup(src->label); + + return ret; +} + + +static virStorageSourcePoolDefPtr +virStorageSourcePoolDefCopy(const virStorageSourcePoolDef *src) +{ + virStorageSourcePoolDefPtr ret; + + ret =3D g_new0(virStorageSourcePoolDef, 1); + + ret->voltype =3D src->voltype; + ret->pooltype =3D src->pooltype; + ret->actualtype =3D src->actualtype; + ret->mode =3D src->mode; + + ret->pool =3D g_strdup(src->pool); + ret->volume =3D g_strdup(src->volume); + + return ret; +} + + +static virStorageSourceSlicePtr +virStorageSourceSliceCopy(const virStorageSourceSlice *src) +{ + virStorageSourceSlicePtr ret =3D g_new0(virStorageSourceSlice, 1); + + ret->offset =3D src->offset; + ret->size =3D src->size; + ret->nodename =3D g_strdup(src->nodename); + + return ret; +} + + +static void +virStorageSourceSliceFree(virStorageSourceSlicePtr slice) +{ + if (!slice) + return; + + g_free(slice->nodename); + g_free(slice); +} + + +/** + * virStorageSourcePtr: + * + * Deep-copies a virStorageSource structure. If @backing chain is true + * then also copies the backing chain recursively, otherwise just + * the top element is copied. This function doesn't copy the + * storage driver access structure and thus the struct needs to be initial= ized + * separately. + */ +virStorageSourcePtr +virStorageSourceCopy(const virStorageSource *src, + bool backingChain) +{ + g_autoptr(virStorageSource) def =3D virStorageSourceNew(); + + def->id =3D src->id; + def->type =3D src->type; + def->protocol =3D src->protocol; + def->format =3D src->format; + def->capacity =3D src->capacity; + def->allocation =3D src->allocation; + def->has_allocation =3D src->has_allocation; + def->physical =3D src->physical; + def->readonly =3D src->readonly; + def->shared =3D src->shared; + def->haveTLS =3D src->haveTLS; + def->tlsFromConfig =3D src->tlsFromConfig; + def->detected =3D src->detected; + def->debugLevel =3D src->debugLevel; + def->debug =3D src->debug; + def->iomode =3D src->iomode; + def->cachemode =3D src->cachemode; + def->discard =3D src->discard; + def->detect_zeroes =3D src->detect_zeroes; + def->sslverify =3D src->sslverify; + def->readahead =3D src->readahead; + def->timeout =3D src->timeout; + + /* storage driver metadata are not copied */ + def->drv =3D NULL; + + def->path =3D g_strdup(src->path); + def->volume =3D g_strdup(src->volume); + def->relPath =3D g_strdup(src->relPath); + def->backingStoreRaw =3D g_strdup(src->backingStoreRaw); + def->backingStoreRawFormat =3D src->backingStoreRawFormat; + def->snapshot =3D g_strdup(src->snapshot); + def->configFile =3D g_strdup(src->configFile); + def->nodeformat =3D g_strdup(src->nodeformat); + def->nodestorage =3D g_strdup(src->nodestorage); + def->compat =3D g_strdup(src->compat); + def->tlsAlias =3D g_strdup(src->tlsAlias); + def->tlsCertdir =3D g_strdup(src->tlsCertdir); + def->query =3D g_strdup(src->query); + + if (src->sliceStorage) + def->sliceStorage =3D virStorageSourceSliceCopy(src->sliceStorage); + + if (src->nhosts) { + if (!(def->hosts =3D virStorageNetHostDefCopy(src->nhosts, src->ho= sts))) + return NULL; + + def->nhosts =3D src->nhosts; + } + + virStorageSourceNetCookiesCopy(def, src); + + if (src->srcpool && + !(def->srcpool =3D virStorageSourcePoolDefCopy(src->srcpool))) + return NULL; + + if (src->features) + def->features =3D virBitmapNewCopy(src->features); + + if (src->encryption && + !(def->encryption =3D virStorageEncryptionCopy(src->encryption))) + return NULL; + + if (src->perms && + !(def->perms =3D virStoragePermsCopy(src->perms))) + return NULL; + + if (src->timestamps && + !(def->timestamps =3D virStorageTimestampsCopy(src->timestamps))) + return NULL; + + if (virStorageSourceSeclabelsCopy(def, src) < 0) + return NULL; + + if (src->auth && + !(def->auth =3D virStorageAuthDefCopy(src->auth))) + return NULL; + + if (src->pr && + !(def->pr =3D virStoragePRDefCopy(src->pr))) + return NULL; + + if (src->nvme) + def->nvme =3D virStorageSourceNVMeDefCopy(src->nvme); + + if (virStorageSourceInitiatorCopy(&def->initiator, &src->initiator) < = 0) + return NULL; + + if (backingChain && src->backingStore) { + if (!(def->backingStore =3D virStorageSourceCopy(src->backingStore, + true))) + return NULL; + } + + /* ssh config passthrough for libguestfs */ + def->ssh_host_key_check_disabled =3D src->ssh_host_key_check_disabled; + def->ssh_user =3D g_strdup(src->ssh_user); + + return g_steal_pointer(&def); +} + + +/** + * virStorageSourceIsSameLocation: + * + * Returns true if the sources @a and @b point to the same storage locatio= n. + * This does not compare any other configuration option + */ +bool +virStorageSourceIsSameLocation(virStorageSourcePtr a, + virStorageSourcePtr b) +{ + size_t i; + + /* there are multiple possibilities to define an empty source */ + if (virStorageSourceIsEmpty(a) && + virStorageSourceIsEmpty(b)) + return true; + + if (virStorageSourceGetActualType(a) !=3D virStorageSourceGetActualTyp= e(b)) + return false; + + if (STRNEQ_NULLABLE(a->path, b->path) || + STRNEQ_NULLABLE(a->volume, b->volume) || + STRNEQ_NULLABLE(a->snapshot, b->snapshot)) + return false; + + if (a->type =3D=3D VIR_STORAGE_TYPE_NETWORK) { + if (a->protocol !=3D b->protocol || + a->nhosts !=3D b->nhosts) + return false; + + for (i =3D 0; i < a->nhosts; i++) { + if (a->hosts[i].transport !=3D b->hosts[i].transport || + a->hosts[i].port !=3D b->hosts[i].port || + STRNEQ_NULLABLE(a->hosts[i].name, b->hosts[i].name) || + STRNEQ_NULLABLE(a->hosts[i].socket, b->hosts[i].socket)) + return false; + } + } + + if (a->type =3D=3D VIR_STORAGE_TYPE_NVME && + !virStorageSourceNVMeDefIsEqual(a->nvme, b->nvme)) + return false; + + return true; +} + + +/** + * virStorageSourceInitChainElement: + * @newelem: New backing chain element disk source + * @old: Existing top level disk source + * @transferLabels: Transfer security labels. + * + * Transfers relevant information from the existing disk source to the new + * backing chain element if they weren't supplied so that labelling info + * and possibly other stuff is correct. + * + * If @transferLabels is true, security labels from the existing disk are = copied + * to the new disk. Otherwise the default domain imagelabel label will be = used. + * + * Returns 0 on success, -1 on error. + */ +int +virStorageSourceInitChainElement(virStorageSourcePtr newelem, + virStorageSourcePtr old, + bool transferLabels) +{ + if (transferLabels && + !newelem->seclabels && + virStorageSourceSeclabelsCopy(newelem, old) < 0) + return -1; + + newelem->shared =3D old->shared; + newelem->readonly =3D old->readonly; + + return 0; +} + + +void +virStorageSourcePoolDefFree(virStorageSourcePoolDefPtr def) +{ + if (!def) + return; + + VIR_FREE(def->pool); + VIR_FREE(def->volume); + + VIR_FREE(def); +} + + +/** + * virStorageSourceGetActualType: + * @def: storage source definition + * + * Returns type of @def. In case when the type is VIR_STORAGE_TYPE_VOLUME + * and virDomainDiskTranslateSourcePool was called on @def the actual type + * of the storage volume is returned rather than VIR_STORAGE_TYPE_VOLUME. + */ +int +virStorageSourceGetActualType(const virStorageSource *def) +{ + if (def->type =3D=3D VIR_STORAGE_TYPE_VOLUME && + def->srcpool && + def->srcpool->actualtype !=3D VIR_STORAGE_TYPE_NONE) + return def->srcpool->actualtype; + + return def->type; +} + + +bool +virStorageSourceIsLocalStorage(const virStorageSource *src) +{ + virStorageType type =3D virStorageSourceGetActualType(src); + + switch (type) { + case VIR_STORAGE_TYPE_FILE: + case VIR_STORAGE_TYPE_BLOCK: + case VIR_STORAGE_TYPE_DIR: + return true; + + case VIR_STORAGE_TYPE_NETWORK: + case VIR_STORAGE_TYPE_VOLUME: + /* While NVMe disks are local, they are not accessible via src->pa= th. + * Therefore, we have to return false here. */ + case VIR_STORAGE_TYPE_NVME: + case VIR_STORAGE_TYPE_LAST: + case VIR_STORAGE_TYPE_NONE: + return false; + } + + return false; +} + + +/** + * virStorageSourceIsEmpty: + * + * @src: disk source to check + * + * Returns true if the guest disk has no associated host storage source + * (such as an empty cdrom drive). + */ +bool +virStorageSourceIsEmpty(virStorageSourcePtr src) +{ + if (virStorageSourceIsLocalStorage(src) && !src->path) + return true; + + if (src->type =3D=3D VIR_STORAGE_TYPE_NONE) + return true; + + if (src->type =3D=3D VIR_STORAGE_TYPE_NETWORK && + src->protocol =3D=3D VIR_STORAGE_NET_PROTOCOL_NONE) + return true; + + return false; +} + + +/** + * virStorageSourceIsBlockLocal: + * @src: disk source definition + * + * Returns true if @src describes a locally accessible block storage sourc= e. + * This includes block devices and host-mapped iSCSI volumes. + */ +bool +virStorageSourceIsBlockLocal(const virStorageSource *src) +{ + return virStorageSourceGetActualType(src) =3D=3D VIR_STORAGE_TYPE_BLOC= K; +} + + +/** + * virStorageSourceBackingStoreClear: + * + * @src: disk source to clear + * + * Clears information about backing store of the current storage file. + */ +void +virStorageSourceBackingStoreClear(virStorageSourcePtr def) +{ + if (!def) + return; + + VIR_FREE(def->relPath); + VIR_FREE(def->backingStoreRaw); + + /* recursively free backing chain */ + virObjectUnref(def->backingStore); + def->backingStore =3D NULL; +} + + +void +virStorageSourceClear(virStorageSourcePtr def) +{ + if (!def) + return; + + VIR_FREE(def->path); + VIR_FREE(def->volume); + VIR_FREE(def->snapshot); + VIR_FREE(def->configFile); + VIR_FREE(def->query); + virStorageSourceNetCookiesClear(def); + virStorageSourcePoolDefFree(def->srcpool); + virBitmapFree(def->features); + VIR_FREE(def->compat); + virStorageEncryptionFree(def->encryption); + virStoragePRDefFree(def->pr); + virStorageSourceNVMeDefFree(def->nvme); + virStorageSourceSeclabelsClear(def); + virStoragePermsFree(def->perms); + VIR_FREE(def->timestamps); + + virStorageSourceSliceFree(def->sliceStorage); + + virStorageNetHostDefFree(def->nhosts, def->hosts); + virStorageAuthDefFree(def->auth); + virObjectUnref(def->privateData); + + VIR_FREE(def->nodestorage); + VIR_FREE(def->nodeformat); + + virStorageSourceBackingStoreClear(def); + + VIR_FREE(def->tlsAlias); + VIR_FREE(def->tlsCertdir); + + VIR_FREE(def->ssh_user); + + virStorageSourceInitiatorClear(&def->initiator); + + /* clear everything except the class header as the object APIs + * will break otherwise */ + memset((char *) def + sizeof(def->parent), 0, + sizeof(*def) - sizeof(def->parent)); +} + + +static void +virStorageSourceDispose(void *obj) +{ + virStorageSourcePtr src =3D obj; + + virStorageSourceClear(src); +} + + +static int +virStorageSourceOnceInit(void) +{ + if (!VIR_CLASS_NEW(virStorageSource, virClassForObject())) + return -1; + + return 0; +} + + +VIR_ONCE_GLOBAL_INIT(virStorageSource); + + +virStorageSourcePtr +virStorageSourceNew(void) +{ + virStorageSourcePtr ret; + + if (virStorageSourceInitialize() < 0) + abort(); + + if (!(ret =3D virObjectNew(virStorageSourceClass))) + abort(); + + return ret; +} + + +/** + * virStorageSourceIsRelative: + * @src: storage source to check + * + * Returns true if given storage source definition is a relative path. + */ +bool +virStorageSourceIsRelative(virStorageSourcePtr src) +{ + virStorageType actual_type =3D virStorageSourceGetActualType(src); + + if (!src->path) + return false; + + switch (actual_type) { + case VIR_STORAGE_TYPE_FILE: + case VIR_STORAGE_TYPE_BLOCK: + case VIR_STORAGE_TYPE_DIR: + return src->path[0] !=3D '/'; + + case VIR_STORAGE_TYPE_NETWORK: + case VIR_STORAGE_TYPE_VOLUME: + case VIR_STORAGE_TYPE_NVME: + case VIR_STORAGE_TYPE_NONE: + case VIR_STORAGE_TYPE_LAST: + return false; + } + + return false; +} + + +static unsigned int +virStorageSourceNetworkDefaultPort(virStorageNetProtocol protocol) +{ + switch (protocol) { + case VIR_STORAGE_NET_PROTOCOL_HTTP: + return 80; + + case VIR_STORAGE_NET_PROTOCOL_HTTPS: + return 443; + + case VIR_STORAGE_NET_PROTOCOL_FTP: + return 21; + + case VIR_STORAGE_NET_PROTOCOL_FTPS: + return 990; + + case VIR_STORAGE_NET_PROTOCOL_TFTP: + return 69; + + case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG: + return 7000; + + case VIR_STORAGE_NET_PROTOCOL_NBD: + return 10809; + + case VIR_STORAGE_NET_PROTOCOL_SSH: + return 22; + + case VIR_STORAGE_NET_PROTOCOL_ISCSI: + return 3260; + + case VIR_STORAGE_NET_PROTOCOL_GLUSTER: + return 24007; + + case VIR_STORAGE_NET_PROTOCOL_RBD: + /* we don't provide a default for RBD */ + return 0; + + case VIR_STORAGE_NET_PROTOCOL_VXHS: + return 9999; + + case VIR_STORAGE_NET_PROTOCOL_LAST: + case VIR_STORAGE_NET_PROTOCOL_NONE: + return 0; + } + + return 0; +} + + +void +virStorageSourceNetworkAssignDefaultPorts(virStorageSourcePtr src) +{ + size_t i; + + for (i =3D 0; i < src->nhosts; i++) { + if (src->hosts[i].transport =3D=3D VIR_STORAGE_NET_HOST_TRANS_TCP = && + src->hosts[i].port =3D=3D 0) + src->hosts[i].port =3D virStorageSourceNetworkDefaultPort(src-= >protocol); + } +} + + +void +virStorageSourceInitiatorParseXML(xmlXPathContextPtr ctxt, + virStorageSourceInitiatorDefPtr initiato= r) +{ + initiator->iqn =3D virXPathString("string(./initiator/iqn/@name)", ctx= t); +} + + +void +virStorageSourceInitiatorFormatXML(virStorageSourceInitiatorDefPtr initiat= or, + virBufferPtr buf) +{ + if (!initiator->iqn) + return; + + virBufferAddLit(buf, "\n"); + virBufferAdjustIndent(buf, 2); + virBufferEscapeString(buf, "\n", initiator->iqn); + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "\n"); +} + + +int +virStorageSourceInitiatorCopy(virStorageSourceInitiatorDefPtr dest, + const virStorageSourceInitiatorDef *src) +{ + dest->iqn =3D g_strdup(src->iqn); + return 0; +} + + +void +virStorageSourceInitiatorClear(virStorageSourceInitiatorDefPtr initiator) +{ + VIR_FREE(initiator->iqn); +} diff --git a/src/conf/storage_source.h b/src/conf/storage_source.h new file mode 100644 index 0000000000..89bba38599 --- /dev/null +++ b/src/conf/storage_source.h @@ -0,0 +1,518 @@ +/* + * storage_source.h: file utility functions for FS storage backend + * + * Copyright (C) 2007-2009, 2012-2016 Red Hat, Inc. + * 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 + * License along with this library. If not, see + * . + */ + +#pragma once + +#include "virbitmap.h" +#include "virenum.h" +#include "virobject.h" +#include "virpci.h" +#include "virseclabel.h" +#include "virsecret.h" +#include "virstorageencryption.h" + +/* Types of disk backends (host resource). Comparable to the public + * virStorageVolType, except we have an undetermined state, don't have + * a netdir type, and add a volume type for reference through a + * storage pool. */ +typedef enum { + VIR_STORAGE_TYPE_NONE, + VIR_STORAGE_TYPE_FILE, + VIR_STORAGE_TYPE_BLOCK, + VIR_STORAGE_TYPE_DIR, + VIR_STORAGE_TYPE_NETWORK, + VIR_STORAGE_TYPE_VOLUME, + VIR_STORAGE_TYPE_NVME, + + VIR_STORAGE_TYPE_LAST +} virStorageType; + +VIR_ENUM_DECL(virStorage); + + +typedef enum { + VIR_STORAGE_FILE_AUTO_SAFE =3D -2, + VIR_STORAGE_FILE_AUTO =3D -1, + VIR_STORAGE_FILE_NONE =3D 0, + VIR_STORAGE_FILE_RAW, + VIR_STORAGE_FILE_DIR, + VIR_STORAGE_FILE_BOCHS, + VIR_STORAGE_FILE_CLOOP, + VIR_STORAGE_FILE_DMG, + VIR_STORAGE_FILE_ISO, + VIR_STORAGE_FILE_VPC, + VIR_STORAGE_FILE_VDI, + + /* Not direct file formats, but used for various drivers */ + VIR_STORAGE_FILE_FAT, + VIR_STORAGE_FILE_VHD, + VIR_STORAGE_FILE_PLOOP, + + /* Not a format, but a marker: all formats below this point have + * libvirt support for following a backing chain */ + VIR_STORAGE_FILE_BACKING, + + VIR_STORAGE_FILE_COW =3D VIR_STORAGE_FILE_BACKING, + VIR_STORAGE_FILE_QCOW, + VIR_STORAGE_FILE_QCOW2, + VIR_STORAGE_FILE_QED, + VIR_STORAGE_FILE_VMDK, + + VIR_STORAGE_FILE_LAST, +} virStorageFileFormat; + +VIR_ENUM_DECL(virStorageFileFormat); + + +typedef enum { + VIR_STORAGE_FILE_FEATURE_LAZY_REFCOUNTS =3D 0, + + VIR_STORAGE_FILE_FEATURE_LAST +} virStorageFileFeature; + +VIR_ENUM_DECL(virStorageFileFeature); + + +typedef struct _virStoragePerms virStoragePerms; +typedef virStoragePerms *virStoragePermsPtr; +struct _virStoragePerms { + mode_t mode; + uid_t uid; + gid_t gid; + char *label; +}; + + +typedef struct _virStorageTimestamps virStorageTimestamps; +typedef virStorageTimestamps *virStorageTimestampsPtr; +struct _virStorageTimestamps { + struct timespec atime; + struct timespec btime; /* birth time unknown if btime.tv_nsec =3D=3D -= 1 */ + struct timespec ctime; + struct timespec mtime; +}; + + +/* Information related to network storage */ +typedef enum { + VIR_STORAGE_NET_PROTOCOL_NONE, + VIR_STORAGE_NET_PROTOCOL_NBD, + VIR_STORAGE_NET_PROTOCOL_RBD, + VIR_STORAGE_NET_PROTOCOL_SHEEPDOG, + VIR_STORAGE_NET_PROTOCOL_GLUSTER, + VIR_STORAGE_NET_PROTOCOL_ISCSI, + VIR_STORAGE_NET_PROTOCOL_HTTP, + VIR_STORAGE_NET_PROTOCOL_HTTPS, + VIR_STORAGE_NET_PROTOCOL_FTP, + VIR_STORAGE_NET_PROTOCOL_FTPS, + VIR_STORAGE_NET_PROTOCOL_TFTP, + VIR_STORAGE_NET_PROTOCOL_SSH, + VIR_STORAGE_NET_PROTOCOL_VXHS, + + VIR_STORAGE_NET_PROTOCOL_LAST +} virStorageNetProtocol; + +VIR_ENUM_DECL(virStorageNetProtocol); + + +typedef enum { + VIR_STORAGE_NET_HOST_TRANS_TCP, + VIR_STORAGE_NET_HOST_TRANS_UNIX, + VIR_STORAGE_NET_HOST_TRANS_RDMA, + + VIR_STORAGE_NET_HOST_TRANS_LAST +} virStorageNetHostTransport; + +VIR_ENUM_DECL(virStorageNetHostTransport); + + +typedef struct _virStorageNetHostDef virStorageNetHostDef; +typedef virStorageNetHostDef *virStorageNetHostDefPtr; +struct _virStorageNetHostDef { + char *name; + unsigned int port; + int transport; /* virStorageNetHostTransport */ + char *socket; /* path to unix socket */ +}; + + +typedef struct _virStorageNetCookieDef virStorageNetCookieDef; +typedef virStorageNetCookieDef *virStorageNetCookieDefPtr; +struct _virStorageNetCookieDef { + char *name; + char *value; +}; + + +void +virStorageNetCookieDefFree(virStorageNetCookieDefPtr def); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(virStorageNetCookieDef, virStorageNetCookieD= efFree); + + +/* Information for a storage volume from a virStoragePool */ + +/* + * Used for volume "type" disk to indicate how to represent + * the disk source if the specified "pool" is of iscsi type. + */ +typedef enum { + VIR_STORAGE_SOURCE_POOL_MODE_DEFAULT =3D 0, + + /* Use the path as it shows up on host, e.g. + * /dev/disk/by-path/ip-$ip-iscsi-$iqn:iscsi.iscsi-pool0-lun-1 + */ + VIR_STORAGE_SOURCE_POOL_MODE_HOST, + + /* Use the URI from the storage pool source element host attribute. E.= g. + * file=3Discsi://demo.org:6000/iqn.1992-01.com.example/1. + */ + VIR_STORAGE_SOURCE_POOL_MODE_DIRECT, + + VIR_STORAGE_SOURCE_POOL_MODE_LAST +} virStorageSourcePoolMode; + +VIR_ENUM_DECL(virStorageSourcePoolMode); + + +typedef struct _virStorageSourcePoolDef virStorageSourcePoolDef; +typedef virStorageSourcePoolDef *virStorageSourcePoolDefPtr; +struct _virStorageSourcePoolDef { + char *pool; /* pool name */ + char *volume; /* volume name */ + int voltype; /* virStorageVolType, internal only */ + int pooltype; /* virStoragePoolType from storage_conf.h, internal only= */ + int actualtype; /* virStorageType, internal only */ + int mode; /* virStorageSourcePoolMode, currently makes sense only for = iscsi pool */ +}; + + +typedef enum { + VIR_STORAGE_AUTH_TYPE_NONE, + VIR_STORAGE_AUTH_TYPE_CHAP, + VIR_STORAGE_AUTH_TYPE_CEPHX, + + VIR_STORAGE_AUTH_TYPE_LAST, +} virStorageAuthType; + +VIR_ENUM_DECL(virStorageAuth); + + +typedef struct _virStorageAuthDef virStorageAuthDef; +typedef virStorageAuthDef *virStorageAuthDefPtr; +struct _virStorageAuthDef { + char *username; + char *secrettype; /* =20 -#include "virstoragefile.h" +#include "storage_source.h" =20 /* ------- virStorageFile backends ------------ */ typedef struct _virStorageFileBackend virStorageFileBackend; diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c index 3489934546..1c61f3c143 100644 --- a/src/util/virstoragefile.c +++ b/src/util/virstoragefile.c @@ -23,84 +23,8 @@ #include "virstoragefile.h" =20 #include "viralloc.h" -#include "virxml.h" #include "virerror.h" -#include "virlog.h" #include "vircommand.h" -#include "virstring.h" -#include "virbuffer.h" -#include "virstorageencryption.h" -#include "virsecret.h" - -#define VIR_FROM_THIS VIR_FROM_STORAGE - -VIR_LOG_INIT("util.storagefile"); - -static virClassPtr virStorageSourceClass; - -VIR_ENUM_IMPL(virStorage, - VIR_STORAGE_TYPE_LAST, - "none", - "file", - "block", - "dir", - "network", - "volume", - "nvme", -); - -VIR_ENUM_IMPL(virStorageFileFormat, - VIR_STORAGE_FILE_LAST, - "none", - "raw", "dir", "bochs", - "cloop", "dmg", "iso", - "vpc", "vdi", - /* Not direct file formats, but used for various drivers */ - "fat", "vhd", "ploop", - /* Formats with backing file below here */ - "cow", "qcow", "qcow2", "qed", "vmdk", -); - -VIR_ENUM_IMPL(virStorageFileFeature, - VIR_STORAGE_FILE_FEATURE_LAST, - "lazy_refcounts", -); - -VIR_ENUM_IMPL(virStorageNetProtocol, - VIR_STORAGE_NET_PROTOCOL_LAST, - "none", - "nbd", - "rbd", - "sheepdog", - "gluster", - "iscsi", - "http", - "https", - "ftp", - "ftps", - "tftp", - "ssh", - "vxhs", -); - -VIR_ENUM_IMPL(virStorageNetHostTransport, - VIR_STORAGE_NET_HOST_TRANS_LAST, - "tcp", - "unix", - "rdma", -); - -VIR_ENUM_IMPL(virStorageSourcePoolMode, - VIR_STORAGE_SOURCE_POOL_MODE_LAST, - "default", - "host", - "direct", -); - -VIR_ENUM_IMPL(virStorageAuth, - VIR_STORAGE_AUTH_TYPE_LAST, - "none", "chap", "ceph", -); =20 =20 #ifdef WITH_UDEV @@ -239,1208 +163,3 @@ int virStorageFileGetNPIVKey(const char *path G_GNUC= _UNUSED, return -1; } #endif - - -/** - * virStorageSourceIsBacking: - * @src: storage source - * - * Returns true if @src is a eligible backing store structure. Useful - * for iterators. - */ -bool -virStorageSourceIsBacking(const virStorageSource *src) -{ - return src && src->type !=3D VIR_STORAGE_TYPE_NONE; -} - -/** - * virStorageSourceHasBacking: - * @src: storage source - * - * Returns true if @src has backing store/chain. - */ -bool -virStorageSourceHasBacking(const virStorageSource *src) -{ - return virStorageSourceIsBacking(src) && src->backingStore && - src->backingStore->type !=3D VIR_STORAGE_TYPE_NONE; -} - - -void -virStorageNetHostDefClear(virStorageNetHostDefPtr def) -{ - if (!def) - return; - - VIR_FREE(def->name); - VIR_FREE(def->socket); -} - - -void -virStorageNetHostDefFree(size_t nhosts, - virStorageNetHostDefPtr hosts) -{ - size_t i; - - if (!hosts) - return; - - for (i =3D 0; i < nhosts; i++) - virStorageNetHostDefClear(&hosts[i]); - - VIR_FREE(hosts); -} - - -static void -virStoragePermsFree(virStoragePermsPtr def) -{ - if (!def) - return; - - VIR_FREE(def->label); - VIR_FREE(def); -} - - -virStorageNetHostDefPtr -virStorageNetHostDefCopy(size_t nhosts, - virStorageNetHostDefPtr hosts) -{ - virStorageNetHostDefPtr ret =3D NULL; - size_t i; - - ret =3D g_new0(virStorageNetHostDef, nhosts); - - for (i =3D 0; i < nhosts; i++) { - virStorageNetHostDefPtr src =3D &hosts[i]; - virStorageNetHostDefPtr dst =3D &ret[i]; - - dst->transport =3D src->transport; - dst->port =3D src->port; - - dst->name =3D g_strdup(src->name); - dst->socket =3D g_strdup(src->socket); - } - - return ret; -} - - -void -virStorageAuthDefFree(virStorageAuthDefPtr authdef) -{ - if (!authdef) - return; - - VIR_FREE(authdef->username); - VIR_FREE(authdef->secrettype); - virSecretLookupDefClear(&authdef->seclookupdef); - VIR_FREE(authdef); -} - - -virStorageAuthDefPtr -virStorageAuthDefCopy(const virStorageAuthDef *src) -{ - g_autoptr(virStorageAuthDef) authdef =3D NULL; - - authdef =3D g_new0(virStorageAuthDef, 1); - - authdef->username =3D g_strdup(src->username); - /* Not present for storage pool, but used for disk source */ - authdef->secrettype =3D g_strdup(src->secrettype); - authdef->authType =3D src->authType; - - virSecretLookupDefCopy(&authdef->seclookupdef, &src->seclookupdef); - - return g_steal_pointer(&authdef); -} - - -virStorageAuthDefPtr -virStorageAuthDefParse(xmlNodePtr node, - xmlXPathContextPtr ctxt) -{ - VIR_XPATH_NODE_AUTORESTORE(ctxt) - virStorageAuthDefPtr ret =3D NULL; - xmlNodePtr secretnode =3D NULL; - g_autoptr(virStorageAuthDef) authdef =3D NULL; - g_autofree char *authtype =3D NULL; - - ctxt->node =3D node; - - authdef =3D g_new0(virStorageAuthDef, 1); - - if (!(authdef->username =3D virXPathString("string(./@username)", ctxt= ))) { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("missing username for auth")); - goto cleanup; - } - - authdef->authType =3D VIR_STORAGE_AUTH_TYPE_NONE; - authtype =3D virXPathString("string(./@type)", ctxt); - if (authtype) { - /* Used by the storage pool instead of the secret type field - * to define whether chap or ceph being used - */ - if ((authdef->authType =3D virStorageAuthTypeFromString(authtype))= < 0) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("unknown auth type '%s'"), authtype); - goto cleanup; - } - } - - if (!(secretnode =3D virXPathNode("./secret ", ctxt))) { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("Missing element in auth")); - goto cleanup; - } - - /* Used by the domain disk xml parsing in order to ensure the - * secrettype =3D virXMLPropString(secretnode, "type"); - - if (virSecretLookupParseSecret(secretnode, &authdef->seclookupdef) < 0) - goto cleanup; - - ret =3D g_steal_pointer(&authdef); - - cleanup: - - return ret; -} - - -void -virStorageAuthDefFormat(virBufferPtr buf, - virStorageAuthDefPtr authdef) -{ - if (authdef->authType =3D=3D VIR_STORAGE_AUTH_TYPE_NONE) { - virBufferEscapeString(buf, "\n", authdef->us= ername); - } else { - virBufferAsprintf(buf, "authType)); - virBufferEscapeString(buf, "username=3D'%s'>\n", authdef->username= ); - } - - virBufferAdjustIndent(buf, 2); - virSecretLookupFormatSecret(buf, authdef->secrettype, - &authdef->seclookupdef); - virBufferAdjustIndent(buf, -2); - virBufferAddLit(buf, "\n"); -} - - -void -virStoragePRDefFree(virStoragePRDefPtr prd) -{ - if (!prd) - return; - - VIR_FREE(prd->path); - VIR_FREE(prd->mgralias); - VIR_FREE(prd); -} - - -virStoragePRDefPtr -virStoragePRDefParseXML(xmlXPathContextPtr ctxt) -{ - virStoragePRDefPtr prd; - virStoragePRDefPtr ret =3D NULL; - g_autofree char *managed =3D NULL; - g_autofree char *type =3D NULL; - g_autofree char *path =3D NULL; - g_autofree char *mode =3D NULL; - - prd =3D g_new0(virStoragePRDef, 1); - - if (!(managed =3D virXPathString("string(./@managed)", ctxt))) { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("missing @managed attribute for ")= ); - goto cleanup; - } - - if ((prd->managed =3D virTristateBoolTypeFromString(managed)) <=3D 0) { - virReportError(VIR_ERR_XML_ERROR, - _("invalid value for 'managed': %s"), managed); - goto cleanup; - } - - type =3D virXPathString("string(./source[1]/@type)", ctxt); - path =3D virXPathString("string(./source[1]/@path)", ctxt); - mode =3D virXPathString("string(./source[1]/@mode)", ctxt); - - if (prd->managed =3D=3D VIR_TRISTATE_BOOL_NO || type || path || mode) { - if (!type) { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("missing connection type for "= )); - goto cleanup; - } - - if (!path) { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("missing path for ")); - goto cleanup; - } - - if (!mode) { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("missing connection mode for "= )); - goto cleanup; - } - } - - if (type && STRNEQ(type, "unix")) { - virReportError(VIR_ERR_XML_ERROR, - _("unsupported connection type for := %s"), - type); - goto cleanup; - } - - if (mode && STRNEQ(mode, "client")) { - virReportError(VIR_ERR_XML_ERROR, - _("unsupported connection mode for := %s"), - mode); - goto cleanup; - } - - prd->path =3D g_steal_pointer(&path); - ret =3D g_steal_pointer(&prd); - - cleanup: - virStoragePRDefFree(prd); - return ret; -} - - -void -virStoragePRDefFormat(virBufferPtr buf, - virStoragePRDefPtr prd, - bool migratable) -{ - virBufferAsprintf(buf, "managed)); - if (prd->path && - (prd->managed =3D=3D VIR_TRISTATE_BOOL_NO || !migratable)) { - virBufferAddLit(buf, ">\n"); - virBufferAdjustIndent(buf, 2); - virBufferAddLit(buf, "path); - virBufferAddLit(buf, " mode=3D'client'/>\n"); - virBufferAdjustIndent(buf, -2); - virBufferAddLit(buf, "\n"); - } else { - virBufferAddLit(buf, "/>\n"); - } -} - - -bool -virStoragePRDefIsEqual(virStoragePRDefPtr a, - virStoragePRDefPtr b) -{ - if (!a && !b) - return true; - - if (!a || !b) - return false; - - if (a->managed !=3D b->managed || - STRNEQ_NULLABLE(a->path, b->path)) - return false; - - return true; -} - - -bool -virStoragePRDefIsManaged(virStoragePRDefPtr prd) -{ - return prd && prd->managed =3D=3D VIR_TRISTATE_BOOL_YES; -} - - -bool -virStorageSourceChainHasManagedPR(virStorageSourcePtr src) -{ - virStorageSourcePtr n; - - for (n =3D src; virStorageSourceIsBacking(n); n =3D n->backingStore) { - if (virStoragePRDefIsManaged(n->pr)) - return true; - } - - return false; -} - - -static virStoragePRDefPtr -virStoragePRDefCopy(virStoragePRDefPtr src) -{ - virStoragePRDefPtr copy =3D NULL; - virStoragePRDefPtr ret =3D NULL; - - copy =3D g_new0(virStoragePRDef, 1); - - copy->managed =3D src->managed; - - copy->path =3D g_strdup(src->path); - copy->mgralias =3D g_strdup(src->mgralias); - - ret =3D g_steal_pointer(©); - - virStoragePRDefFree(copy); - return ret; -} - - -static virStorageSourceNVMeDefPtr -virStorageSourceNVMeDefCopy(const virStorageSourceNVMeDef *src) -{ - virStorageSourceNVMeDefPtr ret =3D NULL; - - ret =3D g_new0(virStorageSourceNVMeDef, 1); - - ret->namespc =3D src->namespc; - ret->managed =3D src->managed; - virPCIDeviceAddressCopy(&ret->pciAddr, &src->pciAddr); - return ret; -} - - -static bool -virStorageSourceNVMeDefIsEqual(const virStorageSourceNVMeDef *a, - const virStorageSourceNVMeDef *b) -{ - if (!a && !b) - return true; - - if (!a || !b) - return false; - - if (a->namespc !=3D b->namespc || - a->managed !=3D b->managed || - !virPCIDeviceAddressEqual(&a->pciAddr, &b->pciAddr)) - return false; - - return true; -} - - -void -virStorageSourceNVMeDefFree(virStorageSourceNVMeDefPtr def) -{ - if (!def) - return; - - VIR_FREE(def); -} - - -bool -virStorageSourceChainHasNVMe(const virStorageSource *src) -{ - const virStorageSource *n; - - for (n =3D src; virStorageSourceIsBacking(n); n =3D n->backingStore) { - if (n->type =3D=3D VIR_STORAGE_TYPE_NVME) - return true; - } - - return false; -} - - -virSecurityDeviceLabelDefPtr -virStorageSourceGetSecurityLabelDef(virStorageSourcePtr src, - const char *model) -{ - size_t i; - - for (i =3D 0; i < src->nseclabels; i++) { - if (STREQ_NULLABLE(src->seclabels[i]->model, model)) - return src->seclabels[i]; - } - - return NULL; -} - - -static void -virStorageSourceSeclabelsClear(virStorageSourcePtr def) -{ - size_t i; - - if (def->seclabels) { - for (i =3D 0; i < def->nseclabels; i++) - virSecurityDeviceLabelDefFree(def->seclabels[i]); - VIR_FREE(def->seclabels); - } -} - - -static int -virStorageSourceSeclabelsCopy(virStorageSourcePtr to, - const virStorageSource *from) -{ - size_t i; - - if (from->nseclabels =3D=3D 0) - return 0; - - to->seclabels =3D g_new0(virSecurityDeviceLabelDefPtr, from->nseclabel= s); - to->nseclabels =3D from->nseclabels; - - for (i =3D 0; i < to->nseclabels; i++) { - if (!(to->seclabels[i] =3D virSecurityDeviceLabelDefCopy(from->sec= labels[i]))) - goto error; - } - - return 0; - - error: - virStorageSourceSeclabelsClear(to); - return -1; -} - - -void -virStorageNetCookieDefFree(virStorageNetCookieDefPtr def) -{ - if (!def) - return; - - g_free(def->name); - g_free(def->value); - - g_free(def); -} - - -static void -virStorageSourceNetCookiesClear(virStorageSourcePtr src) -{ - size_t i; - - if (!src || !src->cookies) - return; - - for (i =3D 0; i < src->ncookies; i++) - virStorageNetCookieDefFree(src->cookies[i]); - - g_clear_pointer(&src->cookies, g_free); - src->ncookies =3D 0; -} - - -static void -virStorageSourceNetCookiesCopy(virStorageSourcePtr to, - const virStorageSource *from) -{ - size_t i; - - if (from->ncookies =3D=3D 0) - return; - - to->cookies =3D g_new0(virStorageNetCookieDefPtr, from->ncookies); - to->ncookies =3D from->ncookies; - - for (i =3D 0; i < from->ncookies; i++) { - to->cookies[i]->name =3D g_strdup(from->cookies[i]->name); - to->cookies[i]->value =3D g_strdup(from->cookies[i]->value); - } -} - - -/* see https://tools.ietf.org/html/rfc6265#section-4.1.1 */ -static const char virStorageSourceCookieValueInvalidChars[] =3D - "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" - "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" - " \",;\\"; - -/* in addition cookie name can't contain these */ -static const char virStorageSourceCookieNameInvalidChars[] =3D - "()<>@:/[]?=3D{}"; - -static int -virStorageSourceNetCookieValidate(virStorageNetCookieDefPtr def) -{ - g_autofree char *val =3D g_strdup(def->value); - const char *checkval =3D val; - size_t len =3D strlen(val); - - /* name must have at least 1 character */ - if (*(def->name) =3D=3D '\0') { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("cookie name must not be empty")); - return -1; - } - - /* check invalid characters in name */ - if (virStringHasChars(def->name, virStorageSourceCookieValueInvalidCha= rs) || - virStringHasChars(def->name, virStorageSourceCookieNameInvalidChar= s)) { - virReportError(VIR_ERR_XML_ERROR, - _("cookie name '%s' contains invalid characters"), - def->name); - return -1; - } - - /* check for optional quotes around the cookie value string */ - if (val[0] =3D=3D '"') { - if (val[len - 1] !=3D '"') { - virReportError(VIR_ERR_XML_ERROR, - _("value of cookie '%s' contains invalid charac= ters"), - def->name); - return -1; - } - - val[len - 1] =3D '\0'; - checkval++; - } - - /* check invalid characters in value */ - if (virStringHasChars(checkval, virStorageSourceCookieValueInvalidChar= s)) { - virReportError(VIR_ERR_XML_ERROR, - _("value of cookie '%s' contains invalid characters= "), - def->name); - return -1; - } - - return 0; -} - - -int -virStorageSourceNetCookiesValidate(virStorageSourcePtr src) -{ - size_t i; - size_t j; - - for (i =3D 0; i < src->ncookies; i++) { - if (virStorageSourceNetCookieValidate(src->cookies[i]) < 0) - return -1; - - for (j =3D i + 1; j < src->ncookies; j++) { - if (STREQ(src->cookies[i]->name, src->cookies[j]->name)) { - virReportError(VIR_ERR_XML_ERROR, _("duplicate cookie '%s'= "), - src->cookies[i]->name); - return -1; - } - } - } - - return 0; -} - - -static virStorageTimestampsPtr -virStorageTimestampsCopy(const virStorageTimestamps *src) -{ - virStorageTimestampsPtr ret; - - ret =3D g_new0(virStorageTimestamps, 1); - - memcpy(ret, src, sizeof(*src)); - - return ret; -} - - -static virStoragePermsPtr -virStoragePermsCopy(const virStoragePerms *src) -{ - virStoragePermsPtr ret; - - ret =3D g_new0(virStoragePerms, 1); - - ret->mode =3D src->mode; - ret->uid =3D src->uid; - ret->gid =3D src->gid; - - ret->label =3D g_strdup(src->label); - - return ret; -} - - -static virStorageSourcePoolDefPtr -virStorageSourcePoolDefCopy(const virStorageSourcePoolDef *src) -{ - virStorageSourcePoolDefPtr ret; - - ret =3D g_new0(virStorageSourcePoolDef, 1); - - ret->voltype =3D src->voltype; - ret->pooltype =3D src->pooltype; - ret->actualtype =3D src->actualtype; - ret->mode =3D src->mode; - - ret->pool =3D g_strdup(src->pool); - ret->volume =3D g_strdup(src->volume); - - return ret; -} - - -static virStorageSourceSlicePtr -virStorageSourceSliceCopy(const virStorageSourceSlice *src) -{ - virStorageSourceSlicePtr ret =3D g_new0(virStorageSourceSlice, 1); - - ret->offset =3D src->offset; - ret->size =3D src->size; - ret->nodename =3D g_strdup(src->nodename); - - return ret; -} - - -static void -virStorageSourceSliceFree(virStorageSourceSlicePtr slice) -{ - if (!slice) - return; - - g_free(slice->nodename); - g_free(slice); -} - - -/** - * virStorageSourcePtr: - * - * Deep-copies a virStorageSource structure. If @backing chain is true - * then also copies the backing chain recursively, otherwise just - * the top element is copied. This function doesn't copy the - * storage driver access structure and thus the struct needs to be initial= ized - * separately. - */ -virStorageSourcePtr -virStorageSourceCopy(const virStorageSource *src, - bool backingChain) -{ - g_autoptr(virStorageSource) def =3D virStorageSourceNew(); - - def->id =3D src->id; - def->type =3D src->type; - def->protocol =3D src->protocol; - def->format =3D src->format; - def->capacity =3D src->capacity; - def->allocation =3D src->allocation; - def->has_allocation =3D src->has_allocation; - def->physical =3D src->physical; - def->readonly =3D src->readonly; - def->shared =3D src->shared; - def->haveTLS =3D src->haveTLS; - def->tlsFromConfig =3D src->tlsFromConfig; - def->detected =3D src->detected; - def->debugLevel =3D src->debugLevel; - def->debug =3D src->debug; - def->iomode =3D src->iomode; - def->cachemode =3D src->cachemode; - def->discard =3D src->discard; - def->detect_zeroes =3D src->detect_zeroes; - def->sslverify =3D src->sslverify; - def->readahead =3D src->readahead; - def->timeout =3D src->timeout; - - /* storage driver metadata are not copied */ - def->drv =3D NULL; - - def->path =3D g_strdup(src->path); - def->volume =3D g_strdup(src->volume); - def->relPath =3D g_strdup(src->relPath); - def->backingStoreRaw =3D g_strdup(src->backingStoreRaw); - def->backingStoreRawFormat =3D src->backingStoreRawFormat; - def->snapshot =3D g_strdup(src->snapshot); - def->configFile =3D g_strdup(src->configFile); - def->nodeformat =3D g_strdup(src->nodeformat); - def->nodestorage =3D g_strdup(src->nodestorage); - def->compat =3D g_strdup(src->compat); - def->tlsAlias =3D g_strdup(src->tlsAlias); - def->tlsCertdir =3D g_strdup(src->tlsCertdir); - def->query =3D g_strdup(src->query); - - if (src->sliceStorage) - def->sliceStorage =3D virStorageSourceSliceCopy(src->sliceStorage); - - if (src->nhosts) { - if (!(def->hosts =3D virStorageNetHostDefCopy(src->nhosts, src->ho= sts))) - return NULL; - - def->nhosts =3D src->nhosts; - } - - virStorageSourceNetCookiesCopy(def, src); - - if (src->srcpool && - !(def->srcpool =3D virStorageSourcePoolDefCopy(src->srcpool))) - return NULL; - - if (src->features) - def->features =3D virBitmapNewCopy(src->features); - - if (src->encryption && - !(def->encryption =3D virStorageEncryptionCopy(src->encryption))) - return NULL; - - if (src->perms && - !(def->perms =3D virStoragePermsCopy(src->perms))) - return NULL; - - if (src->timestamps && - !(def->timestamps =3D virStorageTimestampsCopy(src->timestamps))) - return NULL; - - if (virStorageSourceSeclabelsCopy(def, src) < 0) - return NULL; - - if (src->auth && - !(def->auth =3D virStorageAuthDefCopy(src->auth))) - return NULL; - - if (src->pr && - !(def->pr =3D virStoragePRDefCopy(src->pr))) - return NULL; - - if (src->nvme) - def->nvme =3D virStorageSourceNVMeDefCopy(src->nvme); - - if (virStorageSourceInitiatorCopy(&def->initiator, &src->initiator) < = 0) - return NULL; - - if (backingChain && src->backingStore) { - if (!(def->backingStore =3D virStorageSourceCopy(src->backingStore, - true))) - return NULL; - } - - /* ssh config passthrough for libguestfs */ - def->ssh_host_key_check_disabled =3D src->ssh_host_key_check_disabled; - def->ssh_user =3D g_strdup(src->ssh_user); - - return g_steal_pointer(&def); -} - - -/** - * virStorageSourceIsSameLocation: - * - * Returns true if the sources @a and @b point to the same storage locatio= n. - * This does not compare any other configuration option - */ -bool -virStorageSourceIsSameLocation(virStorageSourcePtr a, - virStorageSourcePtr b) -{ - size_t i; - - /* there are multiple possibilities to define an empty source */ - if (virStorageSourceIsEmpty(a) && - virStorageSourceIsEmpty(b)) - return true; - - if (virStorageSourceGetActualType(a) !=3D virStorageSourceGetActualTyp= e(b)) - return false; - - if (STRNEQ_NULLABLE(a->path, b->path) || - STRNEQ_NULLABLE(a->volume, b->volume) || - STRNEQ_NULLABLE(a->snapshot, b->snapshot)) - return false; - - if (a->type =3D=3D VIR_STORAGE_TYPE_NETWORK) { - if (a->protocol !=3D b->protocol || - a->nhosts !=3D b->nhosts) - return false; - - for (i =3D 0; i < a->nhosts; i++) { - if (a->hosts[i].transport !=3D b->hosts[i].transport || - a->hosts[i].port !=3D b->hosts[i].port || - STRNEQ_NULLABLE(a->hosts[i].name, b->hosts[i].name) || - STRNEQ_NULLABLE(a->hosts[i].socket, b->hosts[i].socket)) - return false; - } - } - - if (a->type =3D=3D VIR_STORAGE_TYPE_NVME && - !virStorageSourceNVMeDefIsEqual(a->nvme, b->nvme)) - return false; - - return true; -} - - -/** - * virStorageSourceInitChainElement: - * @newelem: New backing chain element disk source - * @old: Existing top level disk source - * @transferLabels: Transfer security labels. - * - * Transfers relevant information from the existing disk source to the new - * backing chain element if they weren't supplied so that labelling info - * and possibly other stuff is correct. - * - * If @transferLabels is true, security labels from the existing disk are = copied - * to the new disk. Otherwise the default domain imagelabel label will be = used. - * - * Returns 0 on success, -1 on error. - */ -int -virStorageSourceInitChainElement(virStorageSourcePtr newelem, - virStorageSourcePtr old, - bool transferLabels) -{ - if (transferLabels && - !newelem->seclabels && - virStorageSourceSeclabelsCopy(newelem, old) < 0) - return -1; - - newelem->shared =3D old->shared; - newelem->readonly =3D old->readonly; - - return 0; -} - - -void -virStorageSourcePoolDefFree(virStorageSourcePoolDefPtr def) -{ - if (!def) - return; - - VIR_FREE(def->pool); - VIR_FREE(def->volume); - - VIR_FREE(def); -} - - -/** - * virStorageSourceGetActualType: - * @def: storage source definition - * - * Returns type of @def. In case when the type is VIR_STORAGE_TYPE_VOLUME - * and virDomainDiskTranslateSourcePool was called on @def the actual type - * of the storage volume is returned rather than VIR_STORAGE_TYPE_VOLUME. - */ -int -virStorageSourceGetActualType(const virStorageSource *def) -{ - if (def->type =3D=3D VIR_STORAGE_TYPE_VOLUME && - def->srcpool && - def->srcpool->actualtype !=3D VIR_STORAGE_TYPE_NONE) - return def->srcpool->actualtype; - - return def->type; -} - - -bool -virStorageSourceIsLocalStorage(const virStorageSource *src) -{ - virStorageType type =3D virStorageSourceGetActualType(src); - - switch (type) { - case VIR_STORAGE_TYPE_FILE: - case VIR_STORAGE_TYPE_BLOCK: - case VIR_STORAGE_TYPE_DIR: - return true; - - case VIR_STORAGE_TYPE_NETWORK: - case VIR_STORAGE_TYPE_VOLUME: - /* While NVMe disks are local, they are not accessible via src->pa= th. - * Therefore, we have to return false here. */ - case VIR_STORAGE_TYPE_NVME: - case VIR_STORAGE_TYPE_LAST: - case VIR_STORAGE_TYPE_NONE: - return false; - } - - return false; -} - - -/** - * virStorageSourceIsEmpty: - * - * @src: disk source to check - * - * Returns true if the guest disk has no associated host storage source - * (such as an empty cdrom drive). - */ -bool -virStorageSourceIsEmpty(virStorageSourcePtr src) -{ - if (virStorageSourceIsLocalStorage(src) && !src->path) - return true; - - if (src->type =3D=3D VIR_STORAGE_TYPE_NONE) - return true; - - if (src->type =3D=3D VIR_STORAGE_TYPE_NETWORK && - src->protocol =3D=3D VIR_STORAGE_NET_PROTOCOL_NONE) - return true; - - return false; -} - - -/** - * virStorageSourceIsBlockLocal: - * @src: disk source definition - * - * Returns true if @src describes a locally accessible block storage sourc= e. - * This includes block devices and host-mapped iSCSI volumes. - */ -bool -virStorageSourceIsBlockLocal(const virStorageSource *src) -{ - return virStorageSourceGetActualType(src) =3D=3D VIR_STORAGE_TYPE_BLOC= K; -} - - -/** - * virStorageSourceBackingStoreClear: - * - * @src: disk source to clear - * - * Clears information about backing store of the current storage file. - */ -void -virStorageSourceBackingStoreClear(virStorageSourcePtr def) -{ - if (!def) - return; - - VIR_FREE(def->relPath); - VIR_FREE(def->backingStoreRaw); - - /* recursively free backing chain */ - virObjectUnref(def->backingStore); - def->backingStore =3D NULL; -} - - -void -virStorageSourceClear(virStorageSourcePtr def) -{ - if (!def) - return; - - VIR_FREE(def->path); - VIR_FREE(def->volume); - VIR_FREE(def->snapshot); - VIR_FREE(def->configFile); - VIR_FREE(def->query); - virStorageSourceNetCookiesClear(def); - virStorageSourcePoolDefFree(def->srcpool); - virBitmapFree(def->features); - VIR_FREE(def->compat); - virStorageEncryptionFree(def->encryption); - virStoragePRDefFree(def->pr); - virStorageSourceNVMeDefFree(def->nvme); - virStorageSourceSeclabelsClear(def); - virStoragePermsFree(def->perms); - VIR_FREE(def->timestamps); - - virStorageSourceSliceFree(def->sliceStorage); - - virStorageNetHostDefFree(def->nhosts, def->hosts); - virStorageAuthDefFree(def->auth); - virObjectUnref(def->privateData); - - VIR_FREE(def->nodestorage); - VIR_FREE(def->nodeformat); - - virStorageSourceBackingStoreClear(def); - - VIR_FREE(def->tlsAlias); - VIR_FREE(def->tlsCertdir); - - VIR_FREE(def->ssh_user); - - virStorageSourceInitiatorClear(&def->initiator); - - /* clear everything except the class header as the object APIs - * will break otherwise */ - memset((char *) def + sizeof(def->parent), 0, - sizeof(*def) - sizeof(def->parent)); -} - - -static void -virStorageSourceDispose(void *obj) -{ - virStorageSourcePtr src =3D obj; - - virStorageSourceClear(src); -} - - -static int -virStorageSourceOnceInit(void) -{ - if (!VIR_CLASS_NEW(virStorageSource, virClassForObject())) - return -1; - - return 0; -} - - -VIR_ONCE_GLOBAL_INIT(virStorageSource); - - -virStorageSourcePtr -virStorageSourceNew(void) -{ - virStorageSourcePtr ret; - - if (virStorageSourceInitialize() < 0) - abort(); - - if (!(ret =3D virObjectNew(virStorageSourceClass))) - abort(); - - return ret; -} - - -/** - * virStorageSourceIsRelative: - * @src: storage source to check - * - * Returns true if given storage source definition is a relative path. - */ -bool -virStorageSourceIsRelative(virStorageSourcePtr src) -{ - virStorageType actual_type =3D virStorageSourceGetActualType(src); - - if (!src->path) - return false; - - switch (actual_type) { - case VIR_STORAGE_TYPE_FILE: - case VIR_STORAGE_TYPE_BLOCK: - case VIR_STORAGE_TYPE_DIR: - return src->path[0] !=3D '/'; - - case VIR_STORAGE_TYPE_NETWORK: - case VIR_STORAGE_TYPE_VOLUME: - case VIR_STORAGE_TYPE_NVME: - case VIR_STORAGE_TYPE_NONE: - case VIR_STORAGE_TYPE_LAST: - return false; - } - - return false; -} - - -static unsigned int -virStorageSourceNetworkDefaultPort(virStorageNetProtocol protocol) -{ - switch (protocol) { - case VIR_STORAGE_NET_PROTOCOL_HTTP: - return 80; - - case VIR_STORAGE_NET_PROTOCOL_HTTPS: - return 443; - - case VIR_STORAGE_NET_PROTOCOL_FTP: - return 21; - - case VIR_STORAGE_NET_PROTOCOL_FTPS: - return 990; - - case VIR_STORAGE_NET_PROTOCOL_TFTP: - return 69; - - case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG: - return 7000; - - case VIR_STORAGE_NET_PROTOCOL_NBD: - return 10809; - - case VIR_STORAGE_NET_PROTOCOL_SSH: - return 22; - - case VIR_STORAGE_NET_PROTOCOL_ISCSI: - return 3260; - - case VIR_STORAGE_NET_PROTOCOL_GLUSTER: - return 24007; - - case VIR_STORAGE_NET_PROTOCOL_RBD: - /* we don't provide a default for RBD */ - return 0; - - case VIR_STORAGE_NET_PROTOCOL_VXHS: - return 9999; - - case VIR_STORAGE_NET_PROTOCOL_LAST: - case VIR_STORAGE_NET_PROTOCOL_NONE: - return 0; - } - - return 0; -} - - -void -virStorageSourceNetworkAssignDefaultPorts(virStorageSourcePtr src) -{ - size_t i; - - for (i =3D 0; i < src->nhosts; i++) { - if (src->hosts[i].transport =3D=3D VIR_STORAGE_NET_HOST_TRANS_TCP = && - src->hosts[i].port =3D=3D 0) - src->hosts[i].port =3D virStorageSourceNetworkDefaultPort(src-= >protocol); - } -} - - -void -virStorageSourceInitiatorParseXML(xmlXPathContextPtr ctxt, - virStorageSourceInitiatorDefPtr initiato= r) -{ - initiator->iqn =3D virXPathString("string(./initiator/iqn/@name)", ctx= t); -} - -void -virStorageSourceInitiatorFormatXML(virStorageSourceInitiatorDefPtr initiat= or, - virBufferPtr buf) -{ - if (!initiator->iqn) - return; - - virBufferAddLit(buf, "\n"); - virBufferAdjustIndent(buf, 2); - virBufferEscapeString(buf, "\n", initiator->iqn); - virBufferAdjustIndent(buf, -2); - virBufferAddLit(buf, "\n"); -} - -int -virStorageSourceInitiatorCopy(virStorageSourceInitiatorDefPtr dest, - const virStorageSourceInitiatorDef *src) -{ - dest->iqn =3D g_strdup(src->iqn); - return 0; -} - -void -virStorageSourceInitiatorClear(virStorageSourceInitiatorDefPtr initiator) -{ - VIR_FREE(initiator->iqn); -} diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h index 557e7da81e..d8a8f36831 100644 --- a/src/util/virstoragefile.h +++ b/src/util/virstoragefile.h @@ -21,444 +21,10 @@ =20 #pragma once =20 -#include "virbitmap.h" -#include "virobject.h" -#include "virseclabel.h" -#include "virstorageencryption.h" -#include "virsecret.h" -#include "virenum.h" -#include "virpci.h" - - -/* Types of disk backends (host resource). Comparable to the public - * virStorageVolType, except we have an undetermined state, don't have - * a netdir type, and add a volume type for reference through a - * storage pool. */ -typedef enum { - VIR_STORAGE_TYPE_NONE, - VIR_STORAGE_TYPE_FILE, - VIR_STORAGE_TYPE_BLOCK, - VIR_STORAGE_TYPE_DIR, - VIR_STORAGE_TYPE_NETWORK, - VIR_STORAGE_TYPE_VOLUME, - VIR_STORAGE_TYPE_NVME, - - VIR_STORAGE_TYPE_LAST -} virStorageType; - -VIR_ENUM_DECL(virStorage); - - -typedef enum { - VIR_STORAGE_FILE_AUTO_SAFE =3D -2, - VIR_STORAGE_FILE_AUTO =3D -1, - VIR_STORAGE_FILE_NONE =3D 0, - VIR_STORAGE_FILE_RAW, - VIR_STORAGE_FILE_DIR, - VIR_STORAGE_FILE_BOCHS, - VIR_STORAGE_FILE_CLOOP, - VIR_STORAGE_FILE_DMG, - VIR_STORAGE_FILE_ISO, - VIR_STORAGE_FILE_VPC, - VIR_STORAGE_FILE_VDI, - - /* Not direct file formats, but used for various drivers */ - VIR_STORAGE_FILE_FAT, - VIR_STORAGE_FILE_VHD, - VIR_STORAGE_FILE_PLOOP, - - /* Not a format, but a marker: all formats below this point have - * libvirt support for following a backing chain */ - VIR_STORAGE_FILE_BACKING, - - VIR_STORAGE_FILE_COW =3D VIR_STORAGE_FILE_BACKING, - VIR_STORAGE_FILE_QCOW, - VIR_STORAGE_FILE_QCOW2, - VIR_STORAGE_FILE_QED, - VIR_STORAGE_FILE_VMDK, - - VIR_STORAGE_FILE_LAST, -} virStorageFileFormat; - -VIR_ENUM_DECL(virStorageFileFormat); - -typedef enum { - VIR_STORAGE_FILE_FEATURE_LAZY_REFCOUNTS =3D 0, - - VIR_STORAGE_FILE_FEATURE_LAST -} virStorageFileFeature; - -VIR_ENUM_DECL(virStorageFileFeature); - -typedef struct _virStoragePerms virStoragePerms; -typedef virStoragePerms *virStoragePermsPtr; -struct _virStoragePerms { - mode_t mode; - uid_t uid; - gid_t gid; - char *label; -}; - - -typedef struct _virStorageTimestamps virStorageTimestamps; -typedef virStorageTimestamps *virStorageTimestampsPtr; -struct _virStorageTimestamps { - struct timespec atime; - struct timespec btime; /* birth time unknown if btime.tv_nsec =3D=3D -= 1 */ - struct timespec ctime; - struct timespec mtime; -}; - - -/* Information related to network storage */ -typedef enum { - VIR_STORAGE_NET_PROTOCOL_NONE, - VIR_STORAGE_NET_PROTOCOL_NBD, - VIR_STORAGE_NET_PROTOCOL_RBD, - VIR_STORAGE_NET_PROTOCOL_SHEEPDOG, - VIR_STORAGE_NET_PROTOCOL_GLUSTER, - VIR_STORAGE_NET_PROTOCOL_ISCSI, - VIR_STORAGE_NET_PROTOCOL_HTTP, - VIR_STORAGE_NET_PROTOCOL_HTTPS, - VIR_STORAGE_NET_PROTOCOL_FTP, - VIR_STORAGE_NET_PROTOCOL_FTPS, - VIR_STORAGE_NET_PROTOCOL_TFTP, - VIR_STORAGE_NET_PROTOCOL_SSH, - VIR_STORAGE_NET_PROTOCOL_VXHS, - - VIR_STORAGE_NET_PROTOCOL_LAST -} virStorageNetProtocol; - -VIR_ENUM_DECL(virStorageNetProtocol); - - -typedef enum { - VIR_STORAGE_NET_HOST_TRANS_TCP, - VIR_STORAGE_NET_HOST_TRANS_UNIX, - VIR_STORAGE_NET_HOST_TRANS_RDMA, - - VIR_STORAGE_NET_HOST_TRANS_LAST -} virStorageNetHostTransport; - -VIR_ENUM_DECL(virStorageNetHostTransport); - -typedef struct _virStorageNetHostDef virStorageNetHostDef; -typedef virStorageNetHostDef *virStorageNetHostDefPtr; -struct _virStorageNetHostDef { - char *name; - unsigned int port; - int transport; /* virStorageNetHostTransport */ - char *socket; /* path to unix socket */ -}; - -typedef struct _virStorageNetCookieDef virStorageNetCookieDef; -typedef virStorageNetCookieDef *virStorageNetCookieDefPtr; -struct _virStorageNetCookieDef { - char *name; - char *value; -}; - -void virStorageNetCookieDefFree(virStorageNetCookieDefPtr def); - -G_DEFINE_AUTOPTR_CLEANUP_FUNC(virStorageNetCookieDef, virStorageNetCookieD= efFree); - -/* Information for a storage volume from a virStoragePool */ - -/* - * Used for volume "type" disk to indicate how to represent - * the disk source if the specified "pool" is of iscsi type. - */ -typedef enum { - VIR_STORAGE_SOURCE_POOL_MODE_DEFAULT =3D 0, - - /* Use the path as it shows up on host, e.g. - * /dev/disk/by-path/ip-$ip-iscsi-$iqn:iscsi.iscsi-pool0-lun-1 - */ - VIR_STORAGE_SOURCE_POOL_MODE_HOST, - - /* Use the URI from the storage pool source element host attribute. E.= g. - * file=3Discsi://demo.org:6000/iqn.1992-01.com.example/1. - */ - VIR_STORAGE_SOURCE_POOL_MODE_DIRECT, - - VIR_STORAGE_SOURCE_POOL_MODE_LAST -} virStorageSourcePoolMode; - -VIR_ENUM_DECL(virStorageSourcePoolMode); - -typedef struct _virStorageSourcePoolDef virStorageSourcePoolDef; -struct _virStorageSourcePoolDef { - char *pool; /* pool name */ - char *volume; /* volume name */ - int voltype; /* virStorageVolType, internal only */ - int pooltype; /* virStoragePoolType from storage_conf.h, internal only= */ - int actualtype; /* virStorageType, internal only */ - int mode; /* virStorageSourcePoolMode, currently makes sense only for = iscsi pool */ -}; -typedef virStorageSourcePoolDef *virStorageSourcePoolDefPtr; - - -typedef enum { - VIR_STORAGE_AUTH_TYPE_NONE, - VIR_STORAGE_AUTH_TYPE_CHAP, - VIR_STORAGE_AUTH_TYPE_CEPHX, - - VIR_STORAGE_AUTH_TYPE_LAST, -} virStorageAuthType; -VIR_ENUM_DECL(virStorageAuth); - -typedef struct _virStorageAuthDef virStorageAuthDef; -typedef virStorageAuthDef *virStorageAuthDefPtr; -struct _virStorageAuthDef { - char *username; - char *secrettype; /* (p=none dis=none) header.from= Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [63.128.21.124]) by mx.zohomail.com with SMTPS id 1607961384865992.8904341029933; Mon, 14 Dec 2020 07:56:24 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-210-7SoHchW2N5ij40A_k3ELLA-1; Mon, 14 Dec 2020 10:56:20 -0500 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 18CA5107ACE6; Mon, 14 Dec 2020 15:56:14 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id E3E9860C17; Mon, 14 Dec 2020 15:56:13 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id AD12B50039; Mon, 14 Dec 2020 15:56:13 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 0BEFtwex028666 for ; Mon, 14 Dec 2020 10:55:58 -0500 Received: by smtp.corp.redhat.com (Postfix) id 6751F5D6D5; Mon, 14 Dec 2020 15:55:58 +0000 (UTC) Received: from antique-work.lan (unknown [10.40.194.243]) by smtp.corp.redhat.com (Postfix) with ESMTP id D62E462467 for ; Mon, 14 Dec 2020 15:55:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1607961383; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=CElhpWrhCXeoWSgdC7ksFNLF02o18KlJRWR/dxSAaBY=; b=Jgc4dgSwwBx8eSQIBKVbs6TERJJ2UIkrqLcvdW7pb5YSvylJ9VpeGMvxYRMsDvElmRHOcG IP6XqO/51/PUHUddOIBJeYA79BlUNBD/PKcevj7h9t6qyT6Ipz4UeT1USLFgvLSSrQahHG 1LBNmECZlkj85JmJ8y7qcnzn7BWVZyQ= X-MC-Unique: 7SoHchW2N5ij40A_k3ELLA-1 From: Pavel Hrdina To: libvir-list@redhat.com Subject: [libvirt PATCH 16/17] util: move virStorageEncryption code into conf Date: Mon, 14 Dec 2020 16:55:36 +0100 Message-Id: In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-loop: libvir-list@redhat.com X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=libvir-list-bounces@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" The code handles XML bits and internal definition and should be in conf directory. Signed-off-by: Pavel Hrdina --- po/POTFILES.in | 2 +- src/conf/domain_conf.h | 2 +- src/conf/meson.build | 1 + src/conf/storage_conf.h | 2 +- .../storage_encryption.c} | 4 ++-- .../storage_encryption.h} | 2 +- src/conf/storage_source.h | 2 +- src/libvirt_private.syms | 12 ++++++------ src/util/meson.build | 1 - 9 files changed, 14 insertions(+), 14 deletions(-) rename src/{util/virstorageencryption.c =3D> conf/storage_encryption.c} (9= 9%) rename src/{util/virstorageencryption.h =3D> conf/storage_encryption.h} (9= 8%) diff --git a/po/POTFILES.in b/po/POTFILES.in index 135198820a..3062a4080c 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -43,6 +43,7 @@ @SRCDIR@src/conf/snapshot_conf.c @SRCDIR@src/conf/storage_adapter_conf.c @SRCDIR@src/conf/storage_conf.c +@SRCDIR@src/conf/storage_encryption.c @SRCDIR@src/conf/storage_source.c @SRCDIR@src/conf/virchrdev.c @SRCDIR@src/conf/virdomainmomentobjlist.c @@ -306,7 +307,6 @@ @SRCDIR@src/util/virscsivhost.c @SRCDIR@src/util/virsecret.c @SRCDIR@src/util/virsocketaddr.c -@SRCDIR@src/util/virstorageencryption.c @SRCDIR@src/util/virstoragefile.c @SRCDIR@src/util/virstring.c @SRCDIR@src/util/virsysinfo.c diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 5c95317501..298a1ac261 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -29,7 +29,7 @@ #include "internal.h" #include "virconftypes.h" #include "capabilities.h" -#include "virstorageencryption.h" +#include "storage_encryption.h" #include "cpu_conf.h" #include "virthread.h" #include "virhash.h" diff --git a/src/conf/meson.build b/src/conf/meson.build index 12efaf56cc..709389c9ba 100644 --- a/src/conf/meson.build +++ b/src/conf/meson.build @@ -54,6 +54,7 @@ storage_conf_sources =3D [ 'storage_adapter_conf.c', 'storage_capabilities.c', 'storage_conf.c', + 'storage_encryption.c', 'storage_source.c', 'virstorageobj.c', ] diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h index 47f2bf602d..7835c7aed8 100644 --- a/src/conf/storage_conf.h +++ b/src/conf/storage_conf.h @@ -22,7 +22,7 @@ #pragma once =20 #include "internal.h" -#include "virstorageencryption.h" +#include "storage_encryption.h" #include "storage_source.h" #include "virbitmap.h" #include "virthread.h" diff --git a/src/util/virstorageencryption.c b/src/conf/storage_encryption.c similarity index 99% rename from src/util/virstorageencryption.c rename to src/conf/storage_encryption.c index c893f0babe..020dfdc6a2 100644 --- a/src/util/virstorageencryption.c +++ b/src/conf/storage_encryption.c @@ -1,5 +1,5 @@ /* - * virstorageencryption.c: volume encryption information + * storage_encryption.c: volume encryption information * * Copyright (C) 2009-2014 Red Hat, Inc. * @@ -27,7 +27,7 @@ =20 #include "virbuffer.h" #include "viralloc.h" -#include "virstorageencryption.h" +#include "storage_encryption.h" #include "virxml.h" #include "virerror.h" #include "viruuid.h" diff --git a/src/util/virstorageencryption.h b/src/conf/storage_encryption.h similarity index 98% rename from src/util/virstorageencryption.h rename to src/conf/storage_encryption.h index 352dd373d6..c5673053e6 100644 --- a/src/util/virstorageencryption.h +++ b/src/conf/storage_encryption.h @@ -1,5 +1,5 @@ /* - * virstorageencryption.h: volume encryption information + * storage_encryption.h: volume encryption information * * Copyright (C) 2009-2011, 2014 Red Hat, Inc. * diff --git a/src/conf/storage_source.h b/src/conf/storage_source.h index 89bba38599..dac2e8b71c 100644 --- a/src/conf/storage_source.h +++ b/src/conf/storage_source.h @@ -21,13 +21,13 @@ =20 #pragma once =20 +#include "storage_encryption.h" #include "virbitmap.h" #include "virenum.h" #include "virobject.h" #include "virpci.h" #include "virseclabel.h" #include "virsecret.h" -#include "virstorageencryption.h" =20 /* Types of disk backends (host resource). Comparable to the public * virStorageVolType, except we have an undetermined state, don't have diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 0b0a57e85d..91f795adfc 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1047,6 +1047,12 @@ virStorageVolTypeFromString; virStorageVolTypeToString; =20 =20 +# conf/storage_encryption.h +virStorageEncryptionFormat; +virStorageEncryptionFree; +virStorageEncryptionParseNode; + + # conf/storage_event.h virStoragePoolEventLifecycleNew; virStoragePoolEventRefreshNew; @@ -3207,12 +3213,6 @@ virSocketAddrSetIPv6AddrNetOrder; virSocketAddrSetPort; =20 =20 -# util/virstorageencryption.h -virStorageEncryptionFormat; -virStorageEncryptionFree; -virStorageEncryptionParseNode; - - # util/virstoragefile.h virStorageFileGetNPIVKey; virStorageFileGetSCSIKey; diff --git a/src/util/meson.build b/src/util/meson.build index b510f0ebe9..c077c5cc99 100644 --- a/src/util/meson.build +++ b/src/util/meson.build @@ -88,7 +88,6 @@ util_sources =3D [ 'virsecret.c', 'virsocket.c', 'virsocketaddr.c', - 'virstorageencryption.c', 'virstoragefile.c', 'virstring.c', 'virsysinfo.c', --=20 2.28.0 From nobody Thu May 16 01:02:08 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 63.128.21.124 as permitted sender) client-ip=63.128.21.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 63.128.21.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1607961401; cv=none; d=zohomail.com; s=zohoarc; b=La9xw75tenbVg+aMcw7iFZ6HqcSrfFTXTb2XtS1/oIgU57kory6ToMLkWOGmzZ2FZvLh4sKQtHlRX+uBBmTBeIgrJd7Ib3kGcqoswQTx81hKMb5VJ/kIiM1Eck1vmsvoTpKaxiA0irbYFeh0PAmn8dz992FljIFCrfoMPE7weQo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1607961401; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=8EwrFIm5amzIJxBGJ3w/QID3G52qkFPSIVczI6/zuFE=; b=a0I+iMlZQGlHNNenweWht2viUfC3CM/U+Brbs57HEdslmoCHkj0Rfz9cOnhx91MfV4+bbdWTOWRx7I3YAQarbSz4qTMyRLJYC3Rjm+/TKskdmy1NhWBpQ9piESIrYbYAnolL2hPYUul/a+upeDNY3lIMszHoMh8xwTQ0y/pfexw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 63.128.21.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [63.128.21.124]) by mx.zohomail.com with SMTPS id 1607961400782538.8318600913948; Mon, 14 Dec 2020 07:56:40 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-250-f1yW1dgUPlmCdHCAKn-d0g-1; Mon, 14 Dec 2020 10:56:34 -0500 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id D123C801AAA; Mon, 14 Dec 2020 15:56:28 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id AE1D018F0A; Mon, 14 Dec 2020 15:56:28 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 781B81809CAC; Mon, 14 Dec 2020 15:56:28 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 0BEFu2Bw028696 for ; Mon, 14 Dec 2020 10:56:02 -0500 Received: by smtp.corp.redhat.com (Postfix) id 80C0A5D6D5; Mon, 14 Dec 2020 15:56:02 +0000 (UTC) Received: from antique-work.lan (unknown [10.40.194.243]) by smtp.corp.redhat.com (Postfix) with ESMTP id F09A762686 for ; Mon, 14 Dec 2020 15:55:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1607961396; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=8EwrFIm5amzIJxBGJ3w/QID3G52qkFPSIVczI6/zuFE=; b=aZBOJbK+/2iYaxW+bJaDP+YhwkHTneUCnLLdJkjU+1GUhxM1tsP+mMVdDv89FYWknfGVNr 6zjbDLL9HC9fWWDdQpBOdi0u9Id7BtEKo5q1/xzGmWeyQg4/cKWqTonKpvdI1B5/8SXDLm P08lLu5PHFVcuqcSTvkgIofEN8jA1QA= X-MC-Unique: f1yW1dgUPlmCdHCAKn-d0g-1 From: Pavel Hrdina To: libvir-list@redhat.com Subject: [libvirt PATCH 17/17] storage_file: use virStorageFile prefix for all functions Date: Mon, 14 Dec 2020 16:55:37 +0100 Message-Id: <4f4fcdde7fbced35bb908476ef8cc77b3f2c8adf.1607960951.git.phrdina@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-loop: libvir-list@redhat.com X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=libvir-list-bounces@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" Now that storage file code is separated from storage source definition it makes sense to rename the functions to make it clear. Signed-off-by: Pavel Hrdina --- src/libvirt_private.syms | 18 +++++----- src/libxl/xen_xl.c | 2 +- src/qemu/qemu_domain.c | 16 ++++----- src/qemu/qemu_driver.c | 6 ++-- src/storage/storage_util.c | 6 ++-- src/storage_file/storage_file.c | 60 ++++++++++++++++----------------- src/storage_file/storage_file.h | 42 +++++++++++------------ tests/qemublocktest.c | 6 ++-- tests/virstoragetest.c | 2 +- 9 files changed, 79 insertions(+), 79 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 91f795adfc..c1a5aab7d6 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1681,6 +1681,7 @@ virStorageFileChainLookup; virStorageFileChown; virStorageFileCreate; virStorageFileDeinit; +virStorageFileFindByNodeName; virStorageFileGetBackingStoreStr; virStorageFileGetMetadata; virStorageFileGetMetadataFromBuf; @@ -1689,8 +1690,13 @@ virStorageFileGetRelativeBackingPath; virStorageFileGetUniqueIdentifier; virStorageFileInit; virStorageFileInitAs; +virStorageFileNewFromBacking; +virStorageFileNewFromBackingAbsolute; virStorageFileParseBackingStoreStr; virStorageFileParseChainIndex; +virStorageFileParseRBDColonString; +virStorageFilePrivateDataFormatRelPath; +virStorageFilePrivateDataParseRelPath; virStorageFileProbeFormat; virStorageFileRead; virStorageFileReportBrokenChain; @@ -1700,15 +1706,9 @@ virStorageFileSupportsBackingChainTraversal; virStorageFileSupportsCreate; virStorageFileSupportsSecurityDriver; virStorageFileUnlink; -virStorageSourceFindByNodeName; -virStorageSourceNewFromBacking; -virStorageSourceNewFromBackingAbsolute; -virStorageSourceParseRBDColonString; -virStorageSourcePrivateDataFormatRelPath; -virStorageSourcePrivateDataParseRelPath; -virStorageSourceUpdateBackingSizes; -virStorageSourceUpdateCapacity; -virStorageSourceUpdatePhysicalSize; +virStorageFileUpdateBackingSizes; +virStorageFileUpdateCapacity; +virStorageFileUpdatePhysicalSize; =20 =20 # storage_file/storage_file_backend.h diff --git a/src/libxl/xen_xl.c b/src/libxl/xen_xl.c index 1f97e6bdd4..f26f9bb5b7 100644 --- a/src/libxl/xen_xl.c +++ b/src/libxl/xen_xl.c @@ -640,7 +640,7 @@ xenParseXLDiskSrc(virDomainDiskDefPtr disk, char *srcst= r) =20 virDomainDiskSetType(disk, VIR_STORAGE_TYPE_NETWORK); disk->src->protocol =3D VIR_STORAGE_NET_PROTOCOL_RBD; - ret =3D virStorageSourceParseRBDColonString(tmpstr, disk->src); + ret =3D virStorageFileParseRBDColonString(tmpstr, disk->src); } else { virDomainDiskSetSource(disk, srcstr); =20 diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 8ddb7b70d2..f193c5e417 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -1894,7 +1894,7 @@ qemuStorageSourcePrivateDataParse(xmlXPathContextPtr = ctxt, return -1; } =20 - if (virStorageSourcePrivateDataParseRelPath(ctxt, src) < 0) + if (virStorageFilePrivateDataParseRelPath(ctxt, src) < 0) return -1; =20 return 0; @@ -1936,7 +1936,7 @@ qemuStorageSourcePrivateDataFormat(virStorageSourcePt= r src, if (src->pr) virBufferAsprintf(buf, "\n", src->p= r->mgralias); =20 - if (virStorageSourcePrivateDataFormatRelPath(src, buf) < 0) + if (virStorageFilePrivateDataFormatRelPath(src, buf) < 0) return -1; =20 if (srcPriv) { @@ -2597,15 +2597,15 @@ qemuDomainObjPrivateXMLParseBlockjobNodename(qemuBl= ockJobDataPtr job, return; =20 if (job->disk && - (*src =3D virStorageSourceFindByNodeName(job->disk->src, nodename)= )) + (*src =3D virStorageFileFindByNodeName(job->disk->src, nodename))) return; =20 if (job->chain && - (*src =3D virStorageSourceFindByNodeName(job->chain, nodename))) + (*src =3D virStorageFileFindByNodeName(job->chain, nodename))) return; =20 if (job->mirrorChain && - (*src =3D virStorageSourceFindByNodeName(job->mirrorChain, nodenam= e))) + (*src =3D virStorageFileFindByNodeName(job->mirrorChain, nodename)= )) return; =20 /* the node was in the XML but was not found in the job definitions */ @@ -9920,11 +9920,11 @@ qemuDomainDiskLookupByNodename(virDomainDefPtr def, for (i =3D 0; i < def->ndisks; i++) { virDomainDiskDefPtr domdisk =3D def->disks[i]; =20 - if ((*src =3D virStorageSourceFindByNodeName(domdisk->src, nodenam= e))) + if ((*src =3D virStorageFileFindByNodeName(domdisk->src, nodename)= )) return domdisk; =20 if (domdisk->mirror && - (*src =3D virStorageSourceFindByNodeName(domdisk->mirror, node= name))) + (*src =3D virStorageFileFindByNodeName(domdisk->mirror, nodena= me))) return domdisk; } =20 @@ -9933,7 +9933,7 @@ qemuDomainDiskLookupByNodename(virDomainDefPtr def, virDomainBackupDiskDefPtr backupdisk =3D backupdef->disks + i; =20 if (backupdisk->store && - (*src =3D virStorageSourceFindByNodeName(backupdisk->store= , nodename))) + (*src =3D virStorageFileFindByNodeName(backupdisk->store, = nodename))) return virDomainDiskByTarget(def, backupdisk->name); } } diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index f6554e1506..0818bb9f89 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -10838,7 +10838,7 @@ qemuDomainStorageUpdatePhysical(virQEMUDriverPtr dr= iver, return -1; } =20 - ret =3D virStorageSourceUpdatePhysicalSize(src, fd, &sb); + ret =3D virStorageFileUpdatePhysicalSize(src, fd, &sb); =20 qemuDomainStorageCloseStat(src, &fd); =20 @@ -10906,10 +10906,10 @@ qemuStorageLimitsRefresh(virQEMUDriverPtr driver, goto cleanup; } =20 - if (virStorageSourceUpdateBackingSizes(src, fd, &sb) < 0) + if (virStorageFileUpdateBackingSizes(src, fd, &sb) < 0) goto cleanup; =20 - if (virStorageSourceUpdateCapacity(src, buf, len) < 0) + if (virStorageFileUpdateCapacity(src, buf, len) < 0) goto cleanup; =20 /* If guest is not using raw disk format and is on a host block diff --git a/src/storage/storage_util.c b/src/storage/storage_util.c index 7616ec63a0..9274e91c47 100644 --- a/src/storage/storage_util.c +++ b/src/storage/storage_util.c @@ -1842,7 +1842,7 @@ storageBackendUpdateVolTargetInfo(virStorageVolType v= oltype, } } =20 - if (virStorageSourceUpdateCapacity(target, buf, len) < 0) + if (virStorageFileUpdateCapacity(target, buf, len) < 0) return -1; } =20 @@ -1906,7 +1906,7 @@ virStorageBackendUpdateVolTargetInfoFD(virStorageSour= cePtr target, char *filecon =3D NULL; #endif =20 - if (virStorageSourceUpdateBackingSizes(target, fd, sb) < 0) + if (virStorageFileUpdateBackingSizes(target, fd, sb) < 0) return -1; =20 if (!target->perms) @@ -3449,7 +3449,7 @@ storageBackendProbeTarget(virStorageSourcePtr target, return -1; =20 if (meta->backingStoreRaw) { - virStorageSourceNewFromBacking(meta, &target->backingStore); + virStorageFileNewFromBacking(meta, &target->backingStore); =20 /* XXX: Remote storage doesn't play nicely with volumes backed by * remote storage. To avoid trouble, just fake the backing store i= s RAW diff --git a/src/storage_file/storage_file.c b/src/storage_file/storage_fil= e.c index e5b2f68420..7de3daec33 100644 --- a/src/storage_file/storage_file.c +++ b/src/storage_file/storage_file.c @@ -1292,8 +1292,8 @@ virStorageFileChainLookup(virStorageSourcePtr chain, =20 =20 static virStorageSourcePtr -virStorageSourceNewFromBackingRelative(virStorageSourcePtr parent, - const char *rel) +virStorageFileNewFromBackingRelative(virStorageSourcePtr parent, + const char *rel) { g_autofree char *dirname =3D NULL; g_autoptr(virStorageSource) def =3D virStorageSourceNew(); @@ -1480,8 +1480,8 @@ virStorageSourceRBDAddHost(virStorageSourcePtr src, =20 =20 int -virStorageSourceParseRBDColonString(const char *rbdstr, - virStorageSourcePtr src) +virStorageFileParseRBDColonString(const char *rbdstr, + virStorageSourcePtr src) { char *p, *e, *next; g_autofree char *options =3D NULL; @@ -1691,7 +1691,7 @@ virStorageSourceParseBackingColon(virStorageSourcePtr= src, break; =20 case VIR_STORAGE_NET_PROTOCOL_RBD: - if (virStorageSourceParseRBDColonString(path, src) < 0) + if (virStorageFileParseRBDColonString(path, src) < 0) return -1; break; =20 @@ -2253,7 +2253,7 @@ virStorageSourceParseBackingJSONRBD(virStorageSourceP= tr src, =20 /* legacy syntax passed via 'filename' option */ if ((filename =3D virJSONValueObjectGetString(json, "filename"))) - return virStorageSourceParseRBDColonString(filename, src); + return virStorageFileParseRBDColonString(filename, src); =20 if (!pool || !image) { virReportError(VIR_ERR_INVALID_ARG, "%s", @@ -2487,7 +2487,7 @@ virStorageSourceParseBackingJSON(virStorageSourcePtr = src, =20 =20 /** - * virStorageSourceNewFromBackingAbsolute + * virStorageFileNewFromBackingAbsolute * @path: string representing absolute location of a storage source * @src: filled with virStorageSource object representing @path * @@ -2497,8 +2497,8 @@ virStorageSourceParseBackingJSON(virStorageSourcePtr = src, * error is reported. */ int -virStorageSourceNewFromBackingAbsolute(const char *path, - virStorageSourcePtr *src) +virStorageFileNewFromBackingAbsolute(const char *path, + virStorageSourcePtr *src) { const char *json; const char *dirpath; @@ -2580,10 +2580,10 @@ virStorageSourceNewFromChild(virStorageSourcePtr pa= rent, *child =3D NULL; =20 if (virFileIsRelative(parentRaw)) { - if (!(def =3D virStorageSourceNewFromBackingRelative(parent, paren= tRaw))) + if (!(def =3D virStorageFileNewFromBackingRelative(parent, parentR= aw))) return -1; } else { - if ((rc =3D virStorageSourceNewFromBackingAbsolute(parentRaw, &def= )) < 0) + if ((rc =3D virStorageFileNewFromBackingAbsolute(parentRaw, &def))= < 0) return -1; } =20 @@ -2611,8 +2611,8 @@ virStorageSourceNewFromChild(virStorageSourcePtr pare= nt, =20 =20 int -virStorageSourceNewFromBacking(virStorageSourcePtr parent, - virStorageSourcePtr *backing) +virStorageFileNewFromBacking(virStorageSourcePtr parent, + virStorageSourcePtr *backing) { int rc; =20 @@ -2639,9 +2639,9 @@ virStorageSourceNewFromBacking(virStorageSourcePtr pa= rent, * Returns 0 on success, -1 on error. No libvirt errors are reported. */ int -virStorageSourceUpdatePhysicalSize(virStorageSourcePtr src, - int fd, - struct stat const *sb) +virStorageFileUpdatePhysicalSize(virStorageSourcePtr src, + int fd, + struct stat const *sb) { off_t end; virStorageType actual_type =3D virStorageSourceGetActualType(src); @@ -2687,9 +2687,9 @@ virStorageSourceUpdatePhysicalSize(virStorageSourcePt= r src, * Returns 0 on success, -1 on error. */ int -virStorageSourceUpdateBackingSizes(virStorageSourcePtr src, - int fd, - struct stat const *sb) +virStorageFileUpdateBackingSizes(virStorageSourcePtr src, + int fd, + struct stat const *sb) { /* Get info for normal formats */ if (S_ISREG(sb->st_mode) || fd =3D=3D -1) { @@ -2750,9 +2750,9 @@ virStorageSourceUpdateBackingSizes(virStorageSourcePt= r src, * Returns 0 on success, -1 on error. */ int -virStorageSourceUpdateCapacity(virStorageSourcePtr src, - char *buf, - ssize_t len) +virStorageFileUpdateCapacity(virStorageSourcePtr src, + char *buf, + ssize_t len) { int format =3D src->format; g_autoptr(virStorageSource) meta =3D NULL; @@ -3066,7 +3066,7 @@ virStorageFileGetRelativeBackingPath(virStorageSource= Ptr top, =20 =20 /** - * virStorageSourceFindByNodeName: + * virStorageFileFindByNodeName: * @top: backing chain top * @nodeName: node name to find in backing chain * @@ -3075,8 +3075,8 @@ virStorageFileGetRelativeBackingPath(virStorageSource= Ptr top, * On failure NULL is returned and no error is reported. */ virStorageSourcePtr -virStorageSourceFindByNodeName(virStorageSourcePtr top, - const char *nodeName) +virStorageFileFindByNodeName(virStorageSourcePtr top, + const char *nodeName) { virStorageSourcePtr tmp; =20 @@ -3091,8 +3091,8 @@ virStorageSourceFindByNodeName(virStorageSourcePtr to= p, =20 =20 int -virStorageSourcePrivateDataParseRelPath(xmlXPathContextPtr ctxt, - virStorageSourcePtr src) +virStorageFilePrivateDataParseRelPath(xmlXPathContextPtr ctxt, + virStorageSourcePtr src) { src->relPath =3D virXPathString("string(./relPath)", ctxt); return 0; @@ -3100,8 +3100,8 @@ virStorageSourcePrivateDataParseRelPath(xmlXPathConte= xtPtr ctxt, =20 =20 int -virStorageSourcePrivateDataFormatRelPath(virStorageSourcePtr src, - virBufferPtr buf) +virStorageFilePrivateDataFormatRelPath(virStorageSourcePtr src, + virBufferPtr buf) { if (src->relPath) virBufferEscapeString(buf, "%s\n", src->relPath= ); @@ -3708,7 +3708,7 @@ virStorageFileGetMetadataRecurse(virStorageSourcePtr = src, } =20 if (src->backingStoreRaw) { - if ((rv =3D virStorageSourceNewFromBacking(src, &backingStore)) < = 0) + if ((rv =3D virStorageFileNewFromBacking(src, &backingStore)) < 0) return -1; =20 /* the backing file would not be usable for VM usage */ diff --git a/src/storage_file/storage_file.h b/src/storage_file/storage_fil= e.h index 181efded87..67eb20a866 100644 --- a/src/storage_file/storage_file.h +++ b/src/storage_file/storage_file.h @@ -74,26 +74,26 @@ virStorageFileChainLookup(virStorageSourcePtr chain, ATTRIBUTE_NONNULL(1); =20 int -virStorageSourceUpdatePhysicalSize(virStorageSourcePtr src, - int fd, - struct stat const *sb); +virStorageFileUpdatePhysicalSize(virStorageSourcePtr src, + int fd, + struct stat const *sb); int -virStorageSourceUpdateBackingSizes(virStorageSourcePtr src, - int fd, - struct stat const *sb); +virStorageFileUpdateBackingSizes(virStorageSourcePtr src, + int fd, + struct stat const *sb); =20 int -virStorageSourceUpdateCapacity(virStorageSourcePtr src, - char *buf, - ssize_t len); +virStorageFileUpdateCapacity(virStorageSourcePtr src, + char *buf, + ssize_t len); =20 int -virStorageSourceNewFromBacking(virStorageSourcePtr parent, - virStorageSourcePtr *backing); +virStorageFileNewFromBacking(virStorageSourcePtr parent, + virStorageSourcePtr *backing); =20 int -virStorageSourceParseRBDColonString(const char *rbdstr, - virStorageSourcePtr src) +virStorageFileParseRBDColonString(const char *rbdstr, + virStorageSourcePtr src) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); =20 typedef int @@ -113,21 +113,21 @@ virStorageFileGetRelativeBackingPath(virStorageSource= Ptr from, ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); =20 int -virStorageSourceNewFromBackingAbsolute(const char *path, - virStorageSourcePtr *src); +virStorageFileNewFromBackingAbsolute(const char *path, + virStorageSourcePtr *src); =20 virStorageSourcePtr -virStorageSourceFindByNodeName(virStorageSourcePtr top, - const char *nodeName) +virStorageFileFindByNodeName(virStorageSourcePtr top, + const char *nodeName) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); =20 int -virStorageSourcePrivateDataParseRelPath(xmlXPathContextPtr ctxt, - virStorageSourcePtr src); +virStorageFilePrivateDataParseRelPath(xmlXPathContextPtr ctxt, + virStorageSourcePtr src); =20 int -virStorageSourcePrivateDataFormatRelPath(virStorageSourcePtr src, - virBufferPtr buf); +virStorageFilePrivateDataFormatRelPath(virStorageSourcePtr src, + virBufferPtr buf); =20 int virStorageFileInit(virStorageSourcePtr src); diff --git a/tests/qemublocktest.c b/tests/qemublocktest.c index ee57449868..b31746fa17 100644 --- a/tests/qemublocktest.c +++ b/tests/qemublocktest.c @@ -106,8 +106,8 @@ testBackingXMLjsonXML(const void *args) =20 protocolwrapper =3D g_strdup_printf("json:%s", propsstr); =20 - if (virStorageSourceNewFromBackingAbsolute(protocolwrapper, - &jsonsrc) < 0) { + if (virStorageFileNewFromBackingAbsolute(protocolwrapper, + &jsonsrc) < 0) { fprintf(stderr, "failed to parse disk json\n"); return -1; } @@ -155,7 +155,7 @@ testJSONtoJSON(const void *args) if (virTestLoadFile(infile, &in) < 0) return -1; =20 - if (virStorageSourceNewFromBackingAbsolute(in, &src) < 0) { + if (virStorageFileNewFromBackingAbsolute(in, &src) < 0) { fprintf(stderr, "failed to parse disk json\n"); return -1; } diff --git a/tests/virstoragetest.c b/tests/virstoragetest.c index 59c03255d4..0882c6c86d 100644 --- a/tests/virstoragetest.c +++ b/tests/virstoragetest.c @@ -592,7 +592,7 @@ testBackingParse(const void *args) if (!data->expect) erc =3D -1; =20 - if ((rc =3D virStorageSourceNewFromBackingAbsolute(data->backing, &src= )) !=3D erc) { + if ((rc =3D virStorageFileNewFromBackingAbsolute(data->backing, &src))= !=3D erc) { fprintf(stderr, "expected return value '%d' actual '%d'\n", erc, r= c); return -1; } --=20 2.28.0