1 /*
2  * storage_source_conf.c: file utility functions for FS storage backend
3  *
4  * Copyright (C) 2007-2017 Red Hat, Inc.
5  * Copyright (C) 2007-2008 Daniel P. Berrange
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library.  If not, see
19  * <http://www.gnu.org/licenses/>.
20  */
21 
22 #include <config.h>
23 
24 #include "storage_source_conf.h"
25 
26 #include "viralloc.h"
27 #include "virbuffer.h"
28 #include "virerror.h"
29 #include "virlog.h"
30 #include "virstring.h"
31 
32 #define VIR_FROM_THIS VIR_FROM_STORAGE
33 
34 VIR_LOG_INIT("conf.storage_source_conf");
35 
36 
37 static virClass *virStorageSourceClass;
38 
39 
40 VIR_ENUM_IMPL(virStorage,
41               VIR_STORAGE_TYPE_LAST,
42               "none",
43               "file",
44               "block",
45               "dir",
46               "network",
47               "volume",
48               "nvme",
49               "vhostuser"
50 );
51 
52 
53 VIR_ENUM_IMPL(virStorageFileFormat,
54               VIR_STORAGE_FILE_LAST,
55               "none",
56               "raw", "dir", "bochs",
57               "cloop", "dmg", "iso",
58               "vpc", "vdi",
59               /* Not direct file formats, but used for various drivers */
60               "fat", "vhd", "ploop",
61               /* Formats with backing file below here */
62               "cow", "qcow", "qcow2", "qed", "vmdk",
63 );
64 
65 
66 VIR_ENUM_IMPL(virStorageFileFeature,
67               VIR_STORAGE_FILE_FEATURE_LAST,
68               "lazy_refcounts",
69 );
70 
71 
72 VIR_ENUM_IMPL(virStorageNetProtocol,
73               VIR_STORAGE_NET_PROTOCOL_LAST,
74               "none",
75               "nbd",
76               "rbd",
77               "sheepdog",
78               "gluster",
79               "iscsi",
80               "http",
81               "https",
82               "ftp",
83               "ftps",
84               "tftp",
85               "ssh",
86               "vxhs",
87               "nfs",
88 );
89 
90 
91 VIR_ENUM_IMPL(virStorageNetHostTransport,
92               VIR_STORAGE_NET_HOST_TRANS_LAST,
93               "tcp",
94               "unix",
95               "rdma",
96 );
97 
98 
99 VIR_ENUM_IMPL(virStorageSourcePoolMode,
100               VIR_STORAGE_SOURCE_POOL_MODE_LAST,
101               "default",
102               "host",
103               "direct",
104 );
105 
106 
107 VIR_ENUM_IMPL(virStorageAuth,
108               VIR_STORAGE_AUTH_TYPE_LAST,
109               "none", "chap", "ceph",
110 );
111 
112 
113 /**
114  * virStorageSourceIsBacking:
115  * @src: storage source
116  *
117  * Returns true if @src is a eligible backing store structure. Useful
118  * for iterators.
119  */
120 bool
virStorageSourceIsBacking(const virStorageSource * src)121 virStorageSourceIsBacking(const virStorageSource *src)
122 {
123     return src && src->type != VIR_STORAGE_TYPE_NONE;
124 }
125 
126 /**
127  * virStorageSourceHasBacking:
128  * @src: storage source
129  *
130  * Returns true if @src has backing store/chain.
131  */
132 bool
virStorageSourceHasBacking(const virStorageSource * src)133 virStorageSourceHasBacking(const virStorageSource *src)
134 {
135     return virStorageSourceIsBacking(src) && src->backingStore &&
136            src->backingStore->type != VIR_STORAGE_TYPE_NONE;
137 }
138 
139 
140 void
virStorageNetHostDefClear(virStorageNetHostDef * def)141 virStorageNetHostDefClear(virStorageNetHostDef *def)
142 {
143     if (!def)
144         return;
145 
146     VIR_FREE(def->name);
147     VIR_FREE(def->socket);
148 }
149 
150 
151 void
virStorageNetHostDefFree(size_t nhosts,virStorageNetHostDef * hosts)152 virStorageNetHostDefFree(size_t nhosts,
153                          virStorageNetHostDef *hosts)
154 {
155     size_t i;
156 
157     if (!hosts)
158         return;
159 
160     for (i = 0; i < nhosts; i++)
161         virStorageNetHostDefClear(&hosts[i]);
162 
163     g_free(hosts);
164 }
165 
166 
167 static void
virStoragePermsFree(virStoragePerms * def)168 virStoragePermsFree(virStoragePerms *def)
169 {
170     if (!def)
171         return;
172 
173     g_free(def->label);
174     g_free(def);
175 }
176 
177 
178 virStorageNetHostDef *
virStorageNetHostDefCopy(size_t nhosts,virStorageNetHostDef * hosts)179 virStorageNetHostDefCopy(size_t nhosts,
180                          virStorageNetHostDef *hosts)
181 {
182     virStorageNetHostDef *ret = NULL;
183     size_t i;
184 
185     ret = g_new0(virStorageNetHostDef, nhosts);
186 
187     for (i = 0; i < nhosts; i++) {
188         virStorageNetHostDef *src = &hosts[i];
189         virStorageNetHostDef *dst = &ret[i];
190 
191         dst->transport = src->transport;
192         dst->port = src->port;
193 
194         dst->name = g_strdup(src->name);
195         dst->socket = g_strdup(src->socket);
196     }
197 
198     return ret;
199 }
200 
201 
202 void
virStorageAuthDefFree(virStorageAuthDef * authdef)203 virStorageAuthDefFree(virStorageAuthDef *authdef)
204 {
205     if (!authdef)
206         return;
207 
208     g_free(authdef->username);
209     g_free(authdef->secrettype);
210     virSecretLookupDefClear(&authdef->seclookupdef);
211     g_free(authdef);
212 }
213 
214 
215 virStorageAuthDef *
virStorageAuthDefCopy(const virStorageAuthDef * src)216 virStorageAuthDefCopy(const virStorageAuthDef *src)
217 {
218     g_autoptr(virStorageAuthDef) authdef = NULL;
219 
220     authdef = g_new0(virStorageAuthDef, 1);
221 
222     authdef->username = g_strdup(src->username);
223     /* Not present for storage pool, but used for disk source */
224     authdef->secrettype = g_strdup(src->secrettype);
225     authdef->authType = src->authType;
226 
227     virSecretLookupDefCopy(&authdef->seclookupdef, &src->seclookupdef);
228 
229     return g_steal_pointer(&authdef);
230 }
231 
232 
233 virStorageAuthDef *
virStorageAuthDefParse(xmlNodePtr node,xmlXPathContextPtr ctxt)234 virStorageAuthDefParse(xmlNodePtr node,
235                        xmlXPathContextPtr ctxt)
236 {
237     VIR_XPATH_NODE_AUTORESTORE(ctxt)
238     xmlNodePtr secretnode = NULL;
239     g_autoptr(virStorageAuthDef) authdef = NULL;
240     g_autofree char *authtype = NULL;
241 
242     ctxt->node = node;
243 
244     authdef = g_new0(virStorageAuthDef, 1);
245 
246     if (!(authdef->username = virXPathString("string(./@username)", ctxt))) {
247         virReportError(VIR_ERR_XML_ERROR, "%s",
248                        _("missing username for auth"));
249         return NULL;
250     }
251 
252     authdef->authType = VIR_STORAGE_AUTH_TYPE_NONE;
253     authtype = virXPathString("string(./@type)", ctxt);
254     if (authtype) {
255         /* Used by the storage pool instead of the secret type field
256          * to define whether chap or ceph being used
257          */
258         if ((authdef->authType = virStorageAuthTypeFromString(authtype)) < 0) {
259             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
260                            _("unknown auth type '%s'"), authtype);
261             return NULL;
262         }
263     }
264 
265     if (!(secretnode = virXPathNode("./secret ", ctxt))) {
266         virReportError(VIR_ERR_XML_ERROR, "%s",
267                        _("Missing <secret> element in auth"));
268         return NULL;
269     }
270 
271     /* Used by the domain disk xml parsing in order to ensure the
272      * <secret type='%s' value matches the expected secret type for
273      * the style of disk (iscsi is chap, nbd is ceph). For some reason
274      * the virSecretUsageType{From|To}String() cannot be linked here
275      * and because only the domain parsing code cares - just keep
276      * it as a string.
277      */
278     authdef->secrettype = virXMLPropString(secretnode, "type");
279 
280     if (virSecretLookupParseSecret(secretnode, &authdef->seclookupdef) < 0)
281         return NULL;
282 
283     return g_steal_pointer(&authdef);
284 }
285 
286 
287 void
virStorageAuthDefFormat(virBuffer * buf,virStorageAuthDef * authdef)288 virStorageAuthDefFormat(virBuffer *buf,
289                         virStorageAuthDef *authdef)
290 {
291     if (authdef->authType == VIR_STORAGE_AUTH_TYPE_NONE) {
292         virBufferEscapeString(buf, "<auth username='%s'>\n", authdef->username);
293     } else {
294         virBufferAsprintf(buf, "<auth type='%s' ",
295                           virStorageAuthTypeToString(authdef->authType));
296         virBufferEscapeString(buf, "username='%s'>\n", authdef->username);
297     }
298 
299     virBufferAdjustIndent(buf, 2);
300     virSecretLookupFormatSecret(buf, authdef->secrettype,
301                                 &authdef->seclookupdef);
302     virBufferAdjustIndent(buf, -2);
303     virBufferAddLit(buf, "</auth>\n");
304 }
305 
306 
307 void
virStoragePRDefFree(virStoragePRDef * prd)308 virStoragePRDefFree(virStoragePRDef *prd)
309 {
310     if (!prd)
311         return;
312 
313     g_free(prd->path);
314     g_free(prd->mgralias);
315     g_free(prd);
316 }
317 
318 
319 virStoragePRDef *
virStoragePRDefParseXML(xmlXPathContextPtr ctxt)320 virStoragePRDefParseXML(xmlXPathContextPtr ctxt)
321 {
322     virStoragePRDef *prd;
323     virStoragePRDef *ret = NULL;
324     g_autofree char *managed = NULL;
325     g_autofree char *type = NULL;
326     g_autofree char *path = NULL;
327     g_autofree char *mode = NULL;
328 
329     prd = g_new0(virStoragePRDef, 1);
330 
331     if (!(managed = virXPathString("string(./@managed)", ctxt))) {
332         virReportError(VIR_ERR_XML_ERROR, "%s",
333                        _("missing @managed attribute for <reservations/>"));
334         goto cleanup;
335     }
336 
337     if ((prd->managed = virTristateBoolTypeFromString(managed)) <= 0) {
338         virReportError(VIR_ERR_XML_ERROR,
339                        _("invalid value for 'managed': %s"), managed);
340         goto cleanup;
341     }
342 
343     type = virXPathString("string(./source[1]/@type)", ctxt);
344     path = virXPathString("string(./source[1]/@path)", ctxt);
345     mode = virXPathString("string(./source[1]/@mode)", ctxt);
346 
347     if (prd->managed == VIR_TRISTATE_BOOL_NO || type || path || mode) {
348         if (!type) {
349             virReportError(VIR_ERR_XML_ERROR, "%s",
350                            _("missing connection type for <reservations/>"));
351             goto cleanup;
352         }
353 
354         if (!path) {
355             virReportError(VIR_ERR_XML_ERROR, "%s",
356                            _("missing path for <reservations/>"));
357             goto cleanup;
358         }
359 
360         if (!mode) {
361             virReportError(VIR_ERR_XML_ERROR, "%s",
362                            _("missing connection mode for <reservations/>"));
363             goto cleanup;
364         }
365     }
366 
367     if (type && STRNEQ(type, "unix")) {
368         virReportError(VIR_ERR_XML_ERROR,
369                        _("unsupported connection type for <reservations/>: %s"),
370                        type);
371         goto cleanup;
372     }
373 
374     if (mode && STRNEQ(mode, "client")) {
375         virReportError(VIR_ERR_XML_ERROR,
376                        _("unsupported connection mode for <reservations/>: %s"),
377                        mode);
378         goto cleanup;
379     }
380 
381     prd->path = g_steal_pointer(&path);
382     ret = g_steal_pointer(&prd);
383 
384  cleanup:
385     virStoragePRDefFree(prd);
386     return ret;
387 }
388 
389 
390 void
virStoragePRDefFormat(virBuffer * buf,virStoragePRDef * prd,bool migratable)391 virStoragePRDefFormat(virBuffer *buf,
392                       virStoragePRDef *prd,
393                       bool migratable)
394 {
395     virBufferAsprintf(buf, "<reservations managed='%s'",
396                       virTristateBoolTypeToString(prd->managed));
397     if (prd->path &&
398         (prd->managed == VIR_TRISTATE_BOOL_NO || !migratable)) {
399         virBufferAddLit(buf, ">\n");
400         virBufferAdjustIndent(buf, 2);
401         virBufferAddLit(buf, "<source type='unix'");
402         virBufferEscapeString(buf, " path='%s'", prd->path);
403         virBufferAddLit(buf, " mode='client'/>\n");
404         virBufferAdjustIndent(buf, -2);
405         virBufferAddLit(buf, "</reservations>\n");
406     } else {
407         virBufferAddLit(buf, "/>\n");
408     }
409 }
410 
411 
412 bool
virStoragePRDefIsEqual(virStoragePRDef * a,virStoragePRDef * b)413 virStoragePRDefIsEqual(virStoragePRDef *a,
414                        virStoragePRDef *b)
415 {
416     if (!a && !b)
417         return true;
418 
419     if (!a || !b)
420         return false;
421 
422     if (a->managed != b->managed ||
423         STRNEQ_NULLABLE(a->path, b->path))
424         return false;
425 
426     return true;
427 }
428 
429 
430 bool
virStoragePRDefIsManaged(virStoragePRDef * prd)431 virStoragePRDefIsManaged(virStoragePRDef *prd)
432 {
433     return prd && prd->managed == VIR_TRISTATE_BOOL_YES;
434 }
435 
436 
437 bool
virStorageSourceChainHasManagedPR(virStorageSource * src)438 virStorageSourceChainHasManagedPR(virStorageSource *src)
439 {
440     virStorageSource *n;
441 
442     for (n = src; virStorageSourceIsBacking(n); n = n->backingStore) {
443         if (virStoragePRDefIsManaged(n->pr))
444             return true;
445     }
446 
447     return false;
448 }
449 
450 
451 static virStoragePRDef *
virStoragePRDefCopy(virStoragePRDef * src)452 virStoragePRDefCopy(virStoragePRDef *src)
453 {
454     virStoragePRDef *copy = NULL;
455     virStoragePRDef *ret = NULL;
456 
457     copy = g_new0(virStoragePRDef, 1);
458 
459     copy->managed = src->managed;
460 
461     copy->path = g_strdup(src->path);
462     copy->mgralias = g_strdup(src->mgralias);
463 
464     ret = g_steal_pointer(&copy);
465 
466     virStoragePRDefFree(copy);
467     return ret;
468 }
469 
470 
471 static virStorageSourceNVMeDef *
virStorageSourceNVMeDefCopy(const virStorageSourceNVMeDef * src)472 virStorageSourceNVMeDefCopy(const virStorageSourceNVMeDef *src)
473 {
474     virStorageSourceNVMeDef *ret = NULL;
475 
476     ret = g_new0(virStorageSourceNVMeDef, 1);
477 
478     ret->namespc = src->namespc;
479     ret->managed = src->managed;
480     virPCIDeviceAddressCopy(&ret->pciAddr, &src->pciAddr);
481     return ret;
482 }
483 
484 
485 static bool
virStorageSourceNVMeDefIsEqual(const virStorageSourceNVMeDef * a,const virStorageSourceNVMeDef * b)486 virStorageSourceNVMeDefIsEqual(const virStorageSourceNVMeDef *a,
487                                const virStorageSourceNVMeDef *b)
488 {
489     if (!a && !b)
490         return true;
491 
492     if (!a || !b)
493         return false;
494 
495     if (a->namespc != b->namespc ||
496         a->managed != b->managed ||
497         !virPCIDeviceAddressEqual(&a->pciAddr, &b->pciAddr))
498         return false;
499 
500     return true;
501 }
502 
503 
504 void
virStorageSourceNVMeDefFree(virStorageSourceNVMeDef * def)505 virStorageSourceNVMeDefFree(virStorageSourceNVMeDef *def)
506 {
507     if (!def)
508         return;
509 
510     g_free(def);
511 }
512 
513 
514 bool
virStorageSourceChainHasNVMe(const virStorageSource * src)515 virStorageSourceChainHasNVMe(const virStorageSource *src)
516 {
517     const virStorageSource *n;
518 
519     for (n = src; virStorageSourceIsBacking(n); n = n->backingStore) {
520         if (n->type == VIR_STORAGE_TYPE_NVME)
521             return true;
522     }
523 
524     return false;
525 }
526 
527 
528 virSecurityDeviceLabelDef *
virStorageSourceGetSecurityLabelDef(virStorageSource * src,const char * model)529 virStorageSourceGetSecurityLabelDef(virStorageSource *src,
530                                     const char *model)
531 {
532     size_t i;
533 
534     for (i = 0; i < src->nseclabels; i++) {
535         if (STREQ_NULLABLE(src->seclabels[i]->model, model))
536             return src->seclabels[i];
537     }
538 
539     return NULL;
540 }
541 
542 
543 static void
virStorageSourceSeclabelsClear(virStorageSource * def)544 virStorageSourceSeclabelsClear(virStorageSource *def)
545 {
546     size_t i;
547 
548     if (def->seclabels) {
549         for (i = 0; i < def->nseclabels; i++)
550             virSecurityDeviceLabelDefFree(def->seclabels[i]);
551         VIR_FREE(def->seclabels);
552     }
553 }
554 
555 
556 static int
virStorageSourceSeclabelsCopy(virStorageSource * to,const virStorageSource * from)557 virStorageSourceSeclabelsCopy(virStorageSource *to,
558                               const virStorageSource *from)
559 {
560     size_t i;
561 
562     if (from->nseclabels == 0)
563         return 0;
564 
565     to->seclabels = g_new0(virSecurityDeviceLabelDef *, from->nseclabels);
566     to->nseclabels = from->nseclabels;
567 
568     for (i = 0; i < to->nseclabels; i++) {
569         if (!(to->seclabels[i] = virSecurityDeviceLabelDefCopy(from->seclabels[i])))
570             goto error;
571     }
572 
573     return 0;
574 
575  error:
576     virStorageSourceSeclabelsClear(to);
577     return -1;
578 }
579 
580 
581 void
virStorageNetCookieDefFree(virStorageNetCookieDef * def)582 virStorageNetCookieDefFree(virStorageNetCookieDef *def)
583 {
584     if (!def)
585         return;
586 
587     g_free(def->name);
588     g_free(def->value);
589 
590     g_free(def);
591 }
592 
593 
594 static void
virStorageSourceNetCookiesClear(virStorageSource * src)595 virStorageSourceNetCookiesClear(virStorageSource *src)
596 {
597     size_t i;
598 
599     if (!src || !src->cookies)
600         return;
601 
602     for (i = 0; i < src->ncookies; i++)
603         virStorageNetCookieDefFree(src->cookies[i]);
604 
605     g_clear_pointer(&src->cookies, g_free);
606     src->ncookies = 0;
607 }
608 
609 
610 static void
virStorageSourceNetCookiesCopy(virStorageSource * to,const virStorageSource * from)611 virStorageSourceNetCookiesCopy(virStorageSource *to,
612                                const virStorageSource *from)
613 {
614     size_t i;
615 
616     if (from->ncookies == 0)
617         return;
618 
619     to->cookies = g_new0(virStorageNetCookieDef *, from->ncookies);
620     to->ncookies = from->ncookies;
621 
622     for (i = 0; i < from->ncookies; i++) {
623         to->cookies[i]->name = g_strdup(from->cookies[i]->name);
624         to->cookies[i]->value = g_strdup(from->cookies[i]->value);
625     }
626 }
627 
628 
629 /* see https://tools.ietf.org/html/rfc6265#section-4.1.1 */
630 static const char virStorageSourceCookieValueInvalidChars[] =
631  "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"
632  "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"
633  " \",;\\";
634 
635 /* in addition cookie name can't contain these */
636 static const char virStorageSourceCookieNameInvalidChars[] =
637  "()<>@:/[]?={}";
638 
639 static int
virStorageSourceNetCookieValidate(virStorageNetCookieDef * def)640 virStorageSourceNetCookieValidate(virStorageNetCookieDef *def)
641 {
642     g_autofree char *val = g_strdup(def->value);
643     const char *checkval = val;
644     size_t len = strlen(val);
645 
646     /* name must have at least 1 character */
647     if (*(def->name) == '\0') {
648         virReportError(VIR_ERR_XML_ERROR, "%s",
649                        _("cookie name must not be empty"));
650         return -1;
651     }
652 
653     /* check invalid characters in name */
654     if (virStringHasChars(def->name, virStorageSourceCookieValueInvalidChars) ||
655         virStringHasChars(def->name, virStorageSourceCookieNameInvalidChars)) {
656         virReportError(VIR_ERR_XML_ERROR,
657                        _("cookie name '%s' contains invalid characters"),
658                        def->name);
659         return -1;
660     }
661 
662     /* check for optional quotes around the cookie value string */
663     if (val[0] == '"') {
664         if (val[len - 1] != '"') {
665             virReportError(VIR_ERR_XML_ERROR,
666                            _("value of cookie '%s' contains invalid characters"),
667                            def->name);
668             return -1;
669         }
670 
671         val[len - 1] = '\0';
672         checkval++;
673     }
674 
675     /* check invalid characters in value */
676     if (virStringHasChars(checkval, virStorageSourceCookieValueInvalidChars)) {
677         virReportError(VIR_ERR_XML_ERROR,
678                        _("value of cookie '%s' contains invalid characters"),
679                        def->name);
680         return -1;
681     }
682 
683     return 0;
684 }
685 
686 
687 int
virStorageSourceNetCookiesValidate(virStorageSource * src)688 virStorageSourceNetCookiesValidate(virStorageSource *src)
689 {
690     size_t i;
691     size_t j;
692 
693     for (i = 0; i < src->ncookies; i++) {
694         if (virStorageSourceNetCookieValidate(src->cookies[i]) < 0)
695             return -1;
696 
697         for (j = i + 1; j < src->ncookies; j++) {
698             if (STREQ(src->cookies[i]->name, src->cookies[j]->name)) {
699                 virReportError(VIR_ERR_XML_ERROR, _("duplicate cookie '%s'"),
700                                src->cookies[i]->name);
701                 return -1;
702             }
703         }
704     }
705 
706     return 0;
707 }
708 
709 
710 static virStorageTimestamps *
virStorageTimestampsCopy(const virStorageTimestamps * src)711 virStorageTimestampsCopy(const virStorageTimestamps *src)
712 {
713     virStorageTimestamps *ret;
714 
715     ret = g_new0(virStorageTimestamps, 1);
716 
717     memcpy(ret, src, sizeof(*src));
718 
719     return ret;
720 }
721 
722 
723 static virStoragePerms *
virStoragePermsCopy(const virStoragePerms * src)724 virStoragePermsCopy(const virStoragePerms *src)
725 {
726     virStoragePerms *ret;
727 
728     ret = g_new0(virStoragePerms, 1);
729 
730     ret->mode = src->mode;
731     ret->uid = src->uid;
732     ret->gid = src->gid;
733 
734     ret->label = g_strdup(src->label);
735 
736     return ret;
737 }
738 
739 
740 static virStorageSourcePoolDef *
virStorageSourcePoolDefCopy(const virStorageSourcePoolDef * src)741 virStorageSourcePoolDefCopy(const virStorageSourcePoolDef *src)
742 {
743     virStorageSourcePoolDef *ret;
744 
745     ret = g_new0(virStorageSourcePoolDef, 1);
746 
747     ret->voltype = src->voltype;
748     ret->pooltype = src->pooltype;
749     ret->actualtype = src->actualtype;
750     ret->mode = src->mode;
751 
752     ret->pool = g_strdup(src->pool);
753     ret->volume = g_strdup(src->volume);
754 
755     return ret;
756 }
757 
758 
759 static virStorageSourceSlice *
virStorageSourceSliceCopy(const virStorageSourceSlice * src)760 virStorageSourceSliceCopy(const virStorageSourceSlice *src)
761 {
762     virStorageSourceSlice *ret = g_new0(virStorageSourceSlice, 1);
763 
764     ret->offset = src->offset;
765     ret->size = src->size;
766     ret->nodename = g_strdup(src->nodename);
767 
768     return ret;
769 }
770 
771 
772 static void
virStorageSourceSliceFree(virStorageSourceSlice * slice)773 virStorageSourceSliceFree(virStorageSourceSlice *slice)
774 {
775     if (!slice)
776         return;
777 
778     g_free(slice->nodename);
779     g_free(slice);
780 }
781 
782 
783 /**
784  * virStorageSource *:
785  *
786  * Deep-copies a virStorageSource structure. If @backing chain is true
787  * then also copies the backing chain recursively, otherwise just
788  * the top element is copied. This function doesn't copy the
789  * storage driver access structure and thus the struct needs to be initialized
790  * separately.
791  */
792 virStorageSource *
virStorageSourceCopy(const virStorageSource * src,bool backingChain)793 virStorageSourceCopy(const virStorageSource *src,
794                      bool backingChain)
795 {
796     g_autoptr(virStorageSource) def = virStorageSourceNew();
797 
798     def->id = src->id;
799     def->type = src->type;
800     def->protocol = src->protocol;
801     def->format = src->format;
802     def->capacity = src->capacity;
803     def->allocation = src->allocation;
804     def->has_allocation = src->has_allocation;
805     def->physical = src->physical;
806     def->readonly = src->readonly;
807     def->shared = src->shared;
808     def->haveTLS = src->haveTLS;
809     def->tlsFromConfig = src->tlsFromConfig;
810     def->detected = src->detected;
811     def->debugLevel = src->debugLevel;
812     def->debug = src->debug;
813     def->iomode = src->iomode;
814     def->cachemode = src->cachemode;
815     def->discard = src->discard;
816     def->detect_zeroes = src->detect_zeroes;
817     def->sslverify = src->sslverify;
818     def->readahead = src->readahead;
819     def->timeout = src->timeout;
820     def->metadataCacheMaxSize = src->metadataCacheMaxSize;
821 
822     /* storage driver metadata are not copied */
823     def->drv = NULL;
824 
825     def->path = g_strdup(src->path);
826     def->volume = g_strdup(src->volume);
827     def->relPath = g_strdup(src->relPath);
828     def->backingStoreRaw = g_strdup(src->backingStoreRaw);
829     def->backingStoreRawFormat = src->backingStoreRawFormat;
830     def->snapshot = g_strdup(src->snapshot);
831     def->configFile = g_strdup(src->configFile);
832     def->nodeformat = g_strdup(src->nodeformat);
833     def->nodestorage = g_strdup(src->nodestorage);
834     def->compat = g_strdup(src->compat);
835     def->tlsAlias = g_strdup(src->tlsAlias);
836     def->tlsCertdir = g_strdup(src->tlsCertdir);
837     def->query = g_strdup(src->query);
838 
839     if (src->sliceStorage)
840         def->sliceStorage = virStorageSourceSliceCopy(src->sliceStorage);
841 
842     if (src->nhosts) {
843         if (!(def->hosts = virStorageNetHostDefCopy(src->nhosts, src->hosts)))
844             return NULL;
845 
846         def->nhosts = src->nhosts;
847     }
848 
849     virStorageSourceNetCookiesCopy(def, src);
850 
851     if (src->srcpool &&
852         !(def->srcpool = virStorageSourcePoolDefCopy(src->srcpool)))
853         return NULL;
854 
855     if (src->features)
856         def->features = virBitmapNewCopy(src->features);
857 
858     if (src->encryption &&
859         !(def->encryption = virStorageEncryptionCopy(src->encryption)))
860         return NULL;
861 
862     if (src->perms &&
863         !(def->perms = virStoragePermsCopy(src->perms)))
864         return NULL;
865 
866     if (src->timestamps &&
867         !(def->timestamps = virStorageTimestampsCopy(src->timestamps)))
868         return NULL;
869 
870     if (virStorageSourceSeclabelsCopy(def, src) < 0)
871         return NULL;
872 
873     if (src->auth &&
874         !(def->auth = virStorageAuthDefCopy(src->auth)))
875         return NULL;
876 
877     if (src->pr &&
878         !(def->pr = virStoragePRDefCopy(src->pr)))
879         return NULL;
880 
881     if (src->nvme)
882         def->nvme = virStorageSourceNVMeDefCopy(src->nvme);
883 
884     if (virStorageSourceInitiatorCopy(&def->initiator, &src->initiator) < 0)
885         return NULL;
886 
887     if (backingChain && src->backingStore) {
888         if (!(def->backingStore = virStorageSourceCopy(src->backingStore,
889                                                        true)))
890             return NULL;
891     }
892 
893     /* ssh config passthrough for libguestfs */
894     def->ssh_host_key_check_disabled = src->ssh_host_key_check_disabled;
895     def->ssh_user = g_strdup(src->ssh_user);
896 
897     def->nfs_user = g_strdup(src->nfs_user);
898     def->nfs_group = g_strdup(src->nfs_group);
899     def->nfs_uid = src->nfs_uid;
900     def->nfs_gid = src->nfs_gid;
901 
902     return g_steal_pointer(&def);
903 }
904 
905 
906 /**
907  * virStorageSourceIsSameLocation:
908  *
909  * Returns true if the sources @a and @b point to the same storage location.
910  * This does not compare any other configuration option
911  */
912 bool
virStorageSourceIsSameLocation(virStorageSource * a,virStorageSource * b)913 virStorageSourceIsSameLocation(virStorageSource *a,
914                                virStorageSource *b)
915 {
916     size_t i;
917 
918     /* there are multiple possibilities to define an empty source */
919     if (virStorageSourceIsEmpty(a) &&
920         virStorageSourceIsEmpty(b))
921         return true;
922 
923     if (virStorageSourceGetActualType(a) != virStorageSourceGetActualType(b))
924         return false;
925 
926     if (STRNEQ_NULLABLE(a->path, b->path) ||
927         STRNEQ_NULLABLE(a->volume, b->volume) ||
928         STRNEQ_NULLABLE(a->snapshot, b->snapshot))
929         return false;
930 
931     if (a->type == VIR_STORAGE_TYPE_NETWORK) {
932         if (a->protocol != b->protocol ||
933             a->nhosts != b->nhosts)
934             return false;
935 
936         for (i = 0; i < a->nhosts; i++) {
937             if (a->hosts[i].transport != b->hosts[i].transport ||
938                 a->hosts[i].port != b->hosts[i].port ||
939                 STRNEQ_NULLABLE(a->hosts[i].name, b->hosts[i].name) ||
940                 STRNEQ_NULLABLE(a->hosts[i].socket, b->hosts[i].socket))
941                 return false;
942         }
943     }
944 
945     if (a->type == VIR_STORAGE_TYPE_NVME &&
946         !virStorageSourceNVMeDefIsEqual(a->nvme, b->nvme))
947         return false;
948 
949     return true;
950 }
951 
952 
953 /**
954  * virStorageSourceInitChainElement:
955  * @newelem: New backing chain element disk source
956  * @old: Existing top level disk source
957  * @transferLabels: Transfer security labels.
958  *
959  * Transfers relevant information from the existing disk source to the new
960  * backing chain element if they weren't supplied so that labelling info
961  * and possibly other stuff is correct.
962  *
963  * If @transferLabels is true, security labels from the existing disk are copied
964  * to the new disk. Otherwise the default domain imagelabel label will be used.
965  *
966  * Returns 0 on success, -1 on error.
967  */
968 int
virStorageSourceInitChainElement(virStorageSource * newelem,virStorageSource * old,bool transferLabels)969 virStorageSourceInitChainElement(virStorageSource *newelem,
970                                  virStorageSource *old,
971                                  bool transferLabels)
972 {
973     if (transferLabels &&
974         !newelem->seclabels &&
975         virStorageSourceSeclabelsCopy(newelem, old) < 0)
976         return -1;
977 
978     newelem->shared = old->shared;
979     newelem->readonly = old->readonly;
980 
981     return 0;
982 }
983 
984 
985 void
virStorageSourcePoolDefFree(virStorageSourcePoolDef * def)986 virStorageSourcePoolDefFree(virStorageSourcePoolDef *def)
987 {
988     if (!def)
989         return;
990 
991     g_free(def->pool);
992     g_free(def->volume);
993 
994     g_free(def);
995 }
996 
997 
998 /**
999  * virStorageSourceGetActualType:
1000  * @def: storage source definition
1001  *
1002  * Returns type of @def. In case when the type is VIR_STORAGE_TYPE_VOLUME
1003  * and virDomainDiskTranslateSourcePool was called on @def the actual type
1004  * of the storage volume is returned rather than VIR_STORAGE_TYPE_VOLUME.
1005  */
1006 int
virStorageSourceGetActualType(const virStorageSource * def)1007 virStorageSourceGetActualType(const virStorageSource *def)
1008 {
1009     if (def->type == VIR_STORAGE_TYPE_VOLUME &&
1010         def->srcpool &&
1011         def->srcpool->actualtype != VIR_STORAGE_TYPE_NONE)
1012         return def->srcpool->actualtype;
1013 
1014     return def->type;
1015 }
1016 
1017 
1018 bool
virStorageSourceIsLocalStorage(const virStorageSource * src)1019 virStorageSourceIsLocalStorage(const virStorageSource *src)
1020 {
1021     virStorageType type = virStorageSourceGetActualType(src);
1022 
1023     switch (type) {
1024     case VIR_STORAGE_TYPE_FILE:
1025     case VIR_STORAGE_TYPE_BLOCK:
1026     case VIR_STORAGE_TYPE_DIR:
1027         return true;
1028 
1029     case VIR_STORAGE_TYPE_NETWORK:
1030     case VIR_STORAGE_TYPE_VOLUME:
1031         /* While NVMe disks are local, they are not accessible via src->path.
1032          * Therefore, we have to return false here. */
1033     case VIR_STORAGE_TYPE_NVME:
1034     case VIR_STORAGE_TYPE_VHOST_USER:
1035     case VIR_STORAGE_TYPE_LAST:
1036     case VIR_STORAGE_TYPE_NONE:
1037         return false;
1038     }
1039 
1040     return false;
1041 }
1042 
1043 
1044 /**
1045  * virStorageSourceIsEmpty:
1046  *
1047  * @src: disk source to check
1048  *
1049  * Returns true if the guest disk has no associated host storage source
1050  * (such as an empty cdrom drive).
1051  */
1052 bool
virStorageSourceIsEmpty(virStorageSource * src)1053 virStorageSourceIsEmpty(virStorageSource *src)
1054 {
1055     if (virStorageSourceIsLocalStorage(src) && !src->path)
1056         return true;
1057 
1058     if (src->type == VIR_STORAGE_TYPE_NONE)
1059         return true;
1060 
1061     if (src->type == VIR_STORAGE_TYPE_NETWORK &&
1062         src->protocol == VIR_STORAGE_NET_PROTOCOL_NONE)
1063         return true;
1064 
1065     return false;
1066 }
1067 
1068 
1069 /**
1070  * virStorageSourceIsBlockLocal:
1071  * @src: disk source definition
1072  *
1073  * Returns true if @src describes a locally accessible block storage source.
1074  * This includes block devices and host-mapped iSCSI volumes.
1075  */
1076 bool
virStorageSourceIsBlockLocal(const virStorageSource * src)1077 virStorageSourceIsBlockLocal(const virStorageSource *src)
1078 {
1079     return virStorageSourceGetActualType(src) == VIR_STORAGE_TYPE_BLOCK;
1080 }
1081 
1082 
1083 /**
1084  * virStorageSourceBackingStoreClear:
1085  *
1086  * @src: disk source to clear
1087  *
1088  * Clears information about backing store of the current storage file.
1089  */
1090 void
virStorageSourceBackingStoreClear(virStorageSource * def)1091 virStorageSourceBackingStoreClear(virStorageSource *def)
1092 {
1093     if (!def)
1094         return;
1095 
1096     VIR_FREE(def->relPath);
1097     VIR_FREE(def->backingStoreRaw);
1098 
1099     /* recursively free backing chain */
1100     virObjectUnref(def->backingStore);
1101     def->backingStore = NULL;
1102 }
1103 
1104 
1105 void
virStorageSourceClear(virStorageSource * def)1106 virStorageSourceClear(virStorageSource *def)
1107 {
1108     if (!def)
1109         return;
1110 
1111     VIR_FREE(def->path);
1112     VIR_FREE(def->volume);
1113     VIR_FREE(def->snapshot);
1114     VIR_FREE(def->configFile);
1115     VIR_FREE(def->query);
1116     virStorageSourceNetCookiesClear(def);
1117     virStorageSourcePoolDefFree(def->srcpool);
1118     virBitmapFree(def->features);
1119     VIR_FREE(def->compat);
1120     virStorageEncryptionFree(def->encryption);
1121     virStoragePRDefFree(def->pr);
1122     virStorageSourceNVMeDefFree(def->nvme);
1123     virObjectUnref(def->vhostuser);
1124     virStorageSourceSeclabelsClear(def);
1125     virStoragePermsFree(def->perms);
1126     VIR_FREE(def->timestamps);
1127 
1128     virStorageSourceSliceFree(def->sliceStorage);
1129 
1130     virStorageNetHostDefFree(def->nhosts, def->hosts);
1131     virStorageAuthDefFree(def->auth);
1132     virObjectUnref(def->privateData);
1133 
1134     VIR_FREE(def->nodestorage);
1135     VIR_FREE(def->nodeformat);
1136 
1137     virStorageSourceBackingStoreClear(def);
1138 
1139     VIR_FREE(def->tlsAlias);
1140     VIR_FREE(def->tlsCertdir);
1141 
1142     VIR_FREE(def->ssh_user);
1143 
1144     VIR_FREE(def->nfs_user);
1145     VIR_FREE(def->nfs_group);
1146 
1147     virStorageSourceInitiatorClear(&def->initiator);
1148 
1149     /* clear everything except the class header as the object APIs
1150      * will break otherwise */
1151     memset((char *) def + sizeof(def->parent), 0,
1152            sizeof(*def) - sizeof(def->parent));
1153 }
1154 
1155 
1156 static void
virStorageSourceDispose(void * obj)1157 virStorageSourceDispose(void *obj)
1158 {
1159     virStorageSource *src = obj;
1160 
1161     virStorageSourceClear(src);
1162 }
1163 
1164 
1165 static int
virStorageSourceOnceInit(void)1166 virStorageSourceOnceInit(void)
1167 {
1168     if (!VIR_CLASS_NEW(virStorageSource, virClassForObject()))
1169         return -1;
1170 
1171     return 0;
1172 }
1173 
1174 
1175 VIR_ONCE_GLOBAL_INIT(virStorageSource);
1176 
1177 
1178 virStorageSource *
virStorageSourceNew(void)1179 virStorageSourceNew(void)
1180 {
1181     virStorageSource *ret;
1182 
1183     if (virStorageSourceInitialize() < 0)
1184         abort();
1185 
1186     if (!(ret = virObjectNew(virStorageSourceClass)))
1187         abort();
1188 
1189     return ret;
1190 }
1191 
1192 
1193 /**
1194  * virStorageSourceIsRelative:
1195  * @src: storage source to check
1196  *
1197  * Returns true if given storage source definition is a relative path.
1198  */
1199 bool
virStorageSourceIsRelative(virStorageSource * src)1200 virStorageSourceIsRelative(virStorageSource *src)
1201 {
1202     virStorageType actual_type = virStorageSourceGetActualType(src);
1203 
1204     if (!src->path)
1205         return false;
1206 
1207     switch (actual_type) {
1208     case VIR_STORAGE_TYPE_FILE:
1209     case VIR_STORAGE_TYPE_BLOCK:
1210     case VIR_STORAGE_TYPE_DIR:
1211         return !g_path_is_absolute(src->path);
1212 
1213     case VIR_STORAGE_TYPE_NETWORK:
1214     case VIR_STORAGE_TYPE_VOLUME:
1215     case VIR_STORAGE_TYPE_NVME:
1216     case VIR_STORAGE_TYPE_VHOST_USER:
1217     case VIR_STORAGE_TYPE_NONE:
1218     case VIR_STORAGE_TYPE_LAST:
1219         return false;
1220     }
1221 
1222     return false;
1223 }
1224 
1225 
1226 static unsigned int
virStorageSourceNetworkDefaultPort(virStorageNetProtocol protocol)1227 virStorageSourceNetworkDefaultPort(virStorageNetProtocol protocol)
1228 {
1229     switch (protocol) {
1230         case VIR_STORAGE_NET_PROTOCOL_HTTP:
1231             return 80;
1232 
1233         case VIR_STORAGE_NET_PROTOCOL_HTTPS:
1234             return 443;
1235 
1236         case VIR_STORAGE_NET_PROTOCOL_FTP:
1237             return 21;
1238 
1239         case VIR_STORAGE_NET_PROTOCOL_FTPS:
1240             return 990;
1241 
1242         case VIR_STORAGE_NET_PROTOCOL_TFTP:
1243             return 69;
1244 
1245         case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG:
1246             return 7000;
1247 
1248         case VIR_STORAGE_NET_PROTOCOL_NBD:
1249             return 10809;
1250 
1251         case VIR_STORAGE_NET_PROTOCOL_SSH:
1252             return 22;
1253 
1254         case VIR_STORAGE_NET_PROTOCOL_ISCSI:
1255             return 3260;
1256 
1257         case VIR_STORAGE_NET_PROTOCOL_GLUSTER:
1258             return 24007;
1259 
1260         case VIR_STORAGE_NET_PROTOCOL_RBD:
1261             /* we don't provide a default for RBD */
1262             return 0;
1263 
1264         case VIR_STORAGE_NET_PROTOCOL_VXHS:
1265             return 9999;
1266 
1267         case VIR_STORAGE_NET_PROTOCOL_NFS:
1268             /* Port is not supported by NFS, so no default is provided */
1269             return 0;
1270 
1271         case VIR_STORAGE_NET_PROTOCOL_LAST:
1272         case VIR_STORAGE_NET_PROTOCOL_NONE:
1273             return 0;
1274     }
1275 
1276     return 0;
1277 }
1278 
1279 
1280 void
virStorageSourceNetworkAssignDefaultPorts(virStorageSource * src)1281 virStorageSourceNetworkAssignDefaultPorts(virStorageSource *src)
1282 {
1283     size_t i;
1284 
1285     for (i = 0; i < src->nhosts; i++) {
1286         if (src->hosts[i].transport == VIR_STORAGE_NET_HOST_TRANS_TCP &&
1287             src->hosts[i].port == 0)
1288             src->hosts[i].port = virStorageSourceNetworkDefaultPort(src->protocol);
1289     }
1290 }
1291 
1292 
1293 int
virStorageSourcePrivateDataParseRelPath(xmlXPathContextPtr ctxt,virStorageSource * src)1294 virStorageSourcePrivateDataParseRelPath(xmlXPathContextPtr ctxt,
1295                                         virStorageSource *src)
1296 {
1297     src->relPath = virXPathString("string(./relPath)", ctxt);
1298     return 0;
1299 }
1300 
1301 
1302 int
virStorageSourcePrivateDataFormatRelPath(virStorageSource * src,virBuffer * buf)1303 virStorageSourcePrivateDataFormatRelPath(virStorageSource *src,
1304                                          virBuffer *buf)
1305 {
1306     if (src->relPath)
1307         virBufferEscapeString(buf, "<relPath>%s</relPath>\n", src->relPath);
1308 
1309     return 0;
1310 }
1311 
1312 
1313 void
virStorageSourceInitiatorParseXML(xmlXPathContextPtr ctxt,virStorageSourceInitiatorDef * initiator)1314 virStorageSourceInitiatorParseXML(xmlXPathContextPtr ctxt,
1315                                   virStorageSourceInitiatorDef *initiator)
1316 {
1317     initiator->iqn = virXPathString("string(./initiator/iqn/@name)", ctxt);
1318 }
1319 
1320 
1321 void
virStorageSourceInitiatorFormatXML(virStorageSourceInitiatorDef * initiator,virBuffer * buf)1322 virStorageSourceInitiatorFormatXML(virStorageSourceInitiatorDef *initiator,
1323                                    virBuffer *buf)
1324 {
1325     if (!initiator->iqn)
1326         return;
1327 
1328     virBufferAddLit(buf, "<initiator>\n");
1329     virBufferAdjustIndent(buf, 2);
1330     virBufferEscapeString(buf, "<iqn name='%s'/>\n", initiator->iqn);
1331     virBufferAdjustIndent(buf, -2);
1332     virBufferAddLit(buf, "</initiator>\n");
1333 }
1334 
1335 
1336 int
virStorageSourceInitiatorCopy(virStorageSourceInitiatorDef * dest,const virStorageSourceInitiatorDef * src)1337 virStorageSourceInitiatorCopy(virStorageSourceInitiatorDef *dest,
1338                               const virStorageSourceInitiatorDef *src)
1339 {
1340     dest->iqn = g_strdup(src->iqn);
1341     return 0;
1342 }
1343 
1344 
1345 void
virStorageSourceInitiatorClear(virStorageSourceInitiatorDef * initiator)1346 virStorageSourceInitiatorClear(virStorageSourceInitiatorDef *initiator)
1347 {
1348     VIR_FREE(initiator->iqn);
1349 }
1350