uid_t and gid_t are opaque types, ranging from s32 to u32 to u64.
Unfortunately libvirt uses the value -1 to mean "current process", which
on Linux32 gets converted to ALLONE := +(2^32-1) = 4294967295.
Different libvirt versions used different formatting in the past, which
break one or the other parsing function:
virXPathLong(): (signed long)-1 != (double)ALLONE
virXPathULong(): (unsigned long)-1 != (double)-1
Roll our own version of virXPathULong(), which also accepts -1, which is
silently converted to ALLONE.
For output: do the reverse and print -1 instead of ALLONE.
Signed-off-by: Philipp Hahn <hahn(a)univention.de>
---
src/conf/storage_conf.c | 74 ++++++++++++++++++++++++++++++++++++++---------
1 file changed, 60 insertions(+), 14 deletions(-)
diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
index 9134a22..b267f00 100644
--- a/src/conf/storage_conf.c
+++ b/src/conf/storage_conf.c
@@ -665,7 +665,7 @@ virStorageDefParsePerms(xmlXPathContextPtr ctxt,
const char *permxpath,
int defaultmode) {
char *mode;
- long v;
+ double d;
int ret = -1;
xmlNodePtr relnode;
xmlNodePtr node;
@@ -699,26 +699,57 @@ virStorageDefParsePerms(xmlXPathContextPtr ctxt,
VIR_FREE(mode);
}
+ /* uid_t and gid_t are *opaque* types: on Linux they're u32, on Windows64
+ * they're u64, on Solaris they were s32 in the past. There may be others.
+ *
+ * Unfortunately libvirt uses the value -1 to mean "current process",
which
+ * on Linux32 gets converted to ALLONE:=+(2^32-1).
+ *
+ * Different libvirt versions used different formatting in the past, which
+ * break one or the other parsing function:
+ * virXPathLong(): (signed long)-1 != (double)ALLONE
+ * virXPathULong(): (unsigned long)-1 != (double)-1
+ */
if (virXPathNode("./owner", ctxt) == NULL) {
perms->uid = (uid_t) -1;
} else {
- if (virXPathLong("number(./owner)", ctxt, &v) < 0) {
+ ret = virXPathNumber("number(./owner)", ctxt, &d);
+ if (ret == 0) {
+ if (d == (double) -1) {
+ perms->uid = (uid_t) -1;
+ } else {
+ perms->uid = (uid_t) (unsigned long) d;
+ if (perms->uid != d) {
+ ret = -2;
+ }
+ }
+ }
+ if (ret < 0) {
virReportError(VIR_ERR_XML_ERROR,
"%s", _("malformed owner element"));
goto error;
}
- perms->uid = (int)v;
}
if (virXPathNode("./group", ctxt) == NULL) {
perms->gid = (gid_t) -1;
} else {
- if (virXPathLong("number(./group)", ctxt, &v) < 0) {
+ ret = virXPathNumber("number(./group)", ctxt, &d);
+ if (ret == 0) {
+ if (d == (double) -1) {
+ perms->gid = (gid_t)-1;
+ } else {
+ perms->gid = (gid_t) (unsigned long) d;
+ if (perms->gid != d) {
+ ret = -2;
+ }
+ }
+ }
+ if (ret < 0) {
virReportError(VIR_ERR_XML_ERROR,
"%s", _("malformed group element"));
goto error;
}
- perms->gid = (int)v;
}
/* NB, we're ignoring missing labels here - they'll simply inherit */
@@ -1060,10 +1091,18 @@ virStoragePoolDefFormat(virStoragePoolDefPtr def) {
virBufferAddLit(&buf," <permissions>\n");
virBufferAsprintf(&buf," <mode>0%o</mode>\n",
def->target.perms.mode);
- virBufferAsprintf(&buf," <owner>%d</owner>\n",
- (int) def->target.perms.uid);
- virBufferAsprintf(&buf," <group>%d</group>\n",
- (int) def->target.perms.gid);
+ if (def->target.perms.uid == (uid_t) -1) {
+ virBufferAddLit(&buf, "
<owner>-1</owner>\n");
+ } else {
+ virBufferAsprintf(&buf, "
<owner>%u</owner>\n",
+ (unsigned int) def->target.perms.uid);
+ }
+ if (def->target.perms.gid == (gid_t) -1) {
+ virBufferAddLit(&buf, "
<group>-1</group>\n");
+ } else {
+ virBufferAsprintf(&buf, "
<group>%u</group>\n",
+ (unsigned int) def->target.perms.gid);
+ }
if (def->target.perms.label)
virBufferAsprintf(&buf,"
<label>%s</label>\n",
@@ -1313,11 +1352,18 @@ virStorageVolTargetDefFormat(virStorageVolOptionsPtr options,
virBufferAddLit(buf," <permissions>\n");
virBufferAsprintf(buf," <mode>0%o</mode>\n",
def->perms.mode);
- virBufferAsprintf(buf," <owner>%u</owner>\n",
- (unsigned int) def->perms.uid);
- virBufferAsprintf(buf," <group>%u</group>\n",
- (unsigned int) def->perms.gid);
-
+ if (def->perms.uid == (uid_t) -1) {
+ virBufferAddLit(buf, " <owner>-1</owner>\n");
+ } else {
+ virBufferAsprintf(buf, " <owner>%u</owner>\n",
+ (unsigned int) def->perms.uid);
+ }
+ if (def->perms.gid == (gid_t) -1) {
+ virBufferAddLit(buf, " <group>-1</group>\n");
+ } else {
+ virBufferAsprintf(buf, " <group>%u</group>\n",
+ (unsigned int) def->perms.gid);
+ }
if (def->perms.label)
virBufferAsprintf(buf," <label>%s</label>\n",
--
1.7.10.4