]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/xattr-util.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
28 #include <sys/xattr.h>
30 #include "alloc-util.h"
33 #include "sparse-endian.h"
34 #include "stdio-util.h"
35 #include "time-util.h"
36 #include "xattr-util.h"
38 int getxattr_malloc(const char *path
, const char *name
, char **value
, bool allow_symlink
) {
47 for (l
= 100; ; l
= (size_t) n
+ 1) {
53 n
= lgetxattr(path
, name
, v
, l
);
55 n
= getxattr(path
, name
, v
, l
);
57 if (n
>= 0 && (size_t) n
< l
) {
64 if (n
< 0 && errno
!= ERANGE
)
68 n
= lgetxattr(path
, name
, NULL
, 0);
70 n
= getxattr(path
, name
, NULL
, 0);
76 int fgetxattr_malloc(int fd
, const char *name
, char **value
) {
85 for (l
= 100; ; l
= (size_t) n
+ 1) {
90 n
= fgetxattr(fd
, name
, v
, l
);
92 if (n
>= 0 && (size_t) n
< l
) {
99 if (n
< 0 && errno
!= ERANGE
)
102 n
= fgetxattr(fd
, name
, NULL
, 0);
108 ssize_t
fgetxattrat_fake(int dirfd
, const char *filename
, const char *attribute
, void *value
, size_t size
, int flags
) {
109 char fn
[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
110 _cleanup_close_
int fd
= -1;
113 /* The kernel doesn't have a fgetxattrat() command, hence let's emulate one */
115 fd
= openat(dirfd
, filename
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_PATH
|(flags
& AT_SYMLINK_NOFOLLOW
? O_NOFOLLOW
: 0));
119 xsprintf(fn
, "/proc/self/fd/%i", fd
);
121 l
= getxattr(fn
, attribute
, value
, size
);
128 static int parse_crtime(le64_t le
, usec_t
*usec
) {
134 if (u
== 0 || u
== (uint64_t) -1)
141 int fd_getcrtime(int fd
, usec_t
*usec
) {
148 /* Until Linux gets a real concept of birthtime/creation time,
149 * let's fake one with xattrs */
151 n
= fgetxattr(fd
, "user.crtime_usec", &le
, sizeof(le
));
157 return parse_crtime(le
, usec
);
160 int fd_getcrtime_at(int dirfd
, const char *name
, usec_t
*usec
, int flags
) {
164 n
= fgetxattrat_fake(dirfd
, name
, "user.crtime_usec", &le
, sizeof(le
), flags
);
170 return parse_crtime(le
, usec
);
173 int path_getcrtime(const char *p
, usec_t
*usec
) {
180 n
= getxattr(p
, "user.crtime_usec", &le
, sizeof(le
));
186 return parse_crtime(le
, usec
);
189 int fd_setcrtime(int fd
, usec_t usec
) {
195 usec
= now(CLOCK_REALTIME
);
197 le
= htole64((uint64_t) usec
);
198 if (fsetxattr(fd
, "user.crtime_usec", &le
, sizeof(le
), 0) < 0)