]> git.proxmox.com Git - systemd.git/blob - src/basic/chattr-util.c
Merge tag 'upstream/229'
[systemd.git] / src / basic / chattr-util.c
1 /***
2 This file is part of systemd.
3
4 Copyright 2010 Lennart Poettering
5
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.
10
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.
15
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/>.
18 ***/
19
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <sys/ioctl.h>
23 #include <sys/stat.h>
24 #include <linux/fs.h>
25
26 #include "chattr-util.h"
27 #include "fd-util.h"
28 #include "macro.h"
29
30 int chattr_fd(int fd, unsigned value, unsigned mask) {
31 unsigned old_attr, new_attr;
32 struct stat st;
33
34 assert(fd >= 0);
35
36 if (fstat(fd, &st) < 0)
37 return -errno;
38
39 /* Explicitly check whether this is a regular file or
40 * directory. If it is anything else (such as a device node or
41 * fifo), then the ioctl will not hit the file systems but
42 * possibly drivers, where the ioctl might have different
43 * effects. Notably, DRM is using the same ioctl() number. */
44
45 if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode))
46 return -ENOTTY;
47
48 if (mask == 0)
49 return 0;
50
51 if (ioctl(fd, FS_IOC_GETFLAGS, &old_attr) < 0)
52 return -errno;
53
54 new_attr = (old_attr & ~mask) | (value & mask);
55 if (new_attr == old_attr)
56 return 0;
57
58 if (ioctl(fd, FS_IOC_SETFLAGS, &new_attr) < 0)
59 return -errno;
60
61 return 1;
62 }
63
64 int chattr_path(const char *p, unsigned value, unsigned mask) {
65 _cleanup_close_ int fd = -1;
66
67 assert(p);
68
69 if (mask == 0)
70 return 0;
71
72 fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
73 if (fd < 0)
74 return -errno;
75
76 return chattr_fd(fd, value, mask);
77 }
78
79 int read_attr_fd(int fd, unsigned *ret) {
80 struct stat st;
81
82 assert(fd >= 0);
83
84 if (fstat(fd, &st) < 0)
85 return -errno;
86
87 if (!S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode))
88 return -ENOTTY;
89
90 if (ioctl(fd, FS_IOC_GETFLAGS, ret) < 0)
91 return -errno;
92
93 return 0;
94 }
95
96 int read_attr_path(const char *p, unsigned *ret) {
97 _cleanup_close_ int fd = -1;
98
99 assert(p);
100 assert(ret);
101
102 fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
103 if (fd < 0)
104 return -errno;
105
106 return read_attr_fd(fd, ret);
107 }