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