1*9aa2a9c3Schristos /*-
2*9aa2a9c3Schristos * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3*9aa2a9c3Schristos *
4*9aa2a9c3Schristos * Copyright (c) 1999-2001, 2008 Robert N. M. Watson
5*9aa2a9c3Schristos * All rights reserved.
6*9aa2a9c3Schristos *
7*9aa2a9c3Schristos * Redistribution and use in source and binary forms, with or without
8*9aa2a9c3Schristos * modification, are permitted provided that the following conditions
9*9aa2a9c3Schristos * are met:
10*9aa2a9c3Schristos * 1. Redistributions of source code must retain the above copyright
11*9aa2a9c3Schristos * notice, this list of conditions and the following disclaimer.
12*9aa2a9c3Schristos * 2. Redistributions in binary form must reproduce the above copyright
13*9aa2a9c3Schristos * notice, this list of conditions and the following disclaimer in the
14*9aa2a9c3Schristos * documentation and/or other materials provided with the distribution.
15*9aa2a9c3Schristos *
16*9aa2a9c3Schristos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17*9aa2a9c3Schristos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*9aa2a9c3Schristos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*9aa2a9c3Schristos * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20*9aa2a9c3Schristos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21*9aa2a9c3Schristos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22*9aa2a9c3Schristos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23*9aa2a9c3Schristos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24*9aa2a9c3Schristos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25*9aa2a9c3Schristos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26*9aa2a9c3Schristos * SUCH DAMAGE.
27*9aa2a9c3Schristos */
28*9aa2a9c3Schristos /*
29*9aa2a9c3Schristos * Support functionality for the POSIX.1e ACL interface
30*9aa2a9c3Schristos * These calls are intended only to be called within the library.
31*9aa2a9c3Schristos */
32*9aa2a9c3Schristos
33*9aa2a9c3Schristos #include <sys/cdefs.h>
34*9aa2a9c3Schristos #if 0
35*9aa2a9c3Schristos __FBSDID("$FreeBSD: head/lib/libc/posix1e/acl_support.c 326193 2017-11-25 17:12:48Z pfg $");
36*9aa2a9c3Schristos #else
37*9aa2a9c3Schristos __RCSID("$NetBSD: acl_support.c,v 1.1 2020/05/16 18:31:47 christos Exp $");
38*9aa2a9c3Schristos #endif
39*9aa2a9c3Schristos
40*9aa2a9c3Schristos #include "namespace.h"
41*9aa2a9c3Schristos #include <sys/types.h>
42*9aa2a9c3Schristos #include <sys/acl.h>
43*9aa2a9c3Schristos #include <errno.h>
44*9aa2a9c3Schristos #include <grp.h>
45*9aa2a9c3Schristos #include <pwd.h>
46*9aa2a9c3Schristos #include <stdio.h>
47*9aa2a9c3Schristos #include <stdlib.h>
48*9aa2a9c3Schristos #include <string.h>
49*9aa2a9c3Schristos #include <assert.h>
50*9aa2a9c3Schristos
51*9aa2a9c3Schristos #include "acl_support.h"
52*9aa2a9c3Schristos
53*9aa2a9c3Schristos #define ACL_STRING_PERM_WRITE 'w'
54*9aa2a9c3Schristos #define ACL_STRING_PERM_READ 'r'
55*9aa2a9c3Schristos #define ACL_STRING_PERM_EXEC 'x'
56*9aa2a9c3Schristos #define ACL_STRING_PERM_NONE '-'
57*9aa2a9c3Schristos
58*9aa2a9c3Schristos /*
59*9aa2a9c3Schristos * Return 0, if both ACLs are identical.
60*9aa2a9c3Schristos */
61*9aa2a9c3Schristos int
_acl_differs(const acl_t a,const acl_t b)62*9aa2a9c3Schristos _acl_differs(const acl_t a, const acl_t b)
63*9aa2a9c3Schristos {
64*9aa2a9c3Schristos size_t i;
65*9aa2a9c3Schristos struct acl_entry *entrya, *entryb;
66*9aa2a9c3Schristos
67*9aa2a9c3Schristos assert(_acl_brand(a) == _acl_brand(b));
68*9aa2a9c3Schristos assert(_acl_brand(a) != ACL_BRAND_UNKNOWN);
69*9aa2a9c3Schristos assert(_acl_brand(b) != ACL_BRAND_UNKNOWN);
70*9aa2a9c3Schristos
71*9aa2a9c3Schristos if (a->ats_acl.acl_cnt != b->ats_acl.acl_cnt)
72*9aa2a9c3Schristos return (1);
73*9aa2a9c3Schristos
74*9aa2a9c3Schristos for (i = 0; i < b->ats_acl.acl_cnt; i++) {
75*9aa2a9c3Schristos entrya = &(a->ats_acl.acl_entry[i]);
76*9aa2a9c3Schristos entryb = &(b->ats_acl.acl_entry[i]);
77*9aa2a9c3Schristos
78*9aa2a9c3Schristos if (entrya->ae_tag != entryb->ae_tag ||
79*9aa2a9c3Schristos entrya->ae_id != entryb->ae_id ||
80*9aa2a9c3Schristos entrya->ae_perm != entryb->ae_perm ||
81*9aa2a9c3Schristos entrya->ae_entry_type != entryb->ae_entry_type ||
82*9aa2a9c3Schristos entrya->ae_flags != entryb->ae_flags)
83*9aa2a9c3Schristos return (1);
84*9aa2a9c3Schristos }
85*9aa2a9c3Schristos
86*9aa2a9c3Schristos return (0);
87*9aa2a9c3Schristos }
88*9aa2a9c3Schristos
89*9aa2a9c3Schristos /*
90*9aa2a9c3Schristos * _posix1e_acl_entry_compare -- compare two acl_entry structures to
91*9aa2a9c3Schristos * determine the order they should appear in. Used by _posix1e_acl_sort to
92*9aa2a9c3Schristos * sort ACL entries into the kernel-desired order -- i.e., the order useful
93*9aa2a9c3Schristos * for evaluation and O(n) validity checking. Beter to have an O(nlogn) sort
94*9aa2a9c3Schristos * in userland and an O(n) in kernel than to have both in kernel.
95*9aa2a9c3Schristos */
96*9aa2a9c3Schristos typedef int (*compare)(const void *, const void *);
97*9aa2a9c3Schristos static int
_posix1e_acl_entry_compare(struct acl_entry * a,struct acl_entry * b)98*9aa2a9c3Schristos _posix1e_acl_entry_compare(struct acl_entry *a, struct acl_entry *b)
99*9aa2a9c3Schristos {
100*9aa2a9c3Schristos
101*9aa2a9c3Schristos assert(_entry_brand(a) == ACL_BRAND_POSIX);
102*9aa2a9c3Schristos assert(_entry_brand(b) == ACL_BRAND_POSIX);
103*9aa2a9c3Schristos
104*9aa2a9c3Schristos /*
105*9aa2a9c3Schristos * First, sort between tags -- conveniently defined in the correct
106*9aa2a9c3Schristos * order for verification.
107*9aa2a9c3Schristos */
108*9aa2a9c3Schristos if (a->ae_tag < b->ae_tag)
109*9aa2a9c3Schristos return (-1);
110*9aa2a9c3Schristos if (a->ae_tag > b->ae_tag)
111*9aa2a9c3Schristos return (1);
112*9aa2a9c3Schristos
113*9aa2a9c3Schristos /*
114*9aa2a9c3Schristos * Next compare uids/gids on appropriate types.
115*9aa2a9c3Schristos */
116*9aa2a9c3Schristos
117*9aa2a9c3Schristos if (a->ae_tag == ACL_USER || a->ae_tag == ACL_GROUP) {
118*9aa2a9c3Schristos if (a->ae_id < b->ae_id)
119*9aa2a9c3Schristos return (-1);
120*9aa2a9c3Schristos if (a->ae_id > b->ae_id)
121*9aa2a9c3Schristos return (1);
122*9aa2a9c3Schristos
123*9aa2a9c3Schristos /* shouldn't be equal, fall through to the invalid case */
124*9aa2a9c3Schristos }
125*9aa2a9c3Schristos
126*9aa2a9c3Schristos /*
127*9aa2a9c3Schristos * Don't know how to sort multiple entries of the rest--either it's
128*9aa2a9c3Schristos * a bad entry, or there shouldn't be more than one. Ignore and the
129*9aa2a9c3Schristos * validity checker can get it later.
130*9aa2a9c3Schristos */
131*9aa2a9c3Schristos return (0);
132*9aa2a9c3Schristos }
133*9aa2a9c3Schristos
134*9aa2a9c3Schristos /*
135*9aa2a9c3Schristos * _posix1e_acl_sort -- sort ACL entries in POSIX.1e-formatted ACLs.
136*9aa2a9c3Schristos */
137*9aa2a9c3Schristos void
_posix1e_acl_sort(acl_t acl)138*9aa2a9c3Schristos _posix1e_acl_sort(acl_t acl)
139*9aa2a9c3Schristos {
140*9aa2a9c3Schristos struct acl *acl_int;
141*9aa2a9c3Schristos
142*9aa2a9c3Schristos acl_int = &acl->ats_acl;
143*9aa2a9c3Schristos
144*9aa2a9c3Schristos qsort(&acl_int->acl_entry[0], acl_int->acl_cnt,
145*9aa2a9c3Schristos sizeof(struct acl_entry), (compare) _posix1e_acl_entry_compare);
146*9aa2a9c3Schristos }
147*9aa2a9c3Schristos
148*9aa2a9c3Schristos /*
149*9aa2a9c3Schristos * acl_posix1e -- in what situations should we acl_sort before submission?
150*9aa2a9c3Schristos * We apply posix1e ACL semantics for any ACL of type ACL_TYPE_ACCESS or
151*9aa2a9c3Schristos * ACL_TYPE_DEFAULT
152*9aa2a9c3Schristos */
153*9aa2a9c3Schristos int
_posix1e_acl(acl_t acl,acl_type_t type)154*9aa2a9c3Schristos _posix1e_acl(acl_t acl, acl_type_t type)
155*9aa2a9c3Schristos {
156*9aa2a9c3Schristos
157*9aa2a9c3Schristos if (_acl_brand(acl) != ACL_BRAND_POSIX)
158*9aa2a9c3Schristos return (0);
159*9aa2a9c3Schristos
160*9aa2a9c3Schristos return ((type == ACL_TYPE_ACCESS) || (type == ACL_TYPE_DEFAULT));
161*9aa2a9c3Schristos }
162*9aa2a9c3Schristos
163*9aa2a9c3Schristos /*
164*9aa2a9c3Schristos * _posix1e_acl_check -- given an ACL, check its validity. This is mirrored
165*9aa2a9c3Schristos * from code in sys/kern/kern_acl.c, and if changes are made in one, they
166*9aa2a9c3Schristos * should be made in the other also. This copy of acl_check is made
167*9aa2a9c3Schristos * available * in userland for the benefit of processes wanting to check ACLs
168*9aa2a9c3Schristos * for validity before submitting them to the kernel, or for performing
169*9aa2a9c3Schristos * in userland file system checking. Needless to say, the kernel makes
170*9aa2a9c3Schristos * the real checks on calls to get/setacl.
171*9aa2a9c3Schristos *
172*9aa2a9c3Schristos * See the comments in kernel for explanation -- just briefly, it assumes
173*9aa2a9c3Schristos * an already sorted ACL, and checks based on that assumption. The
174*9aa2a9c3Schristos * POSIX.1e interface, acl_valid(), will perform the sort before calling
175*9aa2a9c3Schristos * this. Returns 0 on success, EINVAL on failure.
176*9aa2a9c3Schristos */
177*9aa2a9c3Schristos int
_posix1e_acl_check(acl_t acl)178*9aa2a9c3Schristos _posix1e_acl_check(acl_t acl)
179*9aa2a9c3Schristos {
180*9aa2a9c3Schristos struct acl *acl_int;
181*9aa2a9c3Schristos struct acl_entry *entry; /* current entry */
182*9aa2a9c3Schristos uid_t highest_uid=0, highest_gid=0;
183*9aa2a9c3Schristos int stage = ACL_USER_OBJ;
184*9aa2a9c3Schristos size_t i = 0;
185*9aa2a9c3Schristos int count_user_obj=0, count_user=0, count_group_obj=0,
186*9aa2a9c3Schristos count_group=0, count_mask=0, count_other=0;
187*9aa2a9c3Schristos
188*9aa2a9c3Schristos acl_int = &acl->ats_acl;
189*9aa2a9c3Schristos
190*9aa2a9c3Schristos /* printf("_posix1e_acl_check: checking acl with %d entries\n",
191*9aa2a9c3Schristos acl->acl_cnt); */
192*9aa2a9c3Schristos while (i < acl_int->acl_cnt) {
193*9aa2a9c3Schristos entry = &acl_int->acl_entry[i];
194*9aa2a9c3Schristos
195*9aa2a9c3Schristos if ((entry->ae_perm | ACL_PERM_BITS) != ACL_PERM_BITS)
196*9aa2a9c3Schristos return (EINVAL);
197*9aa2a9c3Schristos
198*9aa2a9c3Schristos switch(entry->ae_tag) {
199*9aa2a9c3Schristos case ACL_USER_OBJ:
200*9aa2a9c3Schristos /* printf("_posix1e_acl_check: %d: ACL_USER_OBJ\n",
201*9aa2a9c3Schristos i); */
202*9aa2a9c3Schristos if (stage > ACL_USER_OBJ)
203*9aa2a9c3Schristos return (EINVAL);
204*9aa2a9c3Schristos stage = ACL_USER;
205*9aa2a9c3Schristos count_user_obj++;
206*9aa2a9c3Schristos break;
207*9aa2a9c3Schristos
208*9aa2a9c3Schristos case ACL_USER:
209*9aa2a9c3Schristos /* printf("_posix1e_acl_check: %d: ACL_USER\n", i); */
210*9aa2a9c3Schristos if (stage > ACL_USER)
211*9aa2a9c3Schristos return (EINVAL);
212*9aa2a9c3Schristos stage = ACL_USER;
213*9aa2a9c3Schristos if (count_user && (entry->ae_id <= highest_uid))
214*9aa2a9c3Schristos return (EINVAL);
215*9aa2a9c3Schristos highest_uid = entry->ae_id;
216*9aa2a9c3Schristos count_user++;
217*9aa2a9c3Schristos break;
218*9aa2a9c3Schristos
219*9aa2a9c3Schristos case ACL_GROUP_OBJ:
220*9aa2a9c3Schristos /* printf("_posix1e_acl_check: %d: ACL_GROUP_OBJ\n",
221*9aa2a9c3Schristos i); */
222*9aa2a9c3Schristos if (stage > ACL_GROUP_OBJ)
223*9aa2a9c3Schristos return (EINVAL);
224*9aa2a9c3Schristos stage = ACL_GROUP;
225*9aa2a9c3Schristos count_group_obj++;
226*9aa2a9c3Schristos break;
227*9aa2a9c3Schristos
228*9aa2a9c3Schristos case ACL_GROUP:
229*9aa2a9c3Schristos /* printf("_posix1e_acl_check: %d: ACL_GROUP\n", i); */
230*9aa2a9c3Schristos if (stage > ACL_GROUP)
231*9aa2a9c3Schristos return (EINVAL);
232*9aa2a9c3Schristos stage = ACL_GROUP;
233*9aa2a9c3Schristos if (count_group && (entry->ae_id <= highest_gid))
234*9aa2a9c3Schristos return (EINVAL);
235*9aa2a9c3Schristos highest_gid = entry->ae_id;
236*9aa2a9c3Schristos count_group++;
237*9aa2a9c3Schristos break;
238*9aa2a9c3Schristos
239*9aa2a9c3Schristos case ACL_MASK:
240*9aa2a9c3Schristos /* printf("_posix1e_acl_check: %d: ACL_MASK\n", i); */
241*9aa2a9c3Schristos if (stage > ACL_MASK)
242*9aa2a9c3Schristos return (EINVAL);
243*9aa2a9c3Schristos stage = ACL_MASK;
244*9aa2a9c3Schristos count_mask++;
245*9aa2a9c3Schristos break;
246*9aa2a9c3Schristos
247*9aa2a9c3Schristos case ACL_OTHER:
248*9aa2a9c3Schristos /* printf("_posix1e_acl_check: %d: ACL_OTHER\n", i); */
249*9aa2a9c3Schristos if (stage > ACL_OTHER)
250*9aa2a9c3Schristos return (EINVAL);
251*9aa2a9c3Schristos stage = ACL_OTHER;
252*9aa2a9c3Schristos count_other++;
253*9aa2a9c3Schristos break;
254*9aa2a9c3Schristos
255*9aa2a9c3Schristos default:
256*9aa2a9c3Schristos /* printf("_posix1e_acl_check: %d: INVALID\n", i); */
257*9aa2a9c3Schristos return (EINVAL);
258*9aa2a9c3Schristos }
259*9aa2a9c3Schristos i++;
260*9aa2a9c3Schristos }
261*9aa2a9c3Schristos
262*9aa2a9c3Schristos if (count_user_obj != 1)
263*9aa2a9c3Schristos return (EINVAL);
264*9aa2a9c3Schristos
265*9aa2a9c3Schristos if (count_group_obj != 1)
266*9aa2a9c3Schristos return (EINVAL);
267*9aa2a9c3Schristos
268*9aa2a9c3Schristos if (count_mask != 0 && count_mask != 1)
269*9aa2a9c3Schristos return (EINVAL);
270*9aa2a9c3Schristos
271*9aa2a9c3Schristos if (count_other != 1)
272*9aa2a9c3Schristos return (EINVAL);
273*9aa2a9c3Schristos
274*9aa2a9c3Schristos return (0);
275*9aa2a9c3Schristos }
276*9aa2a9c3Schristos
277*9aa2a9c3Schristos /*
278*9aa2a9c3Schristos * Given a right-shifted permission (i.e., direct ACL_PERM_* mask), fill
279*9aa2a9c3Schristos * in a string describing the permissions.
280*9aa2a9c3Schristos */
281*9aa2a9c3Schristos int
_posix1e_acl_perm_to_string(acl_perm_t perm,ssize_t buf_len,char * buf)282*9aa2a9c3Schristos _posix1e_acl_perm_to_string(acl_perm_t perm, ssize_t buf_len, char *buf)
283*9aa2a9c3Schristos {
284*9aa2a9c3Schristos
285*9aa2a9c3Schristos if (buf_len < _POSIX1E_ACL_STRING_PERM_MAXSIZE + 1) {
286*9aa2a9c3Schristos errno = ENOMEM;
287*9aa2a9c3Schristos return (-1);
288*9aa2a9c3Schristos }
289*9aa2a9c3Schristos
290*9aa2a9c3Schristos if ((perm | ACL_PERM_BITS) != ACL_PERM_BITS) {
291*9aa2a9c3Schristos errno = EINVAL;
292*9aa2a9c3Schristos return (-1);
293*9aa2a9c3Schristos }
294*9aa2a9c3Schristos
295*9aa2a9c3Schristos buf[3] = 0; /* null terminate */
296*9aa2a9c3Schristos
297*9aa2a9c3Schristos if (perm & ACL_READ)
298*9aa2a9c3Schristos buf[0] = ACL_STRING_PERM_READ;
299*9aa2a9c3Schristos else
300*9aa2a9c3Schristos buf[0] = ACL_STRING_PERM_NONE;
301*9aa2a9c3Schristos
302*9aa2a9c3Schristos if (perm & ACL_WRITE)
303*9aa2a9c3Schristos buf[1] = ACL_STRING_PERM_WRITE;
304*9aa2a9c3Schristos else
305*9aa2a9c3Schristos buf[1] = ACL_STRING_PERM_NONE;
306*9aa2a9c3Schristos
307*9aa2a9c3Schristos if (perm & ACL_EXECUTE)
308*9aa2a9c3Schristos buf[2] = ACL_STRING_PERM_EXEC;
309*9aa2a9c3Schristos else
310*9aa2a9c3Schristos buf[2] = ACL_STRING_PERM_NONE;
311*9aa2a9c3Schristos
312*9aa2a9c3Schristos return (0);
313*9aa2a9c3Schristos }
314*9aa2a9c3Schristos
315*9aa2a9c3Schristos /*
316*9aa2a9c3Schristos * given a string, return a permission describing it
317*9aa2a9c3Schristos */
318*9aa2a9c3Schristos int
_posix1e_acl_string_to_perm(char * string,acl_perm_t * perm)319*9aa2a9c3Schristos _posix1e_acl_string_to_perm(char *string, acl_perm_t *perm)
320*9aa2a9c3Schristos {
321*9aa2a9c3Schristos acl_perm_t myperm = ACL_PERM_NONE;
322*9aa2a9c3Schristos char *ch;
323*9aa2a9c3Schristos
324*9aa2a9c3Schristos ch = string;
325*9aa2a9c3Schristos while (*ch) {
326*9aa2a9c3Schristos switch(*ch) {
327*9aa2a9c3Schristos case ACL_STRING_PERM_READ:
328*9aa2a9c3Schristos myperm |= ACL_READ;
329*9aa2a9c3Schristos break;
330*9aa2a9c3Schristos case ACL_STRING_PERM_WRITE:
331*9aa2a9c3Schristos myperm |= ACL_WRITE;
332*9aa2a9c3Schristos break;
333*9aa2a9c3Schristos case ACL_STRING_PERM_EXEC:
334*9aa2a9c3Schristos myperm |= ACL_EXECUTE;
335*9aa2a9c3Schristos break;
336*9aa2a9c3Schristos case ACL_STRING_PERM_NONE:
337*9aa2a9c3Schristos break;
338*9aa2a9c3Schristos default:
339*9aa2a9c3Schristos return (EINVAL);
340*9aa2a9c3Schristos }
341*9aa2a9c3Schristos ch++;
342*9aa2a9c3Schristos }
343*9aa2a9c3Schristos
344*9aa2a9c3Schristos *perm = myperm;
345*9aa2a9c3Schristos return (0);
346*9aa2a9c3Schristos }
347*9aa2a9c3Schristos
348*9aa2a9c3Schristos /*
349*9aa2a9c3Schristos * Add an ACL entry without doing much checking, et al
350*9aa2a9c3Schristos */
351*9aa2a9c3Schristos int
_posix1e_acl_add_entry(acl_t acl,acl_tag_t tag,uid_t id,acl_perm_t perm)352*9aa2a9c3Schristos _posix1e_acl_add_entry(acl_t acl, acl_tag_t tag, uid_t id, acl_perm_t perm)
353*9aa2a9c3Schristos {
354*9aa2a9c3Schristos struct acl *acl_int;
355*9aa2a9c3Schristos struct acl_entry *e;
356*9aa2a9c3Schristos
357*9aa2a9c3Schristos acl_int = &acl->ats_acl;
358*9aa2a9c3Schristos
359*9aa2a9c3Schristos if (acl_int->acl_cnt >= ACL_MAX_ENTRIES) {
360*9aa2a9c3Schristos errno = ENOMEM;
361*9aa2a9c3Schristos return (-1);
362*9aa2a9c3Schristos }
363*9aa2a9c3Schristos
364*9aa2a9c3Schristos e = &(acl_int->acl_entry[acl_int->acl_cnt]);
365*9aa2a9c3Schristos e->ae_perm = perm;
366*9aa2a9c3Schristos e->ae_tag = tag;
367*9aa2a9c3Schristos e->ae_id = id;
368*9aa2a9c3Schristos acl_int->acl_cnt++;
369*9aa2a9c3Schristos
370*9aa2a9c3Schristos return (0);
371*9aa2a9c3Schristos }
372*9aa2a9c3Schristos
373*9aa2a9c3Schristos /*
374*9aa2a9c3Schristos * Convert "old" type - ACL_TYPE_{ACCESS,DEFAULT}_OLD - into its "new"
375*9aa2a9c3Schristos * counterpart. It's necessary for the old (pre-NFSv4 ACLs) binaries
376*9aa2a9c3Schristos * to work with new libc and kernel. Fixing 'type' for old binaries with
377*9aa2a9c3Schristos * old libc and new kernel is being done by kern/vfs_acl.c:type_unold().
378*9aa2a9c3Schristos */
379*9aa2a9c3Schristos int
_acl_type_unold(acl_type_t type)380*9aa2a9c3Schristos _acl_type_unold(acl_type_t type)
381*9aa2a9c3Schristos {
382*9aa2a9c3Schristos
383*9aa2a9c3Schristos switch (type) {
384*9aa2a9c3Schristos case ACL_TYPE_ACCESS_OLD:
385*9aa2a9c3Schristos return (ACL_TYPE_ACCESS);
386*9aa2a9c3Schristos case ACL_TYPE_DEFAULT_OLD:
387*9aa2a9c3Schristos return (ACL_TYPE_DEFAULT);
388*9aa2a9c3Schristos default:
389*9aa2a9c3Schristos return (type);
390*9aa2a9c3Schristos }
391*9aa2a9c3Schristos }
392*9aa2a9c3Schristos
393*9aa2a9c3Schristos char *
string_skip_whitespace(char * string)394*9aa2a9c3Schristos string_skip_whitespace(char *string)
395*9aa2a9c3Schristos {
396*9aa2a9c3Schristos
397*9aa2a9c3Schristos while (*string && ((*string == ' ') || (*string == '\t')))
398*9aa2a9c3Schristos string++;
399*9aa2a9c3Schristos
400*9aa2a9c3Schristos return (string);
401*9aa2a9c3Schristos }
402*9aa2a9c3Schristos
403*9aa2a9c3Schristos void
string_trim_trailing_whitespace(char * string)404*9aa2a9c3Schristos string_trim_trailing_whitespace(char *string)
405*9aa2a9c3Schristos {
406*9aa2a9c3Schristos char *end;
407*9aa2a9c3Schristos
408*9aa2a9c3Schristos if (*string == '\0')
409*9aa2a9c3Schristos return;
410*9aa2a9c3Schristos
411*9aa2a9c3Schristos end = string + strlen(string) - 1;
412*9aa2a9c3Schristos
413*9aa2a9c3Schristos while (end != string) {
414*9aa2a9c3Schristos if ((*end == ' ') || (*end == '\t')) {
415*9aa2a9c3Schristos *end = '\0';
416*9aa2a9c3Schristos end--;
417*9aa2a9c3Schristos } else {
418*9aa2a9c3Schristos return;
419*9aa2a9c3Schristos }
420*9aa2a9c3Schristos }
421*9aa2a9c3Schristos
422*9aa2a9c3Schristos return;
423*9aa2a9c3Schristos }
424