s4:dsdb/password_hash: split out a password_hash_needed() function
[Samba.git] / source3 / modules / vfs_nfs4acl_xattr.c
blob9ab7238e0ac2770d6355724f664087ff4bf1421c
1 /*
2 * Convert NFSv4 acls stored per http://www.suse.de/~agruen/nfs4acl/ to NT acls and vice versa.
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
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
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.
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.
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/>.
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"
34 #undef DBGC_CLASS
35 #define DBGC_CLASS DBGC_VFS
37 static struct nfs4acl *nfs4acl_blob2acl(DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
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;
46 ndr_err = ndr_pull_struct_blob(blob, acl, acl,
47 (ndr_pull_flags_fn_t)ndr_pull_nfs4acl);
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;
55 return acl;
58 static DATA_BLOB nfs4acl_acl2blob(TALLOC_CTX *mem_ctx, struct nfs4acl *acl)
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);
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;
70 return blob;
73 static NTSTATUS nfs4_get_nfs4_acl_common(TALLOC_CTX *mem_ctx,
74 DATA_BLOB *blob,
75 struct SMB4ACL_T **ppacl)
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);
83 /* create SMB4ACL data */
84 if((pacl = smb_create_smb4acl(mem_ctx)) == NULL) {
85 TALLOC_FREE(frame);
86 return NT_STATUS_NO_MEMORY;
88 for(i=0; i<nfs4acl->a_count; i++) {
89 SMB_ACE4PROP_T aceprop;
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;
110 if(smb_add_ace4(pacl, &aceprop) == NULL) {
111 TALLOC_FREE(frame);
112 return NT_STATUS_NO_MEMORY;
116 *ppacl = pacl;
117 TALLOC_FREE(frame);
118 return NT_STATUS_OK;
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)
125 NTSTATUS status;
126 DATA_BLOB blob = data_blob_null;
127 ssize_t length;
128 TALLOC_CTX *frame = talloc_stackframe();
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;
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);
145 status = nfs4_get_nfs4_acl_common(mem_ctx, &blob, ppacl);
146 TALLOC_FREE(frame);
147 return status;
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)
154 NTSTATUS status;
155 DATA_BLOB blob = data_blob_null;
156 ssize_t length;
157 TALLOC_CTX *frame = talloc_stackframe();
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;
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);
174 status = nfs4_get_nfs4_acl_common(mem_ctx, &blob, ppacl);
175 TALLOC_FREE(frame);
176 return status;
179 static bool nfs4acl_smb4acl2nfs4acl(TALLOC_CTX *mem_ctx,
180 struct SMB4ACL_T *smbacl,
181 struct nfs4acl **pnfs4acl,
182 bool denymissingspecial)
184 struct nfs4acl *nfs4acl;
185 struct SMB4ACE_T *smbace;
186 bool have_special_id = false;
187 int i;
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;
196 nfs4acl->a_count = smb_get_naces(smbacl);
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;
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);
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 !!! */
235 have_special_id = true;
236 } else {
237 nfs4acl->ace[i].e_who = "";
241 if (!have_special_id && denymissingspecial) {
242 TALLOC_FREE(nfs4acl);
243 errno = EACCES;
244 return false;
247 SMB_ASSERT(i == nfs4acl->a_count);
249 *pnfs4acl = nfs4acl;
250 return true;
253 static bool nfs4acl_xattr_set_smb4acl(vfs_handle_struct *handle,
254 const char *path,
255 struct SMB4ACL_T *smbacl)
257 TALLOC_CTX *frame = talloc_stackframe();
258 struct nfs4acl *nfs4acl;
259 int ret;
260 bool denymissingspecial;
261 DATA_BLOB blob;
263 denymissingspecial = lp_parm_bool(handle->conn->params->service,
264 "nfs4acl_xattr",
265 "denymissingspecial", false);
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;
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;
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)));
286 TALLOC_FREE(frame);
287 return ret == 0;
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)
295 TALLOC_CTX *frame = talloc_stackframe();
296 struct nfs4acl *nfs4acl;
297 int ret;
298 bool denymissingspecial;
299 DATA_BLOB blob;
301 denymissingspecial = lp_parm_bool(fsp->conn->params->service,
302 "nfs4acl_xattr",
303 "denymissingspecial", false);
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;
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;
319 if (fsp->fh->fd == -1) {
320 DEBUG(0, ("Error: fsp->fh->fd == -1\n"));
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)));
327 TALLOC_FREE(frame);
328 return ret == 0;
331 /* nfs4_set_nt_acl()
332 * set the local file's acls obtaining it in NT form
333 * using the NFSv4 format conversion
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)
339 return smb_set_nt_acl_nfs4(handle, fsp, security_info_sent, psd,
340 nfs4acl_xattr_fset_smb4acl);
343 static struct SMB4ACL_T *nfs4acls_defaultacl(TALLOC_CTX *mem_ctx)
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,
352 .aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE,
353 .aceFlags = 0,
354 .aceMask = SMB_ACE4_ALL_MASKS,
357 DEBUG(10, ("Building default full access acl\n"));
359 pacl = smb_create_smb4acl(mem_ctx);
360 if (pacl == NULL) {
361 DEBUG(0, ("talloc failed\n"));
362 errno = ENOMEM;
363 return NULL;
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;
374 return pacl;
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.
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
402 * Todo: Really use mem_ctx after fixing interface of nfs4_acls
404 static struct SMB4ACL_T *nfs4acls_inheritacl(vfs_handle_struct *handle,
405 const char *path,
406 TALLOC_CTX *mem_ctx)
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();
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;
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;
436 isdir = S_ISDIR(smb_fname->st.st_ex_mode);
438 if (!parent_dirname(talloc_tos(),
439 path,
440 &parent_dir,
441 NULL)) {
442 TALLOC_FREE(frame);
443 errno = ENOMEM;
444 return NULL;
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);
453 else if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
454 pparentacl = nfs4acls_defaultacl(frame);
457 else if (!NT_STATUS_IS_OK(status)) {
458 TALLOC_FREE(frame);
459 return NULL;
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;
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;
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;
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;
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;
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);
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);
514 TALLOC_FREE(frame);
515 return pchildacl;
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)
524 struct SMB4ACL_T *pacl;
525 NTSTATUS status;
526 TALLOC_CTX *frame = talloc_stackframe();
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);
533 else if (!NT_STATUS_IS_OK(status)) {
534 TALLOC_FREE(frame);
535 return status;
538 status = smb_fget_nt_acl_nfs4(fsp, security_info, mem_ctx, ppdesc, pacl);
539 TALLOC_FREE(frame);
540 return status;
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)
549 struct SMB4ACL_T *pacl;
550 NTSTATUS status;
551 const char *name = smb_fname->base_name;
552 TALLOC_CTX *frame = talloc_stackframe();
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);
558 else if (!NT_STATUS_IS_OK(status)) {
559 TALLOC_FREE(frame);
560 return status;
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;
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)
575 return nfs4_set_nt_acl(handle, fsp, security_info_sent, psd);
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
583 Function declarations taken from vfs_solarisacl
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)
591 return (SMB_ACL_T)NULL;
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)
598 return (SMB_ACL_T)NULL;
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)
606 return -1;
609 static int nfs4acl_xattr_fail__sys_acl_set_fd(vfs_handle_struct *handle,
610 files_struct *fsp,
611 SMB_ACL_T theacl)
613 return -1;
616 static int nfs4acl_xattr_fail__sys_acl_delete_def_file(vfs_handle_struct *handle,
617 const char *path)
619 return -1;
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)
624 return -1;
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)
629 return -1;
632 /* VFS operations structure */
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,
647 NTSTATUS vfs_nfs4acl_xattr_init(void);
648 NTSTATUS vfs_nfs4acl_xattr_init(void)
650 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "nfs4acl_xattr",
651 &nfs4acl_xattr_fns);