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(©);
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