summaryrefslogtreecommitdiff
path: root/src/basic
diff options
context:
space:
mode:
Diffstat (limited to 'src/basic')
-rw-r--r--src/basic/bitmap.c16
-rw-r--r--src/basic/calendarspec.c8
-rw-r--r--src/basic/cgroup-util.c9
-rw-r--r--src/basic/copy.c6
-rw-r--r--src/basic/fileio.c10
-rw-r--r--src/basic/list.h26
-rw-r--r--src/basic/missing.h4
-rw-r--r--src/basic/smack-util.c117
-rw-r--r--src/basic/smack-util.h24
-rw-r--r--src/basic/socket-util.c8
-rw-r--r--src/basic/terminal-util.c36
-rw-r--r--src/basic/unit-name.c11
-rw-r--r--src/basic/util.c97
-rw-r--r--src/basic/util.h9
14 files changed, 266 insertions, 115 deletions
diff --git a/src/basic/bitmap.c b/src/basic/bitmap.c
index bf9d8d4d7c..7ea3357031 100644
--- a/src/basic/bitmap.c
+++ b/src/basic/bitmap.c
@@ -145,7 +145,10 @@ bool bitmap_isclear(Bitmap *b) {
void bitmap_clear(Bitmap *b) {
assert(b);
+ free(b->bitmaps);
+ b->bitmaps = NULL;
b->n_bitmaps = 0;
+ b->bitmaps_allocated = 0;
}
bool bitmap_iterate(Bitmap *b, Iterator *i, unsigned *n) {
@@ -184,6 +187,9 @@ bool bitmap_iterate(Bitmap *b, Iterator *i, unsigned *n) {
}
bool bitmap_equal(Bitmap *a, Bitmap *b) {
+ size_t common_n_bitmaps;
+ Bitmap *c;
+ unsigned i;
if (!a ^ !b)
return false;
@@ -191,8 +197,14 @@ bool bitmap_equal(Bitmap *a, Bitmap *b) {
if (!a)
return true;
- if (a->n_bitmaps != b->n_bitmaps)
+ common_n_bitmaps = MIN(a->n_bitmaps, b->n_bitmaps);
+ if (memcmp(a->bitmaps, b->bitmaps, sizeof(uint64_t) * common_n_bitmaps) != 0)
return false;
- return memcmp(a->bitmaps, b->bitmaps, sizeof(uint64_t) * a->n_bitmaps) == 0;
+ c = a->n_bitmaps > b->n_bitmaps ? a : b;
+ for (i = common_n_bitmaps; i < c->n_bitmaps; i++)
+ if (c->bitmaps[i] != 0)
+ return false;
+
+ return true;
}
diff --git a/src/basic/calendarspec.c b/src/basic/calendarspec.c
index 2fde3e107e..2dcc9c5575 100644
--- a/src/basic/calendarspec.c
+++ b/src/basic/calendarspec.c
@@ -253,6 +253,7 @@ int calendar_spec_to_string(const CalendarSpec *c, char **p) {
char *buf = NULL;
size_t sz = 0;
FILE *f;
+ int r;
assert(c);
assert(p);
@@ -278,12 +279,11 @@ int calendar_spec_to_string(const CalendarSpec *c, char **p) {
fputc(':', f);
format_chain(f, 2, c->second);
- fflush(f);
-
- if (ferror(f)) {
+ r = fflush_and_check(f);
+ if (r < 0) {
free(buf);
fclose(f);
- return -ENOMEM;
+ return r;
}
fclose(f);
diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c
index 34a3060509..6b3162a35f 100644
--- a/src/basic/cgroup-util.c
+++ b/src/basic/cgroup-util.c
@@ -826,14 +826,12 @@ int cg_install_release_agent(const char *controller, const char *agent) {
} else if (!streq(sc, agent))
return -EEXIST;
- free(fs);
- fs = NULL;
+ fs = mfree(fs);
r = cg_get_path(controller, NULL, "notify_on_release", &fs);
if (r < 0)
return r;
- free(contents);
- contents = NULL;
+ contents = mfree(contents);
r = read_one_line_file(fs, &contents);
if (r < 0)
return r;
@@ -865,8 +863,7 @@ int cg_uninstall_release_agent(const char *controller) {
if (r < 0)
return r;
- free(fs);
- fs = NULL;
+ fs = mfree(fs);
r = cg_get_path(controller, NULL, "release_agent", &fs);
if (r < 0)
diff --git a/src/basic/copy.c b/src/basic/copy.c
index e2d356d676..33427c6a73 100644
--- a/src/basic/copy.c
+++ b/src/basic/copy.c
@@ -467,8 +467,7 @@ int copy_xattr(int fdf, int fdt) {
sza *= 2;
- free(bufa);
- bufa = NULL;
+ bufa = mfree(bufa);
}
p = bufa;
@@ -491,8 +490,7 @@ int copy_xattr(int fdf, int fdt) {
if (m < 0) {
if (errno == ERANGE) {
szb *= 2;
- free(bufb);
- bufb = NULL;
+ bufb = mfree(bufb);
continue;
}
diff --git a/src/basic/fileio.c b/src/basic/fileio.c
index 2216853777..4a9105f421 100644
--- a/src/basic/fileio.c
+++ b/src/basic/fileio.c
@@ -28,21 +28,15 @@
#include "fileio.h"
int write_string_stream(FILE *f, const char *line, bool enforce_newline) {
+
assert(f);
assert(line);
- errno = 0;
-
fputs(line, f);
if (enforce_newline && !endswith(line, "\n"))
fputc('\n', f);
- fflush(f);
-
- if (ferror(f))
- return errno ? -errno : -EIO;
-
- return 0;
+ return fflush_and_check(f);
}
static int write_string_file_atomic(const char *fn, const char *line, bool enforce_newline) {
diff --git a/src/basic/list.h b/src/basic/list.h
index 2939216adb..760abcdab3 100644
--- a/src/basic/list.h
+++ b/src/basic/list.h
@@ -123,6 +123,32 @@
} \
} while(false)
+/* Insert an item before another one (a = where, b = what) */
+#define LIST_INSERT_BEFORE(name,head,a,b) \
+ do { \
+ typeof(*(head)) **_head = &(head), *_a = (a), *_b = (b); \
+ assert(_b); \
+ if (!_a) { \
+ if (!*_head) { \
+ _b->name##_next = NULL; \
+ _b->name##_prev = NULL; \
+ *_head = _b; \
+ } else { \
+ typeof(*(head)) *_tail = (head); \
+ while (_tail->name##_next) \
+ _tail = _tail->name##_next; \
+ _b->name##_next = NULL; \
+ _b->name##_prev = _tail; \
+ _tail->name##_next = _b; \
+ } \
+ } else { \
+ if ((_b->name##_prev = _a->name##_prev)) \
+ _b->name##_prev->name##_next = _b; \
+ _b->name##_next = _a; \
+ _a->name##_prev = _b; \
+ } \
+ } while(false)
+
#define LIST_JUST_US(name,item) \
(!(item)->name##_prev && !(item)->name##_next) \
diff --git a/src/basic/missing.h b/src/basic/missing.h
index ed6cd80c75..34ab0254dd 100644
--- a/src/basic/missing.h
+++ b/src/basic/missing.h
@@ -977,7 +977,11 @@ static inline int raw_clone(unsigned long flags, void *child_stack) {
}
static inline pid_t raw_getpid(void) {
+#if defined(__alpha__)
+ return (pid_t) syscall(__NR_getxpid);
+#else
return (pid_t) syscall(__NR_getpid);
+#endif
}
#if !HAVE_DECL_RENAMEAT2
diff --git a/src/basic/smack-util.c b/src/basic/smack-util.c
index 047aa294f4..6d5c205117 100644
--- a/src/basic/smack-util.c
+++ b/src/basic/smack-util.c
@@ -32,109 +32,93 @@
#define SMACK_FLOOR_LABEL "_"
#define SMACK_STAR_LABEL "*"
-bool mac_smack_use(void) {
#ifdef HAVE_SMACK
+bool mac_smack_use(void) {
static int cached_use = -1;
if (cached_use < 0)
cached_use = access("/sys/fs/smackfs/", F_OK) >= 0;
return cached_use;
-#else
- return false;
-#endif
}
-int mac_smack_apply(const char *path, const char *label) {
- int r = 0;
+static const char* const smack_attr_table[_SMACK_ATTR_MAX] = {
+ [SMACK_ATTR_ACCESS] = "security.SMACK64",
+ [SMACK_ATTR_EXEC] = "security.SMACK64EXEC",
+ [SMACK_ATTR_MMAP] = "security.SMACK64MMAP",
+ [SMACK_ATTR_TRANSMUTE] = "security.SMACK64TRANSMUTE",
+ [SMACK_ATTR_IPIN] = "security.SMACK64IPIN",
+ [SMACK_ATTR_IPOUT] = "security.SMACK64IPOUT",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(smack_attr, SmackAttr);
+int mac_smack_read(const char *path, SmackAttr attr, char **label) {
assert(path);
+ assert(attr >= 0 && attr < _SMACK_ATTR_MAX);
+ assert(label);
-#ifdef HAVE_SMACK
if (!mac_smack_use())
return 0;
- if (label)
- r = lsetxattr(path, "security.SMACK64", label, strlen(label), 0);
- else
- r = lremovexattr(path, "security.SMACK64");
- if (r < 0)
- return -errno;
-#endif
-
- return r;
+ return getxattr_malloc(path, smack_attr_to_string(attr), label, true);
}
-int mac_smack_apply_fd(int fd, const char *label) {
- int r = 0;
-
+int mac_smack_read_fd(int fd, SmackAttr attr, char **label) {
assert(fd >= 0);
+ assert(attr >= 0 && attr < _SMACK_ATTR_MAX);
+ assert(label);
-#ifdef HAVE_SMACK
if (!mac_smack_use())
return 0;
- if (label)
- r = fsetxattr(fd, "security.SMACK64", label, strlen(label), 0);
- else
- r = fremovexattr(fd, "security.SMACK64");
- if (r < 0)
- return -errno;
-#endif
-
- return r;
+ return fgetxattr_malloc(fd, smack_attr_to_string(attr), label);
}
-int mac_smack_apply_ip_out_fd(int fd, const char *label) {
- int r = 0;
+int mac_smack_apply(const char *path, SmackAttr attr, const char *label) {
+ int r;
- assert(fd >= 0);
+ assert(path);
+ assert(attr >= 0 && attr < _SMACK_ATTR_MAX);
-#ifdef HAVE_SMACK
if (!mac_smack_use())
return 0;
if (label)
- r = fsetxattr(fd, "security.SMACK64IPOUT", label, strlen(label), 0);
+ r = lsetxattr(path, smack_attr_to_string(attr), label, strlen(label), 0);
else
- r = fremovexattr(fd, "security.SMACK64IPOUT");
+ r = lremovexattr(path, smack_attr_to_string(attr));
if (r < 0)
return -errno;
-#endif
- return r;
+ return 0;
}
-int mac_smack_apply_ip_in_fd(int fd, const char *label) {
- int r = 0;
+int mac_smack_apply_fd(int fd, SmackAttr attr, const char *label) {
+ int r;
assert(fd >= 0);
+ assert(attr >= 0 && attr < _SMACK_ATTR_MAX);
-#ifdef HAVE_SMACK
if (!mac_smack_use())
return 0;
if (label)
- r = fsetxattr(fd, "security.SMACK64IPIN", label, strlen(label), 0);
+ r = fsetxattr(fd, smack_attr_to_string(attr), label, strlen(label), 0);
else
- r = fremovexattr(fd, "security.SMACK64IPIN");
+ r = fremovexattr(fd, smack_attr_to_string(attr));
if (r < 0)
return -errno;
-#endif
- return r;
+ return 0;
}
int mac_smack_apply_pid(pid_t pid, const char *label) {
-
-#ifdef HAVE_SMACK
const char *p;
-#endif
int r = 0;
assert(label);
-#ifdef HAVE_SMACK
if (!mac_smack_use())
return 0;
@@ -142,21 +126,16 @@ int mac_smack_apply_pid(pid_t pid, const char *label) {
r = write_string_file(p, label, 0);
if (r < 0)
return r;
-#endif
return r;
}
int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
-
-#ifdef HAVE_SMACK
struct stat st;
-#endif
int r = 0;
assert(path);
-#ifdef HAVE_SMACK
if (!mac_smack_use())
return 0;
@@ -202,7 +181,37 @@ int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
r = log_debug_errno(errno, "Unable to fix SMACK label of %s: %m", path);
}
-#endif
return r;
}
+
+
+#else
+bool mac_smack_use(void) {
+ return false;
+}
+
+int mac_smack_read(const char *path, SmackAttr attr, char **label) {
+ return -EOPNOTSUPP;
+}
+
+int mac_smack_read_fd(int fd, SmackAttr attr, char **label) {
+ return -EOPNOTSUPP;
+}
+
+int mac_smack_apply(const char *path, SmackAttr attr, const char *label) {
+ return 0;
+}
+
+int mac_smack_apply_fd(int fd, SmackAttr attr, const char *label) {
+ return 0;
+}
+
+int mac_smack_apply_pid(pid_t pid, const char *label) {
+ return 0;
+}
+
+int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
+ return 0;
+}
+#endif
diff --git a/src/basic/smack-util.h b/src/basic/smack-util.h
index 50f55b1f4b..1052cecf4c 100644
--- a/src/basic/smack-util.h
+++ b/src/basic/smack-util.h
@@ -25,12 +25,28 @@
#include <stdbool.h>
+#include "macro.h"
+
+typedef enum SmackAttr {
+ SMACK_ATTR_ACCESS = 0,
+ SMACK_ATTR_EXEC = 1,
+ SMACK_ATTR_MMAP = 2,
+ SMACK_ATTR_TRANSMUTE = 3,
+ SMACK_ATTR_IPIN = 4,
+ SMACK_ATTR_IPOUT = 5,
+ _SMACK_ATTR_MAX,
+ _SMACK_ATTR_INVALID = -1,
+} SmackAttr;
+
bool mac_smack_use(void);
int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs);
-int mac_smack_apply(const char *path, const char *label);
-int mac_smack_apply_fd(int fd, const char *label);
+const char* smack_attr_to_string(SmackAttr i) _const_;
+SmackAttr smack_attr_from_string(const char *s) _pure_;
+int mac_smack_read(const char *path, SmackAttr attr, char **label);
+int mac_smack_read_fd(int fd, SmackAttr attr, char **label);
+int mac_smack_apply(const char *path, SmackAttr attr, const char *label);
+int mac_smack_apply_fd(int fd, SmackAttr attr, const char *label);
+
int mac_smack_apply_pid(pid_t pid, const char *label);
-int mac_smack_apply_ip_in_fd(int fd, const char *label);
-int mac_smack_apply_ip_out_fd(int fd, const char *label);
diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c
index e8bb10dc9b..8fd3149276 100644
--- a/src/basic/socket-util.c
+++ b/src/basic/socket-util.c
@@ -583,7 +583,7 @@ int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_
} else {
p = strndup(sa->un.sun_path, sizeof(sa->un.sun_path));
- if (!ret)
+ if (!p)
return -ENOMEM;
}
@@ -662,13 +662,13 @@ int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret)
r = sockaddr_pretty(&sa->sa, salen, true, true, &ret);
if (r < 0)
- return log_error_errno(r, "sockadd_pretty() failed: %m");
+ return r;
log_debug_errno(saved_errno, "getnameinfo(%s) failed: %m", ret);
} else {
ret = strdup(host);
if (!ret)
- return log_oom();
+ return -ENOMEM;
}
*_ret = ret;
@@ -683,7 +683,7 @@ int getnameinfo_pretty(int fd, char **ret) {
assert(ret);
if (getsockname(fd, &sa.sa, &salen) < 0)
- return log_error_errno(errno, "getsockname(%d) failed: %m", fd);
+ return -errno;
return socknameinfo_pretty(&sa, salen, ret);
}
diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c
index 042b88f222..cf55263bbf 100644
--- a/src/basic/terminal-util.c
+++ b/src/basic/terminal-util.c
@@ -44,7 +44,7 @@ static volatile unsigned cached_lines = 0;
int chvt(int vt) {
_cleanup_close_ int fd;
- fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
+ fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
if (fd < 0)
return -errno;
@@ -230,14 +230,14 @@ int reset_terminal_fd(int fd, bool switch_to_text) {
* interfere with that. */
/* Disable exclusive mode, just in case */
- ioctl(fd, TIOCNXCL);
+ (void) ioctl(fd, TIOCNXCL);
/* Switch to text mode */
if (switch_to_text)
- ioctl(fd, KDSETMODE, KD_TEXT);
+ (void) ioctl(fd, KDSETMODE, KD_TEXT);
/* Enable console unicode mode */
- ioctl(fd, KDSKBMODE, K_UNICODE);
+ (void) ioctl(fd, KDSKBMODE, K_UNICODE);
if (tcgetattr(fd, &termios) < 0) {
r = -errno;
@@ -276,7 +276,7 @@ int reset_terminal_fd(int fd, bool switch_to_text) {
finish:
/* Just in case, flush all crap out */
- tcflush(fd, TCIOFLUSH);
+ (void) tcflush(fd, TCIOFLUSH);
return r;
}
@@ -284,7 +284,11 @@ finish:
int reset_terminal(const char *name) {
_cleanup_close_ int fd = -1;
- fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
+ /* We open the terminal with O_NONBLOCK here, to ensure we
+ * don't block on carrier if this is a terminal with carrier
+ * configured. */
+
+ fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
if (fd < 0)
return fd;
@@ -304,7 +308,8 @@ int open_terminal(const char *name, int mode) {
* https://bugs.launchpad.net/ubuntu/+source/linux/+bug/554172/comments/245
*/
- assert(!(mode & O_CREAT));
+ if (mode & O_CREAT)
+ return -EINVAL;
for (;;) {
fd = open(name, mode, 0);
@@ -413,9 +418,8 @@ int acquire_terminal(
if (r < 0 && r == -EPERM && ignore_tiocstty_eperm)
r = 0;
- if (r < 0 && (force || fail || r != -EPERM)) {
+ if (r < 0 && (force || fail || r != -EPERM))
goto fail;
- }
if (r >= 0)
break;
@@ -499,7 +503,7 @@ int release_terminal(void) {
struct sigaction sa_old;
int r = 0;
- fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_NDELAY|O_CLOEXEC);
+ fd = open("/dev/tty", O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
if (fd < 0)
return -errno;
@@ -527,7 +531,7 @@ int terminal_vhangup_fd(int fd) {
int terminal_vhangup(const char *name) {
_cleanup_close_ int fd;
- fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC);
+ fd = open_terminal(name, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
if (fd < 0)
return fd;
@@ -574,7 +578,7 @@ int vt_disallocate(const char *name) {
return -EINVAL;
/* Try to deallocate */
- fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
+ fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
if (fd < 0)
return fd;
@@ -612,16 +616,16 @@ void warn_melody(void) {
/* Yeah, this is synchronous. Kinda sucks. But well... */
- ioctl(fd, KIOCSOUND, (int)(1193180/440));
+ (void) ioctl(fd, KIOCSOUND, (int)(1193180/440));
usleep(125*USEC_PER_MSEC);
- ioctl(fd, KIOCSOUND, (int)(1193180/220));
+ (void) ioctl(fd, KIOCSOUND, (int)(1193180/220));
usleep(125*USEC_PER_MSEC);
- ioctl(fd, KIOCSOUND, (int)(1193180/220));
+ (void) ioctl(fd, KIOCSOUND, (int)(1193180/220));
usleep(125*USEC_PER_MSEC);
- ioctl(fd, KIOCSOUND, 0);
+ (void) ioctl(fd, KIOCSOUND, 0);
}
int make_console_stdio(void) {
diff --git a/src/basic/unit-name.c b/src/basic/unit-name.c
index bf52463d81..fa530da456 100644
--- a/src/basic/unit-name.c
+++ b/src/basic/unit-name.c
@@ -673,6 +673,7 @@ int unit_name_mangle_with_suffix(const char *name, UnitNameMangle allow_globs, c
int slice_build_parent_slice(const char *slice, char **ret) {
char *s, *dash;
+ int r;
assert(slice);
assert(ret);
@@ -693,11 +694,11 @@ int slice_build_parent_slice(const char *slice, char **ret) {
if (dash)
strcpy(dash, ".slice");
else {
- free(s);
-
- s = strdup("-.slice");
- if (!s)
- return -ENOMEM;
+ r = free_and_strdup(&s, "-.slice");
+ if (r < 0) {
+ free(s);
+ return r;
+ }
}
*ret = s;
diff --git a/src/basic/util.c b/src/basic/util.c
index f81bf4e31e..d4d3d3c83a 100644
--- a/src/basic/util.c
+++ b/src/basic/util.c
@@ -115,17 +115,23 @@ size_t page_size(void) {
return pgsz;
}
-bool streq_ptr(const char *a, const char *b) {
-
- /* Like streq(), but tries to make sense of NULL pointers */
+int strcmp_ptr(const char *a, const char *b) {
+ /* Like strcmp(), but tries to make sense of NULL pointers */
if (a && b)
- return streq(a, b);
+ return strcmp(a, b);
- if (!a && !b)
- return true;
+ if (!a && b)
+ return -1;
- return false;
+ if (a && !b)
+ return 1;
+
+ return 0;
+}
+
+bool streq_ptr(const char *a, const char *b) {
+ return strcmp_ptr(a, b) == 0;
}
char* endswith(const char *s, const char *postfix) {
@@ -954,7 +960,12 @@ int unhexmem(const char *p, size_t l, void **mem, size_t *len) {
return 0;
}
-/* https://tools.ietf.org/html/rfc4648#section-6 */
+/* https://tools.ietf.org/html/rfc4648#section-6
+ * Notice that base32hex differs from base32 in the alphabet it uses.
+ * The distinction is that the base32hex representation preserves the
+ * order of the underlying data when compared as bytestrings, this is
+ * useful when representing NSEC3 hashes, as one can then verify the
+ * order of hashes directly from their representation. */
char base32hexchar(int x) {
static const char table[32] = "0123456789"
"ABCDEFGHIJKLMNOPQRSTUV";
@@ -6592,3 +6603,73 @@ int reset_uid_gid(void) {
return 0;
}
+
+int getxattr_malloc(const char *path, const char *name, char **value, bool allow_symlink) {
+ char *v;
+ size_t l;
+ ssize_t n;
+
+ assert(path);
+ assert(name);
+ assert(value);
+
+ for (l = 100; ; l = (size_t) n + 1) {
+ v = new0(char, l);
+ if (!v)
+ return -ENOMEM;
+
+ if (allow_symlink)
+ n = lgetxattr(path, name, v, l);
+ else
+ n = getxattr(path, name, v, l);
+
+ if (n >= 0 && (size_t) n < l) {
+ *value = v;
+ return n;
+ }
+
+ free(v);
+
+ if (n < 0 && errno != ERANGE)
+ return -errno;
+
+ if (allow_symlink)
+ n = lgetxattr(path, name, NULL, 0);
+ else
+ n = getxattr(path, name, NULL, 0);
+ if (n < 0)
+ return -errno;
+ }
+}
+
+int fgetxattr_malloc(int fd, const char *name, char **value) {
+ char *v;
+ size_t l;
+ ssize_t n;
+
+ assert(fd >= 0);
+ assert(name);
+ assert(value);
+
+ for (l = 100; ; l = (size_t) n + 1) {
+ v = new0(char, l);
+ if (!v)
+ return -ENOMEM;
+
+ n = fgetxattr(fd, name, v, l);
+
+ if (n >= 0 && (size_t) n < l) {
+ *value = v;
+ return n;
+ }
+
+ free(v);
+
+ if (n < 0 && errno != ERANGE)
+ return -errno;
+
+ n = fgetxattr(fd, name, NULL, 0);
+ if (n < 0)
+ return -errno;
+ }
+}
diff --git a/src/basic/util.h b/src/basic/util.h
index 5c0130d265..426b7f7d16 100644
--- a/src/basic/util.h
+++ b/src/basic/util.h
@@ -71,6 +71,7 @@ size_t page_size(void) _pure_;
#define strncaseeq(a, b, n) (strncasecmp((a), (b), (n)) == 0)
bool streq_ptr(const char *a, const char *b) _pure_;
+int strcmp_ptr(const char *a, const char *b) _pure_;
#define new(t, n) ((t*) malloc_multiply(sizeof(t), (n)))
@@ -84,6 +85,11 @@ bool streq_ptr(const char *a, const char *b) _pure_;
#define malloc0(n) (calloc((n), 1))
+static inline void *mfree(void *memory) {
+ free(memory);
+ return NULL;
+}
+
static inline const char* yes_no(bool b) {
return b ? "yes" : "no";
}
@@ -918,3 +924,6 @@ int parse_mode(const char *s, mode_t *ret);
int mount_move_root(const char *path);
int reset_uid_gid(void);
+
+int getxattr_malloc(const char *path, const char *name, char **value, bool allow_symlink);
+int fgetxattr_malloc(int fd, const char *name, char **value);