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