2 File: __acl_to_any_text.c
4 Copyright (C) 1999, 2000
5 Andreas Gruenbacher, <a.gruenbacher@bestbits.at>
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 #include <acl/libacl.h>
31 static ssize_t acl_entry_to_any_str(const acl_entry_t entry_d, char *text_p,
32 ssize_t size, const acl_entry_t mask_d,
33 const char *prefix, int options);
34 static ssize_t snprint_uint(char *text_p, ssize_t size, unsigned int i);
35 static const char *user_name(uid_t uid);
36 static const char *group_name(gid_t uid);
39 __acl_to_any_text(acl_t acl, ssize_t *len_p, const char *prefix,
40 char separator, const char *suffix, int options)
42 acl_obj *acl_obj_p = ext2int(acl, acl);
43 ssize_t size, len = 0, entry_len = 0,
44 suffix_len = suffix ? strlen(suffix) : 0;
45 string_obj *string_obj_p, *tmp;
46 acl_entry_obj *entry_obj_p, *mask_obj_p = NULL;
49 size = acl->a_used * 15 + 1;
50 string_obj_p = new_var_obj_p(string, size);
54 if (options & (TEXT_SOME_EFFECTIVE|TEXT_ALL_EFFECTIVE)) {
55 /* fetch the ACL_MASK entry */
56 FOREACH_ACL_ENTRY(entry_obj_p, acl_obj_p) {
57 if (entry_obj_p->etag == ACL_MASK) {
58 mask_obj_p = entry_obj_p;
64 FOREACH_ACL_ENTRY(entry_obj_p, acl_obj_p) {
66 entry_len = acl_entry_to_any_str(int2ext(entry_obj_p),
67 string_obj_p->sstr + len,
74 else if (len + entry_len + suffix_len + 1 > size) {
75 while (len + entry_len + suffix_len + 1 > size)
77 tmp = realloc_var_obj_p(string, string_obj_p, size);
84 string_obj_p->sstr[len] = separator;
90 strcpy(string_obj_p->sstr + len, suffix);
93 string_obj_p->sstr[len] = '\0';
97 return (char *)int2ext(string_obj_p);
100 free_obj_p(string_obj_p);
110 #define ABBREV(s, str_len) \
111 if (options & TEXT_ABBREVIATE) { \
118 strncpy(text_p, (s), size); \
122 #define EFFECTIVE_STR "#effective:"
125 acl_entry_to_any_str(const acl_entry_t entry_d, char *text_p, ssize_t size,
126 const acl_entry_t mask_d, const char *prefix, int options)
129 static const char *tabs = "\t\t\t\t";
130 acl_entry_obj *entry_obj_p = ext2int(acl_entry, entry_d);
131 acl_entry_obj *mask_obj_p = NULL;
135 const char *orig_text_p = text_p, *str;
139 mask_obj_p = ext2int(acl_entry, mask_d);
147 strncpy(text_p, prefix, size);
148 ADVANCE(strlen(prefix));
151 type = entry_obj_p->etag;
153 case ACL_USER_OBJ: /* owner */
156 case ACL_USER: /* additional user */
158 if (type == ACL_USER) {
159 if (options & TEXT_NUMERIC_IDS)
162 str = quote(user_name(
163 entry_obj_p->eid.qid), ":, \t\n\r");
165 strncpy(text_p, str, size);
166 ADVANCE(strlen(str));
168 x = snprint_uint(text_p, size,
169 entry_obj_p->eid.qid);
178 case ACL_GROUP_OBJ: /* owning group */
179 case ACL_GROUP: /* additional group */
181 if (type == ACL_GROUP) {
182 if (options & TEXT_NUMERIC_IDS)
185 str = quote(group_name(
186 entry_obj_p->eid.qid), ":, \t\n\r");
188 strncpy(text_p, str, size);
189 ADVANCE(strlen(str));
191 x = snprint_uint(text_p, size,
192 entry_obj_p->eid.qid);
201 case ACL_MASK: /* acl mask */
209 case ACL_OTHER: /* other users */
222 switch ((size >= 3) ? 3 : size) {
224 text_p[2] = (entry_obj_p->eperm.sperm &
225 ACL_EXECUTE) ? 'x' : '-';
228 text_p[1] = (entry_obj_p->eperm.sperm &
229 ACL_WRITE) ? 'w' : '-';
232 text_p[0] = (entry_obj_p->eperm.sperm &
233 ACL_READ) ? 'r' : '-';
239 (options & (TEXT_SOME_EFFECTIVE|TEXT_ALL_EFFECTIVE))) {
240 mask_obj_p = ext2int(acl_entry, mask_d);
244 effective = entry_obj_p->eperm.sperm &
245 mask_obj_p->eperm.sperm;
246 if (effective != entry_obj_p->eperm.sperm ||
247 options & TEXT_ALL_EFFECTIVE) {
248 x = (options & TEXT_SMART_INDENT) ?
249 ((text_p - orig_text_p)/8) : TABS-1;
250 strncpy(text_p, tabs+x, size);
253 strncpy(text_p, EFFECTIVE_STR, size);
254 ADVANCE(sizeof(EFFECTIVE_STR)-1);
256 switch ((size >= 3) ? 3 : size) {
258 text_p[2] = (effective &
259 ACL_EXECUTE) ? 'x' : '-';
262 text_p[1] = (effective &
263 ACL_WRITE) ? 'w' : '-';
266 text_p[0] = (effective &
267 ACL_READ) ? 'r' : '-';
275 /* zero-terminate string (but don't count '\0' character) */
279 return (text_p - orig_text_p); /* total size required, excluding
280 final NULL character. */
288 This function is equivalent to the proposed changes to snprintf:
289 snprintf(text_p, size, "%u", i)
290 (The current snprintf returns -1 if the buffer is too small; the proposal
291 is to return the number of characters that would be required. See the
292 snprintf manual page.)
296 snprint_uint(char *text_p, ssize_t size, unsigned int i)
298 unsigned int tmp = i;
300 unsigned int factor = 1;
302 while ((tmp /= 10) != 0) {
306 if (size && (i == 0)) {
309 while (size > 0 && factor > 0) {
310 *text_p++ = '0' + (i / factor);
326 struct passwd *passwd = getpwuid(uid);
329 return passwd->pw_name;
336 group_name(gid_t gid)
338 struct group *group = getgrgid(gid);
341 return group->gr_name;