chiark / gitweb /
install: use symlink_atomic() instead of unlink()+symlink() when force creating a...
[elogind.git] / src / shared / acl-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 2011,2013 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 <assert.h>
23 #include <sys/acl.h>
24 #include <acl/libacl.h>
25 #include <errno.h>
26 #include <stdbool.h>
27
28 #include "acl-util.h"
29 #include "util.h"
30 #include "strv.h"
31
32 int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *entry) {
33         acl_entry_t i;
34         int found;
35
36         assert(acl);
37         assert(entry);
38
39         for (found = acl_get_entry(acl, ACL_FIRST_ENTRY, &i);
40              found > 0;
41              found = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) {
42
43                 acl_tag_t tag;
44                 uid_t *u;
45                 bool b;
46
47                 if (acl_get_tag_type(i, &tag) < 0)
48                         return -errno;
49
50                 if (tag != ACL_USER)
51                         continue;
52
53                 u = acl_get_qualifier(i);
54                 if (!u)
55                         return -errno;
56
57                 b = *u == uid;
58                 acl_free(u);
59
60                 if (b) {
61                         *entry = i;
62                         return 1;
63                 }
64         }
65
66         if (found < 0)
67                 return -errno;
68
69         return 0;
70 }
71
72 int calc_acl_mask_if_needed(acl_t *acl_p) {
73         acl_entry_t i;
74         int found;
75
76         assert(acl_p);
77
78         for (found = acl_get_entry(*acl_p, ACL_FIRST_ENTRY, &i);
79              found > 0;
80              found = acl_get_entry(*acl_p, ACL_NEXT_ENTRY, &i)) {
81
82                 acl_tag_t tag;
83
84                 if (acl_get_tag_type(i, &tag) < 0)
85                         return -errno;
86
87                 if (tag == ACL_MASK)
88                         return 0;
89         }
90
91         if (found < 0)
92                 return -errno;
93
94         if (acl_calc_mask(acl_p) < 0)
95                 return -errno;
96
97         return 0;
98 }
99
100 int search_acl_groups(char*** dst, const char* path, bool* belong) {
101         acl_t acl;
102
103         assert(path);
104         assert(belong);
105
106         acl = acl_get_file(path, ACL_TYPE_DEFAULT);
107         if (acl) {
108                 acl_entry_t entry;
109                 int r;
110
111                 r = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry);
112                 while (r > 0) {
113                         acl_tag_t tag;
114                         gid_t *gid;
115                         char *name;
116
117                         r = acl_get_tag_type(entry, &tag);
118                         if (r < 0)
119                                 break;
120
121                         if (tag != ACL_GROUP)
122                                 goto next;
123
124                         gid = acl_get_qualifier(entry);
125                         if (!gid)
126                                 break;
127
128                         if (in_gid(*gid) > 0) {
129                                 *belong = true;
130                                 break;
131                         }
132
133                         name = gid_to_name(*gid);
134                         if (!name) {
135                                 acl_free(acl);
136                                 return log_oom();
137                         }
138
139                         r = strv_consume(dst, name);
140                         if (r < 0) {
141                                 acl_free(acl);
142                                 return log_oom();
143                         }
144
145                 next:
146                         r = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry);
147                 }
148
149                 acl_free(acl);
150         }
151
152         return 0;
153 }