Some sysfs files contain either string representation of a bitmap
or just a newline character. An example of such file is:
/sys/devices/system/cpu/isolated. Our current implementation of
virFileReadValueBitmap() fails in the latter case, unfortunately.
Introduce a slightly modified version that accepts empty files.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
src/libvirt_private.syms | 1 +
src/util/virfile.c | 81 ++++++++++++++++++++++++++++++----------
src/util/virfile.h | 2 +
3 files changed, 65 insertions(+), 19 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 0ba6183010..2c7e4b45d3 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2360,6 +2360,7 @@ virFileReadHeaderFD;
virFileReadHeaderQuiet;
virFileReadLimFD;
virFileReadValueBitmap;
+virFileReadValueBitmapAllowEmpty;
virFileReadValueInt;
virFileReadValueScaledInt;
virFileReadValueString;
diff --git a/src/util/virfile.c b/src/util/virfile.c
index deaf4555fd..c769f7d650 100644
--- a/src/util/virfile.c
+++ b/src/util/virfile.c
@@ -4365,26 +4365,12 @@ virFileReadValueScaledInt(unsigned long long *value, const char
*format, ...)
* used for small, interface-like files, so it should not be huge (subjective) */
#define VIR_FILE_READ_VALUE_STRING_MAX 4096
-/**
- * virFileReadValueBitmap:
- * @value: pointer to virBitmap * to be allocated and filled in with the value
- * @format, ...: file to read from
- *
- * Read int from @format and put it into @value.
- *
- * Return -2 for non-existing file, -1 on other errors and 0 if everything went
- * fine.
- */
-int
-virFileReadValueBitmap(virBitmap **value, const char *format, ...)
+static int
+virFileReadValueBitmapImpl(virBitmap **value,
+ const char *path,
+ bool allowEmpty)
{
g_autofree char *str = NULL;
- g_autofree char *path = NULL;
- va_list ap;
-
- va_start(ap, format);
- path = g_strdup_vprintf(format, ap);
- va_end(ap);
if (!virFileExists(path))
return -2;
@@ -4394,13 +4380,70 @@ virFileReadValueBitmap(virBitmap **value, const char *format,
...)
virStringTrimOptionalNewline(str);
- *value = virBitmapParseUnlimited(str);
+ if (allowEmpty) {
+ *value = virBitmapParseUnlimitedAllowEmpty(str);
+ } else {
+ *value = virBitmapParseUnlimited(str);
+ }
+
if (!*value)
return -1;
return 0;
}
+
+/**
+ * virFileReadValueBitmap:
+ * @value: pointer to virBitmap * to be allocated and filled in with the value
+ * @format, ...: file to read from
+ *
+ * Read int from @format and put it into @value.
+ *
+ * Returns: -2 for non-existing file,
+ * -1 on other errors (with error reported),
+ * 0 otherwise.
+ */
+int
+virFileReadValueBitmap(virBitmap **value, const char *format, ...)
+{
+ g_autofree char *path = NULL;
+ va_list ap;
+
+ va_start(ap, format);
+ path = g_strdup_vprintf(format, ap);
+ va_end(ap);
+
+ return virFileReadValueBitmapImpl(value, path, false);
+}
+
+
+/**
+ * virFileReadValueBitmapAllowEmpty:
+ * @value: pointer to virBitmap * to be allocated and filled in with the value
+ * @format, ...: file to read from
+ *
+ * Just like virFileReadValueBitmap(), except if the file is empty or contains
+ * nothing but spaces an empty bitmap is returned instead of an error.
+ *
+ * Returns: -2 for non-existing file,
+ * -1 on other errors (with error reported),
+ * 0 otherwise.
+ */
+int
+virFileReadValueBitmapAllowEmpty(virBitmap **value, const char *format, ...)
+{
+ g_autofree char *path = NULL;
+ va_list ap;
+
+ va_start(ap, format);
+ path = g_strdup_vprintf(format, ap);
+ va_end(ap);
+
+ return virFileReadValueBitmapImpl(value, path, true);
+}
+
+
/**
* virFileReadValueString:
* @value: pointer to char * to be allocated and filled in with the value
diff --git a/src/util/virfile.h b/src/util/virfile.h
index 56fe309bce..7df3fcb840 100644
--- a/src/util/virfile.h
+++ b/src/util/virfile.h
@@ -354,6 +354,8 @@ int virFileReadValueUllongQuiet(unsigned long long *value, const char
*format, .
G_GNUC_PRINTF(2, 3);
int virFileReadValueBitmap(virBitmap **value, const char *format, ...)
G_GNUC_PRINTF(2, 3);
+int virFileReadValueBitmapAllowEmpty(virBitmap **value, const char *format, ...)
+ G_GNUC_PRINTF(2, 3);
int virFileReadValueScaledInt(unsigned long long *value, const char *format, ...)
G_GNUC_PRINTF(2, 3);
int virFileReadValueString(char **value, const char *format, ...)
--
2.43.2