]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/libsystemd/sd-id128/id128-util.c
tree-wide: "<n>bit" → "<n>-bit"
[thirdparty/systemd.git] / src / libsystemd / sd-id128 / id128-util.c
index 3395ba2e58762067f806485e626489c126846471..ee9e91c58d5f9e927dd9570008abc5abca440f7a 100644 (file)
@@ -5,6 +5,7 @@
 #include <unistd.h>
 
 #include "fd-util.h"
+#include "fs-util.h"
 #include "hexdecoct.h"
 #include "id128-util.h"
 #include "io-util.h"
@@ -20,7 +21,7 @@ bool id128_is_valid(const char *s) {
         l = strlen(s);
 
         if (l == SD_ID128_STRING_MAX - 1)
-                /* Plain formatted 128bit hex string */
+                /* Plain formatted 128-bit hex string */
                 return in_charset(s, HEXDIGITS);
 
         if (l == SD_ID128_UUID_STRING_MAX - 1) {
@@ -40,13 +41,15 @@ bool id128_is_valid(const char *s) {
         return false;
 }
 
-int id128_read_fd(int fd, Id128FormatFlag f, sd_id128_t *ret) {
+int id128_read_fd(int fd, Id128Flag f, sd_id128_t *ret) {
         char buffer[SD_ID128_UUID_STRING_MAX + 1]; /* +1 is for trailing newline */
+        sd_id128_t id;
         ssize_t l;
+        int r;
 
         assert(fd >= 0);
 
-        /* Reads an 128bit ID from a file, which may either be in plain format (32 hex digits), or in UUID format, both
+        /* Reads an 128-bit ID from a file, which may either be in plain format (32 hex digits), or in UUID format, both
          * optionally followed by a newline and nothing else. ID files should really be newline terminated, but if they
          * aren't that's OK too, following the rule of "Be conservative in what you send, be liberal in what you
          * accept".
@@ -54,7 +57,7 @@ int id128_read_fd(int fd, Id128FormatFlag f, sd_id128_t *ret) {
          * This returns the following:
          *     -ENOMEDIUM: an empty string,
          *     -ENOPKG:    "uninitialized" or "uninitialized\n",
-         *     -EINVAL:    other invalid strings. */
+         *     -EUCLEAN:   other invalid strings. */
 
         l = loop_read(fd, buffer, sizeof(buffer), false); /* we expect a short read of either 32/33 or 36/37 chars */
         if (l < 0)
@@ -70,46 +73,60 @@ int id128_read_fd(int fd, Id128FormatFlag f, sd_id128_t *ret) {
 
         case SD_ID128_STRING_MAX: /* plain UUID with trailing newline */
                 if (buffer[SD_ID128_STRING_MAX-1] != '\n')
-                        return -EINVAL;
+                        return -EUCLEAN;
 
                 _fallthrough_;
         case SD_ID128_STRING_MAX-1: /* plain UUID without trailing newline */
                 if (!FLAGS_SET(f, ID128_FORMAT_PLAIN))
-                        return -EINVAL;
+                        return -EUCLEAN;
 
                 buffer[SD_ID128_STRING_MAX-1] = 0;
                 break;
 
         case SD_ID128_UUID_STRING_MAX: /* RFC UUID with trailing newline */
                 if (buffer[SD_ID128_UUID_STRING_MAX-1] != '\n')
-                        return -EINVAL;
+                        return -EUCLEAN;
 
                 _fallthrough_;
         case SD_ID128_UUID_STRING_MAX-1: /* RFC UUID without trailing newline */
                 if (!FLAGS_SET(f, ID128_FORMAT_UUID))
-                        return -EINVAL;
+                        return -EUCLEAN;
 
                 buffer[SD_ID128_UUID_STRING_MAX-1] = 0;
                 break;
 
         default:
-                return -EINVAL;
+                return -EUCLEAN;
         }
 
-        return sd_id128_from_string(buffer, ret);
+        r = sd_id128_from_string(buffer, &id);
+        if (r == -EINVAL)
+                return -EUCLEAN;
+        if (r < 0)
+                return r;
+
+        if (FLAGS_SET(f, ID128_REFUSE_NULL) && sd_id128_is_null(id))
+                return -ENOMEDIUM;
+
+        if (ret)
+                *ret = id;
+        return 0;
 }
 
-int id128_read(const char *p, Id128FormatFlag f, sd_id128_t *ret) {
-        _cleanup_close_ int fd = -1;
+int id128_read_at(int dir_fd, const char *path, Id128Flag f, sd_id128_t *ret) {
+        _cleanup_close_ int fd = -EBADF;
+
+        assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
+        assert(path);
 
-        fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY);
+        fd = xopenat(dir_fd, path, O_RDONLY|O_CLOEXEC|O_NOCTTY, /* xopen_flags = */ 0, /* mode = */ 0);
         if (fd < 0)
-                return -errno;
+                return fd;
 
         return id128_read_fd(fd, f, ret);
 }
 
-int id128_write_fd(int fd, Id128FormatFlag f, sd_id128_t id) {
+int id128_write_fd(int fd, Id128Flag f, sd_id128_t id) {
         char buffer[SD_ID128_UUID_STRING_MAX + 1]; /* +1 is for trailing newline */
         size_t sz;
         int r;
@@ -117,6 +134,9 @@ int id128_write_fd(int fd, Id128FormatFlag f, sd_id128_t id) {
         assert(fd >= 0);
         assert(IN_SET((f & ID128_FORMAT_ANY), ID128_FORMAT_PLAIN, ID128_FORMAT_UUID));
 
+        if (FLAGS_SET(f, ID128_REFUSE_NULL) && sd_id128_is_null(id))
+                return -ENOMEDIUM;
+
         if (FLAGS_SET(f, ID128_FORMAT_PLAIN)) {
                 assert_se(sd_id128_to_string(id, buffer));
                 sz = SD_ID128_STRING_MAX;
@@ -139,12 +159,15 @@ int id128_write_fd(int fd, Id128FormatFlag f, sd_id128_t id) {
         return 0;
 }
 
-int id128_write(const char *p, Id128FormatFlag f, sd_id128_t id) {
-        _cleanup_close_ int fd = -1;
+int id128_write_at(int dir_fd, const char *path, Id128Flag f, sd_id128_t id) {
+        _cleanup_close_ int fd = -EBADF;
+
+        assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
+        assert(path);
 
-        fd = open(p, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_TRUNC, 0444);
+        fd = xopenat(dir_fd, path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_TRUNC, /* xopen_flags = */ 0, 0444);
         if (fd < 0)
-                return -errno;
+                return fd;
 
         return id128_write_fd(fd, f, id);
 }
@@ -171,6 +194,7 @@ sd_id128_t id128_make_v4_uuid(sd_id128_t id) {
 }
 
 DEFINE_HASH_OPS(id128_hash_ops, sd_id128_t, id128_hash_func, id128_compare_func);
+DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(id128_hash_ops_free, sd_id128_t, id128_hash_func, id128_compare_func, free);
 
 int id128_get_product(sd_id128_t *ret) {
         sd_id128_t uuid;