]>
Commit | Line | Data |
---|---|---|
53e1b683 | 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
c8b3094d LP |
2 | /*** |
3 | This file is part of systemd. | |
4 | ||
5 | Copyright 2010 Lennart Poettering | |
c8b3094d LP |
6 | ***/ |
7 | ||
11c3a366 TA |
8 | #include <errno.h> |
9 | #include <fcntl.h> | |
c8b3094d LP |
10 | #include <sys/ioctl.h> |
11 | #include <sys/stat.h> | |
12 | #include <linux/fs.h> | |
13 | ||
14 | #include "chattr-util.h" | |
15 | #include "fd-util.h" | |
11c3a366 | 16 | #include "macro.h" |
c8b3094d LP |
17 | |
18 | int chattr_fd(int fd, unsigned value, unsigned mask) { | |
19 | unsigned old_attr, new_attr; | |
20 | struct stat st; | |
21 | ||
22 | assert(fd >= 0); | |
23 | ||
24 | if (fstat(fd, &st) < 0) | |
25 | return -errno; | |
26 | ||
27 | /* Explicitly check whether this is a regular file or | |
28 | * directory. If it is anything else (such as a device node or | |
29 | * fifo), then the ioctl will not hit the file systems but | |
30 | * possibly drivers, where the ioctl might have different | |
31 | * effects. Notably, DRM is using the same ioctl() number. */ | |
32 | ||
33 | if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode)) | |
34 | return -ENOTTY; | |
35 | ||
36 | if (mask == 0) | |
37 | return 0; | |
38 | ||
39 | if (ioctl(fd, FS_IOC_GETFLAGS, &old_attr) < 0) | |
40 | return -errno; | |
41 | ||
42 | new_attr = (old_attr & ~mask) | (value & mask); | |
43 | if (new_attr == old_attr) | |
44 | return 0; | |
45 | ||
46 | if (ioctl(fd, FS_IOC_SETFLAGS, &new_attr) < 0) | |
47 | return -errno; | |
48 | ||
49 | return 1; | |
50 | } | |
51 | ||
52 | int chattr_path(const char *p, unsigned value, unsigned mask) { | |
53 | _cleanup_close_ int fd = -1; | |
54 | ||
55 | assert(p); | |
56 | ||
57 | if (mask == 0) | |
58 | return 0; | |
59 | ||
60 | fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); | |
61 | if (fd < 0) | |
62 | return -errno; | |
63 | ||
64 | return chattr_fd(fd, value, mask); | |
65 | } | |
66 | ||
67 | int read_attr_fd(int fd, unsigned *ret) { | |
68 | struct stat st; | |
69 | ||
70 | assert(fd >= 0); | |
71 | ||
72 | if (fstat(fd, &st) < 0) | |
73 | return -errno; | |
74 | ||
75 | if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode)) | |
76 | return -ENOTTY; | |
77 | ||
78 | if (ioctl(fd, FS_IOC_GETFLAGS, ret) < 0) | |
79 | return -errno; | |
80 | ||
81 | return 0; | |
82 | } | |
83 | ||
84 | int read_attr_path(const char *p, unsigned *ret) { | |
85 | _cleanup_close_ int fd = -1; | |
86 | ||
87 | assert(p); | |
88 | assert(ret); | |
89 | ||
90 | fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); | |
91 | if (fd < 0) | |
92 | return -errno; | |
93 | ||
94 | return read_attr_fd(fd, ret); | |
95 | } |