Efficient xattr handling for VxFS Signed-off-by: Abhidnya Joshi <Abhidnya.Joshi@verit...
[samba.git] / source3 / modules / vfs_nfs4acl_xattr.c
1 /*
2  * Convert NFSv4 acls stored per http://www.suse.de/~agruen/nfs4acl/ to NT acls and vice versa.
3  *
4  * Copyright (C) Jiri Sasek, 2007
5  * based on the foobar.c module which is copyrighted by Volker Lendecke
6  * based on pvfs_acl_nfs4.c  Copyright (C) Andrew Tridgell 2006
7  *
8  * based on vfs_fake_acls:
9  * Copyright (C) Tim Potter, 1999-2000
10  * Copyright (C) Alexander Bokovoy, 2002
11  * Copyright (C) Andrew Bartlett, 2002,2012
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 3 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, see <http://www.gnu.org/licenses/>.
25  *
26  */
27
28 #include "includes.h"
29 #include "system/filesys.h"
30 #include "smbd/smbd.h"
31 #include "nfs4_acls.h"
32 #include "librpc/gen_ndr/ndr_nfs4acl.h"
33
34 #undef DBGC_CLASS
35 #define DBGC_CLASS DBGC_VFS
36
37 static struct nfs4acl *nfs4acl_blob2acl(DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
38 {
39         enum ndr_err_code ndr_err;
40         struct nfs4acl *acl = talloc(mem_ctx, struct nfs4acl);
41         if (!acl) {
42                 errno = ENOMEM;
43                 return NULL;
44         }
45
46         ndr_err = ndr_pull_struct_blob(blob, acl, acl,
47                 (ndr_pull_flags_fn_t)ndr_pull_nfs4acl);
48
49         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
50                 DEBUG(0, ("ndr_pull_acl_t failed: %s\n",
51                           ndr_errstr(ndr_err)));
52                 TALLOC_FREE(acl);
53                 return NULL;
54         }
55         return acl;
56 }
57
58 static DATA_BLOB nfs4acl_acl2blob(TALLOC_CTX *mem_ctx, struct nfs4acl *acl)
59 {
60         enum ndr_err_code ndr_err;
61         DATA_BLOB blob;
62         ndr_err = ndr_push_struct_blob(&blob, mem_ctx, acl,
63                 (ndr_push_flags_fn_t)ndr_push_nfs4acl);
64
65         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
66                 DEBUG(0, ("ndr_push_acl_t failed: %s\n",
67                           ndr_errstr(ndr_err)));
68                 return data_blob_null;
69         }
70         return blob;
71 }
72
73 static NTSTATUS nfs4_get_nfs4_acl_common(TALLOC_CTX *mem_ctx,
74                                          DATA_BLOB *blob,
75                                          struct SMB4ACL_T **ppacl)
76 {
77         int i;
78         struct nfs4acl *nfs4acl = NULL;
79         struct SMB4ACL_T *pacl = NULL;
80         TALLOC_CTX *frame = talloc_stackframe();
81         nfs4acl = nfs4acl_blob2acl(blob, frame);
82
83         /* create SMB4ACL data */
84         if((pacl = smb_create_smb4acl(mem_ctx)) == NULL) {
85                 TALLOC_FREE(frame);
86                 return NT_STATUS_NO_MEMORY;
87         }
88         for(i=0; i<nfs4acl->a_count; i++) {
89                 SMB_ACE4PROP_T aceprop;
90
91                 aceprop.aceType  = (uint32_t) nfs4acl->ace[i].e_type;
92                 aceprop.aceFlags = (uint32_t) nfs4acl->ace[i].e_flags;
93                 aceprop.aceMask  = (uint32_t) nfs4acl->ace[i].e_mask;
94                 aceprop.who.id   = (uint32_t) nfs4acl->ace[i].e_id;
95                 if (!strcmp(nfs4acl->ace[i].e_who,
96                             NFS4ACL_XATTR_OWNER_WHO)) {
97                         aceprop.flags = SMB_ACE4_ID_SPECIAL;
98                         aceprop.who.special_id = SMB_ACE4_WHO_OWNER;
99                 } else if (!strcmp(nfs4acl->ace[i].e_who,
100                                    NFS4ACL_XATTR_GROUP_WHO)) {
101                         aceprop.flags = SMB_ACE4_ID_SPECIAL;
102                         aceprop.who.special_id = SMB_ACE4_WHO_GROUP;
103                 } else if (!strcmp(nfs4acl->ace[i].e_who,
104                                    NFS4ACL_XATTR_EVERYONE_WHO)) {
105                         aceprop.flags = SMB_ACE4_ID_SPECIAL;
106                         aceprop.who.special_id = SMB_ACE4_WHO_EVERYONE;
107                 } else {
108                         aceprop.flags = 0;
109                 }
110                 if(smb_add_ace4(pacl, &aceprop) == NULL) {
111                         TALLOC_FREE(frame);
112                         return NT_STATUS_NO_MEMORY;
113                 }
114         }
115
116         *ppacl = pacl;
117         TALLOC_FREE(frame);
118         return NT_STATUS_OK;
119 }
120
121 /* Fetch the NFSv4 ACL from the xattr, and convert into Samba's internal NFSv4 format */
122 static NTSTATUS nfs4_fget_nfs4_acl(vfs_handle_struct *handle, TALLOC_CTX *mem_ctx,
123                                    files_struct *fsp, struct SMB4ACL_T **ppacl)
124 {
125         NTSTATUS status;
126         DATA_BLOB blob = data_blob_null;
127         ssize_t length;
128         TALLOC_CTX *frame = talloc_stackframe();
129
130         do {
131                 blob.length += 1000;
132                 blob.data = talloc_realloc(frame, blob.data, uint8_t, blob.length);
133                 if (!blob.data) {
134                         TALLOC_FREE(frame);
135                         errno = ENOMEM;
136                         return NT_STATUS_NO_MEMORY;
137                 }
138                 length = SMB_VFS_NEXT_FGETXATTR(handle, fsp, NFS4ACL_XATTR_NAME, blob.data, blob.length);
139                 blob.length = length;
140         } while (length == -1 && errno == ERANGE);
141         if (length == -1) {
142                 TALLOC_FREE(frame);
143                 return map_nt_error_from_unix(errno);
144         }
145         status = nfs4_get_nfs4_acl_common(mem_ctx, &blob, ppacl);
146         TALLOC_FREE(frame);
147         return status;
148 }
149
150 /* Fetch the NFSv4 ACL from the xattr, and convert into Samba's internal NFSv4 format */
151 static NTSTATUS nfs4_get_nfs4_acl(vfs_handle_struct *handle, TALLOC_CTX *mem_ctx,
152                                   const char *path, struct SMB4ACL_T **ppacl)
153 {
154         NTSTATUS status;
155         DATA_BLOB blob = data_blob_null;
156         ssize_t length;
157         TALLOC_CTX *frame = talloc_stackframe();
158
159         do {
160                 blob.length += 1000;
161                 blob.data = talloc_realloc(frame, blob.data, uint8_t, blob.length);
162                 if (!blob.data) {
163                         TALLOC_FREE(frame);
164                         errno = ENOMEM;
165                         return NT_STATUS_NO_MEMORY;
166                 }
167                 length = SMB_VFS_NEXT_GETXATTR(handle, path, NFS4ACL_XATTR_NAME, blob.data, blob.length);
168                 blob.length = length;
169         } while (length == -1 && errno == ERANGE);
170         if (length == -1) {
171                 TALLOC_FREE(frame);
172                 return map_nt_error_from_unix(errno);
173         }
174         status = nfs4_get_nfs4_acl_common(mem_ctx, &blob, ppacl);
175         TALLOC_FREE(frame);
176         return status;
177 }
178
179 static bool nfs4acl_smb4acl2nfs4acl(TALLOC_CTX *mem_ctx,
180                                     struct SMB4ACL_T *smbacl,
181                                     struct nfs4acl **pnfs4acl,
182                                     bool denymissingspecial)
183 {
184         struct nfs4acl *nfs4acl;
185         struct SMB4ACE_T *smbace;
186         bool have_special_id = false;
187         int i;
188
189         /* allocate the field of NFS4 aces */
190         nfs4acl = talloc_zero(mem_ctx, struct nfs4acl);
191         if(nfs4acl == NULL) {
192                 errno = ENOMEM;
193                 return false;
194         }
195
196         nfs4acl->a_count = smb_get_naces(smbacl);
197
198         nfs4acl->ace = talloc_zero_array(nfs4acl, struct nfs4ace,
199                                          nfs4acl->a_count);
200         if(nfs4acl->ace == NULL) {
201                 TALLOC_FREE(nfs4acl);
202                 errno = ENOMEM;
203                 return false;
204         }
205
206         /* handle all aces */
207         for(smbace = smb_first_ace4(smbacl), i = 0;
208                         smbace!=NULL;
209                         smbace = smb_next_ace4(smbace), i++) {
210                 SMB_ACE4PROP_T *aceprop = smb_get_ace4(smbace);
211
212                 nfs4acl->ace[i].e_type        = aceprop->aceType;
213                 nfs4acl->ace[i].e_flags       = aceprop->aceFlags;
214                 nfs4acl->ace[i].e_mask        = aceprop->aceMask;
215                 nfs4acl->ace[i].e_id          = aceprop->who.id;
216                 if(aceprop->flags & SMB_ACE4_ID_SPECIAL) {
217                         switch(aceprop->who.special_id) {
218                         case SMB_ACE4_WHO_EVERYONE:
219                                 nfs4acl->ace[i].e_who =
220                                         NFS4ACL_XATTR_EVERYONE_WHO;
221                                 break;
222                         case SMB_ACE4_WHO_OWNER:
223                                 nfs4acl->ace[i].e_who =
224                                         NFS4ACL_XATTR_OWNER_WHO;
225                                 break;
226                         case SMB_ACE4_WHO_GROUP:
227                                 nfs4acl->ace[i].e_who =
228                                         NFS4ACL_XATTR_GROUP_WHO;
229                                 break;
230                         default:
231                                 DEBUG(8, ("unsupported special_id %d\n", \
232                                         aceprop->who.special_id));
233                                 continue; /* don't add it !!! */
234                         }
235                         have_special_id = true;
236                 } else {
237                         nfs4acl->ace[i].e_who = "";
238                 }
239         }
240
241         if (!have_special_id && denymissingspecial) {
242                 TALLOC_FREE(nfs4acl);
243                 errno = EACCES;
244                 return false;
245         }
246
247         SMB_ASSERT(i == nfs4acl->a_count);
248
249         *pnfs4acl = nfs4acl;
250         return true;
251 }
252
253 static bool nfs4acl_xattr_set_smb4acl(vfs_handle_struct *handle,
254                                       const char *path,
255                                       struct SMB4ACL_T *smbacl)
256 {
257         TALLOC_CTX *frame = talloc_stackframe();
258         struct nfs4acl *nfs4acl;
259         int ret;
260         bool denymissingspecial;
261         DATA_BLOB blob;
262
263         denymissingspecial = lp_parm_bool(handle->conn->params->service,
264                                           "nfs4acl_xattr",
265                                           "denymissingspecial", false);
266
267         if (!nfs4acl_smb4acl2nfs4acl(frame, smbacl, &nfs4acl,
268                                      denymissingspecial)) {
269                 DEBUG(0, ("Failed to convert smb ACL to nfs4 ACL.\n"));
270                 TALLOC_FREE(frame);
271                 return false;
272         }
273
274         blob = nfs4acl_acl2blob(frame, nfs4acl);
275         if (!blob.data) {
276                 DEBUG(0, ("Failed to convert ACL to linear blob for xattr\n"));
277                 TALLOC_FREE(frame);
278                 errno = EINVAL;
279                 return false;
280         }
281         ret = SMB_VFS_NEXT_SETXATTR(handle, path, NFS4ACL_XATTR_NAME,
282                                     blob.data, blob.length, 0);
283         if (ret != 0) {
284                 DEBUG(0, ("can't store acl in xattr: %s\n", strerror(errno)));
285         }
286         TALLOC_FREE(frame);
287         return ret == 0;
288 }
289
290 /* call-back function processing the NT acl -> NFS4 acl using NFSv4 conv. */
291 static bool nfs4acl_xattr_fset_smb4acl(vfs_handle_struct *handle,
292                                        files_struct *fsp,
293                                        struct SMB4ACL_T *smbacl)
294 {
295         TALLOC_CTX *frame = talloc_stackframe();
296         struct nfs4acl *nfs4acl;
297         int ret;
298         bool denymissingspecial;
299         DATA_BLOB blob;
300
301         denymissingspecial = lp_parm_bool(fsp->conn->params->service,
302                                           "nfs4acl_xattr",
303                                           "denymissingspecial", false);
304
305         if (!nfs4acl_smb4acl2nfs4acl(frame, smbacl, &nfs4acl,
306                                      denymissingspecial)) {
307                 DEBUG(0, ("Failed to convert smb ACL to nfs4 ACL.\n"));
308                 TALLOC_FREE(frame);
309                 return false;
310         }
311
312         blob = nfs4acl_acl2blob(frame, nfs4acl);
313         if (!blob.data) {
314                 DEBUG(0, ("Failed to convert ACL to linear blob for xattr\n"));
315                 TALLOC_FREE(frame);
316                 errno = EINVAL;
317                 return false;
318         }
319         if (fsp->fh->fd == -1) {
320                 DEBUG(0, ("Error: fsp->fh->fd == -1\n"));
321         }
322         ret = SMB_VFS_NEXT_FSETXATTR(handle, fsp, NFS4ACL_XATTR_NAME,
323                                      blob.data, blob.length, 0);
324         if (ret != 0) {
325                 DEBUG(0, ("can't store acl in xattr: %s\n", strerror(errno)));
326         }
327         TALLOC_FREE(frame);
328         return ret == 0;
329 }
330
331 /* nfs4_set_nt_acl()
332  * set the local file's acls obtaining it in NT form
333  * using the NFSv4 format conversion
334  */
335 static NTSTATUS nfs4_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
336                            uint32_t security_info_sent,
337                            const struct security_descriptor *psd)
338 {
339         return smb_set_nt_acl_nfs4(handle, fsp, security_info_sent, psd,
340                         nfs4acl_xattr_fset_smb4acl);
341 }
342
343 static struct SMB4ACL_T *nfs4acls_defaultacl(TALLOC_CTX *mem_ctx)
344 {
345         struct SMB4ACL_T *pacl = NULL;
346         struct SMB4ACE_T *pace;
347         SMB_ACE4PROP_T ace = {
348                 .flags = SMB_ACE4_ID_SPECIAL,
349                 .who = {
350                         .id = SMB_ACE4_WHO_EVERYONE,
351                 },
352                 .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE,
353                 .aceFlags = 0,
354                 .aceMask = SMB_ACE4_ALL_MASKS,
355         };
356
357         DEBUG(10, ("Building default full access acl\n"));
358
359         pacl = smb_create_smb4acl(mem_ctx);
360         if (pacl == NULL) {
361                 DEBUG(0, ("talloc failed\n"));
362                 errno = ENOMEM;
363                 return NULL;
364         }
365
366         pace = smb_add_ace4(pacl, &ace);
367         if (pace == NULL) {
368                 DEBUG(0, ("talloc failed\n"));
369                 TALLOC_FREE(pacl);
370                 errno = ENOMEM;
371                 return NULL;
372         }
373
374         return pacl;
375 }
376
377 /*
378  * Because there is no good way to guarantee that a new xattr will be
379  * created on file creation there might be no acl xattr on a file when
380  * trying to read the acl. In this case the acl xattr will get
381  * constructed at that time from the parent acl.
382  * If the parent ACL doesn't have an xattr either the call will
383  * recurse to the next parent directory until the share root is
384  * reached. If the share root doesn't contain an ACL xattr either a
385  * default ACL will be used.
386  * Also a default ACL will be set if a non inheriting ACL is encountered.
387  *
388  * Basic algorithm:
389  *   read acl xattr blob
390  *   if acl xattr blob doesn't exist
391  *     stat current directory to know if it's a file or directory
392  *     read acl xattr blob from parent dir
393  *     acl xattr blob to smb nfs4 acl
394  *     calculate inherited smb nfs4 acl
395  *     without inheritance use default smb nfs4 acl
396  *     smb nfs4 acl to acl xattr blob
397  *     set acl xattr blob
398  *     return smb nfs4 acl
399  *   else
400  *     acl xattr blob to smb nfs4 acl
401  *
402  * Todo: Really use mem_ctx after fixing interface of nfs4_acls
403  */
404 static struct SMB4ACL_T *nfs4acls_inheritacl(vfs_handle_struct *handle,
405         const char *path,
406         TALLOC_CTX *mem_ctx)
407 {
408         char *parent_dir = NULL;
409         struct SMB4ACL_T *pparentacl = NULL;
410         struct SMB4ACL_T *pchildacl = NULL;
411         struct SMB4ACE_T *pace;
412         SMB_ACE4PROP_T ace;
413         bool isdir;
414         struct smb_filename *smb_fname = NULL;
415         NTSTATUS status;
416         int ret;
417         TALLOC_CTX *frame = talloc_stackframe();
418
419         DEBUG(10, ("nfs4acls_inheritacl invoked for %s\n", path));
420         smb_fname = synthetic_smb_fname(frame, path, NULL, NULL, 0);
421         if (smb_fname == NULL) {
422                 TALLOC_FREE(frame);
423                 errno = ENOMEM;
424                 return NULL;
425         }
426
427         ret = SMB_VFS_STAT(handle->conn, smb_fname);
428         if (ret == -1) {
429                 DEBUG(0,("nfs4acls_inheritacl: failed to stat "
430                          "directory %s. Error was %s\n",
431                          smb_fname_str_dbg(smb_fname),
432                          strerror(errno)));
433                 TALLOC_FREE(frame);
434                 return NULL;
435         }
436         isdir = S_ISDIR(smb_fname->st.st_ex_mode);
437
438         if (!parent_dirname(talloc_tos(),
439                             path,
440                             &parent_dir,
441                             NULL)) {
442                 TALLOC_FREE(frame);
443                 errno = ENOMEM;
444                 return NULL;
445         }
446
447         status = nfs4_get_nfs4_acl(handle, frame, parent_dir, &pparentacl);
448         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)
449             && strncmp(parent_dir, ".", 2) != 0) {
450                 pparentacl = nfs4acls_inheritacl(handle, parent_dir,
451                                                  frame);
452         }
453         else if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
454                 pparentacl = nfs4acls_defaultacl(frame);
455
456         }
457         else if (!NT_STATUS_IS_OK(status)) {
458                 TALLOC_FREE(frame);
459                 return NULL;
460         }
461
462         pchildacl = smb_create_smb4acl(mem_ctx);
463         if (pchildacl == NULL) {
464                 DEBUG(0, ("talloc failed\n"));
465                 TALLOC_FREE(frame);
466                 errno = ENOMEM;
467                 return NULL;
468         }
469
470         for (pace = smb_first_ace4(pparentacl); pace != NULL;
471              pace = smb_next_ace4(pace)) {
472                 struct SMB4ACE_T *pchildace;
473                 ace = *smb_get_ace4(pace);
474                 if ((isdir && !(ace.aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE)) ||
475                     (!isdir && !(ace.aceFlags & SMB_ACE4_FILE_INHERIT_ACE))) {
476                         DEBUG(10, ("non inheriting ace type: %d, iflags: %x, "
477                                    "flags: %x, mask: %x, who: %d\n",
478                                    ace.aceType, ace.flags, ace.aceFlags,
479                                    ace.aceMask, ace.who.id));
480                         continue;
481                 }
482                 DEBUG(10, ("inheriting ace type: %d, iflags: %x, "
483                            "flags: %x, mask: %x, who: %d\n",
484                            ace.aceType, ace.flags, ace.aceFlags,
485                            ace.aceMask, ace.who.id));
486                 ace.aceFlags |= SMB_ACE4_INHERITED_ACE;
487                 if (ace.aceFlags & SMB_ACE4_INHERIT_ONLY_ACE) {
488                         ace.aceFlags &= ~SMB_ACE4_INHERIT_ONLY_ACE;
489                 }
490                 if (ace.aceFlags & SMB_ACE4_NO_PROPAGATE_INHERIT_ACE) {
491                         ace.aceFlags &= ~SMB_ACE4_FILE_INHERIT_ACE;
492                         ace.aceFlags &= ~SMB_ACE4_DIRECTORY_INHERIT_ACE;
493                         ace.aceFlags &= ~SMB_ACE4_NO_PROPAGATE_INHERIT_ACE;
494                 }
495                 pchildace = smb_add_ace4(pchildacl, &ace);
496                 if (pchildace == NULL) {
497                         DEBUG(0, ("talloc failed\n"));
498                         TALLOC_FREE(frame);
499                         errno = ENOMEM;
500                         return NULL;
501                 }
502         }
503
504         /* Set a default ACL if we didn't inherit anything. */
505         if (smb_first_ace4(pchildacl) == NULL) {
506                 TALLOC_FREE(pchildacl);
507                 pchildacl = nfs4acls_defaultacl(mem_ctx);
508         }
509
510         /* store the returned ACL to get it directly in the
511            future and avoid dynamic inheritance behavior. */
512         nfs4acl_xattr_set_smb4acl(handle, path, pchildacl);
513
514         TALLOC_FREE(frame);
515         return pchildacl;
516 }
517
518 static NTSTATUS nfs4acl_xattr_fget_nt_acl(struct vfs_handle_struct *handle,
519                                    struct files_struct *fsp,
520                                    uint32_t security_info,
521                                    TALLOC_CTX *mem_ctx,
522                                    struct security_descriptor **ppdesc)
523 {
524         struct SMB4ACL_T *pacl;
525         NTSTATUS status;
526         TALLOC_CTX *frame = talloc_stackframe();
527
528         status = nfs4_fget_nfs4_acl(handle, frame, fsp, &pacl);
529         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
530                 pacl = nfs4acls_inheritacl(handle, fsp->fsp_name->base_name,
531                                            frame);
532         }
533         else if (!NT_STATUS_IS_OK(status)) {
534                 TALLOC_FREE(frame);
535                 return status;
536         }
537
538         status = smb_fget_nt_acl_nfs4(fsp, security_info, mem_ctx, ppdesc, pacl);
539         TALLOC_FREE(frame);
540         return status;
541 }
542
543 static NTSTATUS nfs4acl_xattr_get_nt_acl(struct vfs_handle_struct *handle,
544                                   const struct smb_filename *smb_fname,
545                                   uint32_t security_info,
546                                   TALLOC_CTX *mem_ctx,
547                                   struct security_descriptor **ppdesc)
548 {
549         struct SMB4ACL_T *pacl;
550         NTSTATUS status;
551         const char *name = smb_fname->base_name;
552         TALLOC_CTX *frame = talloc_stackframe();
553
554         status = nfs4_get_nfs4_acl(handle, frame, name, &pacl);
555         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
556                 pacl = nfs4acls_inheritacl(handle, name, frame);
557         }
558         else if (!NT_STATUS_IS_OK(status)) {
559                 TALLOC_FREE(frame);
560                 return status;
561         }
562
563         status = smb_get_nt_acl_nfs4(handle->conn, smb_fname, security_info,
564                                      mem_ctx, ppdesc,
565                                      pacl);
566         TALLOC_FREE(frame);
567         return status;
568 }
569
570 static NTSTATUS nfs4acl_xattr_fset_nt_acl(vfs_handle_struct *handle,
571                          files_struct *fsp,
572                          uint32_t security_info_sent,
573                          const struct security_descriptor *psd)
574 {
575         return nfs4_set_nt_acl(handle, fsp, security_info_sent, psd);
576 }
577
578 /*
579    As long as Samba does not support an exiplicit method for a module
580    to define conflicting vfs methods, we should override all conflicting
581    methods here.  That way, we know we are using the NFSv4 storage
582
583    Function declarations taken from vfs_solarisacl
584 */
585
586 static SMB_ACL_T nfs4acl_xattr_fail__sys_acl_get_file(vfs_handle_struct *handle,
587                                                       const char *path_p,
588                                                       SMB_ACL_TYPE_T type,
589                                                       TALLOC_CTX *mem_ctx)
590 {
591         return (SMB_ACL_T)NULL;
592 }
593
594 static SMB_ACL_T nfs4acl_xattr_fail__sys_acl_get_fd(vfs_handle_struct *handle,
595                                                     files_struct *fsp,
596                                                     TALLOC_CTX *mem_ctx)
597 {
598         return (SMB_ACL_T)NULL;
599 }
600
601 static int nfs4acl_xattr_fail__sys_acl_set_file(vfs_handle_struct *handle,
602                                          const char *name,
603                                          SMB_ACL_TYPE_T type,
604                                          SMB_ACL_T theacl)
605 {
606         return -1;
607 }
608
609 static int nfs4acl_xattr_fail__sys_acl_set_fd(vfs_handle_struct *handle,
610                                        files_struct *fsp,
611                                        SMB_ACL_T theacl)
612 {
613         return -1;
614 }
615
616 static int nfs4acl_xattr_fail__sys_acl_delete_def_file(vfs_handle_struct *handle,
617                                                 const char *path)
618 {
619         return -1;
620 }
621
622 static int nfs4acl_xattr_fail__sys_acl_blob_get_file(vfs_handle_struct *handle, const char *path_p, TALLOC_CTX *mem_ctx, char **blob_description, DATA_BLOB *blob)
623 {
624         return -1;
625 }
626
627 static int nfs4acl_xattr_fail__sys_acl_blob_get_fd(vfs_handle_struct *handle, files_struct *fsp, TALLOC_CTX *mem_ctx, char **blob_description, DATA_BLOB *blob)
628 {
629         return -1;
630 }
631
632 /* VFS operations structure */
633
634 static struct vfs_fn_pointers nfs4acl_xattr_fns = {
635         .sys_acl_get_file_fn = nfs4acl_xattr_fail__sys_acl_get_file,
636         .sys_acl_get_fd_fn = nfs4acl_xattr_fail__sys_acl_get_fd,
637         .sys_acl_blob_get_file_fn = nfs4acl_xattr_fail__sys_acl_blob_get_file,
638         .sys_acl_blob_get_fd_fn = nfs4acl_xattr_fail__sys_acl_blob_get_fd,
639         .sys_acl_set_file_fn = nfs4acl_xattr_fail__sys_acl_set_file,
640         .sys_acl_set_fd_fn = nfs4acl_xattr_fail__sys_acl_set_fd,
641         .sys_acl_delete_def_file_fn = nfs4acl_xattr_fail__sys_acl_delete_def_file,
642         .fget_nt_acl_fn = nfs4acl_xattr_fget_nt_acl,
643         .get_nt_acl_fn = nfs4acl_xattr_get_nt_acl,
644         .fset_nt_acl_fn = nfs4acl_xattr_fset_nt_acl,
645 };
646
647 NTSTATUS vfs_nfs4acl_xattr_init(void);
648 NTSTATUS vfs_nfs4acl_xattr_init(void)
649 {
650         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "nfs4acl_xattr",
651                                 &nfs4acl_xattr_fns);
652 }