r20261: merge 20260 from samba_3_0_24
[abartlet/samba.git/.git] / source3 / modules / vfs_gpfs.c
1 /*
2    Unix SMB/CIFS implementation.
3    Wrap gpfs calls in vfs functions.
4  
5    Copyright (C) Christian Ambach <cambach1@de.ibm.com> 2006
6    
7    Major code contributions by Chetan Shringarpure <chetan.sh@in.ibm.com>
8                             and Gomati Mohanan <gomati.mohanan@in.ibm.com>
9    
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23   
24
25 */
26
27 #include "includes.h"
28
29 #undef DBGC_CLASS
30 #define DBGC_CLASS DBGC_VFS
31
32 #include <gpfs_gpl.h>
33 #include "nfs4_acls.h"
34
35
36 static int vfs_gpfs_kernel_flock(vfs_handle_struct *handle, files_struct *fsp, 
37                                  int fd, uint32 share_mode)
38 {
39
40         START_PROFILE(syscall_kernel_flock);
41
42         kernel_flock(fsp->fh->fd, share_mode);
43
44         if (!set_gpfs_sharemode(fsp, fsp->access_mask, fsp->share_access)) {
45
46                 return -1;
47
48         }
49
50         END_PROFILE(syscall_kernel_flock);
51
52         return 0;
53 }
54
55 static void gpfs_dumpacl(int level, struct gpfs_acl *gacl)
56 {
57         int     i;
58         if (gacl==NULL)
59         {
60                 DEBUG(0, ("gpfs acl is NULL\n"));
61                 return;
62         }
63
64         DEBUG(level, ("gpfs acl: nace: %d, type:%d, version:%d, level:%d, len:%d\n",
65                 gacl->acl_nace, gacl->acl_type, gacl->acl_version, gacl->acl_level, gacl->acl_len));
66         for(i=0; i<gacl->acl_nace; i++)
67         {
68                 struct gpfs_ace_v4 *gace = gacl->ace_v4 + i;
69                 DEBUG(level, ("\tace[%d]: type:%d, flags:0x%x, mask:0x%x, iflags:0x%x, who:%u\n",
70                         i, gace->aceType, gace->aceFlags, gace->aceMask,
71                         gace->aceIFlags, gace->aceWho));
72         }
73 }
74
75 static struct gpfs_acl *gpfs_getacl_alloc(const char *fname, gpfs_aclType_t type)
76 {
77         struct gpfs_acl *acl;
78         size_t len = 200;
79         int ret;
80         TALLOC_CTX *mem_ctx = main_loop_talloc_get();
81
82         acl = (struct gpfs_acl *)talloc_size(mem_ctx, len);
83         if (acl == NULL) {
84                 errno = ENOMEM;
85                 return NULL;
86         }
87
88         acl->acl_len = len;
89         acl->acl_level = 0;
90         acl->acl_version = 0;
91         acl->acl_type = type;
92
93         ret = smbd_gpfs_getacl((char *)fname, GPFS_GETACL_STRUCT | GPFS_ACL_SAMBA, acl);
94         if ((ret != 0) && (errno == ENOSPC)) {
95                 struct gpfs_acl *new_acl = (struct gpfs_acl *)talloc_size(
96                         mem_ctx, acl->acl_len + sizeof(struct gpfs_acl));
97                 if (new_acl == NULL) {
98                         errno = ENOMEM;
99                         return NULL;
100                 }
101
102                 new_acl->acl_len = acl->acl_len;
103                 new_acl->acl_level = acl->acl_level;
104                 new_acl->acl_version = acl->acl_version;
105                 new_acl->acl_type = acl->acl_type;
106                 acl = new_acl;
107
108                 ret = smbd_gpfs_getacl((char *)fname, GPFS_GETACL_STRUCT | GPFS_ACL_SAMBA, acl);
109         }
110         if (ret != 0)
111         {
112                 DEBUG(8, ("smbd_gpfs_getacl failed with %s\n",strerror(errno)));
113                 return NULL;
114         }
115
116         return acl;
117 }
118
119 static BOOL gpfs_get_nfs4_acl(struct files_struct *fsp, SMB4ACL_T **ppacl, BOOL *pretryPosix)
120 {
121         TALLOC_CTX *mem_ctx;
122         int i;
123         struct gpfs_acl *gacl = NULL;
124
125         mem_ctx = main_loop_talloc_get();
126
127         DEBUG(10, ("gpfs_get_nfs4_acl invoked for %s\n", fsp->fsp_name));
128
129         /* First get the real acl length */
130         gacl = gpfs_getacl_alloc(fsp->fsp_name, GPFS_ACL_TYPE_NFS4);
131         if (gacl == NULL) {
132                 DEBUG(9, ("gpfs_getacl failed for %s with %s\n",
133                            fsp->fsp_name, strerror(errno)));
134                 return False;
135         }
136
137         if (gacl->acl_type != GPFS_ACL_TYPE_NFS4) {
138                 DEBUG(10, ("Got non-nfsv4 acl\n"));
139                 *pretryPosix = True;
140                 return False;
141         }
142
143         *ppacl = smb_create_smb4acl();
144
145         DEBUG(10, ("len: %d, level: %d, version: %d, nace: %d\n",
146                    gacl->acl_len, gacl->acl_level, gacl->acl_version,
147                    gacl->acl_nace));
148
149         for (i=0; i<gacl->acl_nace; i++) {
150                 struct gpfs_ace_v4 *gace = &gacl->ace_v4[i];
151                 SMB_ACE4PROP_T smbace;
152                 memset(&smbace, 0, sizeof(SMB4ACE_T));
153
154                 DEBUG(10, ("type: %d, iflags: %x, flags: %x, mask: %x, "
155                            "who: %d\n", gace->aceType, gace->aceIFlags,
156                            gace->aceFlags, gace->aceMask, gace->aceWho));
157
158                 if (gace->aceIFlags & ACE4_IFLAG_SPECIAL_ID) {
159                         smbace.flags |= SMB_ACE4_ID_SPECIAL;
160                         switch (gace->aceWho) {
161                         case ACE4_SPECIAL_OWNER:
162                                 smbace.who.special_id = SMB_ACE4_WHO_OWNER;
163                                 break;
164                         case ACE4_SPECIAL_GROUP:
165                                 smbace.who.special_id = SMB_ACE4_WHO_GROUP;
166                                 break;
167                         case ACE4_SPECIAL_EVERYONE:
168                                 smbace.who.special_id = SMB_ACE4_WHO_EVERYONE;
169                                 break;
170                         default:
171                                 DEBUG(8, ("invalid special gpfs id %d "
172                                           "ignored\n", gace->aceWho));
173                                 continue; /* don't add it */
174                         }
175                 } else {
176                         if (gace->aceFlags & ACE4_FLAG_GROUP_ID)
177                                 smbace.who.gid = gace->aceWho;
178                         else
179                                 smbace.who.uid = gace->aceWho;
180                 }
181
182                 smbace.aceType = gace->aceType;
183                 smbace.aceFlags = gace->aceFlags;
184                 smbace.aceMask = gace->aceMask;
185                 smbace.flags = (gace->aceIFlags&ACE4_IFLAG_SPECIAL_ID) ? SMB_ACE4_ID_SPECIAL : 0;
186
187                 smb_add_ace4(*ppacl, &smbace);
188         }
189
190         return True;
191 }
192
193 static size_t gpfsacl_get_nt_acl_common(files_struct *fsp,
194         uint32 security_info, SEC_DESC **ppdesc)
195 {
196         SMB4ACL_T *pacl = NULL;
197         BOOL    result;
198         BOOL    retryPosix = False;
199
200         *ppdesc = NULL;
201         result = gpfs_get_nfs4_acl(fsp, &pacl, &retryPosix);
202         if (retryPosix)
203         {
204                 DEBUG(10, ("retrying with posix acl...\n"));
205                 return get_nt_acl(fsp, security_info, ppdesc);
206         }
207         if (result==False)
208                 return 0;
209
210         return smb_get_nt_acl_nfs4(fsp, security_info, ppdesc, pacl);
211 }
212
213 size_t gpfsacl_fget_nt_acl(vfs_handle_struct *handle,
214         files_struct *fsp, int fd, uint32 security_info,
215         SEC_DESC **ppdesc)
216 {
217         return gpfsacl_get_nt_acl_common(fsp, security_info, ppdesc);
218 }
219
220 size_t gpfsacl_get_nt_acl(vfs_handle_struct *handle,
221         files_struct *fsp, const char *name,
222         uint32 security_info, SEC_DESC **ppdesc)
223 {
224         return gpfsacl_get_nt_acl_common(fsp, security_info, ppdesc);
225 }
226
227 static BOOL gpfsacl_process_smbacl(files_struct *fsp, SMB4ACL_T *smbacl)
228 {
229         int ret;
230         gpfs_aclLen_t gacl_len;
231         SMB4ACE_T       *smbace;
232         struct gpfs_acl *gacl;
233         TALLOC_CTX *mem_ctx  = main_loop_talloc_get();
234
235         gacl_len = sizeof(struct gpfs_acl) +
236                 (smb_get_naces(smbacl)-1)*sizeof(gpfs_ace_v4_t);
237
238         gacl = talloc_size(mem_ctx, gacl_len);
239         if (gacl == NULL) {
240                 DEBUG(0, ("talloc failed\n"));
241                 errno = ENOMEM;
242                 return False;
243         }
244
245         gacl->acl_len = gacl_len;
246         gacl->acl_level = 0;
247         gacl->acl_version = GPFS_ACL_VERSION_NFS4;
248         gacl->acl_type = GPFS_ACL_TYPE_NFS4;
249         gacl->acl_nace = 0; /* change later... */
250
251         for (smbace=smb_first_ace4(smbacl); smbace!=NULL; smbace = smb_next_ace4(smbace)) {
252                 struct gpfs_ace_v4 *gace = &gacl->ace_v4[gacl->acl_nace];
253                 SMB_ACE4PROP_T  *aceprop = smb_get_ace4(smbace);
254
255                 gace->aceType = aceprop->aceType;
256                 gace->aceFlags = aceprop->aceFlags;
257                 gace->aceMask = aceprop->aceMask;
258                 gace->aceIFlags = (aceprop->flags&SMB_ACE4_ID_SPECIAL) ? ACE4_IFLAG_SPECIAL_ID : 0;
259
260                 if (aceprop->flags&SMB_ACE4_ID_SPECIAL)
261                 {
262                         switch(aceprop->who.special_id)
263                         {
264                         case SMB_ACE4_WHO_EVERYONE:
265                                 gace->aceWho = ACE4_SPECIAL_EVERYONE;
266                                 break;
267                         case SMB_ACE4_WHO_OWNER:
268                                 gace->aceWho = ACE4_SPECIAL_OWNER;
269                                 break;
270                         case SMB_ACE4_WHO_GROUP:
271                                 gace->aceWho = ACE4_SPECIAL_GROUP;
272                                 break;
273                         default:
274                                 DEBUG(8, ("unsupported special_id %d\n", aceprop->who.special_id));
275                                 continue; /* don't add it !!! */
276                         }
277                 } else {
278                         /* just only for the type safety... */
279                         if (aceprop->aceFlags&SMB_ACE4_IDENTIFIER_GROUP)
280                                 gace->aceWho = aceprop->who.gid;
281                         else
282                                 gace->aceWho = aceprop->who.uid;
283                 }
284
285                 gacl->acl_nace++;
286         }
287
288         ret = smbd_gpfs_putacl(fsp->fsp_name, GPFS_PUTACL_STRUCT | GPFS_ACL_SAMBA, gacl);
289         if (ret != 0) {
290                 DEBUG(8, ("gpfs_putacl failed with %s\n", strerror(errno)));
291                 gpfs_dumpacl(8, gacl);
292                 return False;
293         }
294
295         DEBUG(10, ("gpfs_putacl succeeded\n"));
296         return True;
297 }
298
299 static BOOL gpfsacl_set_nt_acl_internal(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
300 {
301         struct gpfs_acl *acl;
302         BOOL    result = False;
303
304         acl = gpfs_getacl_alloc(fsp->fsp_name, GPFS_ACL_TYPE_ACCESS);
305         if (acl == NULL)
306                 return False;
307
308         if (acl->acl_version&GPFS_ACL_VERSION_NFS4)
309         {
310                 result = smb_set_nt_acl_nfs4(
311                         fsp, security_info_sent, psd,
312                         gpfsacl_process_smbacl);
313         } else { /* assume POSIX ACL - by default... */
314                 result = set_nt_acl(fsp, security_info_sent, psd);
315         }
316
317         return result;
318 }
319
320 static BOOL gpfsacl_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info_sent, SEC_DESC *psd)
321 {
322         return gpfsacl_set_nt_acl_internal(fsp, security_info_sent, psd);
323 }
324
325 static BOOL gpfsacl_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, char *name, uint32 security_info_sent, SEC_DESC *psd)
326 {
327         return gpfsacl_set_nt_acl_internal(fsp, security_info_sent, psd);
328 }
329
330 static SMB_ACL_T gpfs2smb_acl(const struct gpfs_acl *pacl)
331 {
332         SMB_ACL_T result;
333         int i;
334
335         result = sys_acl_init(pacl->acl_nace);
336         if (result == NULL) {
337                 errno = ENOMEM;
338                 return NULL;
339         }
340
341         result->count = pacl->acl_nace;
342
343         for (i=0; i<pacl->acl_nace; i++) {
344                 struct smb_acl_entry *ace = &result->acl[i];
345                 const struct gpfs_ace_v1 *g_ace = &pacl->ace_v1[i];
346
347                 DEBUG(10, ("Converting type %d id %lu perm %x\n",
348                            (int)g_ace->ace_type, (unsigned long)g_ace->ace_who,
349                            (int)g_ace->ace_perm));
350
351                 switch (g_ace->ace_type) {
352                 case GPFS_ACL_USER:
353                         ace->a_type = SMB_ACL_USER;
354                         ace->uid = (uid_t)g_ace->ace_who;
355                         break;
356                 case GPFS_ACL_USER_OBJ:
357                         ace->a_type = SMB_ACL_USER_OBJ;
358                         break;
359                 case GPFS_ACL_GROUP:
360                         ace->a_type = SMB_ACL_GROUP;
361                         ace->gid = (gid_t)g_ace->ace_who;
362                         break;
363                 case GPFS_ACL_GROUP_OBJ:
364                         ace->a_type = SMB_ACL_GROUP_OBJ;
365                         break;
366                 case GPFS_ACL_OTHER:
367                         ace->a_type = SMB_ACL_OTHER;
368                         break;
369                 case GPFS_ACL_MASK:
370                         ace->a_type = SMB_ACL_MASK;
371                         break;
372                 default:
373                         DEBUG(10, ("Got invalid ace_type: %d\n",
374                                    g_ace->ace_type));
375                         errno = EINVAL;
376                         SAFE_FREE(result);
377                         return NULL;
378                 }
379
380                 ace->a_perm = 0;
381                 ace->a_perm |= (g_ace->ace_perm & ACL_PERM_READ) ?
382                         SMB_ACL_READ : 0;
383                 ace->a_perm |= (g_ace->ace_perm & ACL_PERM_WRITE) ?
384                         SMB_ACL_WRITE : 0;
385                 ace->a_perm |= (g_ace->ace_perm & ACL_PERM_EXECUTE) ?
386                         SMB_ACL_EXECUTE : 0;
387
388                 DEBUGADD(10, ("Converted to %d perm %x\n",
389                               ace->a_type, ace->a_perm));
390         }
391
392         return result;
393 }
394
395 static SMB_ACL_T gpfsacl_get_posix_acl(const char *path, gpfs_aclType_t type)
396 {
397         struct gpfs_acl *pacl;
398         SMB_ACL_T result = NULL;
399
400         pacl = gpfs_getacl_alloc(path, type);
401
402         if (pacl == NULL) {
403                 DEBUG(10, ("gpfs_getacl failed for %s with %s\n",
404                            path, strerror(errno)));
405                 if (errno == 0) {
406                         errno = EINVAL;
407                 }
408                 goto done;
409         }
410
411         if (pacl->acl_version != GPFS_ACL_VERSION_POSIX) {
412                 DEBUG(10, ("Got acl version %d, expected %d\n",
413                            pacl->acl_version, GPFS_ACL_VERSION_POSIX));
414                 errno = EINVAL;
415                 goto done;
416         }
417         
418         DEBUG(10, ("len: %d, level: %d, version: %d, nace: %d\n",
419                    pacl->acl_len, pacl->acl_level, pacl->acl_version,
420                    pacl->acl_nace));
421
422         result = gpfs2smb_acl(pacl);
423         if (result == NULL) {
424                 goto done;
425         }
426
427  done:
428
429         if (errno != 0) {
430                 SAFE_FREE(result);
431         }
432         return result;  
433 }
434
435 SMB_ACL_T gpfsacl_sys_acl_get_file(vfs_handle_struct *handle,
436                                     
437                                     const char *path_p,
438                                     SMB_ACL_TYPE_T type)
439 {
440         gpfs_aclType_t gpfs_type;
441
442         switch(type) {
443         case SMB_ACL_TYPE_ACCESS:
444                 gpfs_type = GPFS_ACL_TYPE_ACCESS;
445                 break;
446         case SMB_ACL_TYPE_DEFAULT:
447                 gpfs_type = GPFS_ACL_TYPE_DEFAULT;
448                 break;
449         default:
450                 DEBUG(0, ("Got invalid type: %d\n", type));
451                 smb_panic("exiting");
452         }
453
454         return gpfsacl_get_posix_acl(path_p, gpfs_type);
455 }
456
457 SMB_ACL_T gpfsacl_sys_acl_get_fd(vfs_handle_struct *handle,
458                                   files_struct *fsp,
459                                   int fd)
460 {
461         return gpfsacl_get_posix_acl(fsp->fsp_name, GPFS_ACL_TYPE_ACCESS);
462 }
463
464 static struct gpfs_acl *smb2gpfs_acl(const SMB_ACL_T pacl,
465                                      SMB_ACL_TYPE_T type)
466 {
467         gpfs_aclLen_t len;
468         struct gpfs_acl *result;
469         int i;
470         union gpfs_ace_union
471         {
472                 gpfs_ace_v1_t  ace_v1[1]; /* when GPFS_ACL_VERSION_POSIX */
473                 gpfs_ace_v4_t  ace_v4[1]; /* when GPFS_ACL_VERSION_NFS4  */
474         };
475
476         DEBUG(10, ("smb2gpfs_acl: Got ACL with %d entries\n", pacl->count));
477
478         len = sizeof(struct gpfs_acl) - sizeof(union gpfs_ace_union) +
479                 (pacl->count)*sizeof(gpfs_ace_v1_t);
480
481         result = SMB_MALLOC(len);
482         if (result == NULL) {
483                 errno = ENOMEM;
484                 return result;
485         }
486
487         result->acl_len = len;
488         result->acl_level = 0;
489         result->acl_version = GPFS_ACL_VERSION_POSIX;
490         result->acl_type = (type == SMB_ACL_TYPE_DEFAULT) ?
491                 GPFS_ACL_TYPE_DEFAULT : GPFS_ACL_TYPE_ACCESS;
492         result->acl_nace = pacl->count;
493
494         for (i=0; i<pacl->count; i++) {
495                 const struct smb_acl_entry *ace = &pacl->acl[i];
496                 struct gpfs_ace_v1 *g_ace = &result->ace_v1[i];
497                 
498                 DEBUG(10, ("Converting type %d perm %x\n",
499                            (int)ace->a_type, (int)ace->a_perm));
500
501                 g_ace->ace_perm = 0;
502
503                 switch(ace->a_type) {
504                 case SMB_ACL_USER:
505                         g_ace->ace_type = GPFS_ACL_USER;
506                         g_ace->ace_who = (gpfs_uid_t)ace->uid;
507                         break;
508                 case SMB_ACL_USER_OBJ:
509                         g_ace->ace_type = GPFS_ACL_USER_OBJ;
510                         g_ace->ace_perm |= ACL_PERM_CONTROL;
511                         g_ace->ace_who = 0;
512                         break;
513                 case SMB_ACL_GROUP:
514                         g_ace->ace_type = GPFS_ACL_GROUP;
515                         g_ace->ace_who = (gpfs_uid_t)ace->gid;
516                         break;
517                 case SMB_ACL_GROUP_OBJ:
518                         g_ace->ace_type = GPFS_ACL_GROUP_OBJ;
519                         g_ace->ace_who = 0;
520                         break;
521                 case SMB_ACL_MASK:
522                         g_ace->ace_type = GPFS_ACL_MASK;
523                         g_ace->ace_perm = 0x8f;
524                         g_ace->ace_who = 0;
525                         break;
526                 case SMB_ACL_OTHER:
527                         g_ace->ace_type = GPFS_ACL_OTHER;
528                         g_ace->ace_who = 0;
529                         break;
530                 default:
531                         DEBUG(10, ("Got invalid ace_type: %d\n", ace->a_type));
532                         errno = EINVAL;
533                         SAFE_FREE(result);
534                         return NULL;
535                 }
536
537                 g_ace->ace_perm |= (ace->a_perm & SMB_ACL_READ) ?
538                         ACL_PERM_READ : 0;
539                 g_ace->ace_perm |= (ace->a_perm & SMB_ACL_WRITE) ?
540                         ACL_PERM_WRITE : 0;
541                 g_ace->ace_perm |= (ace->a_perm & SMB_ACL_EXECUTE) ?
542                         ACL_PERM_EXECUTE : 0;
543
544                 DEBUGADD(10, ("Converted to %d id %d perm %x\n",
545                               g_ace->ace_type, g_ace->ace_who, g_ace->ace_perm));
546         }
547
548         return result;
549 }
550
551 int gpfsacl_sys_acl_set_file(vfs_handle_struct *handle,
552                               
553                               const char *name,
554                               SMB_ACL_TYPE_T type,
555                               SMB_ACL_T theacl)
556 {
557         struct gpfs_acl *gpfs_acl;
558         int result;
559
560         gpfs_acl = smb2gpfs_acl(theacl, type);
561         if (gpfs_acl == NULL) {
562                 return -1;
563         }
564
565         result = smbd_gpfs_putacl((char *)name, GPFS_PUTACL_STRUCT | GPFS_ACL_SAMBA, gpfs_acl);
566
567         SAFE_FREE(gpfs_acl);
568         return result;
569 }
570
571 int gpfsacl_sys_acl_set_fd(vfs_handle_struct *handle,
572                             files_struct *fsp,
573                             int fd, SMB_ACL_T theacl)
574 {
575         errno = ENOTSUP;
576         return -1;
577 }
578
579 int gpfsacl_sys_acl_delete_def_file(vfs_handle_struct *handle,
580                                      
581                                      const char *path)
582 {
583         errno = ENOTSUP;
584         return -1;
585 }
586
587 /* VFS operations structure */
588
589 static vfs_op_tuple gpfs_op_tuples[] = {
590
591         {SMB_VFS_OP(vfs_gpfs_kernel_flock),
592          SMB_VFS_OP_KERNEL_FLOCK,
593          SMB_VFS_LAYER_OPAQUE},
594
595         {SMB_VFS_OP(gpfsacl_fget_nt_acl),
596         SMB_VFS_OP_FGET_NT_ACL,
597         SMB_VFS_LAYER_TRANSPARENT},
598
599         {SMB_VFS_OP(gpfsacl_get_nt_acl),
600         SMB_VFS_OP_GET_NT_ACL,
601         SMB_VFS_LAYER_TRANSPARENT},
602
603         {SMB_VFS_OP(gpfsacl_fset_nt_acl),
604         SMB_VFS_OP_FSET_NT_ACL,
605         SMB_VFS_LAYER_TRANSPARENT},
606
607         {SMB_VFS_OP(gpfsacl_set_nt_acl),
608         SMB_VFS_OP_SET_NT_ACL,
609         SMB_VFS_LAYER_TRANSPARENT},
610
611         {SMB_VFS_OP(gpfsacl_sys_acl_get_file),
612          SMB_VFS_OP_SYS_ACL_GET_FILE,
613          SMB_VFS_LAYER_TRANSPARENT},
614
615         {SMB_VFS_OP(gpfsacl_sys_acl_get_fd),
616          SMB_VFS_OP_SYS_ACL_GET_FD,
617          SMB_VFS_LAYER_TRANSPARENT},
618
619         {SMB_VFS_OP(gpfsacl_sys_acl_set_file),
620          SMB_VFS_OP_SYS_ACL_SET_FILE,
621          SMB_VFS_LAYER_TRANSPARENT},
622
623         {SMB_VFS_OP(gpfsacl_sys_acl_set_fd),
624          SMB_VFS_OP_SYS_ACL_SET_FD,
625          SMB_VFS_LAYER_TRANSPARENT},
626
627         {SMB_VFS_OP(gpfsacl_sys_acl_delete_def_file),
628          SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE,
629          SMB_VFS_LAYER_TRANSPARENT},
630
631         {SMB_VFS_OP(NULL),
632          SMB_VFS_OP_NOOP,
633          SMB_VFS_LAYER_NOOP}
634
635 };
636
637
638 NTSTATUS vfs_gpfs_init(void);
639 NTSTATUS vfs_gpfs_init(void)
640 {
641         init_gpfs();
642         
643         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "gpfs",
644                                 gpfs_op_tuples);
645 }