2 This file is part of systemd.
4 Copyright 2010 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
26 #include <sys/xattr.h>
28 #include "alloc-util.h"
31 #include "sparse-endian.h"
32 #include "stdio-util.h"
33 #include "time-util.h"
34 #include "xattr-util.h"
36 int getxattr_malloc(const char *path, const char *name, char **value, bool allow_symlink) {
45 for (l = 100; ; l = (size_t) n + 1) {
51 n = lgetxattr(path, name, v, l);
53 n = getxattr(path, name, v, l);
55 if (n >= 0 && (size_t) n < l) {
62 if (n < 0 && errno != ERANGE)
66 n = lgetxattr(path, name, NULL, 0);
68 n = getxattr(path, name, NULL, 0);
74 int fgetxattr_malloc(int fd, const char *name, char **value) {
83 for (l = 100; ; l = (size_t) n + 1) {
88 n = fgetxattr(fd, name, v, l);
90 if (n >= 0 && (size_t) n < l) {
97 if (n < 0 && errno != ERANGE)
100 n = fgetxattr(fd, name, NULL, 0);
106 #if 0 /// UNNEEDED by elogind
107 ssize_t fgetxattrat_fake(int dirfd, const char *filename, const char *attribute, void *value, size_t size, int flags) {
108 char fn[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
109 _cleanup_close_ int fd = -1;
112 /* The kernel doesn't have a fgetxattrat() command, hence let's emulate one */
114 fd = openat(dirfd, filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH|(flags & AT_SYMLINK_NOFOLLOW ? O_NOFOLLOW : 0));
118 xsprintf(fn, "/proc/self/fd/%i", fd);
120 l = getxattr(fn, attribute, value, size);
127 static int parse_crtime(le64_t le, usec_t *usec) {
133 if (u == 0 || u == (uint64_t) -1)
140 int fd_getcrtime(int fd, usec_t *usec) {
147 /* Until Linux gets a real concept of birthtime/creation time,
148 * let's fake one with xattrs */
150 n = fgetxattr(fd, "user.crtime_usec", &le, sizeof(le));
156 return parse_crtime(le, usec);
159 int fd_getcrtime_at(int dirfd, const char *name, usec_t *usec, int flags) {
163 n = fgetxattrat_fake(dirfd, name, "user.crtime_usec", &le, sizeof(le), flags);
169 return parse_crtime(le, usec);
172 int path_getcrtime(const char *p, usec_t *usec) {
179 n = getxattr(p, "user.crtime_usec", &le, sizeof(le));
185 return parse_crtime(le, usec);
188 int fd_setcrtime(int fd, usec_t usec) {
194 usec = now(CLOCK_REALTIME);
196 le = htole64((uint64_t) usec);
197 if (fsetxattr(fd, "user.crtime_usec", &le, sizeof(le), 0) < 0)