1 /*
2  * storage_conf.c: config handling for storage driver
3  *
4  * Copyright (C) 2006-2016 Red Hat, Inc.
5  * Copyright (C) 2006-2008 Daniel P. Berrange
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library.  If not, see
19  * <http://www.gnu.org/licenses/>.
20  */
21 
22 #include <config.h>
23 
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28 
29 #include "virerror.h"
30 #include "datatypes.h"
31 #include "node_device_conf.h"
32 #include "storage_adapter_conf.h"
33 #include "storage_conf.h"
34 #include "storage_source_conf.h"
35 
36 #include "virxml.h"
37 #include "viruuid.h"
38 #include "virbuffer.h"
39 #include "viralloc.h"
40 #include "virfile.h"
41 #include "virscsihost.h"
42 #include "virstring.h"
43 #include "virlog.h"
44 #include "virvhba.h"
45 #include "virutil.h"
46 
47 #define VIR_FROM_THIS VIR_FROM_STORAGE
48 
49 VIR_LOG_INIT("conf.storage_conf");
50 
51 VIR_ENUM_IMPL(virStorageVol,
52               VIR_STORAGE_VOL_LAST,
53               "file", "block", "dir", "network",
54               "netdir", "ploop",
55 );
56 
57 VIR_ENUM_IMPL(virStoragePool,
58               VIR_STORAGE_POOL_LAST,
59               "dir", "fs", "netfs",
60               "logical", "disk", "iscsi",
61               "iscsi-direct", "scsi", "mpath",
62               "rbd", "sheepdog", "gluster",
63               "zfs", "vstorage",
64 );
65 
66 VIR_ENUM_IMPL(virStoragePoolFormatFileSystem,
67               VIR_STORAGE_POOL_FS_LAST,
68               "auto", "ext2", "ext3",
69               "ext4", "ufs", "iso9660", "udf",
70               "gfs", "gfs2", "vfat", "hfs+", "xfs", "ocfs2",
71               "vmfs",
72 );
73 
74 VIR_ENUM_IMPL(virStoragePoolFormatFileSystemNet,
75               VIR_STORAGE_POOL_NETFS_LAST,
76               "auto", "nfs", "glusterfs", "cifs",
77 );
78 
79 VIR_ENUM_IMPL(virStoragePoolFormatDisk,
80               VIR_STORAGE_POOL_DISK_LAST,
81               "unknown", "dos", "dvh", "gpt",
82               "mac", "bsd", "pc98", "sun", "lvm2",
83 );
84 
85 VIR_ENUM_IMPL(virStoragePoolFormatLogical,
86               VIR_STORAGE_POOL_LOGICAL_LAST,
87               "unknown", "lvm2",
88 );
89 
90 
91 VIR_ENUM_IMPL(virStorageVolFormatDisk,
92               VIR_STORAGE_VOL_DISK_LAST,
93               "none", "linux", "fat16",
94               "fat32", "linux-swap",
95               "linux-lvm", "linux-raid",
96               "extended",
97 );
98 
99 VIR_ENUM_IMPL(virStorageVolDefRefreshAllocation,
100               VIR_STORAGE_VOL_DEF_REFRESH_ALLOCATION_LAST,
101               "default", "capacity",
102 );
103 
104 VIR_ENUM_IMPL(virStoragePartedFs,
105               VIR_STORAGE_PARTED_FS_TYPE_LAST,
106               "ext2", "ext2", "fat16",
107               "fat32", "linux-swap",
108               "ext2", "ext2",
109               "extended",
110 );
111 
112 typedef const char *(*virStorageVolFormatToString)(int format);
113 typedef int (*virStorageVolFormatFromString)(const char *format);
114 
115 typedef const char *(*virStoragePoolFormatToString)(int format);
116 typedef int (*virStoragePoolFormatFromString)(const char *format);
117 
118 typedef struct _virStorageVolOptions virStorageVolOptions;
119 struct _virStorageVolOptions {
120     int defaultFormat;
121     int lastFormat;
122     virStorageVolFormatToString formatToString;
123     virStorageVolFormatFromString formatFromString;
124 };
125 
126 /* Flags to indicate mandatory components in the pool source */
127 enum {
128     VIR_STORAGE_POOL_SOURCE_HOST            = (1 << 0),
129     VIR_STORAGE_POOL_SOURCE_DEVICE          = (1 << 1),
130     VIR_STORAGE_POOL_SOURCE_DIR             = (1 << 2),
131     VIR_STORAGE_POOL_SOURCE_ADAPTER         = (1 << 3),
132     VIR_STORAGE_POOL_SOURCE_NAME            = (1 << 4),
133     VIR_STORAGE_POOL_SOURCE_INITIATOR_IQN   = (1 << 5),
134     VIR_STORAGE_POOL_SOURCE_NETWORK         = (1 << 6),
135 };
136 
137 typedef struct _virStoragePoolOptions virStoragePoolOptions;
138 struct _virStoragePoolOptions {
139     unsigned int flags;
140     int defaultFormat;
141     int lastFormat;
142 
143     virXMLNamespace ns;
144 
145     virStoragePoolFormatToString formatToString;
146     virStoragePoolFormatFromString formatFromString;
147 };
148 
149 typedef struct _virStoragePoolTypeInfo virStoragePoolTypeInfo;
150 struct _virStoragePoolTypeInfo {
151     int poolType;
152     virStoragePoolOptions poolOptions;
153     virStorageVolOptions volOptions;
154 };
155 
156 
157 static int
virStorageVolumeFormatFromString(const char * format)158 virStorageVolumeFormatFromString(const char *format)
159 {
160     int ret = virStorageFileFormatTypeFromString(format);
161     if (ret == VIR_STORAGE_FILE_NONE)
162         return -1;
163     return ret;
164 }
165 
166 
167 static virStoragePoolTypeInfo poolTypeInfo[] = {
168     {.poolType = VIR_STORAGE_POOL_LOGICAL,
169      .poolOptions = {
170          .flags = (VIR_STORAGE_POOL_SOURCE_NAME |
171                    VIR_STORAGE_POOL_SOURCE_DEVICE),
172          .defaultFormat = VIR_STORAGE_POOL_LOGICAL_LVM2,
173          .lastFormat = VIR_STORAGE_POOL_LOGICAL_LAST,
174          .formatFromString = virStoragePoolFormatLogicalTypeFromString,
175          .formatToString = virStoragePoolFormatLogicalTypeToString,
176      },
177     },
178     {.poolType = VIR_STORAGE_POOL_DIR,
179      .volOptions = {
180          .defaultFormat = VIR_STORAGE_FILE_RAW,
181          .lastFormat = VIR_STORAGE_FILE_LAST,
182          .formatFromString = virStorageVolumeFormatFromString,
183          .formatToString = virStorageFileFormatTypeToString,
184      },
185     },
186     {.poolType = VIR_STORAGE_POOL_FS,
187      .poolOptions = {
188          .flags = (VIR_STORAGE_POOL_SOURCE_DEVICE),
189          .defaultFormat = VIR_STORAGE_POOL_FS_AUTO,
190          .lastFormat = VIR_STORAGE_POOL_FS_LAST,
191          .formatFromString = virStoragePoolFormatFileSystemTypeFromString,
192          .formatToString = virStoragePoolFormatFileSystemTypeToString,
193       },
194       .volOptions = {
195          .defaultFormat = VIR_STORAGE_FILE_RAW,
196          .lastFormat = VIR_STORAGE_FILE_LAST,
197          .formatFromString = virStorageVolumeFormatFromString,
198          .formatToString = virStorageFileFormatTypeToString,
199       },
200     },
201     {.poolType = VIR_STORAGE_POOL_NETFS,
202      .poolOptions = {
203          .flags = (VIR_STORAGE_POOL_SOURCE_HOST |
204                    VIR_STORAGE_POOL_SOURCE_DIR),
205          .defaultFormat = VIR_STORAGE_POOL_NETFS_AUTO,
206          .lastFormat = VIR_STORAGE_POOL_NETFS_LAST,
207          .formatFromString = virStoragePoolFormatFileSystemNetTypeFromString,
208          .formatToString = virStoragePoolFormatFileSystemNetTypeToString,
209       },
210       .volOptions = {
211          .defaultFormat = VIR_STORAGE_FILE_RAW,
212          .lastFormat = VIR_STORAGE_FILE_LAST,
213          .formatFromString = virStorageVolumeFormatFromString,
214          .formatToString = virStorageFileFormatTypeToString,
215       },
216     },
217     {.poolType = VIR_STORAGE_POOL_ISCSI,
218      .poolOptions = {
219          .flags = (VIR_STORAGE_POOL_SOURCE_HOST |
220                    VIR_STORAGE_POOL_SOURCE_DEVICE |
221                    VIR_STORAGE_POOL_SOURCE_INITIATOR_IQN),
222       },
223     },
224     {.poolType = VIR_STORAGE_POOL_ISCSI_DIRECT,
225      .poolOptions = {
226          .flags = (VIR_STORAGE_POOL_SOURCE_HOST |
227                    VIR_STORAGE_POOL_SOURCE_DEVICE |
228                    VIR_STORAGE_POOL_SOURCE_NETWORK |
229                    VIR_STORAGE_POOL_SOURCE_INITIATOR_IQN),
230       },
231     },
232     {.poolType = VIR_STORAGE_POOL_SCSI,
233      .poolOptions = {
234          .flags = (VIR_STORAGE_POOL_SOURCE_ADAPTER),
235      },
236     },
237     {.poolType = VIR_STORAGE_POOL_RBD,
238      .poolOptions = {
239          .flags = (VIR_STORAGE_POOL_SOURCE_HOST |
240                    VIR_STORAGE_POOL_SOURCE_NETWORK |
241                    VIR_STORAGE_POOL_SOURCE_NAME),
242       },
243       .volOptions = {
244           .defaultFormat = VIR_STORAGE_FILE_RAW,
245           .formatFromString = virStorageVolumeFormatFromString,
246           .formatToString = virStorageFileFormatTypeToString,
247       }
248     },
249     {.poolType = VIR_STORAGE_POOL_SHEEPDOG,
250      .poolOptions = {
251          .flags = (VIR_STORAGE_POOL_SOURCE_HOST |
252                    VIR_STORAGE_POOL_SOURCE_NETWORK |
253                    VIR_STORAGE_POOL_SOURCE_NAME),
254      },
255     },
256     {.poolType = VIR_STORAGE_POOL_GLUSTER,
257      .poolOptions = {
258          .flags = (VIR_STORAGE_POOL_SOURCE_HOST |
259                    VIR_STORAGE_POOL_SOURCE_NETWORK |
260                    VIR_STORAGE_POOL_SOURCE_NAME |
261                    VIR_STORAGE_POOL_SOURCE_DIR),
262      },
263      .volOptions = {
264          .defaultFormat = VIR_STORAGE_FILE_RAW,
265          .lastFormat = VIR_STORAGE_FILE_LAST,
266          .formatToString = virStorageFileFormatTypeToString,
267          .formatFromString = virStorageVolumeFormatFromString,
268      }
269     },
270     {.poolType = VIR_STORAGE_POOL_MPATH,
271     },
272     {.poolType = VIR_STORAGE_POOL_DISK,
273      .poolOptions = {
274          .flags = (VIR_STORAGE_POOL_SOURCE_DEVICE),
275          .defaultFormat = VIR_STORAGE_POOL_DISK_UNKNOWN,
276          .lastFormat = VIR_STORAGE_POOL_DISK_LAST,
277          .formatFromString = virStoragePoolFormatDiskTypeFromString,
278          .formatToString = virStoragePoolFormatDiskTypeToString,
279      },
280      .volOptions = {
281          .defaultFormat = VIR_STORAGE_VOL_DISK_NONE,
282          .lastFormat = VIR_STORAGE_VOL_DISK_LAST,
283          .formatFromString = virStorageVolFormatDiskTypeFromString,
284          .formatToString = virStorageVolFormatDiskTypeToString,
285      },
286     },
287     {.poolType = VIR_STORAGE_POOL_ZFS,
288      .poolOptions = {
289          .flags = (VIR_STORAGE_POOL_SOURCE_NAME |
290                    VIR_STORAGE_POOL_SOURCE_DEVICE),
291      },
292     },
293     {.poolType = VIR_STORAGE_POOL_VSTORAGE,
294      .poolOptions = {
295         .flags = VIR_STORAGE_POOL_SOURCE_NAME,
296      },
297      .volOptions = {
298         .defaultFormat = VIR_STORAGE_FILE_RAW,
299         .lastFormat = VIR_STORAGE_FILE_LAST,
300         .formatFromString = virStorageVolumeFormatFromString,
301         .formatToString = virStorageFileFormatTypeToString,
302      },
303     },
304 };
305 
306 
307 static virStoragePoolTypeInfo *
virStoragePoolTypeInfoLookup(int type)308 virStoragePoolTypeInfoLookup(int type)
309 {
310     size_t i;
311     for (i = 0; i < G_N_ELEMENTS(poolTypeInfo); i++)
312         if (poolTypeInfo[i].poolType == type)
313             return &poolTypeInfo[i];
314 
315     virReportError(VIR_ERR_INTERNAL_ERROR,
316                    _("missing backend for pool type %d"), type);
317     return NULL;
318 }
319 
320 
321 static virStoragePoolOptions *
virStoragePoolOptionsForPoolType(int type)322 virStoragePoolOptionsForPoolType(int type)
323 {
324     virStoragePoolTypeInfo *backend = virStoragePoolTypeInfoLookup(type);
325     if (backend == NULL)
326         return NULL;
327     return &backend->poolOptions;
328 }
329 
330 
331 /* virStoragePoolOptionsPoolTypeSetXMLNamespace:
332  * @type: virStoragePoolType
333  * @ns: xmlopt namespace pointer
334  *
335  * Store the @ns in the pool options for the particular backend.
336  * This allows the parse/format code to then directly call the Namespace
337  * method space (parse, format, href, free) as needed during processing.
338  *
339  * Returns: 0 on success, -1 on failure.
340  */
341 int
virStoragePoolOptionsPoolTypeSetXMLNamespace(int type,virXMLNamespace * ns)342 virStoragePoolOptionsPoolTypeSetXMLNamespace(int type,
343                                              virXMLNamespace *ns)
344 {
345     virStoragePoolTypeInfo *backend = virStoragePoolTypeInfoLookup(type);
346 
347     if (!backend)
348         return -1;
349 
350     backend->poolOptions.ns = *ns;
351 
352     return 0;
353 }
354 
355 
356 static virStorageVolOptions *
virStorageVolOptionsForPoolType(int type)357 virStorageVolOptionsForPoolType(int type)
358 {
359     virStoragePoolTypeInfo *backend = virStoragePoolTypeInfoLookup(type);
360     if (backend == NULL)
361         return NULL;
362     return &backend->volOptions;
363 }
364 
365 
366 int
virStoragePoolOptionsFormatPool(virBuffer * buf,int type)367 virStoragePoolOptionsFormatPool(virBuffer *buf,
368                                 int type)
369 {
370     virStoragePoolOptions *poolOptions;
371 
372     if (!(poolOptions = virStoragePoolOptionsForPoolType(type)))
373         return -1;
374 
375     if (!poolOptions->formatToString)
376         return 0;
377 
378     virBufferAddLit(buf, "<poolOptions>\n");
379     virBufferAdjustIndent(buf, 2);
380 
381     if (poolOptions->formatToString) {
382         size_t i;
383 
384         virBufferAsprintf(buf, "<defaultFormat type='%s'/>\n",
385                           (poolOptions->formatToString)(poolOptions->defaultFormat));
386 
387         virBufferAddLit(buf, "<enum name='sourceFormatType'>\n");
388         virBufferAdjustIndent(buf, 2);
389 
390         for (i = 0; i < poolOptions->lastFormat; i++)
391             virBufferAsprintf(buf, "<value>%s</value>\n",
392                               (poolOptions->formatToString)(i));
393 
394         virBufferAdjustIndent(buf, -2);
395         virBufferAddLit(buf, "</enum>\n");
396     }
397 
398     virBufferAdjustIndent(buf, -2);
399     virBufferAddLit(buf, "</poolOptions>\n");
400     return 0;
401 }
402 
403 
404 int
virStoragePoolOptionsFormatVolume(virBuffer * buf,int type)405 virStoragePoolOptionsFormatVolume(virBuffer *buf,
406                                   int type)
407 {
408     size_t i;
409     virStorageVolOptions *volOptions;
410 
411     if (!(volOptions = virStorageVolOptionsForPoolType(type)))
412         return -1;
413 
414     if (!volOptions->formatToString)
415         return 0;
416 
417     virBufferAddLit(buf, "<volOptions>\n");
418     virBufferAdjustIndent(buf, 2);
419 
420     virBufferAsprintf(buf, "<defaultFormat type='%s'/>\n",
421                       (volOptions->formatToString)(volOptions->defaultFormat));
422 
423     virBufferAddLit(buf, "<enum name='targetFormatType'>\n");
424     virBufferAdjustIndent(buf, 2);
425 
426     for (i = 0; i < volOptions->lastFormat; i++)
427         virBufferAsprintf(buf, "<value>%s</value>\n",
428                           (volOptions->formatToString)(i));
429 
430     virBufferAdjustIndent(buf, -2);
431     virBufferAddLit(buf, "</enum>\n");
432 
433     virBufferAdjustIndent(buf, -2);
434     virBufferAddLit(buf, "</volOptions>\n");
435 
436     return 0;
437 }
438 
439 
440 void
virStorageVolDefFree(virStorageVolDef * def)441 virStorageVolDefFree(virStorageVolDef *def)
442 {
443     size_t i;
444 
445     if (!def)
446         return;
447 
448     g_free(def->name);
449     g_free(def->key);
450 
451     for (i = 0; i < def->source.nextent; i++)
452         g_free(def->source.extents[i].path);
453     g_free(def->source.extents);
454 
455     virStorageSourceClear(&def->target);
456     g_free(def);
457 }
458 
459 
460 void
virStoragePoolSourceDeviceClear(virStoragePoolSourceDevice * dev)461 virStoragePoolSourceDeviceClear(virStoragePoolSourceDevice *dev)
462 {
463     VIR_FREE(dev->freeExtents);
464     VIR_FREE(dev->path);
465 }
466 
467 
468 void
virStoragePoolSourceClear(virStoragePoolSource * source)469 virStoragePoolSourceClear(virStoragePoolSource *source)
470 {
471     size_t i;
472 
473     if (!source)
474         return;
475 
476     for (i = 0; i < source->nhost; i++)
477         VIR_FREE(source->hosts[i].name);
478     VIR_FREE(source->hosts);
479 
480     for (i = 0; i < source->ndevice; i++)
481         virStoragePoolSourceDeviceClear(&source->devices[i]);
482     VIR_FREE(source->devices);
483     VIR_FREE(source->dir);
484     VIR_FREE(source->name);
485     virStorageAdapterClear(&source->adapter);
486     virStorageSourceInitiatorClear(&source->initiator);
487     virStorageAuthDefFree(source->auth);
488     VIR_FREE(source->vendor);
489     VIR_FREE(source->product);
490 }
491 
492 
493 void
virStoragePoolSourceFree(virStoragePoolSource * source)494 virStoragePoolSourceFree(virStoragePoolSource *source)
495 {
496     virStoragePoolSourceClear(source);
497     g_free(source);
498 }
499 
500 
501 void
virStoragePoolDefFree(virStoragePoolDef * def)502 virStoragePoolDefFree(virStoragePoolDef *def)
503 {
504     if (!def)
505         return;
506 
507     g_free(def->name);
508 
509     virStoragePoolSourceClear(&def->source);
510 
511     g_free(def->target.path);
512     g_free(def->target.perms.label);
513     g_free(def->refresh);
514     if (def->namespaceData && def->ns.free)
515         (def->ns.free)(def->namespaceData);
516     g_free(def);
517 }
518 
519 
520 static int
virStoragePoolDefParseSource(xmlXPathContextPtr ctxt,virStoragePoolSource * source,int pool_type,xmlNodePtr node)521 virStoragePoolDefParseSource(xmlXPathContextPtr ctxt,
522                              virStoragePoolSource *source,
523                              int pool_type,
524                              xmlNodePtr node)
525 {
526     xmlNodePtr authnode;
527     xmlNodePtr adapternode;
528     int nsource;
529     size_t i;
530     virStoragePoolOptions *options;
531     int n;
532     g_autoptr(virStorageAuthDef) authdef = NULL;
533     g_autofree char *ver = NULL;
534     g_autofree xmlNodePtr *nodeset = NULL;
535     g_autofree char *sourcedir = NULL;
536     VIR_XPATH_NODE_AUTORESTORE(ctxt)
537 
538     ctxt->node = node;
539 
540     if ((options = virStoragePoolOptionsForPoolType(pool_type)) == NULL)
541         return -1;
542 
543     source->name = virXPathString("string(./name)", ctxt);
544     if (pool_type == VIR_STORAGE_POOL_RBD && source->name == NULL) {
545         virReportError(VIR_ERR_XML_ERROR, "%s",
546                        _("element 'name' is mandatory for RBD pool"));
547         return -1;
548     }
549 
550     if (options->formatFromString) {
551         g_autofree char *format = NULL;
552 
553         format = virXPathString("string(./format/@type)", ctxt);
554         if (format == NULL)
555             source->format = options->defaultFormat;
556         else
557             source->format = options->formatFromString(format);
558 
559         if (source->format < 0) {
560             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
561                            _("unknown pool format type %s"), format);
562             return -1;
563         }
564     }
565 
566     if ((n = virXPathNodeSet("./host", ctxt, &nodeset)) < 0)
567         return -1;
568 
569     if (n) {
570         source->hosts = g_new0(virStoragePoolSourceHost, n);
571         source->nhost = n;
572 
573         for (i = 0; i < source->nhost; i++) {
574             source->hosts[i].name = virXMLPropString(nodeset[i], "name");
575             if (!source->hosts[i].name) {
576                 virReportError(VIR_ERR_XML_ERROR, "%s",
577                                _("missing storage pool host name"));
578                 return -1;
579             }
580 
581             if (virXMLPropInt(nodeset[i], "port", 10, VIR_XML_PROP_NONE,
582                               &source->hosts[i].port, 0) < 0)
583                 return -1;
584         }
585     }
586 
587     VIR_FREE(nodeset);
588 
589     virStorageSourceInitiatorParseXML(ctxt, &source->initiator);
590 
591     nsource = virXPathNodeSet("./device", ctxt, &nodeset);
592     if (nsource < 0)
593         return -1;
594 
595     for (i = 0; i < nsource; i++) {
596         virStoragePoolSourceDevice dev = { .path = NULL };
597         dev.path = virXMLPropString(nodeset[i], "path");
598 
599         if (dev.path == NULL) {
600             virReportError(VIR_ERR_XML_ERROR, "%s",
601                            _("missing storage pool source device path"));
602             return -1;
603         }
604 
605         if (virXMLPropTristateBool(nodeset[i], "part_separator",
606                                    VIR_XML_PROP_NONE,
607                                    &dev.part_separator) < 0) {
608             virStoragePoolSourceDeviceClear(&dev);
609             return -1;
610         }
611 
612         VIR_APPEND_ELEMENT(source->devices, source->ndevice, dev);
613     }
614 
615     sourcedir = virXPathString("string(./dir/@path)", ctxt);
616     if (sourcedir)
617         source->dir = virFileSanitizePath(sourcedir);
618     /* In gluster, a missing dir defaults to "/" */
619     if (!source->dir && pool_type == VIR_STORAGE_POOL_GLUSTER)
620         source->dir = g_strdup("/");
621 
622     if ((adapternode = virXPathNode("./adapter", ctxt))) {
623         if (virStorageAdapterParseXML(&source->adapter, adapternode, ctxt) < 0)
624             return -1;
625     }
626 
627     if ((authnode = virXPathNode("./auth", ctxt))) {
628         if (!(authdef = virStorageAuthDefParse(authnode, ctxt)))
629             return -1;
630 
631         if (authdef->authType == VIR_STORAGE_AUTH_TYPE_NONE) {
632             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
633                            _("storage pool missing auth type"));
634             return -1;
635         }
636 
637         source->auth = g_steal_pointer(&authdef);
638     }
639 
640     /* Option protocol version string (NFSvN) */
641     if ((ver = virXPathString("string(./protocol/@ver)", ctxt))) {
642         if ((source->format != VIR_STORAGE_POOL_NETFS_NFS) &&
643             (source->format != VIR_STORAGE_POOL_NETFS_AUTO)) {
644             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
645                            _("storage pool protocol ver unsupported for "
646                              "pool type '%s'"),
647                            virStoragePoolFormatFileSystemNetTypeToString(source->format));
648             return -1;
649         }
650         if (virStrToLong_uip(ver, NULL, 0, &source->protocolVer) < 0) {
651             virReportError(VIR_ERR_XML_ERROR,
652                            _("storage pool protocol ver '%s' is malformed"),
653                            ver);
654             return -1;
655         }
656     }
657 
658     source->vendor = virXPathString("string(./vendor/@name)", ctxt);
659     source->product = virXPathString("string(./product/@name)", ctxt);
660 
661     return 0;
662 }
663 
664 
665 virStoragePoolSource *
virStoragePoolDefParseSourceString(const char * srcSpec,int pool_type)666 virStoragePoolDefParseSourceString(const char *srcSpec,
667                                    int pool_type)
668 {
669     g_autoptr(xmlDoc) doc = NULL;
670     g_autoptr(xmlXPathContext) xpath_ctxt = NULL;
671     g_autoptr(virStoragePoolSource) def = NULL;
672 
673     if (!(doc = virXMLParseStringCtxtRoot(srcSpec,
674                                           _("(storage_source_specification)"),
675                                           "source",
676                                           &xpath_ctxt)))
677         return NULL;
678 
679     def = g_new0(virStoragePoolSource, 1);
680 
681     if (virStoragePoolDefParseSource(xpath_ctxt, def, pool_type,
682                                      xpath_ctxt->node) < 0)
683         return NULL;
684 
685     return g_steal_pointer(&def);
686 }
687 
688 
689 static int
virStorageDefParsePerms(xmlXPathContextPtr ctxt,virStoragePerms * perms,const char * permxpath)690 virStorageDefParsePerms(xmlXPathContextPtr ctxt,
691                         virStoragePerms *perms,
692                         const char *permxpath)
693 {
694     long long val;
695     VIR_XPATH_NODE_AUTORESTORE(ctxt)
696     xmlNodePtr node;
697     g_autofree char *mode = NULL;
698 
699     node = virXPathNode(permxpath, ctxt);
700     if (node == NULL) {
701         /* Set default values if there is not <permissions> element */
702         perms->mode = (mode_t) -1;
703         perms->uid = (uid_t) -1;
704         perms->gid = (gid_t) -1;
705         perms->label = NULL;
706         return 0;
707     }
708 
709     ctxt->node = node;
710 
711     if ((mode = virXPathString("string(./mode)", ctxt))) {
712         int tmp;
713 
714         if (virStrToLong_i(mode, NULL, 8, &tmp) < 0 || (tmp & ~0777)) {
715             virReportError(VIR_ERR_XML_ERROR, "%s",
716                            _("malformed octal mode"));
717             return -1;
718         }
719         perms->mode = tmp;
720     } else {
721         perms->mode = (mode_t) -1;
722     }
723 
724     if (virXPathNode("./owner", ctxt) == NULL) {
725         perms->uid = (uid_t) -1;
726     } else {
727         /* We previously could output -1, so continue to parse it */
728         if (virXPathLongLong("number(./owner)", ctxt, &val) < 0 ||
729             ((uid_t)val != val &&
730              val != -1)) {
731             virReportError(VIR_ERR_XML_ERROR, "%s",
732                            _("malformed owner element"));
733             return -1;
734         }
735 
736         perms->uid = val;
737     }
738 
739     if (virXPathNode("./group", ctxt) == NULL) {
740         perms->gid = (gid_t) -1;
741     } else {
742         /* We previously could output -1, so continue to parse it */
743         if (virXPathLongLong("number(./group)", ctxt, &val) < 0 ||
744             ((gid_t) val != val &&
745              val != -1)) {
746             virReportError(VIR_ERR_XML_ERROR, "%s",
747                            _("malformed group element"));
748             return -1;
749         }
750         perms->gid = val;
751     }
752 
753     /* NB, we're ignoring missing labels here - they'll simply inherit */
754     perms->label = virXPathString("string(./label)", ctxt);
755     return 0;
756 }
757 
758 
759 static int
virStoragePoolDefRefreshParse(xmlXPathContextPtr ctxt,virStoragePoolDef * def)760 virStoragePoolDefRefreshParse(xmlXPathContextPtr ctxt,
761                               virStoragePoolDef *def)
762 {
763     g_autofree virStoragePoolDefRefresh *refresh = NULL;
764     g_autofree char *allocation = NULL;
765     int tmp;
766 
767     allocation = virXPathString("string(./refresh/volume/@allocation)", ctxt);
768 
769     if (!allocation)
770         return 0;
771 
772     if ((tmp = virStorageVolDefRefreshAllocationTypeFromString(allocation)) < 0) {
773         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
774                        _("unknown storage pool volume refresh allocation type %s"),
775                        allocation);
776         return -1;
777     }
778 
779     refresh = g_new0(virStoragePoolDefRefresh, 1);
780 
781     refresh->volume.allocation = tmp;
782     def->refresh = g_steal_pointer(&refresh);
783     return 0;
784 }
785 
786 
787 static void
virStoragePoolDefRefreshFormat(virBuffer * buf,virStoragePoolDefRefresh * refresh)788 virStoragePoolDefRefreshFormat(virBuffer *buf,
789                                virStoragePoolDefRefresh *refresh)
790 {
791     if (!refresh)
792         return;
793 
794     virBufferAddLit(buf, "<refresh>\n");
795     virBufferAdjustIndent(buf, 2);
796     virBufferAsprintf(buf, "<volume allocation='%s'/>\n",
797                       virStorageVolDefRefreshAllocationTypeToString(refresh->volume.allocation));
798     virBufferAdjustIndent(buf, -2);
799     virBufferAddLit(buf, "</refresh>\n");
800 }
801 
802 
803 static int
virStoragePoolDefParseFeatures(virStoragePoolDef * def,xmlXPathContextPtr ctxt)804 virStoragePoolDefParseFeatures(virStoragePoolDef *def,
805                                xmlXPathContextPtr ctxt)
806 {
807     g_autofree char *cow = virXPathString("string(./features/cow/@state)", ctxt);
808 
809     if (cow) {
810         int val;
811         if (def->type != VIR_STORAGE_POOL_FS &&
812             def->type != VIR_STORAGE_POOL_DIR) {
813             virReportError(VIR_ERR_NO_SUPPORT, "%s",
814                            _("cow feature may only be used for 'fs' and 'dir' pools"));
815             return -1;
816         }
817         if ((val = virTristateBoolTypeFromString(cow)) <= 0) {
818             virReportError(VIR_ERR_XML_ERROR,
819                            _("invalid storage pool cow feature state '%s'"),
820                            cow);
821             return -1;
822         }
823         def->features.cow = val;
824     }
825 
826     return 0;
827 }
828 
829 
830 virStoragePoolDef *
virStoragePoolDefParseXML(xmlXPathContextPtr ctxt)831 virStoragePoolDefParseXML(xmlXPathContextPtr ctxt)
832 {
833     virStoragePoolOptions *options;
834     xmlNodePtr source_node;
835     g_autoptr(virStoragePoolDef) def = NULL;
836     virStoragePoolType type;
837     g_autofree char *uuid = NULL;
838     g_autofree char *target_path = NULL;
839 
840     def = g_new0(virStoragePoolDef, 1);
841 
842     if (virXMLPropEnum(ctxt->node, "type", virStoragePoolTypeFromString,
843                        VIR_XML_PROP_REQUIRED, &type) < 0)
844         return NULL;
845 
846     def->type = type;
847 
848     if ((options = virStoragePoolOptionsForPoolType(def->type)) == NULL)
849         return NULL;
850 
851     source_node = virXPathNode("./source", ctxt);
852     if (source_node) {
853         if (virStoragePoolDefParseSource(ctxt, &def->source, def->type,
854                                          source_node) < 0)
855             return NULL;
856     } else {
857         if (options->formatFromString)
858             def->source.format = options->defaultFormat;
859     }
860 
861     def->name = virXPathString("string(./name)", ctxt);
862     if (def->name == NULL &&
863         options->flags & VIR_STORAGE_POOL_SOURCE_NAME)
864         def->name = g_strdup(def->source.name);
865 
866     if (def->name == NULL) {
867         virReportError(VIR_ERR_XML_ERROR, "%s",
868                        _("missing pool source name element"));
869         return NULL;
870     }
871 
872     if (strchr(def->name, '/')) {
873         virReportError(VIR_ERR_XML_ERROR,
874                        _("name %s cannot contain '/'"), def->name);
875         return NULL;
876     }
877 
878     uuid = virXPathString("string(./uuid)", ctxt);
879     if (uuid == NULL) {
880         if (virUUIDGenerate(def->uuid) < 0) {
881             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
882                            _("unable to generate uuid"));
883             return NULL;
884         }
885     } else {
886         if (virUUIDParse(uuid, def->uuid) < 0) {
887             virReportError(VIR_ERR_XML_ERROR, "%s",
888                            _("malformed uuid element"));
889             return NULL;
890         }
891     }
892 
893     if (virStoragePoolDefParseFeatures(def, ctxt) < 0)
894         return NULL;
895 
896     if (options->flags & VIR_STORAGE_POOL_SOURCE_HOST) {
897         if (!def->source.nhost) {
898             virReportError(VIR_ERR_XML_ERROR, "%s",
899                            _("missing storage pool source host name"));
900             return NULL;
901         }
902     }
903 
904     if (options->flags & VIR_STORAGE_POOL_SOURCE_DIR) {
905         if (!def->source.dir) {
906             virReportError(VIR_ERR_XML_ERROR, "%s",
907                            _("missing storage pool source path"));
908             return NULL;
909         }
910     }
911     if (options->flags & VIR_STORAGE_POOL_SOURCE_NAME) {
912         if (def->source.name == NULL) {
913             /* source name defaults to pool name */
914             def->source.name = g_strdup(def->name);
915         }
916     }
917 
918     if ((options->flags & VIR_STORAGE_POOL_SOURCE_ADAPTER) &&
919         (virStorageAdapterValidate(&def->source.adapter)) < 0)
920             return NULL;
921 
922     /* If DEVICE is the only source type, then its required */
923     if (options->flags == VIR_STORAGE_POOL_SOURCE_DEVICE) {
924         if (!def->source.ndevice) {
925             virReportError(VIR_ERR_XML_ERROR, "%s",
926                            _("missing storage pool source device name"));
927             return NULL;
928         }
929     }
930 
931     /* When we are working with a virtual disk we can skip the target
932      * path and permissions */
933     if (!(options->flags & VIR_STORAGE_POOL_SOURCE_NETWORK)) {
934         if (def->type == VIR_STORAGE_POOL_LOGICAL) {
935             target_path = g_strdup_printf("/dev/%s", def->source.name);
936         } else if (def->type == VIR_STORAGE_POOL_ZFS) {
937             target_path = g_strdup_printf("/dev/zvol/%s", def->source.name);
938         } else {
939             target_path = virXPathString("string(./target/path)", ctxt);
940             if (!target_path) {
941                 virReportError(VIR_ERR_XML_ERROR, "%s",
942                                _("missing storage pool target path"));
943                 return NULL;
944             }
945         }
946         def->target.path = virFileSanitizePath(target_path);
947         if (!def->target.path)
948             return NULL;
949 
950         if (virStorageDefParsePerms(ctxt, &def->target.perms,
951                                     "./target/permissions") < 0)
952             return NULL;
953     }
954 
955     if (def->type == VIR_STORAGE_POOL_ISCSI_DIRECT &&
956         !def->source.initiator.iqn) {
957         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
958                        _("missing initiator IQN"));
959         return NULL;
960     }
961 
962     if (virStoragePoolDefRefreshParse(ctxt, def) < 0)
963         return NULL;
964 
965     /* Make a copy of all the callback pointers here for easier use,
966      * especially during the virStoragePoolSourceClear method */
967     def->ns = options->ns;
968     if (def->ns.parse) {
969         if (virXMLNamespaceRegister(ctxt, &def->ns) < 0)
970             return NULL;
971         if ((def->ns.parse)(ctxt, &def->namespaceData) < 0)
972             return NULL;
973     }
974 
975     return g_steal_pointer(&def);
976 }
977 
978 
979 virStoragePoolDef *
virStoragePoolDefParseNode(xmlDocPtr xml,xmlNodePtr root)980 virStoragePoolDefParseNode(xmlDocPtr xml,
981                            xmlNodePtr root)
982 {
983     g_autoptr(xmlXPathContext) ctxt = NULL;
984 
985     if (!virXMLNodeNameEqual(root, "pool")) {
986         virReportError(VIR_ERR_XML_ERROR,
987                        _("unexpected root element <%s>, "
988                          "expecting <pool>"),
989                        root->name);
990         return NULL;
991     }
992 
993     if (!(ctxt = virXMLXPathContextNew(xml)))
994         return NULL;
995 
996     ctxt->node = root;
997     return virStoragePoolDefParseXML(ctxt);
998 }
999 
1000 
1001 static virStoragePoolDef *
virStoragePoolDefParse(const char * xmlStr,const char * filename,unsigned int flags)1002 virStoragePoolDefParse(const char *xmlStr,
1003                        const char *filename,
1004                        unsigned int flags)
1005 {
1006     virStoragePoolDef *ret = NULL;
1007     g_autoptr(xmlDoc) xml = NULL;
1008 
1009     if ((xml = virXMLParse(filename, xmlStr, _("(storage_pool_definition)"),
1010                            "storagepool.rng", flags & VIR_STORAGE_POOL_DEFINE_VALIDATE))) {
1011         ret = virStoragePoolDefParseNode(xml, xmlDocGetRootElement(xml));
1012     }
1013 
1014     return ret;
1015 }
1016 
1017 
1018 virStoragePoolDef *
virStoragePoolDefParseString(const char * xmlStr,unsigned int flags)1019 virStoragePoolDefParseString(const char *xmlStr,
1020                              unsigned int flags)
1021 {
1022     return virStoragePoolDefParse(xmlStr, NULL, flags);
1023 }
1024 
1025 
1026 virStoragePoolDef *
virStoragePoolDefParseFile(const char * filename)1027 virStoragePoolDefParseFile(const char *filename)
1028 {
1029     return virStoragePoolDefParse(NULL, filename, 0);
1030 }
1031 
1032 
1033 static int
virStoragePoolSourceFormat(virBuffer * buf,virStoragePoolOptions * options,virStoragePoolSource * src)1034 virStoragePoolSourceFormat(virBuffer *buf,
1035                            virStoragePoolOptions *options,
1036                            virStoragePoolSource *src)
1037 {
1038     size_t i, j;
1039 
1040     virBufferAddLit(buf, "<source>\n");
1041     virBufferAdjustIndent(buf, 2);
1042 
1043     if ((options->flags & VIR_STORAGE_POOL_SOURCE_HOST) && src->nhost) {
1044         for (i = 0; i < src->nhost; i++) {
1045             virBufferEscapeString(buf, "<host name='%s'",
1046                                   src->hosts[i].name);
1047             if (src->hosts[i].port)
1048                 virBufferAsprintf(buf, " port='%d'", src->hosts[i].port);
1049             virBufferAddLit(buf, "/>\n");
1050         }
1051     }
1052 
1053     if ((options->flags & VIR_STORAGE_POOL_SOURCE_DEVICE) &&
1054         src->ndevice) {
1055         for (i = 0; i < src->ndevice; i++) {
1056             virBufferEscapeString(buf, "<device path='%s'",
1057                                   src->devices[i].path);
1058             if (src->devices[i].part_separator !=
1059                 VIR_TRISTATE_BOOL_ABSENT) {
1060                 virBufferAsprintf(buf, " part_separator='%s'",
1061                                   virTristateBoolTypeToString(src->devices[i].part_separator));
1062             }
1063             if (src->devices[i].nfreeExtent) {
1064                 virBufferAddLit(buf, ">\n");
1065                 virBufferAdjustIndent(buf, 2);
1066                 for (j = 0; j < src->devices[i].nfreeExtent; j++) {
1067                     virBufferAsprintf(buf, "<freeExtent start='%llu' end='%llu'/>\n",
1068                                       src->devices[i].freeExtents[j].start,
1069                                       src->devices[i].freeExtents[j].end);
1070                 }
1071                 virBufferAdjustIndent(buf, -2);
1072                 virBufferAddLit(buf, "</device>\n");
1073             } else {
1074                 virBufferAddLit(buf, "/>\n");
1075             }
1076         }
1077     }
1078 
1079     if (options->flags & VIR_STORAGE_POOL_SOURCE_DIR)
1080         virBufferEscapeString(buf, "<dir path='%s'/>\n", src->dir);
1081 
1082     if ((options->flags & VIR_STORAGE_POOL_SOURCE_ADAPTER) &&
1083         (src->adapter.type == VIR_STORAGE_ADAPTER_TYPE_FC_HOST ||
1084          src->adapter.type == VIR_STORAGE_ADAPTER_TYPE_SCSI_HOST))
1085         virStorageAdapterFormat(buf, &src->adapter);
1086 
1087     if (options->flags & VIR_STORAGE_POOL_SOURCE_NAME)
1088         virBufferEscapeString(buf, "<name>%s</name>\n", src->name);
1089 
1090     if (options->flags & VIR_STORAGE_POOL_SOURCE_INITIATOR_IQN)
1091         virStorageSourceInitiatorFormatXML(&src->initiator, buf);
1092 
1093     if (options->formatToString) {
1094         const char *format = (options->formatToString)(src->format);
1095         if (!format) {
1096             virReportError(VIR_ERR_INTERNAL_ERROR,
1097                            _("unknown pool format number %d"),
1098                            src->format);
1099             return -1;
1100         }
1101         virBufferAsprintf(buf, "<format type='%s'/>\n", format);
1102     }
1103 
1104     if (src->auth)
1105         virStorageAuthDefFormat(buf, src->auth);
1106 
1107     if (src->protocolVer)
1108         virBufferAsprintf(buf, "<protocol ver='%u'/>\n", src->protocolVer);
1109 
1110     virBufferEscapeString(buf, "<vendor name='%s'/>\n", src->vendor);
1111     virBufferEscapeString(buf, "<product name='%s'/>\n", src->product);
1112 
1113     virBufferAdjustIndent(buf, -2);
1114     virBufferAddLit(buf, "</source>\n");
1115     return 0;
1116 }
1117 
1118 
1119 static void
virStoragePoolDefFormatFeatures(virBuffer * buf,virStoragePoolDef * def)1120 virStoragePoolDefFormatFeatures(virBuffer *buf,
1121                                 virStoragePoolDef *def)
1122 {
1123     if (def->features.cow == VIR_TRISTATE_BOOL_ABSENT)
1124         return;
1125 
1126     virBufferAddLit(buf, "<features>\n");
1127     virBufferAdjustIndent(buf, 2);
1128     if (def->features.cow != VIR_TRISTATE_BOOL_ABSENT)
1129         virBufferAsprintf(buf, "<cow state='%s'/>\n",
1130                           virTristateBoolTypeToString(def->features.cow));
1131     virBufferAdjustIndent(buf, -2);
1132     virBufferAddLit(buf, "</features>\n");
1133 }
1134 
1135 
1136 static int
virStoragePoolDefFormatBuf(virBuffer * buf,virStoragePoolDef * def)1137 virStoragePoolDefFormatBuf(virBuffer *buf,
1138                            virStoragePoolDef *def)
1139 {
1140     virStoragePoolOptions *options;
1141     char uuid[VIR_UUID_STRING_BUFLEN];
1142     const char *type;
1143 
1144     options = virStoragePoolOptionsForPoolType(def->type);
1145     if (options == NULL)
1146         return -1;
1147 
1148     type = virStoragePoolTypeToString(def->type);
1149     if (!type) {
1150         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1151                        _("unexpected pool type"));
1152         return -1;
1153     }
1154     virBufferAsprintf(buf, "<pool type='%s'", type);
1155     if (def->namespaceData && def->ns.format)
1156         virXMLNamespaceFormatNS(buf, &def->ns);
1157     virBufferAddLit(buf, ">\n");
1158     virBufferAdjustIndent(buf, 2);
1159     virBufferEscapeString(buf, "<name>%s</name>\n", def->name);
1160 
1161     virUUIDFormat(def->uuid, uuid);
1162     virBufferAsprintf(buf, "<uuid>%s</uuid>\n", uuid);
1163 
1164     virBufferAsprintf(buf, "<capacity unit='bytes'>%llu</capacity>\n",
1165                       def->capacity);
1166     virBufferAsprintf(buf, "<allocation unit='bytes'>%llu</allocation>\n",
1167                       def->allocation);
1168     virBufferAsprintf(buf, "<available unit='bytes'>%llu</available>\n",
1169                       def->available);
1170 
1171     virStoragePoolDefFormatFeatures(buf, def);
1172 
1173     if (virStoragePoolSourceFormat(buf, options, &def->source) < 0)
1174         return -1;
1175 
1176     /* RBD, Sheepdog, Gluster and Iscsi-direct devices are not local block devs nor
1177      * files, so they don't have a target */
1178     if (def->type != VIR_STORAGE_POOL_RBD &&
1179         def->type != VIR_STORAGE_POOL_SHEEPDOG &&
1180         def->type != VIR_STORAGE_POOL_GLUSTER &&
1181         def->type != VIR_STORAGE_POOL_ISCSI_DIRECT) {
1182         virBufferAddLit(buf, "<target>\n");
1183         virBufferAdjustIndent(buf, 2);
1184 
1185         virBufferEscapeString(buf, "<path>%s</path>\n", def->target.path);
1186 
1187         if (def->target.perms.mode != (mode_t) -1 ||
1188             def->target.perms.uid != (uid_t) -1 ||
1189             def->target.perms.gid != (gid_t) -1 ||
1190             def->target.perms.label) {
1191             virBufferAddLit(buf, "<permissions>\n");
1192             virBufferAdjustIndent(buf, 2);
1193             if (def->target.perms.mode != (mode_t) -1)
1194                 virBufferAsprintf(buf, "<mode>0%o</mode>\n",
1195                                   def->target.perms.mode);
1196             if (def->target.perms.uid != (uid_t) -1)
1197                 virBufferAsprintf(buf, "<owner>%d</owner>\n",
1198                                   (int) def->target.perms.uid);
1199             if (def->target.perms.gid != (gid_t) -1)
1200                 virBufferAsprintf(buf, "<group>%d</group>\n",
1201                                   (int) def->target.perms.gid);
1202             virBufferEscapeString(buf, "<label>%s</label>\n",
1203                                   def->target.perms.label);
1204 
1205             virBufferAdjustIndent(buf, -2);
1206             virBufferAddLit(buf, "</permissions>\n");
1207         }
1208 
1209         virBufferAdjustIndent(buf, -2);
1210         virBufferAddLit(buf, "</target>\n");
1211     }
1212 
1213     virStoragePoolDefRefreshFormat(buf, def->refresh);
1214 
1215     if (def->namespaceData && def->ns.format) {
1216         if ((def->ns.format)(buf, def->namespaceData) < 0)
1217             return -1;
1218     }
1219 
1220     virBufferAdjustIndent(buf, -2);
1221     virBufferAddLit(buf, "</pool>\n");
1222 
1223     return 0;
1224 }
1225 
1226 
1227 char *
virStoragePoolDefFormat(virStoragePoolDef * def)1228 virStoragePoolDefFormat(virStoragePoolDef *def)
1229 {
1230     g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
1231 
1232     if (virStoragePoolDefFormatBuf(&buf, def) < 0)
1233         return NULL;
1234 
1235     return virBufferContentAndReset(&buf);
1236 }
1237 
1238 
1239 static int
virStorageSize(const char * unit,const char * val,unsigned long long * ret)1240 virStorageSize(const char *unit,
1241                const char *val,
1242                unsigned long long *ret)
1243 {
1244     if (virStrToLong_ullp(val, NULL, 10, ret) < 0) {
1245         virReportError(VIR_ERR_XML_ERROR, "%s",
1246                        _("malformed capacity element"));
1247         return -1;
1248     }
1249     /* off_t is signed, so you cannot create a file larger than 2**63
1250      * bytes in the first place.  */
1251     if (virScaleInteger(ret, unit, 1, LLONG_MAX) < 0)
1252         return -1;
1253 
1254     return 0;
1255 }
1256 
1257 
1258 static int
virStorageCheckCompat(const char * compat)1259 virStorageCheckCompat(const char *compat)
1260 {
1261     unsigned int result;
1262     g_auto(GStrv) version = NULL;
1263 
1264     if (!compat)
1265         return 0;
1266 
1267     version = g_strsplit(compat, ".", 2);
1268     if (!version || !version[1] ||
1269         virStrToLong_ui(version[0], NULL, 10, &result) < 0 ||
1270         virStrToLong_ui(version[1], NULL, 10, &result) < 0) {
1271         virReportError(VIR_ERR_XML_ERROR, "%s",
1272                        _("forbidden characters in 'compat' attribute"));
1273         return -1;
1274     }
1275     return 0;
1276 }
1277 
1278 
1279 static virStorageVolDef *
virStorageVolDefParseXML(virStoragePoolDef * pool,xmlXPathContextPtr ctxt,unsigned int flags)1280 virStorageVolDefParseXML(virStoragePoolDef *pool,
1281                          xmlXPathContextPtr ctxt,
1282                          unsigned int flags)
1283 {
1284     virStorageVolOptions *options;
1285     xmlNodePtr node;
1286     size_t i;
1287     int n;
1288     g_autoptr(virStorageVolDef) def = NULL;
1289     g_autofree char *type = NULL;
1290     g_autofree char *allocation = NULL;
1291     g_autofree char *capacity = NULL;
1292     g_autofree char *unit = NULL;
1293     g_autofree char *backingStore = NULL;
1294     g_autofree xmlNodePtr *nodes = NULL;
1295 
1296     virCheckFlags(VIR_VOL_XML_PARSE_NO_CAPACITY |
1297                   VIR_VOL_XML_PARSE_OPT_CAPACITY, NULL);
1298 
1299     options = virStorageVolOptionsForPoolType(pool->type);
1300     if (options == NULL)
1301         return NULL;
1302 
1303     def = g_new0(virStorageVolDef, 1);
1304 
1305     def->target.type = VIR_STORAGE_TYPE_FILE;
1306 
1307     def->name = virXPathString("string(./name)", ctxt);
1308     if (def->name == NULL) {
1309         virReportError(VIR_ERR_XML_ERROR, "%s",
1310                        _("missing volume name element"));
1311         return NULL;
1312     }
1313 
1314     /* Normally generated by pool refresh, but useful for unit tests */
1315     def->key = virXPathString("string(./key)", ctxt);
1316 
1317     /* Technically overridden by pool refresh, but useful for unit tests */
1318     type = virXPathString("string(./@type)", ctxt);
1319     if (type) {
1320         if ((def->type = virStorageVolTypeFromString(type)) < 0) {
1321             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1322                            _("unknown volume type '%s'"), type);
1323             return NULL;
1324         }
1325     }
1326 
1327     if ((backingStore = virXPathString("string(./backingStore/path)", ctxt))) {
1328         def->target.backingStore = virStorageSourceNew();
1329         def->target.backingStore->type = VIR_STORAGE_TYPE_FILE;
1330         def->target.backingStore->path = g_steal_pointer(&backingStore);
1331 
1332         if (options->formatFromString) {
1333             g_autofree char *format = NULL;
1334 
1335             format = virXPathString("string(./backingStore/format/@type)", ctxt);
1336             if (format == NULL)
1337                 def->target.backingStore->format = options->defaultFormat;
1338             else
1339                 def->target.backingStore->format = (options->formatFromString)(format);
1340 
1341             if (def->target.backingStore->format < 0) {
1342                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1343                                _("unknown volume format type %s"), format);
1344                 return NULL;
1345             }
1346         }
1347 
1348         def->target.backingStore->perms = g_new0(virStoragePerms, 1);
1349         if (virStorageDefParsePerms(ctxt, def->target.backingStore->perms,
1350                                     "./backingStore/permissions") < 0)
1351             return NULL;
1352     }
1353 
1354     capacity = virXPathString("string(./capacity)", ctxt);
1355     unit = virXPathString("string(./capacity/@unit)", ctxt);
1356     if (capacity) {
1357         if (virStorageSize(unit, capacity, &def->target.capacity) < 0)
1358             return NULL;
1359     } else if (!(flags & VIR_VOL_XML_PARSE_NO_CAPACITY) &&
1360                !((flags & VIR_VOL_XML_PARSE_OPT_CAPACITY) &&
1361                  virStorageSourceHasBacking(&def->target))) {
1362         virReportError(VIR_ERR_XML_ERROR, "%s", _("missing capacity element"));
1363         return NULL;
1364     }
1365     VIR_FREE(unit);
1366 
1367     allocation = virXPathString("string(./allocation)", ctxt);
1368     if (allocation) {
1369         unit = virXPathString("string(./allocation/@unit)", ctxt);
1370         if (virStorageSize(unit, allocation, &def->target.allocation) < 0)
1371             return NULL;
1372         def->target.has_allocation = true;
1373     } else {
1374         def->target.allocation = def->target.capacity;
1375     }
1376 
1377     def->target.path = virXPathString("string(./target/path)", ctxt);
1378     if (options->formatFromString) {
1379         g_autofree char *format = NULL;
1380 
1381         format = virXPathString("string(./target/format/@type)", ctxt);
1382         if (format == NULL)
1383             def->target.format = options->defaultFormat;
1384         else
1385             def->target.format = (options->formatFromString)(format);
1386 
1387         if (def->target.format < 0) {
1388             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1389                            _("unknown volume format type %s"), format);
1390             return NULL;
1391         }
1392     }
1393 
1394     def->target.perms = g_new0(virStoragePerms, 1);
1395     if (virStorageDefParsePerms(ctxt, def->target.perms,
1396                                 "./target/permissions") < 0)
1397         return NULL;
1398 
1399     node = virXPathNode("./target/encryption", ctxt);
1400     if (node != NULL) {
1401         def->target.encryption = virStorageEncryptionParseNode(node, ctxt);
1402         if (def->target.encryption == NULL)
1403             return NULL;
1404     }
1405 
1406     def->target.compat = virXPathString("string(./target/compat)", ctxt);
1407     if (virStorageCheckCompat(def->target.compat) < 0)
1408         return NULL;
1409 
1410     if (virXPathNode("./target/nocow", ctxt))
1411         def->target.nocow = true;
1412 
1413     if (virParseScaledValue("./target/clusterSize",
1414                             "./target/clusterSize/@unit",
1415                             ctxt, &def->target.clusterSize,
1416                             1, ULLONG_MAX, false) < 0) {
1417         return NULL;
1418     }
1419 
1420     if (virXPathNode("./target/features", ctxt)) {
1421         if ((n = virXPathNodeSet("./target/features/*", ctxt, &nodes)) < 0)
1422             return NULL;
1423 
1424         if (!def->target.compat)
1425             def->target.compat = g_strdup("1.1");
1426 
1427         def->target.features = virBitmapNew(VIR_STORAGE_FILE_FEATURE_LAST);
1428 
1429         for (i = 0; i < n; i++) {
1430             int f = virStorageFileFeatureTypeFromString((const char*)nodes[i]->name);
1431 
1432             if (f < 0) {
1433                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unsupported feature %s"),
1434                                (const char*)nodes[i]->name);
1435                 return NULL;
1436             }
1437             ignore_value(virBitmapSetBit(def->target.features, f));
1438         }
1439         VIR_FREE(nodes);
1440     }
1441 
1442     return g_steal_pointer(&def);
1443 }
1444 
1445 
1446 virStorageVolDef *
virStorageVolDefParseNode(virStoragePoolDef * pool,xmlDocPtr xml,xmlNodePtr root,unsigned int flags)1447 virStorageVolDefParseNode(virStoragePoolDef *pool,
1448                           xmlDocPtr xml,
1449                           xmlNodePtr root,
1450                           unsigned int flags)
1451 {
1452     g_autoptr(xmlXPathContext) ctxt = NULL;
1453 
1454     if (!virXMLNodeNameEqual(root, "volume")) {
1455         virReportError(VIR_ERR_XML_ERROR,
1456                        _("unexpected root element <%s>, "
1457                          "expecting <volume>"),
1458                        root->name);
1459         return NULL;
1460     }
1461 
1462     if (!(ctxt = virXMLXPathContextNew(xml)))
1463         return NULL;
1464 
1465     ctxt->node = root;
1466     return virStorageVolDefParseXML(pool, ctxt, flags);
1467 }
1468 
1469 
1470 static virStorageVolDef *
virStorageVolDefParse(virStoragePoolDef * pool,const char * xmlStr,const char * filename,unsigned int flags)1471 virStorageVolDefParse(virStoragePoolDef *pool,
1472                       const char *xmlStr,
1473                       const char *filename,
1474                       unsigned int flags)
1475 {
1476     virStorageVolDef *ret = NULL;
1477     g_autoptr(xmlDoc) xml = NULL;
1478 
1479     if ((xml = virXMLParse(filename, xmlStr, _("(storage_volume_definition)"), NULL, false))) {
1480         ret = virStorageVolDefParseNode(pool, xml, xmlDocGetRootElement(xml), flags);
1481     }
1482 
1483     return ret;
1484 }
1485 
1486 
1487 virStorageVolDef *
virStorageVolDefParseString(virStoragePoolDef * pool,const char * xmlStr,unsigned int flags)1488 virStorageVolDefParseString(virStoragePoolDef *pool,
1489                             const char *xmlStr,
1490                             unsigned int flags)
1491 {
1492     return virStorageVolDefParse(pool, xmlStr, NULL, flags);
1493 }
1494 
1495 
1496 virStorageVolDef *
virStorageVolDefParseFile(virStoragePoolDef * pool,const char * filename,unsigned int flags)1497 virStorageVolDefParseFile(virStoragePoolDef *pool,
1498                           const char *filename,
1499                           unsigned int flags)
1500 {
1501     return virStorageVolDefParse(pool, NULL, filename, flags);
1502 }
1503 
1504 
1505 static void
virStorageVolTimestampFormat(virBuffer * buf,const char * name,struct timespec * ts)1506 virStorageVolTimestampFormat(virBuffer *buf, const char *name,
1507                              struct timespec *ts)
1508 {
1509     if (ts->tv_nsec < 0)
1510         return;
1511     virBufferAsprintf(buf, "<%s>%llu", name,
1512                       (unsigned long long) ts->tv_sec);
1513     if (ts->tv_nsec)
1514        virBufferAsprintf(buf, ".%09ld", ts->tv_nsec);
1515     virBufferAsprintf(buf, "</%s>\n", name);
1516 }
1517 
1518 
1519 static int
virStorageVolTargetDefFormat(virStorageVolOptions * options,virBuffer * buf,virStorageSource * def,const char * type)1520 virStorageVolTargetDefFormat(virStorageVolOptions *options,
1521                              virBuffer *buf,
1522                              virStorageSource *def,
1523                              const char *type)
1524 {
1525     virBufferAsprintf(buf, "<%s>\n", type);
1526     virBufferAdjustIndent(buf, 2);
1527 
1528     virBufferEscapeString(buf, "<path>%s</path>\n", def->path);
1529 
1530     if (options->formatToString) {
1531         const char *format = (options->formatToString)(def->format);
1532         if (!format) {
1533             virReportError(VIR_ERR_INTERNAL_ERROR,
1534                            _("unknown volume format number %d"),
1535                            def->format);
1536             return -1;
1537         }
1538         virBufferAsprintf(buf, "<format type='%s'/>\n", format);
1539     }
1540 
1541     if (def->perms &&
1542         (def->perms->mode != (mode_t) -1 ||
1543          def->perms->uid != (uid_t) -1 ||
1544          def->perms->gid != (gid_t) -1 ||
1545          def->perms->label)) {
1546         virBufferAddLit(buf, "<permissions>\n");
1547         virBufferAdjustIndent(buf, 2);
1548 
1549         if (def->perms->mode != (mode_t) -1)
1550             virBufferAsprintf(buf, "<mode>0%o</mode>\n",
1551                               def->perms->mode);
1552         if (def->perms->uid != (uid_t) -1)
1553             virBufferAsprintf(buf, "<owner>%d</owner>\n",
1554                               (int) def->perms->uid);
1555         if (def->perms->gid != (gid_t) -1)
1556             virBufferAsprintf(buf, "<group>%d</group>\n",
1557                               (int) def->perms->gid);
1558 
1559         virBufferEscapeString(buf, "<label>%s</label>\n",
1560                               def->perms->label);
1561 
1562         virBufferAdjustIndent(buf, -2);
1563         virBufferAddLit(buf, "</permissions>\n");
1564     }
1565 
1566     if (def->timestamps) {
1567         virBufferAddLit(buf, "<timestamps>\n");
1568         virBufferAdjustIndent(buf, 2);
1569         virStorageVolTimestampFormat(buf, "atime", &def->timestamps->atime);
1570         virStorageVolTimestampFormat(buf, "mtime", &def->timestamps->mtime);
1571         virStorageVolTimestampFormat(buf, "ctime", &def->timestamps->ctime);
1572         virStorageVolTimestampFormat(buf, "btime", &def->timestamps->btime);
1573         virBufferAdjustIndent(buf, -2);
1574         virBufferAddLit(buf, "</timestamps>\n");
1575     }
1576 
1577     if (def->encryption &&
1578         virStorageEncryptionFormat(buf, def->encryption) < 0)
1579             return -1;
1580 
1581     virBufferEscapeString(buf, "<compat>%s</compat>\n", def->compat);
1582 
1583     if (def->clusterSize > 0) {
1584         virBufferAsprintf(buf, "<clusterSize unit='B'>%llu</clusterSize>\n",
1585                           def->clusterSize);
1586     }
1587 
1588     if (def->features) {
1589         size_t i;
1590         bool empty = virBitmapIsAllClear(def->features);
1591 
1592         if (empty) {
1593             virBufferAddLit(buf, "<features/>\n");
1594         } else {
1595             virBufferAddLit(buf, "<features>\n");
1596             virBufferAdjustIndent(buf, 2);
1597         }
1598 
1599         for (i = 0; i < VIR_STORAGE_FILE_FEATURE_LAST; i++) {
1600             if (virBitmapIsBitSet(def->features, i))
1601                 virBufferAsprintf(buf, "<%s/>\n",
1602                                   virStorageFileFeatureTypeToString(i));
1603         }
1604         if (!empty) {
1605             virBufferAdjustIndent(buf, -2);
1606             virBufferAddLit(buf, "</features>\n");
1607         }
1608     }
1609 
1610     virBufferAdjustIndent(buf, -2);
1611     virBufferAsprintf(buf, "</%s>\n", type);
1612     return 0;
1613 }
1614 
1615 
1616 static void
virStorageVolDefFormatSourceExtents(virBuffer * buf,virStorageVolDef * def)1617 virStorageVolDefFormatSourceExtents(virBuffer *buf,
1618                                     virStorageVolDef *def)
1619 {
1620     size_t i;
1621     const char *thispath = NULL;
1622 
1623     for (i = 0; i < def->source.nextent; i++) {
1624         if (thispath == NULL ||
1625             STRNEQ(thispath, def->source.extents[i].path)) {
1626             if (thispath != NULL)
1627                 virBufferAddLit(buf, "</device>\n");
1628 
1629             virBufferEscapeString(buf, "<device path='%s'>\n",
1630                                   def->source.extents[i].path);
1631         }
1632 
1633         virBufferAdjustIndent(buf, 2);
1634         virBufferAsprintf(buf, "<extent start='%llu' end='%llu'/>\n",
1635                           def->source.extents[i].start,
1636                           def->source.extents[i].end);
1637         virBufferAdjustIndent(buf, -2);
1638         thispath = def->source.extents[i].path;
1639     }
1640     if (thispath != NULL)
1641         virBufferAddLit(buf, "</device>\n");
1642 }
1643 
1644 
1645 char *
virStorageVolDefFormat(virStoragePoolDef * pool,virStorageVolDef * def)1646 virStorageVolDefFormat(virStoragePoolDef *pool,
1647                        virStorageVolDef *def)
1648 {
1649     virStorageVolOptions *options;
1650     g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
1651     g_auto(virBuffer) sourceChildBuf = VIR_BUFFER_INITIALIZER;
1652 
1653     options = virStorageVolOptionsForPoolType(pool->type);
1654     if (options == NULL)
1655         return NULL;
1656 
1657     virBufferAsprintf(&buf, "<volume type='%s'>\n",
1658                       virStorageVolTypeToString(def->type));
1659     virBufferAdjustIndent(&buf, 2);
1660 
1661     virBufferEscapeString(&buf, "<name>%s</name>\n", def->name);
1662     virBufferEscapeString(&buf, "<key>%s</key>\n", def->key);
1663 
1664     virBufferSetIndent(&sourceChildBuf, virBufferGetIndent(&buf) + 2);
1665 
1666     if (def->source.nextent)
1667         virStorageVolDefFormatSourceExtents(&sourceChildBuf, def);
1668 
1669     virXMLFormatElement(&buf, "source", NULL, &sourceChildBuf);
1670 
1671     virBufferAsprintf(&buf, "<capacity unit='bytes'>%llu</capacity>\n",
1672                       def->target.capacity);
1673     virBufferAsprintf(&buf, "<allocation unit='bytes'>%llu</allocation>\n",
1674                       def->target.allocation);
1675     /* NB: Display only - since virStorageVolInfo is limited to just
1676      * 'capacity' and 'allocation' on output. Since we don't read this
1677      * in, be sure it was filled in before printing */
1678     if (def->target.physical)
1679         virBufferAsprintf(&buf, "<physical unit='bytes'>%llu</physical>\n",
1680                           def->target.physical);
1681 
1682     if (virStorageVolTargetDefFormat(options, &buf,
1683                                      &def->target, "target") < 0)
1684         return NULL;
1685 
1686     if (virStorageSourceHasBacking(&def->target) &&
1687         virStorageVolTargetDefFormat(options, &buf,
1688                                      def->target.backingStore,
1689                                      "backingStore") < 0)
1690         return NULL;
1691 
1692     virBufferAdjustIndent(&buf, -2);
1693     virBufferAddLit(&buf, "</volume>\n");
1694 
1695     return virBufferContentAndReset(&buf);
1696 }
1697 
1698 
1699 static int
virStoragePoolSaveXML(const char * path,virStoragePoolDef * def,const char * xml)1700 virStoragePoolSaveXML(const char *path,
1701                       virStoragePoolDef *def,
1702                       const char *xml)
1703 {
1704     char uuidstr[VIR_UUID_STRING_BUFLEN];
1705 
1706     virUUIDFormat(def->uuid, uuidstr);
1707     return virXMLSaveFile(path,
1708                           virXMLPickShellSafeComment(def->name, uuidstr),
1709                           "pool-edit", xml);
1710 }
1711 
1712 
1713 int
virStoragePoolSaveState(const char * stateFile,virStoragePoolDef * def)1714 virStoragePoolSaveState(const char *stateFile,
1715                         virStoragePoolDef *def)
1716 {
1717     g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
1718     g_autofree char *xml = NULL;
1719 
1720     virBufferAddLit(&buf, "<poolstate>\n");
1721     virBufferAdjustIndent(&buf, 2);
1722 
1723     if (virStoragePoolDefFormatBuf(&buf, def) < 0)
1724         return -1;
1725 
1726     virBufferAdjustIndent(&buf, -2);
1727     virBufferAddLit(&buf, "</poolstate>\n");
1728 
1729     if (!(xml = virBufferContentAndReset(&buf)))
1730         return -1;
1731 
1732     if (virStoragePoolSaveXML(stateFile, def, xml))
1733         return -1;
1734 
1735     return 0;
1736 }
1737 
1738 
1739 int
virStoragePoolSaveConfig(const char * configFile,virStoragePoolDef * def)1740 virStoragePoolSaveConfig(const char *configFile,
1741                          virStoragePoolDef *def)
1742 {
1743     g_autofree char *xml = NULL;
1744 
1745     if (!(xml = virStoragePoolDefFormat(def))) {
1746         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1747                        _("failed to generate XML"));
1748         return -1;
1749     }
1750 
1751     return virStoragePoolSaveXML(configFile, def, xml);
1752 }
1753 
1754 
1755 virStoragePoolSource *
virStoragePoolSourceListNewSource(virStoragePoolSourceList * list)1756 virStoragePoolSourceListNewSource(virStoragePoolSourceList *list)
1757 {
1758     virStoragePoolSource *source;
1759 
1760     VIR_REALLOC_N(list->sources, list->nsources + 1);
1761 
1762     source = &list->sources[list->nsources++];
1763     memset(source, 0, sizeof(*source));
1764 
1765     return source;
1766 }
1767 
1768 
1769 char *
virStoragePoolSourceListFormat(virStoragePoolSourceList * def)1770 virStoragePoolSourceListFormat(virStoragePoolSourceList *def)
1771 {
1772     virStoragePoolOptions *options;
1773     g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
1774     const char *type;
1775     size_t i;
1776 
1777     options = virStoragePoolOptionsForPoolType(def->type);
1778     if (options == NULL)
1779         return NULL;
1780 
1781     type = virStoragePoolTypeToString(def->type);
1782     if (!type) {
1783         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1784                        _("unexpected pool type"));
1785         return NULL;
1786     }
1787 
1788     virBufferAddLit(&buf, "<sources>\n");
1789     virBufferAdjustIndent(&buf, 2);
1790 
1791     for (i = 0; i < def->nsources; i++)
1792         virStoragePoolSourceFormat(&buf, options, &def->sources[i]);
1793 
1794     virBufferAdjustIndent(&buf, -2);
1795     virBufferAddLit(&buf, "</sources>\n");
1796 
1797     return virBufferContentAndReset(&buf);
1798 }
1799 
1800 
1801 void
virStoragePoolSourceListFree(virStoragePoolSourceList * list)1802 virStoragePoolSourceListFree(virStoragePoolSourceList *list)
1803 {
1804     size_t i;
1805 
1806     if (!list)
1807         return;
1808 
1809     for (i = 0; i < list->nsources; i++)
1810         virStoragePoolSourceClear(&list->sources[i]);
1811 
1812     g_free(list->sources);
1813     g_free(list);
1814 }
1815