Add ignore support and logging
[dtbartle/zfs.git] / acl-2.2.42-CITI_NFS4_ALL-2.dif
1 diff --git a/exports b/exports
2 index 59c1311..2296b7d 100644
3 --- a/exports
4 +++ b/exports
5 @@ -67,3 +67,33 @@ ACL_1.1 {
6         perm_copy_fd;
7         perm_copy_file;
8  } ACL_1.0;
9 +
10 +ACL_1.2 {
11 +       global:
12 +       acl_nfs4_add_ace;
13 +       acl_nfs4_add_pair;
14 +       acl_nfs4_free;
15 +       acl_nfs4_new;
16 +       acl_nfs4_set_dir;
17 +       acl_nfs4_set_who;
18 +       acl_nfs4_copy_acl;
19 +       acl_nfs4_xattr_load;
20 +       acl_nfs4_xattr_pack;
21 +       acl_nfs4_xattr_size;
22 +       acl_nfs4_remove_ace;
23 +
24 +       acl_n4tp_acl_trans;
25 +
26 +       acl_ptn4_get_mask;
27 +       acl_ptn4_acl_trans;
28 +
29 +       acl_nfs4_get_whotype;
30 +       acl_nfs4_get_who;
31 +       acl_nfs4_entries;
32 +
33 +       local:
34 +       __posix_acl_from_nfs4_xattr;
35 +       nfs4_get_who_from_uid;
36 +       nfs4_get_who_from_gid;
37 +
38 +} ACL_1.1;
39 diff --git a/include/builddefs.in b/include/builddefs.in
40 index db444d5..2201533 100644
41 --- a/include/builddefs.in
42 +++ b/include/builddefs.in
43 @@ -80,7 +80,7 @@ endif
44  
45  GCFLAGS = $(OPTIMIZER) $(DEBUG) -funsigned-char -fno-strict-aliasing -Wall \
46           -DVERSION=\"$(PKG_VERSION)\" -DLOCALEDIR=\"$(PKG_LOCALE_DIR)\"  \
47 -         -DPACKAGE=\"$(PKG_NAME)\" -I$(TOPDIR)/include
48 +         -DPACKAGE=\"$(PKG_NAME)\" -I$(TOPDIR)/include -DUSE_NFSV4_TRANS
49  
50  # Global, Platform, Local CFLAGS
51  CFLAGS += $(GCFLAGS) $(PCFLAGS) $(LCFLAGS)
52 diff --git a/include/libacl_nfs4.h b/include/libacl_nfs4.h
53 new file mode 100644
54 index 0000000..b29b802
55 --- /dev/null
56 +++ b/include/libacl_nfs4.h
57 @@ -0,0 +1,97 @@
58 +#include <sys/types.h>
59 +#include <pwd.h>
60 +#include <grp.h>
61 +#include <sys/acl.h>
62 +#include <stdlib.h>
63 +#include <sys/queue.h>
64 +#include <nfs4.h>
65 +#include <sys/errno.h>
66 +#include <string.h>
67 +
68 +/* mode bit translations: */
69 +#define NFS4_READ_MODE NFS4_ACE_READ_DATA
70 +#define NFS4_WRITE_MODE (NFS4_ACE_WRITE_DATA | NFS4_ACE_APPEND_DATA)
71 +#define NFS4_EXECUTE_MODE NFS4_ACE_EXECUTE
72 +#define NFS4_ANYONE_MODE (NFS4_ACE_READ_ATTRIBUTES | NFS4_ACE_READ_ACL | \
73 +               NFS4_ACE_SYNCHRONIZE)
74 +#define NFS4_OWNER_MODE (NFS4_ACE_WRITE_ATTRIBUTES | NFS4_ACE_WRITE_ACL)
75 +
76 +#define NFS4_ACE_MASK_IGNORE (NFS4_ACE_DELETE | NFS4_ACE_WRITE_OWNER \
77 +               | NFS4_ACE_READ_NAMED_ATTRS | NFS4_ACE_WRITE_NAMED_ATTRS)
78 +/* XXX not sure about the following.  Note that e.g. DELETE_CHILD is wrong in
79 + * general (should only be ignored on files). */
80 +#define MASK_EQUAL(mask1, mask2) \
81 +       (((mask1) & NFS4_ACE_MASK_ALL & ~NFS4_ACE_MASK_IGNORE & \
82 +                                               ~NFS4_ACE_DELETE_CHILD) \
83 +        == ((mask2) & NFS4_ACE_MASK_ALL & ~NFS4_ACE_MASK_IGNORE & \
84 +                                               ~NFS4_ACE_DELETE_CHILD))
85 +
86 +/* Maximum length of the ace->who attribute */
87 +#define NFS4_ACL_WHO_LENGTH_MAX                2048
88 +#define NFS4_ACL_WHO_BUFFER_LEN_GUESS  255
89 +
90 +/* NFS4 acl xattr name */
91 +#define ACL_NFS4_XATTR "system.nfs4_acl"
92 +
93 +/* Macro for finding empty tailqs */
94 +#define TAILQ_IS_EMPTY(head) (head.tqh_first == NULL)
95 +
96 +/* Flags to pass certain properties around */
97 +#define NFS4_ACL_NOFLAGS                       0x00
98 +#define NFS4_ACL_ISFILE                                0x00
99 +#define NFS4_ACL_ISDIR                         0x01
100 +#define NFS4_ACL_OWNER                         0x02
101 +#define NFS4_ACL_REQUEST_DEFAULT       0x04
102 +#define NFS4_ACL_RAW                           0x01
103 +
104 +#define NFS4_XDR_MOD                           4
105 +
106 +typedef u_int32_t u32;
107 +
108 +enum { ACL_NFS4_NOT_USED = 0,
109 +               ACL_NFS4_USED
110 +};
111 +
112 +struct ace_container {
113 +       struct nfs4_ace *ace;
114 +       TAILQ_ENTRY(ace_container) l_ace;
115 +};
116 +
117 +TAILQ_HEAD(ace_container_list_head, ace_container);
118 +
119 +/**** Public functions ****/
120 +
121 +/** Manipulation functions **/
122 +extern int                             acl_nfs4_add_ace(struct nfs4_acl *, u32, u32, u32, int, char*);
123 +extern int                             acl_nfs4_add_pair(struct nfs4_acl *, int, u32, int, char*);
124 +extern void                            acl_nfs4_free(struct nfs4_acl *);
125 +extern struct nfs4_acl *acl_nfs4_new(u32);
126 +extern int                             acl_nfs4_set_who(struct nfs4_ace*, int, char*);
127 +extern struct nfs4_acl *acl_nfs4_copy_acl(struct nfs4_acl *);
128 +extern struct nfs4_acl *acl_nfs4_xattr_load(char *, int, u32);
129 +extern int                             acl_nfs4_xattr_pack(struct nfs4_acl *, char**);
130 +extern int                             acl_nfs4_xattr_size(struct nfs4_acl *);
131 +extern void                            acl_nfs4_remove_ace(struct nfs4_acl * acl, struct nfs4_ace * ace);
132 +
133 +/** Conversion functions **/
134 +
135 +/* nfs4 -> posix */
136 +extern acl_t           acl_n4tp_acl_trans(struct nfs4_acl *, acl_type_t);
137 +
138 +/* posix -> nfs4 */
139 +extern int                             acl_ptn4_get_mask(u32* mask, acl_permset_t perms,
140 +                                                               int iflags);
141 +extern int acl_ptn4_acl_trans(acl_t, struct nfs4_acl *, acl_type_t, u32, char*);
142 +
143 +
144 +/** Access Functions **/
145 +extern inline int      acl_nfs4_get_whotype(char*);
146 +extern int                     acl_nfs4_get_who(struct nfs4_ace*, int*, char**);
147 +
148 +/**** Private(?) functions ****/
149 +acl_t          __posix_acl_from_nfs4_xattr(char*, int, acl_type_t, u32);
150 +
151 +/* These will change */
152 +char * nfs4_get_who_from_uid(uid_t);
153 +char * nfs4_get_who_from_gid(gid_t);
154 +/* End change */
155 diff --git a/include/nfs4.h b/include/nfs4.h
156 new file mode 100644
157 index 0000000..43a6418
158 --- /dev/null
159 +++ b/include/nfs4.h
160 @@ -0,0 +1,397 @@
161 +/*
162 + *  NFSv4 protocol definitions.
163 + *
164 + *  Copyright (c) 2002 The Regents of the University of Michigan.
165 + *  All rights reserved.
166 + *
167 + *  Kendrick Smith <kmsmith@umich.edu>
168 + *  Andy Adamson   <andros@umich.edu>
169 + */
170 +
171 +#include<sys/types.h>
172 +#include<sys/queue.h>
173 +
174 +#ifndef _LINUX_NFS4_H
175 +#define _LINUX_NFS4_H
176 +
177 +#define NFS4_VERIFIER_SIZE     8
178 +#define NFS4_FHSIZE            128
179 +#define NFS4_MAXNAMLEN         NAME_MAX
180 +
181 +#define NFS4_ACCESS_READ        0x0001
182 +#define NFS4_ACCESS_LOOKUP      0x0002
183 +#define NFS4_ACCESS_MODIFY      0x0004
184 +#define NFS4_ACCESS_EXTEND      0x0008
185 +#define NFS4_ACCESS_DELETE      0x0010
186 +#define NFS4_ACCESS_EXECUTE     0x0020
187 +
188 +#define NFS4_FH_PERISTENT              0x0000
189 +#define NFS4_FH_NOEXPIRE_WITH_OPEN     0x0001
190 +#define NFS4_FH_VOLATILE_ANY           0x0002
191 +#define NFS4_FH_VOL_MIGRATION          0x0004
192 +#define NFS4_FH_VOL_RENAME             0x0008
193 +
194 +#define NFS4_OPEN_RESULT_CONFIRM 0x0002
195 +
196 +#define NFS4_SHARE_ACCESS_READ 0x0001
197 +#define NFS4_SHARE_ACCESS_WRITE        0x0002
198 +#define NFS4_SHARE_ACCESS_BOTH 0x0003
199 +#define NFS4_SHARE_DENY_READ   0x0001
200 +#define NFS4_SHARE_DENY_WRITE  0x0002
201 +#define NFS4_SHARE_DENY_BOTH   0x0003
202 +
203 +#define NFS4_SET_TO_SERVER_TIME        0
204 +#define NFS4_SET_TO_CLIENT_TIME        1
205 +
206 +#define NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE 0
207 +#define NFS4_ACE_ACCESS_DENIED_ACE_TYPE  1
208 +#define NFS4_ACE_SYSTEM_AUDIT_ACE_TYPE   2
209 +#define NFS4_ACE_SYSTEM_ALARM_ACE_TYPE   3
210 +
211 +#define ACL4_SUPPORT_ALLOW_ACL 0x01
212 +#define ACL4_SUPPORT_DENY_ACL  0x02
213 +#define ACL4_SUPPORT_AUDIT_ACL 0x04
214 +#define ACL4_SUPPORT_ALARM_ACL 0x08
215 +
216 +#define NFS4_ACE_FILE_INHERIT_ACE             0x00000001
217 +#define NFS4_ACE_DIRECTORY_INHERIT_ACE        0x00000002
218 +#define NFS4_ACE_NO_PROPAGATE_INHERIT_ACE     0x00000004
219 +#define NFS4_ACE_INHERIT_ONLY_ACE             0x00000008
220 +#define NFS4_ACE_SUCCESSFUL_ACCESS_ACE_FLAG   0x00000010
221 +#define NFS4_ACE_FAILED_ACCESS_ACE_FLAG       0x00000020
222 +#define NFS4_ACE_IDENTIFIER_GROUP             0x00000040
223 +#define NFS4_ACE_OWNER                        0x00000080
224 +#define NFS4_ACE_GROUP                        0x00000100
225 +#define NFS4_ACE_EVERYONE                     0x00000200
226 +
227 +#define NFS4_ACE_READ_DATA                    0x00000001
228 +#define NFS4_ACE_LIST_DIRECTORY               0x00000001
229 +#define NFS4_ACE_WRITE_DATA                   0x00000002
230 +#define NFS4_ACE_ADD_FILE                     0x00000002
231 +#define NFS4_ACE_APPEND_DATA                  0x00000004
232 +#define NFS4_ACE_ADD_SUBDIRECTORY             0x00000004
233 +#define NFS4_ACE_READ_NAMED_ATTRS             0x00000008
234 +#define NFS4_ACE_WRITE_NAMED_ATTRS            0x00000010
235 +#define NFS4_ACE_EXECUTE                      0x00000020
236 +#define NFS4_ACE_DELETE_CHILD                 0x00000040
237 +#define NFS4_ACE_READ_ATTRIBUTES              0x00000080
238 +#define NFS4_ACE_WRITE_ATTRIBUTES             0x00000100
239 +#define NFS4_ACE_DELETE                       0x00010000
240 +#define NFS4_ACE_READ_ACL                     0x00020000
241 +#define NFS4_ACE_WRITE_ACL                    0x00040000
242 +#define NFS4_ACE_WRITE_OWNER                  0x00080000
243 +#define NFS4_ACE_SYNCHRONIZE                  0x00100000
244 +#define NFS4_ACE_GENERIC_READ                 0x00120081
245 +#define NFS4_ACE_GENERIC_WRITE                0x00160106
246 +#define NFS4_ACE_GENERIC_EXECUTE              0x001200A0
247 +#define NFS4_ACE_MASK_ALL                     0x001F01FF
248 +
249 +enum nfs4_acl_whotype {
250 +       NFS4_ACL_WHO_NAMED = 0,
251 +       NFS4_ACL_WHO_OWNER,
252 +       NFS4_ACL_WHO_GROUP,
253 +       NFS4_ACL_WHO_EVERYONE,
254 +};
255 +
256 +#define NFS4_ACL_WHO_OWNER_STRING              "OWNER@"
257 +#define NFS4_ACL_WHO_GROUP_STRING              "GROUP@"
258 +#define NFS4_ACL_WHO_EVERYONE_STRING   "EVERYONE@"
259 +
260 +struct nfs4_ace {
261 +       u_int32_t       type;
262 +       u_int32_t       flag;
263 +       u_int32_t       access_mask;
264 +       char*   who;
265 +       TAILQ_ENTRY(nfs4_ace) l_ace;
266 +};
267 +
268 +TAILQ_HEAD(ace_list_head, nfs4_ace);
269 +
270 +struct nfs4_acl {
271 +       u_int32_t               naces;
272 +       u_int32_t               is_directory;
273 +       struct ace_list_head    ace_head;
274 +};
275 +
276 +typedef struct { char data[NFS4_VERIFIER_SIZE]; } nfs4_verifier;
277 +typedef struct { char data[16]; } nfs4_stateid;
278 +
279 +enum nfs_opnum4 {
280 +       OP_ACCESS = 3,
281 +       OP_CLOSE = 4,
282 +       OP_COMMIT = 5,
283 +       OP_CREATE = 6,
284 +       OP_DELEGPURGE = 7,
285 +       OP_DELEGRETURN = 8,
286 +       OP_GETATTR = 9,
287 +       OP_GETFH = 10,
288 +       OP_LINK = 11,
289 +       OP_LOCK = 12,
290 +       OP_LOCKT = 13,
291 +       OP_LOCKU = 14,
292 +       OP_LOOKUP = 15,
293 +       OP_LOOKUPP = 16,
294 +       OP_NVERIFY = 17,
295 +       OP_OPEN = 18,
296 +       OP_OPENATTR = 19,
297 +       OP_OPEN_CONFIRM = 20,
298 +       OP_OPEN_DOWNGRADE = 21,
299 +       OP_PUTFH = 22,
300 +       OP_PUTPUBFH = 23,
301 +       OP_PUTROOTFH = 24,
302 +       OP_READ = 25,
303 +       OP_READDIR = 26,
304 +       OP_READLINK = 27,
305 +       OP_REMOVE = 28,
306 +       OP_RENAME = 29,
307 +       OP_RENEW = 30,
308 +       OP_RESTOREFH = 31,
309 +       OP_SAVEFH = 32,
310 +       OP_SECINFO = 33,
311 +       OP_SETATTR = 34,
312 +       OP_SETCLIENTID = 35,
313 +       OP_SETCLIENTID_CONFIRM = 36,
314 +       OP_VERIFY = 37,
315 +       OP_WRITE = 38,
316 +       OP_RELEASE_LOCKOWNER = 39,
317 +       OP_ILLEGAL = 10044,
318 +};
319 +
320 +enum nfsstat4 {
321 +       NFS4_OK = 0,
322 +       NFS4ERR_PERM = 1,
323 +       NFS4ERR_NOENT = 2,
324 +       NFS4ERR_IO = 5,
325 +       NFS4ERR_NXIO = 6,
326 +       NFS4ERR_ACCESS = 13,
327 +       NFS4ERR_EXIST = 17,
328 +       NFS4ERR_XDEV = 18,
329 +       /* Unused/reserved 19 */
330 +       NFS4ERR_NOTDIR = 20,
331 +       NFS4ERR_ISDIR = 21,
332 +       NFS4ERR_INVAL = 22,
333 +       NFS4ERR_FBIG = 27,
334 +       NFS4ERR_NOSPC = 28,
335 +       NFS4ERR_ROFS = 30,
336 +       NFS4ERR_MLINK = 31,
337 +       NFS4ERR_NAMETOOLONG = 63,
338 +       NFS4ERR_NOTEMPTY = 66,
339 +       NFS4ERR_DQUOT = 69,
340 +       NFS4ERR_STALE = 70,
341 +       NFS4ERR_BADHANDLE = 10001,
342 +       NFS4ERR_BAD_COOKIE = 10003,
343 +       NFS4ERR_NOTSUPP = 10004,
344 +       NFS4ERR_TOOSMALL = 10005,
345 +       NFS4ERR_SERVERFAULT = 10006,
346 +       NFS4ERR_BADTYPE = 10007,
347 +       NFS4ERR_DELAY = 10008,
348 +       NFS4ERR_SAME = 10009,
349 +       NFS4ERR_DENIED = 10010,
350 +       NFS4ERR_EXPIRED = 10011,
351 +       NFS4ERR_LOCKED = 10012,
352 +       NFS4ERR_GRACE = 10013,
353 +       NFS4ERR_FHEXPIRED = 10014,
354 +       NFS4ERR_SHARE_DENIED = 10015,
355 +       NFS4ERR_WRONGSEC = 10016,
356 +       NFS4ERR_CLID_INUSE = 10017,
357 +       NFS4ERR_RESOURCE = 10018,
358 +       NFS4ERR_MOVED = 10019,
359 +       NFS4ERR_NOFILEHANDLE = 10020,
360 +       NFS4ERR_MINOR_VERS_MISMATCH = 10021,
361 +       NFS4ERR_STALE_CLIENTID = 10022,
362 +       NFS4ERR_STALE_STATEID = 10023,
363 +       NFS4ERR_OLD_STATEID = 10024,
364 +       NFS4ERR_BAD_STATEID = 10025,
365 +       NFS4ERR_BAD_SEQID = 10026,
366 +       NFS4ERR_NOT_SAME = 10027,
367 +       NFS4ERR_LOCK_RANGE = 10028,
368 +       NFS4ERR_SYMLINK = 10029,
369 +       NFS4ERR_RESTOREFH = 10030,
370 +       NFS4ERR_LEASE_MOVED = 10031,
371 +       NFS4ERR_ATTRNOTSUPP = 10032,
372 +       NFS4ERR_NO_GRACE = 10033,
373 +       NFS4ERR_RECLAIM_BAD = 10034,
374 +       NFS4ERR_RECLAIM_CONFLICT = 10035,
375 +       NFS4ERR_BADXDR = 10036,
376 +       NFS4ERR_LOCKS_HELD = 10037,
377 +       NFS4ERR_OPENMODE = 10038,
378 +       NFS4ERR_BADOWNER = 10039,
379 +       NFS4ERR_BADCHAR = 10040,
380 +       NFS4ERR_BADNAME = 10041,
381 +       NFS4ERR_BAD_RANGE = 10042,
382 +       NFS4ERR_LOCK_NOTSUPP = 10043,
383 +       NFS4ERR_OP_ILLEGAL = 10044,
384 +       NFS4ERR_DEADLOCK = 10045,
385 +       NFS4ERR_FILE_OPEN = 10046,
386 +       NFS4ERR_ADMIN_REVOKED = 10047,
387 +       NFS4ERR_CB_PATH_DOWN = 10048
388 +};
389 +
390 +/*
391 + * Note: NF4BAD is not actually part of the protocol; it is just used
392 + * internally by nfsd.
393 + */
394 +enum nfs_ftype4 {
395 +       NF4BAD          = 0,
396 +        NF4REG          = 1,    /* Regular File */
397 +        NF4DIR          = 2,    /* Directory */
398 +        NF4BLK          = 3,    /* Special File - block device */
399 +        NF4CHR          = 4,    /* Special File - character device */
400 +        NF4LNK          = 5,    /* Symbolic Link */
401 +        NF4SOCK         = 6,    /* Special File - socket */
402 +        NF4FIFO         = 7,    /* Special File - fifo */
403 +        NF4ATTRDIR      = 8,    /* Attribute Directory */
404 +        NF4NAMEDATTR    = 9     /* Named Attribute */
405 +};
406 +
407 +enum open_claim_type4 {
408 +       NFS4_OPEN_CLAIM_NULL = 0,
409 +       NFS4_OPEN_CLAIM_PREVIOUS = 1,
410 +       NFS4_OPEN_CLAIM_DELEGATE_CUR = 2,
411 +       NFS4_OPEN_CLAIM_DELEGATE_PREV = 3
412 +};
413 +
414 +enum opentype4 {
415 +       NFS4_OPEN_NOCREATE = 0,
416 +       NFS4_OPEN_CREATE = 1
417 +};
418 +
419 +enum createmode4 {
420 +       NFS4_CREATE_UNCHECKED = 0,
421 +       NFS4_CREATE_GUARDED = 1,
422 +       NFS4_CREATE_EXCLUSIVE = 2
423 +};
424 +
425 +enum limit_by4 {
426 +       NFS4_LIMIT_SIZE = 1,
427 +       NFS4_LIMIT_BLOCKS = 2
428 +};
429 +
430 +enum open_delegation_type4 {
431 +       NFS4_OPEN_DELEGATE_NONE = 0,
432 +       NFS4_OPEN_DELEGATE_READ = 1,
433 +       NFS4_OPEN_DELEGATE_WRITE = 2
434 +};
435 +
436 +enum lock_type4 {
437 +       NFS4_UNLOCK_LT = 0,
438 +       NFS4_READ_LT = 1,
439 +       NFS4_WRITE_LT = 2,
440 +       NFS4_READW_LT = 3,
441 +       NFS4_WRITEW_LT = 4
442 +};
443 +
444 +
445 +/* Mandatory Attributes */
446 +#define FATTR4_WORD0_SUPPORTED_ATTRS    (1UL << 0)
447 +#define FATTR4_WORD0_TYPE               (1UL << 1)
448 +#define FATTR4_WORD0_FH_EXPIRE_TYPE     (1UL << 2)
449 +#define FATTR4_WORD0_CHANGE             (1UL << 3)
450 +#define FATTR4_WORD0_SIZE               (1UL << 4)
451 +#define FATTR4_WORD0_LINK_SUPPORT       (1UL << 5)
452 +#define FATTR4_WORD0_SYMLINK_SUPPORT    (1UL << 6)
453 +#define FATTR4_WORD0_NAMED_ATTR         (1UL << 7)
454 +#define FATTR4_WORD0_FSID               (1UL << 8)
455 +#define FATTR4_WORD0_UNIQUE_HANDLES     (1UL << 9)
456 +#define FATTR4_WORD0_LEASE_TIME         (1UL << 10)
457 +#define FATTR4_WORD0_RDATTR_ERROR       (1UL << 11)
458 +
459 +/* Recommended Attributes */
460 +#define FATTR4_WORD0_ACL                (1UL << 12)
461 +#define FATTR4_WORD0_ACLSUPPORT         (1UL << 13)
462 +#define FATTR4_WORD0_ARCHIVE            (1UL << 14)
463 +#define FATTR4_WORD0_CANSETTIME         (1UL << 15)
464 +#define FATTR4_WORD0_CASE_INSENSITIVE   (1UL << 16)
465 +#define FATTR4_WORD0_CASE_PRESERVING    (1UL << 17)
466 +#define FATTR4_WORD0_CHOWN_RESTRICTED   (1UL << 18)
467 +#define FATTR4_WORD0_FILEHANDLE         (1UL << 19)
468 +#define FATTR4_WORD0_FILEID             (1UL << 20)
469 +#define FATTR4_WORD0_FILES_AVAIL        (1UL << 21)
470 +#define FATTR4_WORD0_FILES_FREE         (1UL << 22)
471 +#define FATTR4_WORD0_FILES_TOTAL        (1UL << 23)
472 +#define FATTR4_WORD0_FS_LOCATIONS       (1UL << 24)
473 +#define FATTR4_WORD0_HIDDEN             (1UL << 25)
474 +#define FATTR4_WORD0_HOMOGENEOUS        (1UL << 26)
475 +#define FATTR4_WORD0_MAXFILESIZE        (1UL << 27)
476 +#define FATTR4_WORD0_MAXLINK            (1UL << 28)
477 +#define FATTR4_WORD0_MAXNAME            (1UL << 29)
478 +#define FATTR4_WORD0_MAXREAD            (1UL << 30)
479 +#define FATTR4_WORD0_MAXWRITE           (1UL << 31)
480 +#define FATTR4_WORD1_MIMETYPE           (1UL << 0)
481 +#define FATTR4_WORD1_MODE               (1UL << 1)
482 +#define FATTR4_WORD1_NO_TRUNC           (1UL << 2)
483 +#define FATTR4_WORD1_NUMLINKS           (1UL << 3)
484 +#define FATTR4_WORD1_OWNER              (1UL << 4)
485 +#define FATTR4_WORD1_OWNER_GROUP        (1UL << 5)
486 +#define FATTR4_WORD1_QUOTA_HARD         (1UL << 6)
487 +#define FATTR4_WORD1_QUOTA_SOFT         (1UL << 7)
488 +#define FATTR4_WORD1_QUOTA_USED         (1UL << 8)
489 +#define FATTR4_WORD1_RAWDEV             (1UL << 9)
490 +#define FATTR4_WORD1_SPACE_AVAIL        (1UL << 10)
491 +#define FATTR4_WORD1_SPACE_FREE         (1UL << 11)
492 +#define FATTR4_WORD1_SPACE_TOTAL        (1UL << 12)
493 +#define FATTR4_WORD1_SPACE_USED         (1UL << 13)
494 +#define FATTR4_WORD1_SYSTEM             (1UL << 14)
495 +#define FATTR4_WORD1_TIME_ACCESS        (1UL << 15)
496 +#define FATTR4_WORD1_TIME_ACCESS_SET    (1UL << 16)
497 +#define FATTR4_WORD1_TIME_BACKUP        (1UL << 17)
498 +#define FATTR4_WORD1_TIME_CREATE        (1UL << 18)
499 +#define FATTR4_WORD1_TIME_DELTA         (1UL << 19)
500 +#define FATTR4_WORD1_TIME_METADATA      (1UL << 20)
501 +#define FATTR4_WORD1_TIME_MODIFY        (1UL << 21)
502 +#define FATTR4_WORD1_TIME_MODIFY_SET    (1UL << 22)
503 +#define FATTR4_WORD1_MOUNTED_ON_FILEID  (1UL << 23)
504 +
505 +#define NFSPROC4_NULL 0
506 +#define NFSPROC4_COMPOUND 1
507 +#define NFS4_MINOR_VERSION 0
508 +#define NFS4_DEBUG 1
509 +
510 +#ifdef __KERNEL__
511 +
512 +/* Index of predefined Linux client operations */
513 +
514 +enum {
515 +       NFSPROC4_CLNT_NULL = 0,         /* Unused */
516 +       NFSPROC4_CLNT_READ,
517 +       NFSPROC4_CLNT_WRITE,
518 +       NFSPROC4_CLNT_COMMIT,
519 +       NFSPROC4_CLNT_OPEN,
520 +       NFSPROC4_CLNT_OPEN_CONFIRM,
521 +       NFSPROC4_CLNT_OPEN_RECLAIM,
522 +       NFSPROC4_CLNT_OPEN_DOWNGRADE,
523 +       NFSPROC4_CLNT_CLOSE,
524 +       NFSPROC4_CLNT_SETATTR,
525 +       NFSPROC4_CLNT_FSINFO,
526 +       NFSPROC4_CLNT_RENEW,
527 +       NFSPROC4_CLNT_SETCLIENTID,
528 +       NFSPROC4_CLNT_SETCLIENTID_CONFIRM,
529 +       NFSPROC4_CLNT_LOCK,
530 +       NFSPROC4_CLNT_LOCKT,
531 +       NFSPROC4_CLNT_LOCKU,
532 +       NFSPROC4_CLNT_ACCESS,
533 +       NFSPROC4_CLNT_GETATTR,
534 +       NFSPROC4_CLNT_LOOKUP,
535 +       NFSPROC4_CLNT_LOOKUP_ROOT,
536 +       NFSPROC4_CLNT_REMOVE,
537 +       NFSPROC4_CLNT_RENAME,
538 +       NFSPROC4_CLNT_LINK,
539 +       NFSPROC4_CLNT_CREATE,
540 +       NFSPROC4_CLNT_PATHCONF,
541 +       NFSPROC4_CLNT_STATFS,
542 +       NFSPROC4_CLNT_READLINK,
543 +       NFSPROC4_CLNT_READDIR,
544 +       NFSPROC4_CLNT_SERVER_CAPS,
545 +       NFSPROC4_CLNT_DELEGRETURN,
546 +       NFSPROC4_CLNT_GETACL,
547 +       NFSPROC4_CLNT_SETACL,
548 +};
549 +
550 +#endif
551 +#endif
552 +
553 +/*
554 + * Local variables:
555 + *  c-basic-offset: 8
556 + * End:
557 + */
558 diff --git a/libacl/Makefile b/libacl/Makefile
559 index 5ac4810..3fcb146 100644
560 --- a/libacl/Makefile
561 +++ b/libacl/Makefile
562 @@ -8,19 +8,35 @@ LTLDFLAGS += -Wl,--version-script,$(TOPDIR)/exports
563  include $(TOPDIR)/include/builddefs
564  
565  LTLIBRARY = libacl.la
566 -LTLIBS = -lattr $(LIBMISC)
567 +LTLIBS = -lattr -lnfsidmap $(LIBMISC)
568  LTDEPENDENCIES = $(LIBMISC)
569 -LT_CURRENT = 2
570 +LT_CURRENT = 3
571  LT_REVISION = 0
572 -LT_AGE = 1
573 +LT_AGE = 2
574 +
575 +CFILES = $(POSIX_CFILES) $(LIBACL_CFILES) $(LIBACL_NFS4_CFILES) \
576 +       $(INTERNAL_CFILES) perm_copy_fd.c perm_copy_file.c
577  
578 -CFILES = $(POSIX_CFILES) $(LIBACL_CFILES) $(INTERNAL_CFILES) \
579 -        perm_copy_fd.c perm_copy_file.c
580  HFILES = libobj.h libacl.h byteorder.h __acl_from_xattr.h __acl_to_xattr.h \
581 -        perm_copy.h
582 +        perm_copy.h $(LIBACL_NFS4_HFILES)
583  
584  LCFLAGS = -include perm_copy.h
585  
586 +LIBACL_NFS4_CFILES = \
587 +       acl_nfs4_get_who.c \
588 +       acl_n4tp_acl_trans.c       acl_nfs4_get_whotype.c \
589 +       acl_nfs4_new.c \
590 +       acl_nfs4_add_ace.c         acl_nfs4_remove_ace.c \
591 +       acl_nfs4_add_pair.c \
592 +       acl_nfs4_copy_acl.c        acl_nfs4_set_who.c \
593 +       acl_nfs4_free.c            acl_nfs4_xattr_load.c \
594 +       acl_nfs4_xattr_pack.c      acl_nfs4_xattr_size.c \
595 +       acl_ptn4_acl_trans.c \
596 +       acl_ptn4_get_mask.c        __posix_acl_from_nfs4_xattr.c \
597 +
598 +
599 +LIBACL_NFS4_HFILES = ../include/libacl_nfs4.h ../include/nfs4.h
600 +
601  POSIX_CFILES = \
602         acl_add_perm.c acl_calc_mask.c acl_clear_perms.c acl_copy_entry.c \
603         acl_copy_ext.c acl_copy_int.c acl_create_entry.c acl_delete_def_file.c \
604 diff --git a/libacl/__posix_acl_from_nfs4_xattr.c b/libacl/__posix_acl_from_nfs4_xattr.c
605 new file mode 100644
606 index 0000000..8941024
607 --- /dev/null
608 +++ b/libacl/__posix_acl_from_nfs4_xattr.c
609 @@ -0,0 +1,60 @@
610 +/*
611 + *  NFSv4 ACL Code
612 + *  Convert NFSv4 xattr values to a posix ACL
613 + *
614 + *  Copyright (c) 2002, 2003 The Regents of the University of Michigan.
615 + *  All rights reserved.
616 + *
617 + *  Nathaniel Gallaher <ngallahe@umich.edu>
618 + *
619 + *  Redistribution and use in source and binary forms, with or without
620 + *  modification, are permitted provided that the following conditions
621 + *  are met:
622 + *
623 + *  1. Redistributions of source code must retain the above copyright
624 + *     notice, this list of conditions and the following disclaimer.
625 + *  2. Redistributions in binary form must reproduce the above copyright
626 + *     notice, this list of conditions and the following disclaimer in the
627 + *     documentation and/or other materials provided with the distribution.
628 + *  3. Neither the name of the University nor the names of its
629 + *     contributors may be used to endorse or promote products derived
630 + *     from this software without specific prior written permission.
631 + *
632 + *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
633 + *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
634 + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
635 + *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
636 + *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
637 + *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
638 + *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
639 + *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
640 + *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
641 + *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
642 + *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
643 + */
644 +
645 +#include <acl/libacl.h>
646 +#include "libacl_nfs4.h"
647 +
648 +/* xattr_v is a char buffer filled with the nfsv4 xattr value.
649 + * xattr_size should be the byte count of the length of the xattr_v
650 + * data size. xattr_v may be larger than <xattr_size> bytes, but only
651 + * the first <xattr_size> bytes will be read. <type> is the posix acl
652 + * type requested. Currently either default, or access */
653 +
654 +acl_t __posix_acl_from_nfs4_xattr(char* xattr_v,
655 +               int xattr_size, acl_type_t ptype, u32 is_dir)
656 +{
657 +       struct nfs4_acl *       nfsacl = NULL;
658 +       acl_t pacl;
659 +
660 +       nfsacl = acl_nfs4_xattr_load(xattr_v, xattr_size, is_dir);
661 +       if(nfsacl == NULL) {
662 +               return NULL;
663 +       }
664 +
665 +       pacl = acl_n4tp_acl_trans(nfsacl, ptype);
666 +
667 +       return pacl;
668 +}
669 +
670 diff --git a/libacl/acl_extended_file.c b/libacl/acl_extended_file.c
671 index 1850aa2..d657eb1 100644
672 --- a/libacl/acl_extended_file.c
673 +++ b/libacl/acl_extended_file.c
674 @@ -22,6 +22,7 @@
675  #include <unistd.h>
676  #include <attr/xattr.h>
677  #include "libacl.h"
678 +#include "libacl_nfs4.h"
679  
680  #include "byteorder.h"
681  #include "acl_ea.h"
682 @@ -33,6 +34,34 @@ acl_extended_file(const char *path_p)
683         int base_size = sizeof(acl_ea_header) + 3 * sizeof(acl_ea_entry);
684         int retval;
685  
686 +       /* XXX: Ugh: what's the easiest way to do this, taking
687 +        * into account default acl's, and that length alone won't do this?
688 +        * Also I'm a little uncomfortable with the amount of #ifdef
689 +        * NFS4 stuff that's going on.  We need a cleaner separation. */
690 +#ifdef USE_NFSV4_TRANS
691 +       retval = getxattr(path_p, ACL_NFS4_XATTR, NULL, 0);
692 +       if (retval < 0 && errno != ENOATTR && errno != EOPNOTSUPP)
693 +               return -1;
694 +       if (retval >= 0) {
695 +               struct nfs4_acl *nfsacl;
696 +               char *ext_acl_p = alloca(retval);
697 +               if (!ext_acl_p)
698 +                       return -1;
699 +
700 +               retval = getxattr(path_p, ACL_NFS4_XATTR, ext_acl_p, retval);
701 +               if (retval == -1)
702 +                       return -1;
703 +
704 +               nfsacl = acl_nfs4_xattr_load(ext_acl_p, retval, NFS4_ACL_ISFILE);
705 +               if (nfsacl) {
706 +                       int count = nfsacl->naces;
707 +                       acl_nfs4_free(nfsacl);
708 +                       return count > 6;
709 +               }
710 +               return 0;
711 +       }
712 +#endif
713 +
714         retval = getxattr(path_p, ACL_EA_ACCESS, NULL, 0);
715         if (retval < 0 && errno != ENOATTR && errno != ENODATA)
716                 return -1;
717 diff --git a/libacl/acl_get_fd.c b/libacl/acl_get_fd.c
718 index b424bfd..6b057cd 100644
719 --- a/libacl/acl_get_fd.c
720 +++ b/libacl/acl_get_fd.c
721 @@ -28,6 +28,10 @@
722  #include "libacl.h"
723  #include "__acl_from_xattr.h"
724  
725 +#ifdef USE_NFSV4_TRANS
726 + #include "libacl_nfs4.h"
727 +#endif
728 +
729  #include "byteorder.h"
730  #include "acl_ea.h"
731  
732 @@ -38,31 +42,59 @@ acl_get_fd(int fd)
733  {
734         const size_t size_guess = acl_ea_size(16);
735         char *ext_acl_p = alloca(size_guess);
736 +       char *name = ACL_EA_ACCESS;
737         int retval;
738 +       int nfsv4acls;
739  
740         if (!ext_acl_p)
741                 return NULL;
742 -       retval = fgetxattr(fd, ACL_EA_ACCESS, ext_acl_p, size_guess);
743 +
744 +#ifdef USE_NFSV4_TRANS
745 +       retval = fgetxattr(fd, ACL_NFS4_XATTR, ext_acl_p, size_guess);
746 +       if(retval == -1 && (errno == ENOATTR || errno == EOPNOTSUPP)) {
747 +               nfsv4acls = ACL_NFS4_NOT_USED;
748 +               retval = fgetxattr(fd, name, ext_acl_p, size_guess);
749 +       } else {
750 +               nfsv4acls = ACL_NFS4_USED;
751 +               name = ACL_NFS4_XATTR;
752 +       }
753 +#else
754 +       retval = fgetxattr(fd, name, ext_acl_p, size_guess);
755 +#endif
756 +
757         if (retval == -1 && errno == ERANGE) {
758 -               retval = fgetxattr(fd, ACL_EA_ACCESS, NULL, 0);
759 +               retval = fgetxattr(fd, name, NULL, 0);
760                 if (retval > 0) {
761                         ext_acl_p = alloca(retval);
762                         if (!ext_acl_p)
763                                 return NULL;
764 -                       retval = fgetxattr(fd, ACL_EA_ACCESS, ext_acl_p,retval);
765 +                       retval = fgetxattr(fd, name, ext_acl_p, retval);
766                 }
767         }
768         if (retval > 0) {
769 -               acl_t acl = __acl_from_xattr(ext_acl_p, retval);
770 -               return acl;
771 +#ifdef USE_NFSV4_TRANS
772 +               if(nfsv4acls == ACL_NFS4_USED) {
773 +                       acl_t acl = __posix_acl_from_nfs4_xattr(ext_acl_p, retval,
774 +                                       ACL_TYPE_ACCESS, NFS4_ACL_ISFILE);
775 +
776 +                       return acl;
777 +               }
778 +               else
779 +#endif
780 +               {
781 +                       acl_t acl = __acl_from_xattr(ext_acl_p, retval);
782 +                       return acl;
783 +               }
784         } else if (retval == 0 || errno == ENOATTR || errno == ENODATA) {
785                 struct stat st;
786  
787 -               if (fstat(fd, &st) == 0)
788 -                       return acl_from_mode(st.st_mode);
789 -               else
790 +               if (fstat(fd, &st) != 0) {
791                         return NULL;
792 -       } else
793 +               }
794 +
795 +               return acl_from_mode(st.st_mode);
796 +       } else {
797                 return NULL;
798 +       }
799  }
800  
801 diff --git a/libacl/acl_get_file.c b/libacl/acl_get_file.c
802 index 8895e90..15da288 100644
803 --- a/libacl/acl_get_file.c
804 +++ b/libacl/acl_get_file.c
805 @@ -28,6 +28,10 @@
806  #include "libacl.h"
807  #include "__acl_from_xattr.h"
808  
809 +#ifdef USE_NFSV4_TRANS
810 + #include "libacl_nfs4.h"
811 +#endif
812 +
813  #include "byteorder.h"
814  #include "acl_ea.h"
815  
816 @@ -40,6 +44,8 @@ acl_get_file(const char *path_p, acl_type_t type)
817         char *ext_acl_p = alloca(size_guess);
818         const char *name;
819         int retval;
820 +       int nfsv4acls;
821 +       int iflags;
822  
823         switch(type) {
824                 case ACL_TYPE_ACCESS:
825 @@ -55,8 +61,20 @@ acl_get_file(const char *path_p, acl_type_t type)
826  
827         if (!ext_acl_p)
828                 return NULL;
829 +#ifdef USE_NFSV4_TRANS
830 +       retval = getxattr(path_p, ACL_NFS4_XATTR, ext_acl_p, size_guess);
831 +       if((retval == -1) && (errno == ENOATTR || errno == EOPNOTSUPP)) {
832 +               nfsv4acls = ACL_NFS4_NOT_USED;
833 +               retval = getxattr(path_p, name, ext_acl_p, size_guess);
834 +       } else {
835 +               nfsv4acls = ACL_NFS4_USED;
836 +               name = ACL_NFS4_XATTR;
837 +       }
838 +#else
839         retval = getxattr(path_p, name, ext_acl_p, size_guess);
840 -       if (retval == -1 && errno == ERANGE) {
841 +#endif
842 +
843 +       if ((retval == -1) && (errno == ERANGE)) {
844                 retval = getxattr(path_p, name, NULL, 0);
845                 if (retval > 0) {
846                         ext_acl_p = alloca(retval);
847 @@ -66,9 +84,29 @@ acl_get_file(const char *path_p, acl_type_t type)
848                 }
849         }
850         if (retval > 0) {
851 -               acl_t acl = __acl_from_xattr(ext_acl_p, retval);
852 -               return acl;
853 -       } else if (retval == 0 || errno == ENOATTR || errno == ENODATA) {
854 +#ifdef USE_NFSV4_TRANS
855 +               if(nfsv4acls == ACL_NFS4_USED) {
856 +                       struct stat st;
857 +
858 +                       iflags = NFS4_ACL_ISFILE;
859 +
860 +                       if (stat(path_p, &st) != 0)
861 +                               return NULL;
862 +
863 +                       if (S_ISDIR(st.st_mode))
864 +                               iflags = NFS4_ACL_ISDIR;
865 +
866 +                       acl_t acl = __posix_acl_from_nfs4_xattr(ext_acl_p, retval, type,
867 +                                       iflags);
868 +                       return acl;
869 +               }
870 +               else
871 +#endif
872 +               {
873 +                       acl_t acl = __acl_from_xattr(ext_acl_p, retval);
874 +                       return acl;
875 +               }
876 +       } else if ((retval == 0) || (errno == ENOATTR) || (errno == ENODATA)) {
877                 struct stat st;
878  
879                 if (stat(path_p, &st) != 0)
880 diff --git a/libacl/acl_n4tp_acl_trans.c b/libacl/acl_n4tp_acl_trans.c
881 new file mode 100644
882 index 0000000..3b0563f
883 --- /dev/null
884 +++ b/libacl/acl_n4tp_acl_trans.c
885 @@ -0,0 +1,454 @@
886 +/*
887 + *  NFSv4 ACL Code
888 + *  Convert NFSv4 ACL to a POSIX ACL
889 + *
890 + *  Copyright (c) 2002, 2003 The Regents of the University of Michigan.
891 + *  All rights reserved.
892 + *
893 + *  Nathaniel Gallaher <ngallahe@umich.edu>
894 + *
895 + *  Redistribution and use in source and binary forms, with or without
896 + *  modification, are permitted provided that the following conditions
897 + *  are met:
898 + *
899 + *  1. Redistributions of source code must retain the above copyright
900 + *     notice, this list of conditions and the following disclaimer.
901 + *  2. Redistributions in binary form must reproduce the above copyright
902 + *     notice, this list of conditions and the following disclaimer in the
903 + *     documentation and/or other materials provided with the distribution.
904 + *  3. Neither the name of the University nor the names of its
905 + *     contributors may be used to endorse or promote products derived
906 + *     from this software without specific prior written permission.
907 + *
908 + *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
909 + *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
910 + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
911 + *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
912 + *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
913 + *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
914 + *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
915 + *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
916 + *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
917 + *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
918 + *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
919 + */
920 +
921 +#include <acl/libacl.h>
922 +#include <nfsidmap.h>
923 +#include "libacl_nfs4.h"
924 +
925 +
926 +/*
927 + * While processing the NFSv4 ACE, this maintains bitmasks representing
928 + * which permission bits have been allowed and which denied to a given
929 + * entity: */
930 +struct posix_ace_state {
931 +       u_int32_t allow;
932 +       u_int32_t deny;
933 +};
934 +
935 +struct posix_user_ace_state {
936 +       uid_t uid;
937 +       struct posix_ace_state perms;
938 +};
939 +
940 +struct posix_ace_state_array {
941 +       int n;
942 +       struct posix_user_ace_state aces[];
943 +};
944 +
945 +/*
946 + * While processing the NFSv4 ACE, this maintains the partial permissions
947 + * calculated so far: */
948 +
949 +struct posix_acl_state {
950 +       struct posix_ace_state owner;
951 +       struct posix_ace_state group;
952 +       struct posix_ace_state other;
953 +       struct posix_ace_state everyone;
954 +       struct posix_ace_state mask; /* Deny unused in this case */
955 +       struct posix_ace_state_array *users;
956 +       struct posix_ace_state_array *groups;
957 +};
958 +
959 +static int
960 +init_state(struct posix_acl_state *state, int cnt)
961 +{
962 +       int alloc;
963 +
964 +       memset(state, 0, sizeof(struct posix_acl_state));
965 +       /*
966 +        * In the worst case, each individual acl could be for a distinct
967 +        * named user or group, but we don't know which, so we allocate
968 +        * enough space for either:
969 +        */
970 +       alloc = sizeof(struct posix_ace_state_array)
971 +               + cnt*sizeof(struct posix_user_ace_state);
972 +       state->users = calloc(1, alloc);
973 +       if (!state->users)
974 +               return -ENOMEM;
975 +       state->groups = calloc(1, alloc);
976 +       if (!state->groups) {
977 +               free(state->users);
978 +               return -ENOMEM;
979 +       }
980 +       return 0;
981 +}
982 +
983 +static void
984 +free_state(struct posix_acl_state *state) {
985 +       free(state->users);
986 +       free(state->groups);
987 +}
988 +
989 +static inline void add_to_mask(struct posix_acl_state *state, struct posix_ace_state *astate)
990 +{
991 +       state->mask.allow |= astate->allow;
992 +}
993 +
994 +/*
995 + * We only map from NFSv4 to POSIX ACLs when getting ACLs, when we err on the
996 + * side of permissiveness (so as not to make the file appear more secure than
997 + * it really is), so the mode bit mapping below is optimistic.
998 + */
999 +static void
1000 +set_mode_from_nfs4(acl_entry_t pace, u_int32_t perm, int is_dir)
1001 +{
1002 +       u32 write_mode = NFS4_WRITE_MODE;
1003 +       acl_permset_t perms;
1004 +
1005 +       acl_get_permset(pace, &perms);
1006 +       acl_clear_perms(perms);
1007 +       if (is_dir)
1008 +               write_mode |= NFS4_ACE_DELETE_CHILD;
1009 +       if (perm & NFS4_READ_MODE)
1010 +               acl_add_perm(perms, ACL_READ);
1011 +       if (perm & write_mode)
1012 +               acl_add_perm(perms, ACL_WRITE);
1013 +       if (perm & NFS4_EXECUTE_MODE)
1014 +               acl_add_perm(perms, ACL_EXECUTE);
1015 +       acl_set_permset(pace, perms);
1016 +}
1017 +
1018 +/* XXX: add a "check allow" that can warn on e.g. allows of WRITE_ACL
1019 + * to non-owner? */
1020 +
1021 +/* XXX: replace error returns by errno sets all over.  Ugh. */
1022 +
1023 +static acl_t
1024 +posix_state_to_acl(struct posix_acl_state *state, int is_dir)
1025 +{
1026 +       acl_entry_t pace;
1027 +       acl_t pacl;
1028 +       int nace;
1029 +       int i, error = 0;
1030 +
1031 +       if (state->users->n || state->groups->n)
1032 +               nace = 4 + state->users->n + state->groups->n;
1033 +       else
1034 +               nace = 3;
1035 +       pacl = acl_init(nace);
1036 +       if (!pacl)
1037 +               return NULL;
1038 +
1039 +       error = acl_create_entry(&pacl, &pace);
1040 +       if (error)
1041 +               goto out_err;
1042 +       acl_set_tag_type(pace, ACL_USER_OBJ);
1043 +       set_mode_from_nfs4(pace, state->owner.allow, is_dir);
1044 +
1045 +       for (i=0; i < state->users->n; i++) {
1046 +               error = acl_create_entry(&pacl, &pace);
1047 +               if (error)
1048 +                       goto out_err;
1049 +               acl_set_tag_type(pace, ACL_USER);
1050 +               set_mode_from_nfs4(pace, state->users->aces[i].perms.allow,
1051 +                                       is_dir);
1052 +               acl_set_qualifier(pace, &state->users->aces[i].uid);
1053 +               add_to_mask(state, &state->users->aces[i].perms);
1054 +       }
1055 +
1056 +       error = acl_create_entry(&pacl, &pace);
1057 +       if (error)
1058 +               goto out_err;
1059 +       acl_set_tag_type(pace, ACL_GROUP_OBJ);
1060 +       set_mode_from_nfs4(pace, state->group.allow, is_dir);
1061 +       add_to_mask(state, &state->group);
1062 +
1063 +       for (i=0; i < state->groups->n; i++) {
1064 +               error = acl_create_entry(&pacl, &pace);
1065 +               if (error)
1066 +                       goto out_err;
1067 +               acl_set_tag_type(pace, ACL_GROUP);
1068 +               set_mode_from_nfs4(pace, state->groups->aces[i].perms.allow,
1069 +                                       is_dir);
1070 +               acl_set_qualifier(pace, &state->groups->aces[i].uid);
1071 +               add_to_mask(state, &state->groups->aces[i].perms);
1072 +       }
1073 +
1074 +       if (nace > 3) {
1075 +               error = acl_create_entry(&pacl, &pace);
1076 +               if (error)
1077 +                       goto out_err;
1078 +               acl_set_tag_type(pace, ACL_MASK);
1079 +               set_mode_from_nfs4(pace, state->mask.allow, is_dir);
1080 +       }
1081 +
1082 +       error = acl_create_entry(&pacl, &pace);
1083 +       if (error)
1084 +               goto out_err;
1085 +       acl_set_tag_type(pace, ACL_OTHER);
1086 +       set_mode_from_nfs4(pace, state->other.allow, is_dir);
1087 +
1088 +       return pacl;
1089 +out_err:
1090 +       acl_free(pacl);
1091 +       return NULL;
1092 +}
1093 +
1094 +static inline void allow_bits(struct posix_ace_state *astate, u32 mask)
1095 +{
1096 +       /* Allow all bits in the mask not already denied: */
1097 +       astate->allow |= mask & ~astate->deny;
1098 +}
1099 +
1100 +static inline void deny_bits(struct posix_ace_state *astate, u32 mask)
1101 +{
1102 +       /* Deny all bits in the mask not already allowed: */
1103 +       astate->deny |= mask & ~astate->allow;
1104 +}
1105 +
1106 +static int find_uid(struct posix_acl_state *state, uid_t uid)
1107 +{
1108 +       int i;
1109 +       struct posix_ace_state_array *users = state->users;
1110 +
1111 +       for (i = 0; i < users->n; i++)
1112 +               if (users->aces[i].uid == uid)
1113 +                       return i;
1114 +       /* Not found: */
1115 +       users->n++;
1116 +       users->aces[i].uid = uid;
1117 +       users->aces[i].perms.allow = state->everyone.allow;
1118 +       users->aces[i].perms.deny  = state->everyone.deny;
1119 +
1120 +       return i;
1121 +}
1122 +
1123 +static int find_gid(struct posix_acl_state *state, uid_t uid)
1124 +{
1125 +       int i;
1126 +       struct posix_ace_state_array *groups = state->groups;
1127 +
1128 +       for (i = 0; i < groups->n; i++)
1129 +               if (groups->aces[i].uid == uid)
1130 +                       return i;
1131 +       /* Not found: */
1132 +       groups->n++;
1133 +       groups->aces[i].uid = uid;
1134 +       groups->aces[i].perms.allow = state->other.allow;
1135 +       groups->aces[i].perms.deny  = state->other.deny;
1136 +
1137 +       return i;
1138 +}
1139 +
1140 +static void deny_bits_array(struct posix_ace_state_array *a, u32 mask)
1141 +{
1142 +       int i;
1143 +
1144 +       for (i=0; i < a->n; i++)
1145 +               deny_bits(&a->aces[i].perms, mask);
1146 +}
1147 +
1148 +static void allow_bits_array(struct posix_ace_state_array *a, u32 mask)
1149 +{
1150 +       int i;
1151 +
1152 +       for (i=0; i < a->n; i++)
1153 +               allow_bits(&a->aces[i].perms, mask);
1154 +}
1155 +
1156 +static acl_tag_t acl_n4tp_get_whotype(struct nfs4_ace *ace)
1157 +{
1158 +       int nfs4type;
1159 +       int result;
1160 +
1161 +       result = acl_nfs4_get_who(ace, &nfs4type, NULL);
1162 +       if (result < 0)
1163 +               return -1;
1164 +
1165 +       switch (nfs4type) {
1166 +               case NFS4_ACL_WHO_NAMED:
1167 +                       return (ace->flag & NFS4_ACE_IDENTIFIER_GROUP ?
1168 +                                       ACL_GROUP : ACL_USER);
1169 +               case NFS4_ACL_WHO_OWNER:
1170 +                       return ACL_USER_OBJ;
1171 +               case NFS4_ACL_WHO_GROUP:
1172 +                       return ACL_GROUP_OBJ;
1173 +               case NFS4_ACL_WHO_EVERYONE:
1174 +                       return ACL_OTHER;
1175 +       }
1176 +       errno = EINVAL;
1177 +       return -1;
1178 +}
1179 +
1180 +static int process_one_v4_ace(struct posix_acl_state *state,
1181 +                               struct nfs4_ace *ace)
1182 +{
1183 +       u32 mask = ace->access_mask;
1184 +       uid_t id;
1185 +       int i;
1186 +
1187 +       if (nfs4_init_name_mapping(NULL))
1188 +               return -1;
1189 +
1190 +       switch (acl_n4tp_get_whotype(ace)) {
1191 +       case ACL_USER_OBJ:
1192 +               if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) {
1193 +                       allow_bits(&state->owner, mask);
1194 +               } else {
1195 +                       deny_bits(&state->owner, mask);
1196 +               }
1197 +               break;
1198 +       case ACL_USER:
1199 +               if (nfs4_name_to_uid(ace->who, &id))
1200 +                       return -1;
1201 +               i = find_uid(state, id);
1202 +               if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) {
1203 +                       allow_bits(&state->users->aces[i].perms, mask);
1204 +                       mask = state->users->aces[i].perms.allow;
1205 +                       allow_bits(&state->owner, mask);
1206 +               } else {
1207 +                       deny_bits(&state->users->aces[i].perms, mask);
1208 +               }
1209 +               break;
1210 +       case ACL_GROUP_OBJ:
1211 +               if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) {
1212 +                       allow_bits(&state->group, mask);
1213 +                       mask = state->group.allow;
1214 +                       allow_bits(&state->owner, mask);
1215 +                       allow_bits(&state->everyone, mask);
1216 +                       allow_bits_array(state->users, mask);
1217 +               } else {
1218 +                       deny_bits(&state->group, mask);
1219 +               }
1220 +               break;
1221 +       case ACL_GROUP:
1222 +               if (nfs4_name_to_gid(ace->who, &id))
1223 +                       return -1;
1224 +               i = find_gid(state, id);
1225 +               if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) {
1226 +                       allow_bits(&state->groups->aces[i].perms, mask);
1227 +                       mask = state->groups->aces[i].perms.allow;
1228 +                       allow_bits(&state->owner, mask);
1229 +                       allow_bits(&state->everyone, mask);
1230 +                       allow_bits_array(state->users, mask);
1231 +               } else {
1232 +                       deny_bits(&state->groups->aces[i].perms, mask);
1233 +               }
1234 +               break;
1235 +       case ACL_OTHER:
1236 +               if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) {
1237 +                       allow_bits(&state->owner, mask);
1238 +                       allow_bits(&state->group, mask);
1239 +                       allow_bits(&state->other, mask);
1240 +                       allow_bits(&state->everyone, mask);
1241 +                       allow_bits_array(state->users, mask);
1242 +                       allow_bits_array(state->groups, mask);
1243 +               } else {
1244 +                       deny_bits(&state->owner, mask);
1245 +                       deny_bits(&state->group, mask);
1246 +                       deny_bits(&state->other, mask);
1247 +                       deny_bits(&state->everyone, mask);
1248 +                       deny_bits_array(state->users, mask);
1249 +                       deny_bits_array(state->groups, mask);
1250 +               }
1251 +       }
1252 +       return 0;
1253 +}
1254 +
1255 +#define FILE_OR_DIR_INHERIT (NFS4_ACE_FILE_INHERIT_ACE \
1256 +                               | NFS4_ACE_DIRECTORY_INHERIT_ACE)
1257 +
1258 +/* Strip or keep inheritance aces depending on type of posix acl requested */
1259 +static void acl_nfs4_check_inheritance(struct nfs4_acl *acl, u32 iflags)
1260 +{
1261 +       struct nfs4_ace * cur_ace;
1262 +       struct nfs4_ace * temp_ace;
1263 +
1264 +       cur_ace = acl->ace_head.tqh_first;
1265 +
1266 +       while (cur_ace) {
1267 +               /* get the next ace now in case we free the current ace */
1268 +               temp_ace = cur_ace;
1269 +               cur_ace = cur_ace->l_ace.tqe_next;
1270 +
1271 +               if (iflags & NFS4_ACL_REQUEST_DEFAULT) {
1272 +                       if (!(temp_ace->flag & FILE_OR_DIR_INHERIT))
1273 +                               acl_nfs4_remove_ace(acl, temp_ace);
1274 +               } else {
1275 +                       if (temp_ace->flag & NFS4_ACE_INHERIT_ONLY_ACE)
1276 +                               acl_nfs4_remove_ace(acl, temp_ace);
1277 +               }
1278 +       }
1279 +}
1280 +
1281 +acl_t acl_n4tp_acl_trans(struct nfs4_acl * nacl_p, acl_type_t ptype)
1282 +{
1283 +       struct posix_acl_state state;
1284 +       acl_t pacl;
1285 +       struct nfs4_acl * temp_acl;
1286 +       struct nfs4_ace * cur_ace;
1287 +       int ret;
1288 +       u32 iflags = NFS4_ACL_NOFLAGS;
1289 +
1290 +       if (ptype == ACL_TYPE_DEFAULT) {
1291 +               if (nacl_p->is_directory)
1292 +                       iflags |= NFS4_ACL_REQUEST_DEFAULT;
1293 +               else {
1294 +                       errno = EINVAL;
1295 +                       return NULL;
1296 +               }
1297 +       }
1298 +
1299 +       /* Copy so we can delete bits without borking the original */
1300 +       temp_acl = acl_nfs4_copy_acl(nacl_p);
1301 +       if (temp_acl == NULL)
1302 +               return NULL;
1303 +
1304 +       acl_nfs4_check_inheritance(temp_acl, iflags);
1305 +
1306 +       if (ptype == ACL_TYPE_DEFAULT && temp_acl->naces == 0) {
1307 +               acl_nfs4_free(temp_acl);
1308 +               return acl_init(0);
1309 +       }
1310 +
1311 +       ret = init_state(&state, temp_acl->naces);
1312 +       if (ret)
1313 +               goto free_failed;
1314 +
1315 +       cur_ace = temp_acl->ace_head.tqh_first;
1316 +       while (cur_ace) {
1317 +               if (process_one_v4_ace(&state, cur_ace)) {
1318 +                       free_state(&state);
1319 +                       goto free_failed;
1320 +               }
1321 +               cur_ace = cur_ace->l_ace.tqe_next;
1322 +       }
1323 +
1324 +       acl_nfs4_free(temp_acl);
1325 +
1326 +       pacl = posix_state_to_acl(&state, nacl_p->is_directory);
1327 +
1328 +       free_state(&state);
1329 +
1330 +       ret = acl_valid(pacl);
1331 +       if (ret < 0)
1332 +               goto free_failed;
1333 +
1334 +       return pacl;
1335 +
1336 +free_failed:
1337 +       acl_nfs4_free(temp_acl);
1338 +       return NULL;
1339 +}
1340 diff --git a/libacl/acl_nfs4_add_ace.c b/libacl/acl_nfs4_add_ace.c
1341 new file mode 100644
1342 index 0000000..4c1ff9a
1343 --- /dev/null
1344 +++ b/libacl/acl_nfs4_add_ace.c
1345 @@ -0,0 +1,83 @@
1346 +/*
1347 + *  NFSv4 ACL Code
1348 + *  Add an ace to the acl
1349 + *
1350 + *  Copyright (c) 2002, 2003 The Regents of the University of Michigan.
1351 + *  All rights reserved.
1352 + *
1353 + *  Marius Aamodt Eriksen <marius@umich.edu>
1354 + *  J. Bruce Fields <bfields@umich.edu>
1355 + *  Nathaniel Gallaher <ngallahe@umich.edu>
1356 + *  Jeff Sedlak <jsedlak@umich.edu>
1357 + *
1358 + *  Redistribution and use in source and binary forms, with or without
1359 + *  modification, are permitted provided that the following conditions
1360 + *  are met:
1361 + *
1362 + *  1. Redistributions of source code must retain the above copyright
1363 + *     notice, this list of conditions and the following disclaimer.
1364 + *  2. Redistributions in binary form must reproduce the above copyright
1365 + *     notice, this list of conditions and the following disclaimer in the
1366 + *     documentation and/or other materials provided with the distribution.
1367 + *  3. Neither the name of the University nor the names of its
1368 + *     contributors may be used to endorse or promote products derived
1369 + *     from this software without specific prior written permission.
1370 + *
1371 + *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
1372 + *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
1373 + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1374 + *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1375 + *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1376 + *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1377 + *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
1378 + *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
1379 + *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
1380 + *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1381 + *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1382 + */
1383 +
1384 +#include "libacl_nfs4.h"
1385 +
1386 +int
1387 +acl_nfs4_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask,
1388 +               int whotype, char* who)
1389 +{
1390 +       struct nfs4_ace *ace;
1391 +       int result;
1392 +
1393 +       if(acl == NULL)
1394 +       {
1395 +               errno = EINVAL;
1396 +               return -1;
1397 +       }
1398 +
1399 +       if ((ace = malloc(sizeof(*ace))) == NULL)
1400 +       {
1401 +               errno = ENOMEM;
1402 +               return -1;
1403 +       }
1404 +
1405 +       ace->type = type;
1406 +       ace->flag = flag;
1407 +
1408 +       if( type == NFS4_ACE_ACCESS_DENIED_ACE_TYPE )
1409 +               access_mask = access_mask & ~(NFS4_ACE_MASK_IGNORE);
1410 +
1411 +
1412 +       /* Castrate delete_child if we aren't a directory */
1413 +       if (!acl->is_directory)
1414 +               access_mask &= ~NFS4_ACE_DELETE_CHILD;
1415 +
1416 +
1417 +       ace->access_mask = access_mask & NFS4_ACE_MASK_ALL;
1418 +
1419 +       result = acl_nfs4_set_who(ace, whotype, who);
1420 +       if(result < 0)
1421 +               return -1;
1422 +
1423 +       TAILQ_INSERT_TAIL(&acl->ace_head, ace, l_ace);
1424 +       acl->naces++;
1425 +
1426 +       return 0;
1427 +}
1428 +
1429 diff --git a/libacl/acl_nfs4_add_pair.c b/libacl/acl_nfs4_add_pair.c
1430 new file mode 100644
1431 index 0000000..d849fb9
1432 --- /dev/null
1433 +++ b/libacl/acl_nfs4_add_pair.c
1434 @@ -0,0 +1,60 @@
1435 +/*
1436 + *  Add a pair of aces to the acl. The ace masks are complements of each other
1437 + *  This keeps us from walking off the end of the acl
1438 + *
1439 + *  Copyright (c) 2004 The Regents of the University of Michigan.
1440 + *  All rights reserved.
1441 + *
1442 + *  Marius Aamodt Eriksen <marius@umich.edu>
1443 + *  J. Bruce Fields <bfields@umich.edu>
1444 + *  Nathaniel Gallaher <ngallahe@umich.edu>
1445 + *  Jeff Sedlak <jsedlak@umich.edu>
1446 + *
1447 + *  Redistribution and use in source and binary forms, with or without
1448 + *  modification, are permitted provided that the following conditions
1449 + *  are met:
1450 + *
1451 + *  1. Redistributions of source code must retain the above copyright
1452 + *     notice, this list of conditions, the following disclaimer, and
1453 + *     any and all other licensing or copyright notices included in
1454 + *     any files in this distribution.
1455 + *  2. Redistributions in binary form must reproduce the above copyright
1456 + *     notice, this list of conditions and the following disclaimer in the
1457 + *     documentation and/or other materials provided with the distribution.
1458 + *  3. Neither the name of the University nor the names of its
1459 + *     contributors may be used to endorse or promote products derived
1460 + *     from this software without specific prior written permission.
1461 + *
1462 + *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
1463 + *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
1464 + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1465 + *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1466 + *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1467 + *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1468 + *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
1469 + *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
1470 + *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
1471 + *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1472 + *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1473 + *
1474 + */
1475 +
1476 +
1477 +#include "libacl_nfs4.h"
1478 +
1479 +int
1480 +acl_nfs4_add_pair(struct nfs4_acl *acl, int eflag, u32 mask, int ownertype,
1481 +               char* owner)
1482 +{
1483 +       int error;
1484 +
1485 +       error = acl_nfs4_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
1486 +                                eflag, mask, ownertype, owner);
1487 +       if (error < 0)
1488 +               return error;
1489 +       error = acl_nfs4_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
1490 +                               eflag, ~mask, ownertype, owner);
1491 +       return error;
1492 +}
1493 +
1494 +
1495 diff --git a/libacl/acl_nfs4_copy_acl.c b/libacl/acl_nfs4_copy_acl.c
1496 new file mode 100644
1497 index 0000000..4ce63f7
1498 --- /dev/null
1499 +++ b/libacl/acl_nfs4_copy_acl.c
1500 @@ -0,0 +1,85 @@
1501 +/*
1502 + *  NFSv4 ACL Code
1503 + *  Deep copy an NFS4 ACL
1504 + *
1505 + *  Copyright (c) 2002, 2003 The Regents of the University of Michigan.
1506 + *  All rights reserved.
1507 + *
1508 + *  Nathaniel Gallaher <ngallahe@umich.edu>
1509 + *
1510 + *  Redistribution and use in source and binary forms, with or without
1511 + *  modification, are permitted provided that the following conditions
1512 + *  are met:
1513 + *
1514 + *  1. Redistributions of source code must retain the above copyright
1515 + *     notice, this list of conditions and the following disclaimer.
1516 + *  2. Redistributions in binary form must reproduce the above copyright
1517 + *     notice, this list of conditions and the following disclaimer in the
1518 + *     documentation and/or other materials provided with the distribution.
1519 + *  3. Neither the name of the University nor the names of its
1520 + *     contributors may be used to endorse or promote products derived
1521 + *     from this software without specific prior written permission.
1522 + *
1523 + *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
1524 + *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
1525 + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1526 + *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1527 + *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1528 + *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1529 + *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
1530 + *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
1531 + *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
1532 + *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1533 + *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1534 + */
1535 +
1536 +#include "libacl_nfs4.h"
1537 +
1538 +struct nfs4_acl * acl_nfs4_copy_acl(struct nfs4_acl * nacl)
1539 +{
1540 +       struct nfs4_acl * new_acl;
1541 +       struct nfs4_ace * ace;
1542 +       u32 nace;
1543 +       u32 num_aces;
1544 +       int result;
1545 +
1546 +       if(nacl == NULL) {
1547 +               errno = EINVAL;
1548 +               goto failed;
1549 +       }
1550 +
1551 +       num_aces = nacl->naces;
1552 +
1553 +       new_acl = acl_nfs4_new(nacl->is_directory);
1554 +       if(new_acl == NULL)
1555 +               goto failed;
1556 +
1557 +       ace = nacl->ace_head.tqh_first;
1558 +       nace = 1;
1559 +
1560 +       while(1)
1561 +       {
1562 +               if(ace == NULL) {
1563 +                       if(nace > num_aces)
1564 +                               break;
1565 +                       else
1566 +                               goto free_failed;
1567 +               }
1568 +
1569 +               result = acl_nfs4_add_ace(new_acl, ace->type, ace->flag,
1570 +                               ace->access_mask, acl_nfs4_get_whotype(ace->who), ace->who);
1571 +               if(result < 0)
1572 +                       goto free_failed;
1573 +
1574 +               ace = ace->l_ace.tqe_next;
1575 +               nace++;
1576 +       }
1577 +
1578 +       return new_acl;
1579 +
1580 +free_failed:
1581 +       acl_nfs4_free(new_acl);
1582 +
1583 +failed:
1584 +       return NULL;
1585 +}
1586 diff --git a/libacl/acl_nfs4_free.c b/libacl/acl_nfs4_free.c
1587 new file mode 100644
1588 index 0000000..9cab808
1589 --- /dev/null
1590 +++ b/libacl/acl_nfs4_free.c
1591 @@ -0,0 +1,61 @@
1592 +/*
1593 + *  Copyright (c) 2004 The Regents of the University of Michigan.
1594 + *  All rights reserved.
1595 + *
1596 + *  Marius Aamodt Eriksen <marius@umich.edu>
1597 + *  J. Bruce Fields <bfields@umich.edu>
1598 + *  Nathaniel Gallaher <ngallahe@umich.edu>
1599 + *  Jeff Sedlak <jsedlak@umich.edu>
1600 + *
1601 + *  Redistribution and use in source and binary forms, with or without
1602 + *  modification, are permitted provided that the following conditions
1603 + *  are met:
1604 + *
1605 + *  1. Redistributions of source code must retain the above copyright
1606 + *     notice, this list of conditions, the following disclaimer, and
1607 + *     any and all other licensing or copyright notices included in
1608 + *     any files in this distribution.
1609 + *  2. Redistributions in binary form must reproduce the above copyright
1610 + *     notice, this list of conditions and the following disclaimer in the
1611 + *     documentation and/or other materials provided with the distribution.
1612 + *  3. Neither the name of the University nor the names of its
1613 + *     contributors may be used to endorse or promote products derived
1614 + *     from this software without specific prior written permission.
1615 + *
1616 + *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
1617 + *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
1618 + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1619 + *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1620 + *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1621 + *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1622 + *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
1623 + *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
1624 + *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
1625 + *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1626 + *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1627 + *
1628 + */
1629 +
1630 +#include "libacl_nfs4.h"
1631 +
1632 +void
1633 +acl_nfs4_free(struct nfs4_acl *acl)
1634 +{
1635 +       struct nfs4_ace *ace;
1636 +
1637 +       if (!acl)
1638 +               return;
1639 +
1640 +       while (!TAILQ_IS_EMPTY(acl->ace_head)) {
1641 +               ace = (acl)->ace_head.tqh_first;
1642 +
1643 +               TAILQ_REMOVE( &(acl->ace_head), ace, l_ace);
1644 +               free(ace->who);
1645 +               free(ace);
1646 +       }
1647 +
1648 +       free(acl);
1649 +
1650 +       return;
1651 +}
1652 +
1653 diff --git a/libacl/acl_nfs4_get_who.c b/libacl/acl_nfs4_get_who.c
1654 new file mode 100644
1655 index 0000000..8c21b16
1656 --- /dev/null
1657 +++ b/libacl/acl_nfs4_get_who.c
1658 @@ -0,0 +1,103 @@
1659 +/*
1660 + *  NFSv4 ACL Code
1661 + *  Read the who value from the ace and return its type and optionally
1662 + *  its value.
1663 + *
1664 + *  Ace is a reference to the ace to extract the who value from.
1665 + *  Type is a reference where the value of the whotype will be stored.
1666 + *  Who is a double reference that should either be passed as NULL
1667 + *  (and thus no who string will be returned) or as a pointer to a
1668 + *  char* where the who string will be allocated. This string must be
1669 + *  freed by the caller.
1670 + *
1671 + *  Copyright (c) 2002, 2003 The Regents of the University of Michigan.
1672 + *  All rights reserved.
1673 + *
1674 + *  Nathaniel Gallaher <ngallahe@umich.edu>
1675 + *
1676 + *  Redistribution and use in source and binary forms, with or without
1677 + *  modification, are permitted provided that the following conditions
1678 + *  are met:
1679 + *
1680 + *  1. Redistributions of source code must retain the above copyright
1681 + *     notice, this list of conditions and the following disclaimer.
1682 + *  2. Redistributions in binary form must reproduce the above copyright
1683 + *     notice, this list of conditions and the following disclaimer in the
1684 + *     documentation and/or other materials provided with the distribution.
1685 + *  3. Neither the name of the University nor the names of its
1686 + *     contributors may be used to endorse or promote products derived
1687 + *     from this software without specific prior written permission.
1688 + *
1689 + *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
1690 + *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
1691 + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1692 + *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1693 + *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1694 + *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1695 + *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
1696 + *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
1697 + *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
1698 + *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1699 + *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1700 + */
1701 +
1702 +#include "libacl_nfs4.h"
1703 +
1704 +int acl_nfs4_get_who(struct nfs4_ace* ace, int* type, char** who)
1705 +{
1706 +       int itype;
1707 +       char* iwho = NULL;
1708 +       int wholen;
1709 +
1710 +       if(ace == NULL || ace->who == NULL)
1711 +               goto inval_failed;
1712 +
1713 +       itype = acl_nfs4_get_whotype(ace->who);
1714 +
1715 +       if(type != NULL) {
1716 +               *type = itype;
1717 +       }
1718 +
1719 +
1720 +       if(who == NULL)
1721 +               return 0;
1722 +
1723 +       switch(itype)
1724 +       {
1725 +               case NFS4_ACL_WHO_NAMED:
1726 +                       iwho = ace->who;
1727 +                       break;
1728 +               case NFS4_ACL_WHO_OWNER:
1729 +                       iwho = NFS4_ACL_WHO_OWNER_STRING;
1730 +                       break;
1731 +               case NFS4_ACL_WHO_GROUP:
1732 +                       iwho = NFS4_ACL_WHO_GROUP_STRING;
1733 +                       break;
1734 +               case NFS4_ACL_WHO_EVERYONE:
1735 +                       iwho = NFS4_ACL_WHO_EVERYONE_STRING;
1736 +                       break;
1737 +               default:
1738 +                       goto inval_failed;
1739 +       }
1740 +
1741 +       wholen = strlen(iwho);
1742 +       if(wholen < 0)
1743 +               goto inval_failed;
1744 +
1745 +       (*who) = (char *) malloc(sizeof(char) * (wholen + 1));
1746 +       if((*who) == NULL) {
1747 +               errno = ENOMEM;
1748 +               goto failed;
1749 +       }
1750 +
1751 +       strcpy((*who), iwho);
1752 +
1753 +       return 0;
1754 +
1755 +inval_failed:
1756 +       errno = EINVAL;
1757 +
1758 +failed:
1759 +       return -1;
1760 +}
1761 +
1762 diff --git a/libacl/acl_nfs4_get_whotype.c b/libacl/acl_nfs4_get_whotype.c
1763 new file mode 100644
1764 index 0000000..10574f8
1765 --- /dev/null
1766 +++ b/libacl/acl_nfs4_get_whotype.c
1767 @@ -0,0 +1,60 @@
1768 +/*
1769 + *  NFSv4 ACL Code
1770 + *  Get the whotype of the who string passed
1771 + *
1772 + *  Copyright (c) 2002, 2003 The Regents of the University of Michigan.
1773 + *  All rights reserved.
1774 + *
1775 + *  Marius Aamodt Eriksen <marius@umich.edu>
1776 + *  J. Bruce Fields <bfields@umich.edu>
1777 + *  Nathaniel Gallaher <ngallahe@umich.edu>
1778 + *  Jeff Sedlak <jsedlak@umich.edu>
1779 + *
1780 + *  Redistribution and use in source and binary forms, with or without
1781 + *  modification, are permitted provided that the following conditions
1782 + *  are met:
1783 + *
1784 + *  1. Redistributions of source code must retain the above copyright
1785 + *     notice, this list of conditions and the following disclaimer.
1786 + *  2. Redistributions in binary form must reproduce the above copyright
1787 + *     notice, this list of conditions and the following disclaimer in the
1788 + *     documentation and/or other materials provided with the distribution.
1789 + *  3. Neither the name of the University nor the names of its
1790 + *     contributors may be used to endorse or promote products derived
1791 + *     from this software without specific prior written permission.
1792 + *
1793 + *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
1794 + *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
1795 + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1796 + *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1797 + *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1798 + *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1799 + *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
1800 + *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
1801 + *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
1802 + *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1803 + *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1804 + */
1805 +
1806 +#include "libacl_nfs4.h"
1807 +
1808 +inline int
1809 +acl_nfs4_get_whotype(char *p)
1810 +{
1811 +       if(0 == strcmp(p, NFS4_ACL_WHO_OWNER_STRING) &&
1812 +                       strlen(p) == strlen(NFS4_ACL_WHO_OWNER_STRING)) {
1813 +               return NFS4_ACL_WHO_OWNER;
1814 +       }
1815 +       if(0 == strcmp(p, NFS4_ACL_WHO_GROUP_STRING) &&
1816 +                       strlen(p) == strlen(NFS4_ACL_WHO_GROUP_STRING)) {
1817 +               return NFS4_ACL_WHO_GROUP;
1818 +       }
1819 +       if(0 == strcmp(p, NFS4_ACL_WHO_EVERYONE_STRING) &&
1820 +                       strlen(p) == strlen(NFS4_ACL_WHO_EVERYONE_STRING)) {
1821 +               return NFS4_ACL_WHO_EVERYONE;
1822 +       }
1823 +
1824 +       return NFS4_ACL_WHO_NAMED;
1825 +}
1826 +
1827 +
1828 diff --git a/libacl/acl_nfs4_new.c b/libacl/acl_nfs4_new.c
1829 new file mode 100644
1830 index 0000000..658a282
1831 --- /dev/null
1832 +++ b/libacl/acl_nfs4_new.c
1833 @@ -0,0 +1,58 @@
1834 +/*
1835 + *  Common NFSv4 ACL handling code.
1836 + *  Create a new NFSv4 ACL
1837 + *
1838 + *  Copyright (c) 2002, 2003 The Regents of the University of Michigan.
1839 + *  All rights reserved.
1840 + *
1841 + *  Marius Aamodt Eriksen <marius@umich.edu>
1842 + *  J. Bruce Fields <bfields@umich.edu>
1843 + *  Nathaniel Gallaher <ngallahe@umich.edu>
1844 + *  Jeff Sedlak <jsedlak@umich.edu>
1845 + *
1846 + *  Redistribution and use in source and binary forms, with or without
1847 + *  modification, are permitted provided that the following conditions
1848 + *  are met:
1849 + *
1850 + *  1. Redistributions of source code must retain the above copyright
1851 + *     notice, this list of conditions and the following disclaimer.
1852 + *  2. Redistributions in binary form must reproduce the above copyright
1853 + *     notice, this list of conditions and the following disclaimer in the
1854 + *     documentation and/or other materials provided with the distribution.
1855 + *  3. Neither the name of the University nor the names of its
1856 + *     contributors may be used to endorse or promote products derived
1857 + *     from this software without specific prior written permission.
1858 + *
1859 + *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
1860 + *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
1861 + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1862 + *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1863 + *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1864 + *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1865 + *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
1866 + *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
1867 + *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
1868 + *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1869 + *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1870 + */
1871 +
1872 +
1873 +
1874 +#include "libacl_nfs4.h"
1875 +
1876 +struct nfs4_acl *
1877 +acl_nfs4_new(u32 is_dir)
1878 +{
1879 +       struct nfs4_acl *acl;
1880 +
1881 +       if ((acl = malloc(sizeof(*acl))) == NULL)
1882 +               return NULL;
1883 +
1884 +       acl->naces = 0;
1885 +       acl->is_directory = is_dir;
1886 +
1887 +       TAILQ_INIT(&acl->ace_head);
1888 +
1889 +       return acl;
1890 +}
1891 +
1892 diff --git a/libacl/acl_nfs4_remove_ace.c b/libacl/acl_nfs4_remove_ace.c
1893 new file mode 100644
1894 index 0000000..f7dbba2
1895 --- /dev/null
1896 +++ b/libacl/acl_nfs4_remove_ace.c
1897 @@ -0,0 +1,48 @@
1898 +/*
1899 + *  NFSv4 ACL Code
1900 + *  Remove an ace from an NFS4 ACL
1901 + *
1902 + *  Copyright (c) 2004 The Regents of the University of Michigan.
1903 + *  All rights reserved.
1904 + *
1905 + *  Nathaniel Gallaher <ngallahe@umich.edu>
1906 + *
1907 + *  Redistribution and use in source and binary forms, with or without
1908 + *  modification, are permitted provided that the following conditions
1909 + *  are met:
1910 + *
1911 + *  1. Redistributions of source code must retain the above copyright
1912 + *     notice, this list of conditions, the following disclaimer, and
1913 + *     any and all other licensing or copyright notices included in
1914 + *     any files in this distribution.
1915 + *  2. Redistributions in binary form must reproduce the above copyright
1916 + *     notice, this list of conditions and the following disclaimer in the
1917 + *     documentation and/or other materials provided with the distribution.
1918 + *  3. Neither the name of the University nor the names of its
1919 + *     contributors may be used to endorse or promote products derived
1920 + *     from this software without specific prior written permission.
1921 + *
1922 + *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
1923 + *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
1924 + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1925 + *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1926 + *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1927 + *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1928 + *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
1929 + *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
1930 + *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
1931 + *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1932 + *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1933 + *
1934 + */
1935 +
1936 +#include "libacl_nfs4.h"
1937 +
1938 +void acl_nfs4_remove_ace(struct nfs4_acl * acl, struct nfs4_ace * ace)
1939 +{
1940 +       TAILQ_REMOVE(&acl->ace_head, ace, l_ace);
1941 +       free(ace->who);
1942 +       free(ace);
1943 +       acl->naces--;
1944 +}
1945 +
1946 diff --git a/libacl/acl_nfs4_set_who.c b/libacl/acl_nfs4_set_who.c
1947 new file mode 100644
1948 index 0000000..c0ddfa7
1949 --- /dev/null
1950 +++ b/libacl/acl_nfs4_set_who.c
1951 @@ -0,0 +1,92 @@
1952 +/*
1953 + *  NFSv4 ACL Code
1954 + *  Write the who entry in the nfs4 ace. Who is a user supplied buffer
1955 + *  containing a named who entry (null terminated string) if type is
1956 + *  set to NFS4_ACL_WHO_NAMED. Otherwise, the who buffer is not used.
1957 + *  The user supplied who buffer must be freed by the caller.
1958 + *
1959 + *  This code allocates the who buffer used in the ace. This must be freed
1960 + *  upon ace removal by the ace_remove or acl_free.
1961 + *
1962 + *  Copyright (c) 2002, 2003 The Regents of the University of Michigan.
1963 + *  All rights reserved.
1964 + *
1965 + *  Nathaniel Gallaher <ngallahe@umich.edu>
1966 + *
1967 + *  Redistribution and use in source and binary forms, with or without
1968 + *  modification, are permitted provided that the following conditions
1969 + *  are met:
1970 + *
1971 + *  1. Redistributions of source code must retain the above copyright
1972 + *     notice, this list of conditions and the following disclaimer.
1973 + *  2. Redistributions in binary form must reproduce the above copyright
1974 + *     notice, this list of conditions and the following disclaimer in the
1975 + *     documentation and/or other materials provided with the distribution.
1976 + *  3. Neither the name of the University nor the names of its
1977 + *     contributors may be used to endorse or promote products derived
1978 + *     from this software without specific prior written permission.
1979 + *
1980 + *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
1981 + *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
1982 + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1983 + *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1984 + *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1985 + *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1986 + *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
1987 + *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
1988 + *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
1989 + *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1990 + *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1991 + */
1992 +
1993 +#include "libacl_nfs4.h"
1994 +
1995 +int acl_nfs4_set_who(struct nfs4_ace* ace, int type, char* who)
1996 +{
1997 +       char* iwho = NULL;
1998 +       int wholen;
1999 +
2000 +       if(ace == NULL)
2001 +               goto inval_failed;
2002 +
2003 +       switch(type)
2004 +       {
2005 +               case NFS4_ACL_WHO_NAMED:
2006 +                       if(who == NULL)
2007 +                               goto inval_failed;
2008 +                       iwho = who;
2009 +                       break;
2010 +               case NFS4_ACL_WHO_OWNER:
2011 +                       iwho = NFS4_ACL_WHO_OWNER_STRING;
2012 +                       break;
2013 +               case NFS4_ACL_WHO_GROUP:
2014 +                       iwho = NFS4_ACL_WHO_GROUP_STRING;
2015 +                       break;
2016 +               case NFS4_ACL_WHO_EVERYONE:
2017 +                       iwho = NFS4_ACL_WHO_EVERYONE_STRING;
2018 +                       break;
2019 +               default:
2020 +                       goto inval_failed;
2021 +       }
2022 +
2023 +       wholen = strlen(iwho);
2024 +       if(wholen < 1)
2025 +               goto inval_failed;
2026 +
2027 +       ace->who = (char *) malloc(sizeof(char) * (wholen + 1));
2028 +       if(ace->who == NULL) {
2029 +               errno = ENOMEM;
2030 +               goto failed;
2031 +       }
2032 +
2033 +       strcpy(ace->who, iwho);
2034 +
2035 +       return 0;
2036 +
2037 +inval_failed:
2038 +       errno = EINVAL;
2039 +
2040 +failed:
2041 +       return -1;
2042 +}
2043 +
2044 diff --git a/libacl/acl_nfs4_xattr_load.c b/libacl/acl_nfs4_xattr_load.c
2045 new file mode 100644
2046 index 0000000..e045cd2
2047 --- /dev/null
2048 +++ b/libacl/acl_nfs4_xattr_load.c
2049 @@ -0,0 +1,191 @@
2050 +/*
2051 + *  NFSv4 ACL Code
2052 + *  Convert NFSv4 xattr values to a posix ACL
2053 + *
2054 + *  Copyright (c) 2002, 2003 The Regents of the University of Michigan.
2055 + *  All rights reserved.
2056 + *
2057 + *  Nathaniel Gallaher <ngallahe@umich.edu>
2058 + *
2059 + *  Redistribution and use in source and binary forms, with or without
2060 + *  modification, are permitted provided that the following conditions
2061 + *  are met:
2062 + *
2063 + *  1. Redistributions of source code must retain the above copyright
2064 + *     notice, this list of conditions and the following disclaimer.
2065 + *  2. Redistributions in binary form must reproduce the above copyright
2066 + *     notice, this list of conditions and the following disclaimer in the
2067 + *     documentation and/or other materials provided with the distribution.
2068 + *  3. Neither the name of the University nor the names of its
2069 + *     contributors may be used to endorse or promote products derived
2070 + *     from this software without specific prior written permission.
2071 + *
2072 + *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
2073 + *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
2074 + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2075 + *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2076 + *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2077 + *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2078 + *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
2079 + *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
2080 + *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
2081 + *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2082 + *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2083 + */
2084 +
2085 +
2086 +#include <acl/libacl.h>
2087 +#include <netinet/in.h>
2088 +#include "libacl_nfs4.h"
2089 +
2090 +
2091 +struct nfs4_acl * acl_nfs4_xattr_load(
2092 +               char *  xattr_v,
2093 +               int             xattr_size,
2094 +               u32             is_dir)
2095 +{
2096 +       struct nfs4_acl *       nacl_p;
2097 +       char* bufp = xattr_v;
2098 +       int bufs = xattr_size;
2099 +       u32 ace_n;
2100 +       u32     wholen;
2101 +       char* who;
2102 +       int d_ptr;
2103 +       u32 num_aces;
2104 +
2105 +       u32 type, flag, access_mask;
2106 +
2107 +       if(xattr_size < sizeof(u32)) {
2108 +               errno = EINVAL;
2109 +               return NULL;
2110 +       }
2111 +
2112 +       if((nacl_p = acl_nfs4_new(is_dir)) == NULL) {
2113 +               errno = ENOMEM;
2114 +               return NULL;
2115 +       }
2116 +
2117 +       /* Grab the number of aces in the acl */
2118 +       num_aces = (u32)ntohl(*((u32*)(bufp)));
2119 +
2120 +#ifdef LIBACL_NFS4_DEBUG
2121 +       printf(" Got number of aces: %d\n", nacl_p->naces);
2122 +#endif
2123 +
2124 +
2125 +       d_ptr = sizeof(u32);
2126 +       bufp += d_ptr;
2127 +       bufs -= d_ptr;
2128 +
2129 +       for(ace_n = 0; num_aces > ace_n ; ace_n++)
2130 +       {
2131 +#ifdef LIBACL_NFS4_DEBUG
2132 +               printf(" Getting Ace #%d of %d\n", ace_n, num_aces);
2133 +#endif
2134 +               /* Get the acl type */
2135 +               if(bufs <= 0) {
2136 +                       errno = EINVAL;
2137 +                       goto bad_xattr_val;
2138 +               }
2139 +
2140 +               type = (u32)ntohl(*((u32*)bufp));
2141 +#ifdef LIBACL_NFS4_DEBUG
2142 +               printf("  Type: %x\n", type);
2143 +#endif
2144 +
2145 +               d_ptr = sizeof(u32);
2146 +               bufp += d_ptr;
2147 +               bufs -= d_ptr;
2148 +
2149 +               /* Get the acl flag */
2150 +               if(bufs <= 0) {
2151 +                       errno = EINVAL;
2152 +                       goto bad_xattr_val;
2153 +               }
2154 +
2155 +               flag = (u32)ntohl(*((u32*)bufp));
2156 +#ifdef LIBACL_NFS4_DEBUG
2157 +               printf("  Flag: %x\n", flag);
2158 +#endif
2159 +
2160 +               bufp += d_ptr;
2161 +               bufs -= d_ptr;
2162 +
2163 +               /* Get the access mask */
2164 +
2165 +               if(bufs <= 0) {
2166 +                       errno = EINVAL;
2167 +                       goto bad_xattr_val;
2168 +               }
2169 +
2170 +               access_mask = (u32)ntohl(*((u32*)bufp));
2171 +#ifdef LIBACL_NFS4_DEBUG
2172 +               printf("  Access Mask: %x\n", access_mask);
2173 +#endif
2174 +
2175 +               bufp += d_ptr;
2176 +               bufs -= d_ptr;
2177 +
2178 +               /* Get the who string length*/
2179 +               if(bufs <= 0) {
2180 +                       errno = EINVAL;
2181 +                       goto bad_xattr_val;
2182 +               }
2183 +
2184 +               wholen = (u32)ntohl(*((u32*)bufp));
2185 +#ifdef LIBACL_NFS4_DEBUG
2186 +               printf("  Wholen: %d\n", wholen);
2187 +#endif
2188 +
2189 +               bufp += d_ptr;
2190 +               bufs -= d_ptr;
2191 +
2192 +               /* Get the who string */
2193 +               if(bufs <= 0) {
2194 +                       errno = EINVAL;
2195 +                       goto bad_xattr_val;
2196 +               }
2197 +
2198 +               who = (char *) malloc((wholen+1) * sizeof(char));
2199 +               if(who == NULL)
2200 +               {
2201 +                       errno = ENOMEM;
2202 +                       goto bad_xattr_val;
2203 +               }
2204 +
2205 +               memcpy(who, bufp, wholen);
2206 +
2207 +               who[wholen] = '\0';
2208 +
2209 +#ifdef LIBACL_NFS4_DEBUG
2210 +               printf("  Who: %s\n", who);
2211 +#endif
2212 +
2213 +               d_ptr = ((wholen / sizeof(u32))*sizeof(u32));
2214 +               if(wholen % sizeof(u32) != 0)
2215 +                       d_ptr += sizeof(u32);
2216 +
2217 +               bufp += d_ptr;
2218 +               bufs -= d_ptr;
2219 +
2220 +               /* Make sure we aren't outside our domain */
2221 +               if(bufs < 0) {
2222 +                       free(who);
2223 +                       goto bad_xattr_val;
2224 +               }
2225 +
2226 +               if(acl_nfs4_add_ace(nacl_p, type, flag, access_mask, acl_nfs4_get_whotype(who), who) < 0) {
2227 +                       free(who);
2228 +                       goto bad_xattr_val;
2229 +               }
2230 +
2231 +               free(who);
2232 +       }
2233 +
2234 +       return nacl_p;
2235 +
2236 +bad_xattr_val:
2237 +       /* We bailed for some reason */
2238 +       acl_nfs4_free(nacl_p);
2239 +       return NULL;
2240 +}
2241 diff --git a/libacl/acl_nfs4_xattr_pack.c b/libacl/acl_nfs4_xattr_pack.c
2242 new file mode 100644
2243 index 0000000..6274f48
2244 --- /dev/null
2245 +++ b/libacl/acl_nfs4_xattr_pack.c
2246 @@ -0,0 +1,148 @@
2247 +/*
2248 + *  NFSv4 ACL Code
2249 + *  Pack an NFS4 ACL into an XDR encoded buffer.
2250 + *
2251 + *  Copyright (c) 2002, 2003 The Regents of the University of Michigan.
2252 + *  All rights reserved.
2253 + *
2254 + *  Nathaniel Gallaher <ngallahe@umich.edu>
2255 + *
2256 + *  Redistribution and use in source and binary forms, with or without
2257 + *  modification, are permitted provided that the following conditions
2258 + *  are met:
2259 + *
2260 + *  1. Redistributions of source code must retain the above copyright
2261 + *     notice, this list of conditions and the following disclaimer.
2262 + *  2. Redistributions in binary form must reproduce the above copyright
2263 + *     notice, this list of conditions and the following disclaimer in the
2264 + *     documentation and/or other materials provided with the distribution.
2265 + *  3. Neither the name of the University nor the names of its
2266 + *     contributors may be used to endorse or promote products derived
2267 + *     from this software without specific prior written permission.
2268 + *
2269 + *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
2270 + *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
2271 + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2272 + *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2273 + *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2274 + *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2275 + *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
2276 + *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
2277 + *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
2278 + *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2279 + *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2280 + */
2281 +
2282 +#include <libacl_nfs4.h>
2283 +#include <netinet/in.h>
2284 +
2285 +int acl_nfs4_xattr_pack(struct nfs4_acl * acl, char** bufp)
2286 +{
2287 +       struct nfs4_ace * ace;
2288 +       int buflen;
2289 +       int rbuflen;
2290 +       int num_aces;
2291 +       int ace_num;
2292 +       int wholen;
2293 +       int result;
2294 +       char* p;
2295 +       char* who;
2296 +
2297 +       if(acl == NULL || bufp == NULL)
2298 +       {
2299 +               errno = EINVAL;
2300 +               goto failed;
2301 +       }
2302 +
2303 +       buflen = acl_nfs4_xattr_size(acl);
2304 +       if(buflen < 0)
2305 +       {
2306 +               goto failed;
2307 +       }
2308 +
2309 +       *bufp = (char*) malloc(buflen);
2310 +       if(*bufp == NULL) {
2311 +               errno = ENOMEM;
2312 +               goto failed;
2313 +       }
2314 +
2315 +       p = *bufp;
2316 +
2317 +       num_aces = acl->naces;
2318 +
2319 +       *((u32*)p) = htonl(num_aces);
2320 +
2321 +       rbuflen = sizeof(u32);
2322 +       p += sizeof(u32);
2323 +
2324 +       ace = acl->ace_head.tqh_first;
2325 +       ace_num = 1;
2326 +
2327 +       while(1)
2328 +       {
2329 +               if(ace == NULL)
2330 +               {
2331 +                       if(ace_num > num_aces) {
2332 +                               break;
2333 +                       } else {
2334 +                               errno = ENODATA;
2335 +                               goto failed;
2336 +                       }
2337 +               }
2338 +
2339 +               *((u32*)p) = htonl(ace->type);
2340 +               p += sizeof(u32);
2341 +               rbuflen += sizeof(u32);
2342 +
2343 +               *((u32*)p) = htonl(ace->flag);
2344 +               p += sizeof(u32);
2345 +               rbuflen += sizeof(u32);
2346 +
2347 +               *((u32*)p) = htonl(ace->access_mask);
2348 +               p += sizeof(u32);
2349 +               rbuflen += sizeof(u32);
2350 +
2351 +               result = acl_nfs4_get_who(ace, NULL, &who);
2352 +               if(result < 0) {
2353 +                       goto free_failed;
2354 +               }
2355 +
2356 +               wholen = strlen(who);
2357 +               *((u32*)p) = htonl(wholen);
2358 +               rbuflen += sizeof(u32);
2359 +
2360 +               p += sizeof(u32);
2361 +
2362 +               memcpy(p, who, wholen);
2363 +               free(who);
2364 +
2365 +               p += (wholen / NFS4_XDR_MOD) * NFS4_XDR_MOD;
2366 +               if(wholen % NFS4_XDR_MOD) {
2367 +                       p += NFS4_XDR_MOD;
2368 +               }
2369 +
2370 +               rbuflen += (wholen / NFS4_XDR_MOD) * NFS4_XDR_MOD;
2371 +               if(wholen % NFS4_XDR_MOD) {
2372 +                       rbuflen += NFS4_XDR_MOD;
2373 +               }
2374 +
2375 +               ace = ace->l_ace.tqe_next;
2376 +               ace_num++;
2377 +       }
2378 +
2379 +       if (buflen != rbuflen)
2380 +       {
2381 +               goto free_failed;
2382 +       }
2383 +       return buflen;
2384 +
2385 +free_failed:
2386 +       free(*bufp);
2387 +       *bufp = NULL;
2388 +
2389 +failed:
2390 +       return -1;
2391 +}
2392 +
2393 +
2394 +
2395 diff --git a/libacl/acl_nfs4_xattr_size.c b/libacl/acl_nfs4_xattr_size.c
2396 new file mode 100644
2397 index 0000000..a20b5d6
2398 --- /dev/null
2399 +++ b/libacl/acl_nfs4_xattr_size.c
2400 @@ -0,0 +1,91 @@
2401 +/*
2402 + *  NFSv4 ACL Code
2403 + *  Return the expected xattr XDR encoded size of the nfs acl. Used for
2404 + *  figuring the size of the xattr buffer.
2405 + *
2406 + *  Copyright (c) 2002, 2003 The Regents of the University of Michigan.
2407 + *  All rights reserved.
2408 + *
2409 + *  Nathaniel Gallaher <ngallahe@umich.edu>
2410 + *
2411 + *  Redistribution and use in source and binary forms, with or without
2412 + *  modification, are permitted provided that the following conditions
2413 + *  are met:
2414 + *
2415 + *  1. Redistributions of source code must retain the above copyright
2416 + *     notice, this list of conditions and the following disclaimer.
2417 + *  2. Redistributions in binary form must reproduce the above copyright
2418 + *     notice, this list of conditions and the following disclaimer in the
2419 + *     documentation and/or other materials provided with the distribution.
2420 + *  3. Neither the name of the University nor the names of its
2421 + *     contributors may be used to endorse or promote products derived
2422 + *     from this software without specific prior written permission.
2423 + *
2424 + *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
2425 + *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
2426 + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2427 + *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2428 + *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2429 + *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2430 + *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
2431 + *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
2432 + *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
2433 + *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2434 + *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2435 + */
2436 +
2437 +#include <libacl_nfs4.h>
2438 +
2439 +int acl_nfs4_xattr_size(struct nfs4_acl * acl)
2440 +{
2441 +       int size = 0;
2442 +       struct nfs4_ace * ace;
2443 +       int ace_num;
2444 +       int num_aces;
2445 +
2446 +       if(acl == NULL) {
2447 +               errno = EINVAL;
2448 +               goto failed;
2449 +       }
2450 +
2451 +       /* Space for number of aces */
2452 +       size += sizeof(u32);
2453 +
2454 +       ace = acl->ace_head.tqh_first;
2455 +       ace_num = 1;
2456 +
2457 +       num_aces = acl->naces;
2458 +
2459 +       while(1)
2460 +       {
2461 +               if(ace == NULL) {
2462 +                       if(ace_num > num_aces) {
2463 +                               break;
2464 +                       } else {
2465 +                               errno = ENODATA;
2466 +                               goto failed;
2467 +                       }
2468 +               }
2469 +
2470 +               /* space for type, flag, and mask */
2471 +               size += (3 * sizeof(u32));
2472 +
2473 +               /* space for strlen */
2474 +               size += sizeof(u32);
2475 +
2476 +               /* space for the who string... xdr encoded */
2477 +               size += (strlen(ace->who) / NFS4_XDR_MOD) * NFS4_XDR_MOD * sizeof(char);
2478 +               if(strlen(ace->who) % NFS4_XDR_MOD) {
2479 +                       size += NFS4_XDR_MOD;
2480 +               }
2481 +
2482 +               ace = ace->l_ace.tqe_next;
2483 +               ace_num++;
2484 +       }
2485 +
2486 +       return size;
2487 +
2488 +failed:
2489 +       return -1;
2490 +}
2491 +
2492 diff --git a/libacl/acl_ptn4_acl_trans.c b/libacl/acl_ptn4_acl_trans.c
2493 new file mode 100644
2494 index 0000000..4dbd4c5
2495 --- /dev/null
2496 +++ b/libacl/acl_ptn4_acl_trans.c
2497 @@ -0,0 +1,509 @@
2498 +/*
2499 + *  NFSv4 ACL Code
2500 + *  Convert a posix ACL to an NFSv4 ACL
2501 + *
2502 + *  Copyright (c) 2002, 2003 The Regents of the University of Michigan.
2503 + *  All rights reserved.
2504 + *
2505 + *  Nathaniel Gallaher <ngallahe@umich.edu>
2506 + *  J. Bruce Fields <bfields@umich.edu>
2507 + *
2508 + *  Redistribution and use in source and binary forms, with or without
2509 + *  modification, are permitted provided that the following conditions
2510 + *  are met:
2511 + *
2512 + *  1. Redistributions of source code must retain the above copyright
2513 + *     notice, this list of conditions and the following disclaimer.
2514 + *  2. Redistributions in binary form must reproduce the above copyright
2515 + *     notice, this list of conditions and the following disclaimer in the
2516 + *     documentation and/or other materials provided with the distribution.
2517 + *  3. Neither the name of the University nor the names of its
2518 + *     contributors may be used to endorse or promote products derived
2519 + *     from this software without specific prior written permission.
2520 + *
2521 + *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
2522 + *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
2523 + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2524 + *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2525 + *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2526 + *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2527 + *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
2528 + *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
2529 + *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
2530 + *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2531 + *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2532 + */
2533 +
2534 +#include <acl/libacl.h>
2535 +#include <nfsidmap.h>
2536 +#include "libacl_nfs4.h"
2537 +
2538 +
2539 +#define FILE_OR_DIR_INHERIT (NFS4_ACE_FILE_INHERIT_ACE \
2540 +               | NFS4_ACE_DIRECTORY_INHERIT_ACE)
2541 +#define NFS4_INHERITANCE_FLAGS (FILE_OR_DIR_INHERIT | NFS4_ACE_INHERIT_ONLY_ACE)
2542 +
2543 +/* Plan:
2544 + * 1: if setting default, remove all purely inherited aces, and replace
2545 + *    all dual-use aces by purely effective aces
2546 + * 2: if setting effective, remove all purely effective aces, and replace
2547 + *    all dual-use aces by purely inherited ones
2548 + */
2549 +static void purge_aces(struct nfs4_acl *nacl, acl_type_t type)
2550 +{
2551 +       struct nfs4_ace *p, *next;
2552 +
2553 +       for (p = nacl->ace_head.tqh_first; p != NULL; p = next) {
2554 +               next = p->l_ace.tqe_next;
2555 +
2556 +               if (!(p->flag & FILE_OR_DIR_INHERIT)) {
2557 +                       /* purely effective */
2558 +                       if (type == ACL_TYPE_ACCESS)
2559 +                               acl_nfs4_remove_ace(nacl, p);
2560 +               } else if (p->flag & NFS4_ACE_INHERIT_ONLY_ACE) {
2561 +                       /* purely inherited */
2562 +                       if (type == ACL_TYPE_DEFAULT)
2563 +                               acl_nfs4_remove_ace(nacl, p);
2564 +               } else {
2565 +                       /* both effective and inherited */
2566 +                       if (type == ACL_TYPE_DEFAULT) {
2567 +                               /* Change to purely effective */
2568 +                               p->flag &= ~NFS4_INHERITANCE_FLAGS;
2569 +                       } else { /* ACL_TYPE_ACCESS */
2570 +                               /* Change to purely inherited */
2571 +                               p->flag |= NFS4_INHERITANCE_FLAGS;
2572 +                       }
2573 +               }
2574 +
2575 +       }
2576 +}
2577
2578 +int
2579 +acl_ptn4_acl_trans(acl_t pacl, struct nfs4_acl *acl, acl_type_t type, u32 is_dir, char *nfs_domain)
2580 +{
2581 +       int eflag;
2582 +       u32 mask, mask_mask = 0;
2583 +       int num_aces;
2584 +       int result, result2;
2585 +       u32 iflags = NFS4_ACL_NOFLAGS;
2586 +       int allocated = 0;
2587 +
2588 +       acl_entry_t pace_p;
2589 +       acl_tag_t ace_type;
2590 +       acl_permset_t perms;
2591 +
2592 +       char who_buf_static[NFS4_ACL_WHO_BUFFER_LEN_GUESS];
2593 +       char *who_buf = NULL;
2594 +       int who_buflen;
2595 +       int who_buflen_static = NFS4_ACL_WHO_BUFFER_LEN_GUESS;
2596 +       uid_t * uid_p;
2597 +       gid_t * gid_p;
2598 +
2599 +       eflag = 0;
2600 +
2601 +       if (type == ACL_TYPE_DEFAULT) {
2602 +               eflag = NFS4_INHERITANCE_FLAGS;
2603 +               iflags |= NFS4_ACL_REQUEST_DEFAULT;
2604 +       }
2605 +
2606 +       purge_aces(acl, type);
2607 +
2608 +       if (is_dir & NFS4_ACL_ISDIR)
2609 +               iflags |= NFS4_ACL_ISDIR;
2610 +
2611 +
2612 +       if (pacl == NULL || (acl_valid(pacl) < 0 || acl_entries(pacl) == 0)) {
2613 +               errno = EINVAL;
2614 +               goto out;
2615 +       }
2616 +
2617 +       /* Start Conversion */
2618 +
2619 +       /* 3 aces minimum (mode bits) */
2620 +       num_aces = acl_entries(pacl);
2621 +       if (num_aces < 3) {
2622 +               errno = EINVAL;
2623 +               goto out;
2624 +       }
2625 +
2626 +       /* Get the mask entry */
2627 +
2628 +       result = acl_get_entry(pacl, ACL_FIRST_ENTRY, &pace_p);
2629 +       if (result < 0)
2630 +               goto out;
2631 +
2632 +       while (result > 0 && mask_mask == 0) {
2633 +               result = acl_get_tag_type(pace_p, &ace_type);
2634 +               if (result < 0)
2635 +                       goto out;
2636 +
2637 +               if (ace_type == ACL_MASK) {
2638 +                       result = acl_get_permset(pace_p, &perms);
2639 +                       if(result < 0)
2640 +                               goto out;
2641 +
2642 +                       result = acl_ptn4_get_mask(&mask_mask, perms, iflags);
2643 +                       if(result < 0)
2644 +                               goto out;
2645 +
2646 +                       mask_mask = ~mask_mask;
2647 +               }
2648 +
2649 +               result = acl_get_entry(pacl, ACL_NEXT_ENTRY, &pace_p);
2650 +               if (result < 0)
2651 +                       goto out;
2652 +       }
2653 +
2654 +       /* Get the file owner entry */
2655 +       result = acl_get_entry(pacl, ACL_FIRST_ENTRY, &pace_p);
2656 +       if (result < 0)
2657 +               goto out;
2658 +
2659 +       result = acl_get_tag_type(pace_p, &ace_type);
2660 +       if (result < 0)
2661 +               goto out;
2662 +
2663 +       if (ace_type != ACL_USER_OBJ) {
2664 +               errno = EINVAL;
2665 +               goto out;
2666 +       }
2667 +
2668 +       result = acl_get_permset(pace_p, &perms);
2669 +       if (result < 0)
2670 +               goto out;
2671 +
2672 +       result = acl_ptn4_get_mask(&mask, perms, iflags | NFS4_ACL_OWNER);
2673 +       if (result < 0)
2674 +               goto out;
2675 +
2676 +       result = acl_nfs4_add_pair(acl, eflag, mask, NFS4_ACL_WHO_OWNER, NULL);
2677 +
2678 +       if (result < 0)
2679 +               goto out;
2680 +
2681 +       result = acl_get_entry(pacl, ACL_NEXT_ENTRY, &pace_p);
2682 +       if (result < 0)
2683 +               goto out;
2684 +
2685 +       result2 = acl_get_tag_type(pace_p, &ace_type);
2686 +       if (result2 < 0)
2687 +               goto out;
2688 +
2689 +       while (ace_type == ACL_USER && result > 0) {
2690 +               result = acl_get_permset(pace_p, &perms);
2691 +               if (result < 0)
2692 +                       goto out;
2693 +
2694 +               result = acl_ptn4_get_mask(&mask, perms, iflags);
2695 +               if (result < 0)
2696 +                       goto out;
2697 +
2698 +               uid_p = acl_get_qualifier(pace_p);
2699 +
2700 +               who_buf = who_buf_static;
2701 +               who_buflen = who_buflen_static;
2702 +
2703 +               result = nfs4_init_name_mapping(NULL);
2704 +               result = nfs4_uid_to_name(*uid_p, nfs_domain, who_buf, who_buflen);
2705 +
2706 +
2707 +               while (result == -ENOBUFS) {
2708 +                       if (who_buf != who_buf_static)
2709 +                               free(who_buf);
2710 +
2711 +                       /* Increase the size by a full buflen unit */
2712 +                       who_buflen += who_buflen_static;
2713 +                       who_buf = malloc(who_buflen);
2714 +
2715 +                       if (who_buf == NULL) {
2716 +                               result = -ENOMEM;
2717 +                               break;
2718 +                       }
2719 +
2720 +                       result = nfs4_init_name_mapping(NULL);
2721 +                       result = nfs4_uid_to_name(*uid_p, nfs_domain, who_buf, who_buflen);
2722 +
2723 +               }
2724 +               acl_free(uid_p);
2725 +               if (result < 0) {
2726 +                       errno = -result;
2727 +                       goto out;
2728 +               }
2729 +
2730 +               if (who_buf == NULL)
2731 +                       goto out;
2732 +
2733 +               result = acl_nfs4_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
2734 +                               eflag,  mask_mask, NFS4_ACL_WHO_NAMED, who_buf);
2735 +               if (result < 0) {
2736 +                       if(who_buf != who_buf_static)
2737 +                               free(who_buf);
2738 +                       goto out;
2739 +               }
2740 +
2741 +               result = acl_nfs4_add_pair(acl, eflag, mask, NFS4_ACL_WHO_NAMED,
2742 +                               who_buf);
2743 +               if (who_buf != who_buf_static)
2744 +                       free(who_buf);
2745 +               if (result < 0)
2746 +                       goto out;
2747 +
2748 +               result = acl_get_entry(pacl, ACL_NEXT_ENTRY, &pace_p);
2749 +               if (result <= 0)
2750 +                       goto out;
2751 +
2752 +               result2 = acl_get_tag_type(pace_p, &ace_type);
2753 +               if (result2 < 0)
2754 +                       goto out;
2755 +
2756 +       }
2757 +
2758 +       /* In the case of groups, we apply allow ACEs first, then deny ACEs,
2759 +        * since a user can be in more than one group.  */
2760 +
2761 +       /* allow ACEs */
2762 +
2763 +       if (num_aces > 3) {
2764 +               result2 = acl_get_tag_type(pace_p, &ace_type);
2765 +               if (result2 < 0)
2766 +                       goto out;
2767 +
2768 +               if (ace_type != ACL_GROUP_OBJ) {
2769 +                       errno = EINVAL;
2770 +                       goto out;
2771 +               }
2772 +
2773 +               result = acl_nfs4_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
2774 +                               NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask,
2775 +                               NFS4_ACL_WHO_GROUP, NULL);
2776 +
2777 +               if (result < 0)
2778 +                       goto out;
2779 +       }
2780 +
2781 +       result = acl_get_permset(pace_p, &perms);
2782 +       if (result < 0)
2783 +               goto out;
2784 +
2785 +       result = acl_ptn4_get_mask(&mask, perms, iflags);
2786 +       if (result < 0)
2787 +               goto out;
2788 +
2789 +       result = acl_nfs4_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
2790 +                       NFS4_ACE_IDENTIFIER_GROUP | eflag, mask, NFS4_ACL_WHO_GROUP, NULL);
2791 +
2792 +       if (result < 0)
2793 +               goto out;
2794 +
2795 +       result = acl_get_entry(pacl, ACL_NEXT_ENTRY, &pace_p);
2796 +       if (result <= 0)
2797 +               goto out;
2798 +
2799 +       result2 = acl_get_tag_type(pace_p, &ace_type);
2800 +       if (result2 < 0)
2801 +               goto out;
2802 +
2803 +       while (ace_type == ACL_GROUP && result > 0) {
2804 +               result = acl_get_permset(pace_p, &perms);
2805 +               if (result < 0)
2806 +                       goto out;
2807 +
2808 +               result = acl_ptn4_get_mask(&mask, perms, iflags);
2809 +               if (result < 0)
2810 +                       goto out;
2811 +
2812 +               gid_p = acl_get_qualifier(pace_p);
2813 +
2814 +               who_buf = who_buf_static;
2815 +               who_buflen = who_buflen_static;
2816 +
2817 +               result = nfs4_gid_to_name(*gid_p, nfs_domain, who_buf, who_buflen);
2818 +
2819 +
2820 +               while (result == -ENOBUFS) {
2821 +                       if (who_buf != who_buf_static)
2822 +                               free(who_buf);
2823 +
2824 +                       /* Increase the size by a full buflen unit */
2825 +                       who_buflen += who_buflen_static;
2826 +                       who_buf = malloc(who_buflen);
2827 +
2828 +                       if (who_buf == NULL) {
2829 +                               result = -ENOMEM;
2830 +                               break;
2831 +                       }
2832 +
2833 +                       result = nfs4_gid_to_name(*gid_p, nfs_domain, who_buf, who_buflen);
2834 +               }
2835 +
2836 +               acl_free(gid_p);
2837 +
2838 +               if (result < 0) {
2839 +                       errno = -result;
2840 +                       goto out;
2841 +               }
2842 +
2843 +               if (who_buf == NULL)
2844 +                       goto out;
2845 +
2846 +               result = acl_nfs4_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
2847 +                               NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask,
2848 +                               NFS4_ACL_WHO_NAMED, who_buf);
2849 +               if (result < 0) {
2850 +                       if(who_buf != who_buf_static)
2851 +                               free(who_buf);
2852 +                       goto out;
2853 +               }
2854 +
2855 +               result = acl_nfs4_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
2856 +                       NFS4_ACE_IDENTIFIER_GROUP | eflag, mask,
2857 +                               NFS4_ACL_WHO_NAMED, who_buf);
2858 +
2859 +               if (who_buf != who_buf_static)
2860 +                       free(who_buf);
2861 +
2862 +               if (result < 0)
2863 +                       goto out;
2864 +               result = acl_get_entry(pacl, ACL_NEXT_ENTRY, &pace_p);
2865 +               if (result <= 0)
2866 +                       goto out;
2867 +
2868 +               result2 = acl_get_tag_type(pace_p, &ace_type);
2869 +               if (result2 < 0)
2870 +                       goto out;
2871 +       }
2872 +
2873 +       /* deny ACEs */
2874 +
2875 +       result = acl_get_entry(pacl, ACL_FIRST_ENTRY, &pace_p);
2876 +       if (result <= 0)
2877 +               goto out;
2878 +
2879 +       result2 = acl_get_tag_type(pace_p, &ace_type);
2880 +       if (result2 < 0)
2881 +               goto out;
2882 +
2883 +       while (ace_type != ACL_GROUP_OBJ && result > 0) {
2884 +               result = acl_get_entry(pacl, ACL_NEXT_ENTRY, &pace_p);
2885 +               if(result <= 0)
2886 +                       goto out;
2887 +
2888 +               result2 = acl_get_tag_type(pace_p, &ace_type);
2889 +               if(result2 < 0)
2890 +                       goto out;
2891 +       }
2892 +
2893 +       result = acl_get_permset(pace_p, &perms);
2894 +       if (result < 0)
2895 +               goto out;
2896 +
2897 +       result = acl_ptn4_get_mask(&mask, perms, iflags);
2898 +       if (result < 0)
2899 +               goto out;
2900 +
2901 +       result = acl_nfs4_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
2902 +                       NFS4_ACE_IDENTIFIER_GROUP | eflag, ~mask, NFS4_ACL_WHO_GROUP,
2903 +                       NULL);
2904 +
2905 +       if (result < 0)
2906 +               goto out;
2907 +
2908 +       result = acl_get_entry(pacl, ACL_NEXT_ENTRY, &pace_p);
2909 +       if (result <= 0)
2910 +               goto out;
2911 +
2912 +       result2 = acl_get_tag_type(pace_p, &ace_type);
2913 +       if (result2 < 0)
2914 +               goto out;
2915 +
2916 +       while (ace_type == ACL_GROUP && result > 0) {
2917 +               result = acl_get_permset(pace_p, &perms);
2918 +               if (result < 0)
2919 +                       goto out;
2920 +
2921 +               result = acl_ptn4_get_mask(&mask, perms, iflags);
2922 +               if (result < 0)
2923 +                       goto out;
2924 +
2925 +               gid_p = acl_get_qualifier(pace_p);
2926 +
2927 +               who_buf = who_buf_static;
2928 +               who_buflen = who_buflen_static;
2929 +
2930 +               result = nfs4_gid_to_name(*gid_p, nfs_domain, who_buf, who_buflen);
2931 +
2932 +
2933 +               while (result == -ENOBUFS) {
2934 +                       if (who_buf != who_buf_static)
2935 +                               free(who_buf);
2936 +
2937 +                       /* Increase the size by a full buflen unit */
2938 +                       who_buflen += who_buflen_static;
2939 +                       who_buf = malloc(who_buflen);
2940 +
2941 +                       if (who_buf == NULL) {
2942 +                               result = -ENOMEM;
2943 +                               break;
2944 +                       }
2945 +
2946 +                       result = nfs4_gid_to_name(*gid_p, nfs_domain, who_buf, who_buflen);
2947 +               }
2948 +
2949 +               acl_free(gid_p);
2950 +
2951 +               if (result < 0) {
2952 +                       errno = -result;
2953 +                       goto out;
2954 +               }
2955 +
2956 +               if (who_buf == NULL)
2957 +                       goto out;
2958 +
2959 +               result = acl_nfs4_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
2960 +                               NFS4_ACE_IDENTIFIER_GROUP | eflag, ~mask,
2961 +                                       NFS4_ACL_WHO_NAMED, who_buf);
2962 +               if (who_buf != who_buf_static)
2963 +                       free(who_buf);
2964 +               if (result < 0)
2965 +                       goto out;
2966 +
2967 +               result = acl_get_entry(pacl, ACL_NEXT_ENTRY, &pace_p);
2968 +               if (result <= 0)
2969 +                       goto out;
2970 +
2971 +               result2 = acl_get_tag_type(pace_p, &ace_type);
2972 +               if (result2 < 0)
2973 +                       goto out;
2974 +       }
2975 +
2976 +       if (ace_type == ACL_MASK) {
2977 +               result = acl_get_entry(pacl, ACL_NEXT_ENTRY, &pace_p);
2978 +               if (result <= 0)
2979 +                       goto out;
2980 +
2981 +               result2 = acl_get_tag_type(pace_p, &ace_type);
2982 +               if (result2 < 0)
2983 +                       goto out;
2984 +       }
2985 +
2986 +       if (ace_type != ACL_OTHER) {
2987 +               errno = EINVAL;
2988 +               goto out;
2989 +       }
2990 +
2991 +       result = acl_get_permset(pace_p, &perms);
2992 +       if (result < 0)
2993 +               goto out;
2994 +
2995 +       result = acl_ptn4_get_mask(&mask, perms, iflags);
2996 +       if (result < 0)
2997 +               goto out;
2998 +
2999 +       result = acl_nfs4_add_pair(acl, eflag, mask, NFS4_ACL_WHO_EVERYONE, NULL);
3000 +
3001 +       return result;
3002 +out:
3003 +       if (allocated)
3004 +               acl_nfs4_free(acl);
3005 +       return -1;
3006 +}
3007 diff --git a/libacl/acl_ptn4_get_mask.c b/libacl/acl_ptn4_get_mask.c
3008 new file mode 100644
3009 index 0000000..a6b117b
3010 --- /dev/null
3011 +++ b/libacl/acl_ptn4_get_mask.c
3012 @@ -0,0 +1,81 @@
3013 +/*
3014 + *  NFSv4 ACL Code
3015 + *  Translate POSIX permissions to an NFSv4 mask
3016 + *
3017 + *  Copyright (c) 2002, 2003 The Regents of the University of Michigan.
3018 + *  All rights reserved.
3019 + *
3020 + *  Nathaniel Gallaher <ngallahe@umich.edu>
3021 + *
3022 + *  Redistribution and use in source and binary forms, with or without
3023 + *  modification, are permitted provided that the following conditions
3024 + *  are met:
3025 + *
3026 + *  1. Redistributions of source code must retain the above copyright
3027 + *     notice, this list of conditions and the following disclaimer.
3028 + *  2. Redistributions in binary form must reproduce the above copyright
3029 + *     notice, this list of conditions and the following disclaimer in the
3030 + *     documentation and/or other materials provided with the distribution.
3031 + *  3. Neither the name of the University nor the names of its
3032 + *     contributors may be used to endorse or promote products derived
3033 + *     from this software without specific prior written permission.
3034 + *
3035 + *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
3036 + *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
3037 + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
3038 + *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3039 + *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
3040 + *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
3041 + *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
3042 + *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
3043 + *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
3044 + *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3045 + *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3046 + */
3047 +
3048 +#include <acl/libacl.h>
3049 +#include <libacl_nfs4.h>
3050 +
3051 +int acl_ptn4_get_mask(u32* mask, acl_permset_t perms, int iflags)
3052 +{
3053 +       int result;
3054 +
3055 +       *mask = NFS4_ANYONE_MODE;
3056 +
3057 +       if (perms == NULL) {
3058 +               errno = EINVAL;
3059 +               goto failed;
3060 +       }
3061 +
3062 +       if (iflags & NFS4_ACL_OWNER)
3063 +               *mask |= NFS4_OWNER_MODE;
3064 +
3065 +       result = acl_get_perm(perms, ACL_READ);
3066 +       if (result < 0)
3067 +               goto failed;
3068 +       else if(result == 1)
3069 +               *mask |= NFS4_READ_MODE;
3070 +
3071 +       result = acl_get_perm(perms, ACL_WRITE);
3072 +       if (result < 0)
3073 +               goto failed;
3074 +       else if (result == 1) {
3075 +               *mask |= NFS4_WRITE_MODE;
3076 +               if (iflags & NFS4_ACL_ISDIR)
3077 +                       *mask |= NFS4_ACE_DELETE_CHILD;
3078 +       }
3079 +
3080 +       result = acl_get_perm(perms, ACL_EXECUTE);
3081 +       if (result < 0)
3082 +               goto failed;
3083 +       else if (result == 1)
3084 +               *mask |= NFS4_EXECUTE_MODE;
3085 +
3086 +       return 0;
3087 +
3088 +failed:
3089 +       return -1;
3090 +}
3091 +
3092 +
3093 +
3094 diff --git a/libacl/acl_set_fd.c b/libacl/acl_set_fd.c
3095 index 7df0c17..8ce8b19 100644
3096 --- a/libacl/acl_set_fd.c
3097 +++ b/libacl/acl_set_fd.c
3098 @@ -24,6 +24,11 @@
3099  #include "libacl.h"
3100  #include "__acl_to_xattr.h"
3101  
3102 +#ifdef USE_NFSV4_TRANS
3103 + #include "libacl_nfs4.h"
3104 + #include <nfsidmap.h>
3105 +#endif
3106 +
3107  #include "byteorder.h"
3108  #include "acl_ea.h"
3109  
3110 @@ -37,10 +42,42 @@ acl_set_fd(int fd, acl_t acl)
3111         const char *name = ACL_EA_ACCESS;
3112         size_t size;
3113         int error;
3114 +#ifdef USE_NFSV4_TRANS
3115 +       int retval;
3116 +       struct nfs4_acl * nacl;
3117 +#endif
3118  
3119         if (!acl_obj_p)
3120                 return -1;
3121 +
3122 +#ifdef USE_NFSV4_TRANS
3123 +       retval = fgetxattr(fd, ACL_NFS4_XATTR, NULL, 0);
3124 +
3125 +       if(retval == -1 && (errno == ENOATTR || errno == EOPNOTSUPP)) {
3126 +               ext_acl_p = __acl_to_xattr(acl_obj_p, &size);
3127 +       } else {
3128 +               char domain[NFS4_MAX_DOMAIN_LEN];
3129 +               nfs4_init_name_mapping(NULL);
3130 +               error = nfs4_get_default_domain(NULL, domain, sizeof(domain));
3131 +               if (error)
3132 +                       return -1;
3133 +               nacl = acl_nfs4_new(0);
3134 +               if (acl == NULL) {
3135 +                       errno = ENOMEM;
3136 +                       return -1;
3137 +               }
3138 +               error = acl_ptn4_acl_trans(acl, nacl, ACL_TYPE_ACCESS, 0, domain);
3139 +               if (error)
3140 +                       return -1;
3141 +
3142 +               size = acl_nfs4_xattr_pack(nacl, &ext_acl_p);
3143 +               name = ACL_NFS4_XATTR;
3144 +               acl_nfs4_free(nacl);
3145 +       }
3146 +#else
3147         ext_acl_p = __acl_to_xattr(acl_obj_p, &size);
3148 +#endif
3149 +
3150         if (!ext_acl_p)
3151                 return -1;
3152         error = fsetxattr(fd, name, (char *)ext_acl_p, size, 0);
3153 diff --git a/libacl/acl_set_file.c b/libacl/acl_set_file.c
3154 index 20d7ee3..a209be1 100644
3155 --- a/libacl/acl_set_file.c
3156 +++ b/libacl/acl_set_file.c
3157 @@ -26,9 +26,38 @@
3158  #include "libacl.h"
3159  #include "__acl_to_xattr.h"
3160  
3161 +#ifdef USE_NFSV4_TRANS
3162 + #include "libacl_nfs4.h"
3163 + #include <nfsidmap.h>
3164 +#endif
3165 +
3166  #include "byteorder.h"
3167  #include "acl_ea.h"
3168  
3169 +#ifdef USE_NFSV4_TRANS
3170 +static struct nfs4_acl *get_nfs4_acl(const char *path_p, int is_dir)
3171 +{
3172 +       struct nfs4_acl * acl = NULL;
3173 +       ssize_t ret;
3174 +       char *buf;
3175 +
3176 +       ret = getxattr(path_p, ACL_NFS4_XATTR, NULL, 0);
3177 +       if (ret < 0)
3178 +               return NULL;
3179 +       buf = malloc(ret);
3180 +       if (buf == NULL)
3181 +               return NULL;
3182 +       ret = getxattr(path_p, ACL_NFS4_XATTR, buf, ret);
3183 +       if (ret < 0)
3184 +               goto out_free;
3185 +       acl = acl_nfs4_xattr_load(buf, ret, is_dir);
3186 +
3187 +out_free:
3188 +       free(buf);
3189 +       return acl;
3190 +}
3191 +
3192 +#endif
3193  
3194  /* 23.4.22 */
3195  int
3196 @@ -39,9 +68,15 @@ acl_set_file(const char *path_p, acl_type_t type, acl_t acl)
3197         const char *name;
3198         size_t size;
3199         int error;
3200 +       struct stat st;
3201 +#ifdef USE_NFSV4_TRANS
3202 +       struct nfs4_acl * nacl;
3203 +       int is_dir = NFS4_ACL_ISFILE;
3204 +#endif
3205  
3206         if (!acl_obj_p)
3207                 return -1;
3208 +
3209         switch (type) {
3210                 case ACL_TYPE_ACCESS:
3211                         name = ACL_EA_ACCESS;
3212 @@ -54,8 +89,41 @@ acl_set_file(const char *path_p, acl_type_t type, acl_t acl)
3213                         return -1;
3214         }
3215  
3216 +
3217 +#ifdef USE_NFSV4_TRANS
3218 +       if (stat(path_p, &st) != 0)
3219 +               return -1;
3220 +       if (S_ISDIR(st.st_mode))
3221 +               is_dir = NFS4_ACL_ISDIR;
3222 +       if (type == ACL_TYPE_DEFAULT && !is_dir) {
3223 +               errno = EACCES;
3224 +               return -1;
3225 +       }
3226 +       nacl = get_nfs4_acl(path_p, is_dir);
3227 +       if (nacl == NULL && (errno == ENOATTR || errno == EOPNOTSUPP))
3228 +               ext_acl_p = __acl_to_xattr(acl_obj_p, &size);
3229 +       else {
3230 +               char domain[NFS4_MAX_DOMAIN_LEN];
3231 +
3232 +               nfs4_init_name_mapping(NULL);
3233 +               error = nfs4_get_default_domain(NULL, domain, sizeof(domain));
3234 +               if (error) {
3235 +                       acl_nfs4_free(nacl);
3236 +                       return -1;
3237 +               }
3238 +               error = acl_ptn4_acl_trans(acl, nacl, type, is_dir, domain);
3239 +               if (error) {
3240 +                       acl_nfs4_free(nacl);
3241 +                       return -1;
3242 +               }
3243 +
3244 +               size = acl_nfs4_xattr_pack(nacl, &ext_acl_p);
3245 +               name = ACL_NFS4_XATTR;
3246 +               acl_nfs4_free(nacl);
3247 +       }
3248 +#else
3249 +
3250         if (type == ACL_TYPE_DEFAULT) {
3251 -               struct stat st;
3252  
3253                 if (stat(path_p, &st) != 0)
3254                         return -1;
3255 @@ -68,6 +136,8 @@ acl_set_file(const char *path_p, acl_type_t type, acl_t acl)
3256         }
3257  
3258         ext_acl_p = __acl_to_xattr(acl_obj_p, &size);
3259 +#endif
3260 +
3261         if (!ext_acl_p)
3262                 return -1;
3263         error = setxattr(path_p, name, (char *)ext_acl_p, size, 0);
3264 diff --git a/libacl/libacl_nfs4.h b/libacl/libacl_nfs4.h
3265 new file mode 100644
3266 index 0000000..b29b802
3267 --- /dev/null
3268 +++ b/libacl/libacl_nfs4.h
3269 @@ -0,0 +1,97 @@
3270 +#include <sys/types.h>
3271 +#include <pwd.h>
3272 +#include <grp.h>
3273 +#include <sys/acl.h>
3274 +#include <stdlib.h>
3275 +#include <sys/queue.h>
3276 +#include <nfs4.h>
3277 +#include <sys/errno.h>
3278 +#include <string.h>
3279 +
3280 +/* mode bit translations: */
3281 +#define NFS4_READ_MODE NFS4_ACE_READ_DATA
3282 +#define NFS4_WRITE_MODE (NFS4_ACE_WRITE_DATA | NFS4_ACE_APPEND_DATA)
3283 +#define NFS4_EXECUTE_MODE NFS4_ACE_EXECUTE
3284 +#define NFS4_ANYONE_MODE (NFS4_ACE_READ_ATTRIBUTES | NFS4_ACE_READ_ACL | \
3285 +               NFS4_ACE_SYNCHRONIZE)
3286 +#define NFS4_OWNER_MODE (NFS4_ACE_WRITE_ATTRIBUTES | NFS4_ACE_WRITE_ACL)
3287 +
3288 +#define NFS4_ACE_MASK_IGNORE (NFS4_ACE_DELETE | NFS4_ACE_WRITE_OWNER \
3289 +               | NFS4_ACE_READ_NAMED_ATTRS | NFS4_ACE_WRITE_NAMED_ATTRS)
3290 +/* XXX not sure about the following.  Note that e.g. DELETE_CHILD is wrong in
3291 + * general (should only be ignored on files). */
3292 +#define MASK_EQUAL(mask1, mask2) \
3293 +       (((mask1) & NFS4_ACE_MASK_ALL & ~NFS4_ACE_MASK_IGNORE & \
3294 +                                               ~NFS4_ACE_DELETE_CHILD) \
3295 +        == ((mask2) & NFS4_ACE_MASK_ALL & ~NFS4_ACE_MASK_IGNORE & \
3296 +                                               ~NFS4_ACE_DELETE_CHILD))
3297 +
3298 +/* Maximum length of the ace->who attribute */
3299 +#define NFS4_ACL_WHO_LENGTH_MAX                2048
3300 +#define NFS4_ACL_WHO_BUFFER_LEN_GUESS  255
3301 +
3302 +/* NFS4 acl xattr name */
3303 +#define ACL_NFS4_XATTR "system.nfs4_acl"
3304 +
3305 +/* Macro for finding empty tailqs */
3306 +#define TAILQ_IS_EMPTY(head) (head.tqh_first == NULL)
3307 +
3308 +/* Flags to pass certain properties around */
3309 +#define NFS4_ACL_NOFLAGS                       0x00
3310 +#define NFS4_ACL_ISFILE                                0x00
3311 +#define NFS4_ACL_ISDIR                         0x01
3312 +#define NFS4_ACL_OWNER                         0x02
3313 +#define NFS4_ACL_REQUEST_DEFAULT       0x04
3314 +#define NFS4_ACL_RAW                           0x01
3315 +
3316 +#define NFS4_XDR_MOD                           4
3317 +
3318 +typedef u_int32_t u32;
3319 +
3320 +enum { ACL_NFS4_NOT_USED = 0,
3321 +               ACL_NFS4_USED
3322 +};
3323 +
3324 +struct ace_container {
3325 +       struct nfs4_ace *ace;
3326 +       TAILQ_ENTRY(ace_container) l_ace;
3327 +};
3328 +
3329 +TAILQ_HEAD(ace_container_list_head, ace_container);
3330 +
3331 +/**** Public functions ****/
3332 +
3333 +/** Manipulation functions **/
3334 +extern int                             acl_nfs4_add_ace(struct nfs4_acl *, u32, u32, u32, int, char*);
3335 +extern int                             acl_nfs4_add_pair(struct nfs4_acl *, int, u32, int, char*);
3336 +extern void                            acl_nfs4_free(struct nfs4_acl *);
3337 +extern struct nfs4_acl *acl_nfs4_new(u32);
3338 +extern int                             acl_nfs4_set_who(struct nfs4_ace*, int, char*);
3339 +extern struct nfs4_acl *acl_nfs4_copy_acl(struct nfs4_acl *);
3340 +extern struct nfs4_acl *acl_nfs4_xattr_load(char *, int, u32);
3341 +extern int                             acl_nfs4_xattr_pack(struct nfs4_acl *, char**);
3342 +extern int                             acl_nfs4_xattr_size(struct nfs4_acl *);
3343 +extern void                            acl_nfs4_remove_ace(struct nfs4_acl * acl, struct nfs4_ace * ace);
3344 +
3345 +/** Conversion functions **/
3346 +
3347 +/* nfs4 -> posix */
3348 +extern acl_t           acl_n4tp_acl_trans(struct nfs4_acl *, acl_type_t);
3349 +
3350 +/* posix -> nfs4 */
3351 +extern int                             acl_ptn4_get_mask(u32* mask, acl_permset_t perms,
3352 +                                                               int iflags);
3353 +extern int acl_ptn4_acl_trans(acl_t, struct nfs4_acl *, acl_type_t, u32, char*);
3354 +
3355 +
3356 +/** Access Functions **/
3357 +extern inline int      acl_nfs4_get_whotype(char*);
3358 +extern int                     acl_nfs4_get_who(struct nfs4_ace*, int*, char**);
3359 +
3360 +/**** Private(?) functions ****/
3361 +acl_t          __posix_acl_from_nfs4_xattr(char*, int, acl_type_t, u32);
3362 +
3363 +/* These will change */
3364 +char * nfs4_get_who_from_uid(uid_t);
3365 +char * nfs4_get_who_from_gid(gid_t);
3366 +/* End change */