gpfs: Include gpfs_fcntl.h only from vfs_gpfs header file
[samba.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 3 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, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "smbd/smbd.h"
26 #include "librpc/gen_ndr/ndr_xattr.h"
27 #include "include/smbprofile.h"
28 #include "modules/non_posix_acls.h"
29 #include "libcli/security/security.h"
30
31 #undef DBGC_CLASS
32 #define DBGC_CLASS DBGC_VFS
33
34 #include "nfs4_acls.h"
35 #include "vfs_gpfs.h"
36 #include "system/filesys.h"
37 #include "auth.h"
38 #include "lib/util/tevent_unix.h"
39
40 #ifndef GPFS_GETACL_NATIVE
41 #define GPFS_GETACL_NATIVE 0x00000004
42 #endif
43
44 struct gpfs_config_data {
45         bool sharemodes;
46         bool leases;
47         bool hsm;
48         bool syncio;
49         bool winattr;
50         bool ftruncate;
51         bool getrealfilename;
52         bool dfreequota;
53         bool prealloc;
54         bool acl;
55         bool settimes;
56         bool recalls;
57 };
58
59 static inline unsigned int gpfs_acl_flags(gpfs_acl_t *gacl)
60 {
61         if (gacl->acl_level == 1) { /* GPFS_ACL_LEVEL_V4FLAGS */
62                 /* gacl->v4Level1.acl_flags requires gpfs 3.5 */
63                 return *(unsigned int *)&gacl->ace_v4;
64         }
65         return 0;
66 }
67
68 static inline gpfs_ace_v4_t *gpfs_ace_ptr(gpfs_acl_t *gacl, unsigned int i)
69 {
70         if (gacl->acl_level == 1) { /* GPFS_ACL_LEVEL_V4FLAGS */
71                 /* &gacl->v4Level1.ace_v4[i] requires gpfs 3.5 */
72                 char *ptr = (char *)&gacl->ace_v4[i] + sizeof(unsigned int);
73                 return (gpfs_ace_v4_t *)ptr;
74         }
75         return &gacl->ace_v4[i];
76 }
77
78 static bool set_gpfs_sharemode(files_struct *fsp, uint32 access_mask,
79                                uint32 share_access)
80 {
81         unsigned int allow = GPFS_SHARE_NONE;
82         unsigned int deny = GPFS_DENY_NONE;
83         int result;
84
85         if ((fsp == NULL) || (fsp->fh == NULL) || (fsp->fh->fd < 0)) {
86                 /* No real file, don't disturb */
87                 return True;
88         }
89
90         allow |= (access_mask & (FILE_WRITE_DATA|FILE_APPEND_DATA|
91                                  DELETE_ACCESS)) ? GPFS_SHARE_WRITE : 0;
92         allow |= (access_mask & (FILE_READ_DATA|FILE_EXECUTE)) ?
93                 GPFS_SHARE_READ : 0;
94
95         if (allow == GPFS_SHARE_NONE) {
96                 DEBUG(10, ("special case am=no_access:%x\n",access_mask));
97         }
98         else {
99                 deny |= (share_access & FILE_SHARE_WRITE) ?
100                         0 : GPFS_DENY_WRITE;
101                 deny |= (share_access & (FILE_SHARE_READ)) ?
102                         0 : GPFS_DENY_READ;
103         }
104         DEBUG(10, ("am=%x, allow=%d, sa=%x, deny=%d\n",
105                    access_mask, allow, share_access, deny));
106
107         result = gpfswrap_set_share(fsp->fh->fd, allow, deny);
108         if (result != 0) {
109                 if (errno == ENOSYS) {
110                         DEBUG(5, ("VFS module vfs_gpfs loaded, but gpfs "
111                                   "set_share function support not available. "
112                                   "Allowing access\n"));
113                         return True;
114                 } else {
115                         DEBUG(10, ("gpfs_set_share failed: %s\n",
116                                    strerror(errno)));
117                 }
118         }
119
120         return (result == 0);
121 }
122
123 static int vfs_gpfs_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
124                                  uint32 share_mode, uint32 access_mask)
125 {
126
127         struct gpfs_config_data *config;
128         int ret = 0;
129
130         START_PROFILE(syscall_kernel_flock);
131
132         SMB_VFS_HANDLE_GET_DATA(handle, config,
133                                 struct gpfs_config_data,
134                                 return -1);
135
136         if(!config->sharemodes) {
137                 return 0;
138         }
139
140         kernel_flock(fsp->fh->fd, share_mode, access_mask);
141
142         if (!set_gpfs_sharemode(fsp, access_mask, fsp->share_access)) {
143                 ret = -1;
144         }
145
146         END_PROFILE(syscall_kernel_flock);
147
148         return ret;
149 }
150
151 static int vfs_gpfs_close(vfs_handle_struct *handle, files_struct *fsp)
152 {
153
154         struct gpfs_config_data *config;
155
156         SMB_VFS_HANDLE_GET_DATA(handle, config,
157                                 struct gpfs_config_data,
158                                 return -1);
159
160         if (config->sharemodes && (fsp->fh != NULL) && (fsp->fh->fd != -1)) {
161                 set_gpfs_sharemode(fsp, 0, 0);
162         }
163
164         return SMB_VFS_NEXT_CLOSE(handle, fsp);
165 }
166
167 static int set_gpfs_lease(int fd, int leasetype)
168 {
169         int gpfs_type = GPFS_LEASE_NONE;
170
171         if (leasetype == F_RDLCK) {
172                 gpfs_type = GPFS_LEASE_READ;
173         }
174         if (leasetype == F_WRLCK) {
175                 gpfs_type = GPFS_LEASE_WRITE;
176         }
177
178         /* we unconditionally set CAP_LEASE, rather than looking for
179            -1/EACCES as there is a bug in some versions of
180            libgpfs_gpl.so which results in a leaked fd on /dev/ss0
181            each time we try this with the wrong capabilities set
182         */
183         linux_set_lease_capability();
184         return gpfswrap_set_lease(fd, gpfs_type);
185 }
186
187 static int vfs_gpfs_setlease(vfs_handle_struct *handle, files_struct *fsp, 
188                              int leasetype)
189 {
190         struct gpfs_config_data *config;
191         int ret=0;
192
193         START_PROFILE(syscall_linux_setlease);
194
195         SMB_VFS_HANDLE_GET_DATA(handle, config,
196                                 struct gpfs_config_data,
197                                 return -1);
198
199         if (linux_set_lease_sighandler(fsp->fh->fd) == -1)
200                 return -1;
201
202         if (config->leases) {
203                 /*
204                  * Ensure the lease owner is root to allow
205                  * correct delivery of lease-break signals.
206                  */
207                 become_root();
208                 ret = set_gpfs_lease(fsp->fh->fd,leasetype);
209                 unbecome_root();
210         }
211
212         END_PROFILE(syscall_linux_setlease);
213
214         return ret;
215 }
216
217 static int vfs_gpfs_get_real_filename(struct vfs_handle_struct *handle,
218                                       const char *path,
219                                       const char *name,
220                                       TALLOC_CTX *mem_ctx,
221                                       char **found_name)
222 {
223         int result;
224         char *full_path;
225         char real_pathname[PATH_MAX+1];
226         int buflen;
227         bool mangled;
228         struct gpfs_config_data *config;
229
230         SMB_VFS_HANDLE_GET_DATA(handle, config,
231                                 struct gpfs_config_data,
232                                 return -1);
233
234         if (!config->getrealfilename) {
235                 return SMB_VFS_NEXT_GET_REAL_FILENAME(handle, path, name,
236                                                       mem_ctx, found_name);
237         }
238
239         mangled = mangle_is_mangled(name, handle->conn->params);
240         if (mangled) {
241                 return SMB_VFS_NEXT_GET_REAL_FILENAME(handle, path, name,
242                                                       mem_ctx, found_name);
243         }
244
245         full_path = talloc_asprintf(talloc_tos(), "%s/%s", path, name);
246         if (full_path == NULL) {
247                 errno = ENOMEM;
248                 return -1;
249         }
250
251         buflen = sizeof(real_pathname) - 1;
252
253         result = gpfswrap_get_realfilename_path(full_path, real_pathname,
254                                                 &buflen);
255
256         TALLOC_FREE(full_path);
257
258         if ((result == -1) && (errno == ENOSYS)) {
259                 return SMB_VFS_NEXT_GET_REAL_FILENAME(
260                         handle, path, name, mem_ctx, found_name);
261         }
262
263         if (result == -1) {
264                 DEBUG(10, ("smbd_gpfs_get_realfilename_path returned %s\n",
265                            strerror(errno)));
266                 return -1;
267         }
268
269         /*
270          * GPFS does not necessarily null-terminate the returned path
271          * but instead returns the buffer length in buflen.
272          */
273
274         if (buflen < sizeof(real_pathname)) {
275                 real_pathname[buflen] = '\0';
276         } else {
277                 real_pathname[sizeof(real_pathname)-1] = '\0';
278         }
279
280         DEBUG(10, ("smbd_gpfs_get_realfilename_path: %s/%s -> %s\n",
281                    path, name, real_pathname));
282
283         name = strrchr_m(real_pathname, '/');
284         if (name == NULL) {
285                 errno = ENOENT;
286                 return -1;
287         }
288
289         *found_name = talloc_strdup(mem_ctx, name+1);
290         if (*found_name == NULL) {
291                 errno = ENOMEM;
292                 return -1;
293         }
294
295         return 0;
296 }
297
298 static void sd2gpfs_control(uint16_t control, struct gpfs_acl *gacl)
299 {
300         unsigned int gpfs_aclflags = 0;
301         control &= SEC_DESC_DACL_PROTECTED | SEC_DESC_SACL_PROTECTED |
302                 SEC_DESC_DACL_AUTO_INHERITED | SEC_DESC_SACL_AUTO_INHERITED |
303                 SEC_DESC_DACL_DEFAULTED | SEC_DESC_SACL_DEFAULTED |
304                 SEC_DESC_DACL_PRESENT | SEC_DESC_SACL_PRESENT;
305         gpfs_aclflags = control << 8;
306         if (!(control & SEC_DESC_DACL_PRESENT))
307                 gpfs_aclflags |= 0x00800000; /* ACL4_FLAG_NULL_DACL; */
308         if (!(control & SEC_DESC_SACL_PRESENT))
309                 gpfs_aclflags |= 0x01000000; /* ACL4_FLAG_NULL_SACL; */
310         gacl->acl_level = 1; /* GPFS_ACL_LEVEL_V4FLAGS*/
311         /* gacl->v4Level1.acl_flags requires gpfs 3.5 */
312         *(unsigned int *)&gacl->ace_v4 = gpfs_aclflags;
313 }
314
315 static uint16_t gpfs2sd_control(unsigned int gpfs_aclflags)
316 {
317         uint16_t control = gpfs_aclflags >> 8;
318         control &= SEC_DESC_DACL_PROTECTED | SEC_DESC_SACL_PROTECTED |
319                 SEC_DESC_DACL_AUTO_INHERITED | SEC_DESC_SACL_AUTO_INHERITED |
320                 SEC_DESC_DACL_DEFAULTED | SEC_DESC_SACL_DEFAULTED |
321                 SEC_DESC_DACL_PRESENT | SEC_DESC_SACL_PRESENT;
322         control |= SEC_DESC_SELF_RELATIVE;
323         return control;
324 }
325
326 static void gpfs_dumpacl(int level, struct gpfs_acl *gacl)
327 {
328         gpfs_aclCount_t i;
329         if (gacl==NULL)
330         {
331                 DEBUG(0, ("gpfs acl is NULL\n"));
332                 return;
333         }
334
335         DEBUG(level, ("len: %d, level: %d, version: %d, nace: %d, "
336                       "control: %x\n",
337                       gacl->acl_len, gacl->acl_level, gacl->acl_version,
338                       gacl->acl_nace, gpfs_acl_flags(gacl)));
339
340         for(i=0; i<gacl->acl_nace; i++)
341         {
342                 struct gpfs_ace_v4 *gace = gpfs_ace_ptr(gacl, i);
343                 DEBUG(level, ("\tace[%d]: type:%d, flags:0x%x, mask:0x%x, "
344                               "iflags:0x%x, who:%u\n",
345                               i, gace->aceType, gace->aceFlags, gace->aceMask,
346                               gace->aceIFlags, gace->aceWho));
347         }
348 }
349
350 /*
351  * get the ACL from GPFS, allocated on the specified mem_ctx
352  * internally retries when initial buffer was too small
353  *
354  * caller needs to cast result to either
355  * raw = yes: struct gpfs_opaque_acl
356  * raw = no: struct gpfs_acl
357  *
358  */
359 static void *vfs_gpfs_getacl(TALLOC_CTX *mem_ctx,
360                          const char *fname,
361                          const bool raw,
362                          const gpfs_aclType_t type)
363 {
364
365         void *aclbuf;
366         size_t size = 512;
367         int ret, flags;
368         unsigned int *len;
369         size_t struct_size;
370
371 again:
372
373         aclbuf = talloc_zero_size(mem_ctx, size);
374         if (aclbuf == NULL) {
375                 errno = ENOMEM;
376                 return NULL;
377         }
378
379         if (raw) {
380                 struct gpfs_opaque_acl *buf = (struct gpfs_opaque_acl *) aclbuf;
381                 buf->acl_type = type;
382                 flags = GPFS_GETACL_NATIVE;
383                 len = (unsigned int *) &(buf->acl_buffer_len);
384                 struct_size = sizeof(struct gpfs_opaque_acl);
385         } else {
386                 struct gpfs_acl *buf = (struct gpfs_acl *) aclbuf;
387                 buf->acl_type = type;
388                 buf->acl_level = 1; /* GPFS_ACL_LEVEL_V4FLAGS */
389                 flags = GPFS_GETACL_STRUCT;
390                 len = &(buf->acl_len);
391                 /* reserve space for control flags in gpfs 3.5 and beyond */
392                 struct_size = sizeof(struct gpfs_acl) + sizeof(unsigned int);
393         }
394
395         /* set the length of the buffer as input value */
396         *len = size;
397
398         errno = 0;
399         ret = gpfswrap_getacl(discard_const_p(char, fname), flags, aclbuf);
400         if ((ret != 0) && (errno == ENOSPC)) {
401                 /*
402                  * get the size needed to accommodate the complete buffer
403                  *
404                  * the value returned only applies to the ACL blob in the
405                  * struct so make sure to also have headroom for the first
406                  * struct members by adding room for the complete struct
407                  * (might be a few bytes too much then)
408                  */
409                 size = *len + struct_size;
410                 talloc_free(aclbuf);
411                 DEBUG(10, ("Increasing ACL buffer size to %zu\n", size));
412                 goto again;
413         }
414
415         if (ret != 0) {
416                 DEBUG(5, ("smbd_gpfs_getacl failed with %s\n",
417                           strerror(errno)));
418                 talloc_free(aclbuf);
419                 return NULL;
420         }
421
422         return aclbuf;
423 }
424
425 /* Tries to get nfs4 acls and returns SMB ACL allocated.
426  * On failure returns 1 if it got non-NFSv4 ACL to prompt 
427  * retry with POSIX ACL checks.
428  * On failure returns -1 if there is system (GPFS) error, check errno.
429  * Returns 0 on success
430  */
431 static int gpfs_get_nfs4_acl(TALLOC_CTX *mem_ctx, const char *fname, SMB4ACL_T **ppacl)
432 {
433         gpfs_aclCount_t i;
434         struct gpfs_acl *gacl = NULL;
435         DEBUG(10, ("gpfs_get_nfs4_acl invoked for %s\n", fname));
436
437         /* Get the ACL */
438         gacl = (struct gpfs_acl*) vfs_gpfs_getacl(talloc_tos(), fname,
439                                                   false, 0);
440         if (gacl == NULL) {
441                 DEBUG(9, ("gpfs_getacl failed for %s with %s\n",
442                            fname, strerror(errno)));
443                 return -1;
444         }
445
446         if (gacl->acl_type != GPFS_ACL_TYPE_NFS4) {
447                 DEBUG(10, ("Got non-nfsv4 acl\n"));
448                 /* Retry with POSIX ACLs check */
449                 talloc_free(gacl);
450                 return 1;
451         }
452
453         *ppacl = smb_create_smb4acl(mem_ctx);
454
455         if (gacl->acl_level == 1) { /* GPFS_ACL_LEVEL_V4FLAGS */
456                 uint16_t control = gpfs2sd_control(gpfs_acl_flags(gacl));
457                 smbacl4_set_controlflags(*ppacl, control);
458         }
459
460         DEBUG(10, ("len: %d, level: %d, version: %d, nace: %d, control: %x\n",
461                    gacl->acl_len, gacl->acl_level, gacl->acl_version,
462                    gacl->acl_nace, gpfs_acl_flags(gacl)));
463
464         for (i=0; i<gacl->acl_nace; i++) {
465                 struct gpfs_ace_v4 *gace = gpfs_ace_ptr(gacl, i);
466                 SMB_ACE4PROP_T smbace;
467                 DEBUG(10, ("type: %d, iflags: %x, flags: %x, mask: %x, "
468                            "who: %d\n", gace->aceType, gace->aceIFlags,
469                            gace->aceFlags, gace->aceMask, gace->aceWho));
470
471                 ZERO_STRUCT(smbace);
472                 if (gace->aceIFlags & ACE4_IFLAG_SPECIAL_ID) {
473                         smbace.flags |= SMB_ACE4_ID_SPECIAL;
474                         switch (gace->aceWho) {
475                         case ACE4_SPECIAL_OWNER:
476                                 smbace.who.special_id = SMB_ACE4_WHO_OWNER;
477                                 break;
478                         case ACE4_SPECIAL_GROUP:
479                                 smbace.who.special_id = SMB_ACE4_WHO_GROUP;
480                                 break;
481                         case ACE4_SPECIAL_EVERYONE:
482                                 smbace.who.special_id = SMB_ACE4_WHO_EVERYONE;
483                                 break;
484                         default:
485                                 DEBUG(8, ("invalid special gpfs id %d "
486                                           "ignored\n", gace->aceWho));
487                                 continue; /* don't add it */
488                         }
489                 } else {
490                         if (gace->aceFlags & ACE4_FLAG_GROUP_ID)
491                                 smbace.who.gid = gace->aceWho;
492                         else
493                                 smbace.who.uid = gace->aceWho;
494                 }
495
496                 /* remove redundant deny entries */
497                 if (i > 0 && gace->aceType == SMB_ACE4_ACCESS_DENIED_ACE_TYPE) {
498                         struct gpfs_ace_v4 *prev = gpfs_ace_ptr(gacl, i - 1);
499                         if (prev->aceType == SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE &&
500                             prev->aceFlags == gace->aceFlags &&
501                             prev->aceIFlags == gace->aceIFlags &&
502                             (gace->aceMask & prev->aceMask) == 0 &&
503                             gace->aceWho == prev->aceWho) {
504                                 /* it's redundant - skip it */
505                                 continue;
506                         }
507                 }
508
509                 smbace.aceType = gace->aceType;
510                 smbace.aceFlags = gace->aceFlags;
511                 smbace.aceMask = gace->aceMask;
512                 smb_add_ace4(*ppacl, &smbace);
513         }
514
515         talloc_free(gacl);
516
517         return 0;
518 }
519
520 static NTSTATUS gpfsacl_fget_nt_acl(vfs_handle_struct *handle,
521         files_struct *fsp, uint32 security_info,
522         TALLOC_CTX *mem_ctx,
523         struct security_descriptor **ppdesc)
524 {
525         SMB4ACL_T *pacl = NULL;
526         int     result;
527         struct gpfs_config_data *config;
528         TALLOC_CTX *frame = talloc_stackframe();
529         NTSTATUS status;
530
531         *ppdesc = NULL;
532
533         SMB_VFS_HANDLE_GET_DATA(handle, config,
534                                 struct gpfs_config_data,
535                                 return NT_STATUS_INTERNAL_ERROR);
536
537         if (!config->acl) {
538                 status = SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, security_info,
539                                                   mem_ctx, ppdesc);
540                 TALLOC_FREE(frame);
541                 return status;
542         }
543
544         result = gpfs_get_nfs4_acl(frame, fsp->fsp_name->base_name, &pacl);
545
546         if (result == 0) {
547                 status = smb_fget_nt_acl_nfs4(fsp, security_info, mem_ctx,
548                                               ppdesc, pacl);
549                 TALLOC_FREE(frame);
550                 return status;
551         }
552
553         if (result > 0) {
554                 DEBUG(10, ("retrying with posix acl...\n"));
555                 status = posix_fget_nt_acl(fsp, security_info,
556                                            mem_ctx, ppdesc);
557                 TALLOC_FREE(frame);
558                 return status;
559         }
560
561         TALLOC_FREE(frame);
562
563         /* GPFS ACL was not read, something wrong happened, error code is set in errno */
564         return map_nt_error_from_unix(errno);
565 }
566
567 static NTSTATUS gpfsacl_get_nt_acl(vfs_handle_struct *handle,
568         const char *name,
569         uint32 security_info,
570         TALLOC_CTX *mem_ctx, struct security_descriptor **ppdesc)
571 {
572         SMB4ACL_T *pacl = NULL;
573         int     result;
574         struct gpfs_config_data *config;
575         TALLOC_CTX *frame = talloc_stackframe();
576         NTSTATUS status;
577
578         *ppdesc = NULL;
579
580         SMB_VFS_HANDLE_GET_DATA(handle, config,
581                                 struct gpfs_config_data,
582                                 return NT_STATUS_INTERNAL_ERROR);
583
584         if (!config->acl) {
585                 status = SMB_VFS_NEXT_GET_NT_ACL(handle, name, security_info,
586                                                  mem_ctx, ppdesc);
587                 TALLOC_FREE(frame);
588                 return status;
589         }
590
591         result = gpfs_get_nfs4_acl(frame, name, &pacl);
592
593         if (result == 0) {
594                 status = smb_get_nt_acl_nfs4(handle->conn, name, security_info,
595                                            mem_ctx, ppdesc, pacl);
596                 TALLOC_FREE(frame);
597                 return status;
598         }
599
600         if (result > 0) {
601                 DEBUG(10, ("retrying with posix acl...\n"));
602                 status =  posix_get_nt_acl(handle->conn, name, security_info,
603                                            mem_ctx, ppdesc);
604                 TALLOC_FREE(frame);
605                 return status;
606         }
607
608         /* GPFS ACL was not read, something wrong happened, error code is set in errno */
609         TALLOC_FREE(frame);
610         return map_nt_error_from_unix(errno);
611 }
612
613 static struct gpfs_acl *vfs_gpfs_smbacl2gpfsacl(TALLOC_CTX *mem_ctx,
614                                                 files_struct *fsp,
615                                                 SMB4ACL_T *smbacl,
616                                                 bool controlflags)
617 {
618         struct gpfs_acl *gacl;
619         gpfs_aclLen_t gacl_len;
620         SMB4ACE_T *smbace;
621
622         gacl_len = offsetof(gpfs_acl_t, ace_v4) + sizeof(unsigned int)
623                 + smb_get_naces(smbacl) * sizeof(gpfs_ace_v4_t);
624
625         gacl = (struct gpfs_acl *)TALLOC_SIZE(mem_ctx, gacl_len);
626         if (gacl == NULL) {
627                 DEBUG(0, ("talloc failed\n"));
628                 errno = ENOMEM;
629                 return NULL;
630         }
631
632         gacl->acl_level = 0; /* GPFS_ACL_LEVEL_BASE */
633         gacl->acl_version = GPFS_ACL_VERSION_NFS4;
634         gacl->acl_type = GPFS_ACL_TYPE_NFS4;
635         gacl->acl_nace = 0; /* change later... */
636
637         if (controlflags) {
638                 gacl->acl_level = 1; /* GPFS_ACL_LEVEL_V4FLAGS */
639                 sd2gpfs_control(smbacl4_get_controlflags(smbacl), gacl);
640         }
641
642         for (smbace=smb_first_ace4(smbacl); smbace!=NULL; smbace = smb_next_ace4(smbace)) {
643                 struct gpfs_ace_v4 *gace = gpfs_ace_ptr(gacl, gacl->acl_nace);
644                 SMB_ACE4PROP_T  *aceprop = smb_get_ace4(smbace);
645
646                 gace->aceType = aceprop->aceType;
647                 gace->aceFlags = aceprop->aceFlags;
648                 gace->aceMask = aceprop->aceMask;
649
650                 /*
651                  * GPFS can't distinguish between WRITE and APPEND on
652                  * files, so one being set without the other is an
653                  * error. Sorry for the many ()'s :-)
654                  */
655
656                 if (!fsp->is_directory
657                     &&
658                     ((((gace->aceMask & ACE4_MASK_WRITE) == 0)
659                       && ((gace->aceMask & ACE4_MASK_APPEND) != 0))
660                      ||
661                      (((gace->aceMask & ACE4_MASK_WRITE) != 0)
662                       && ((gace->aceMask & ACE4_MASK_APPEND) == 0)))
663                     &&
664                     lp_parm_bool(fsp->conn->params->service, "gpfs",
665                                  "merge_writeappend", True)) {
666                         DEBUG(2, ("vfs_gpfs.c: file [%s]: ACE contains "
667                                   "WRITE^APPEND, setting WRITE|APPEND\n",
668                                   fsp_str_dbg(fsp)));
669                         gace->aceMask |= ACE4_MASK_WRITE|ACE4_MASK_APPEND;
670                 }
671
672                 gace->aceIFlags = (aceprop->flags&SMB_ACE4_ID_SPECIAL) ? ACE4_IFLAG_SPECIAL_ID : 0;
673
674                 if (aceprop->flags&SMB_ACE4_ID_SPECIAL)
675                 {
676                         switch(aceprop->who.special_id)
677                         {
678                         case SMB_ACE4_WHO_EVERYONE:
679                                 gace->aceWho = ACE4_SPECIAL_EVERYONE;
680                                 break;
681                         case SMB_ACE4_WHO_OWNER:
682                                 gace->aceWho = ACE4_SPECIAL_OWNER;
683                                 break;
684                         case SMB_ACE4_WHO_GROUP:
685                                 gace->aceWho = ACE4_SPECIAL_GROUP;
686                                 break;
687                         default:
688                                 DEBUG(8, ("unsupported special_id %d\n", aceprop->who.special_id));
689                                 continue; /* don't add it !!! */
690                         }
691                 } else {
692                         /* just only for the type safety... */
693                         if (aceprop->aceFlags&SMB_ACE4_IDENTIFIER_GROUP)
694                                 gace->aceWho = aceprop->who.gid;
695                         else
696                                 gace->aceWho = aceprop->who.uid;
697                 }
698
699                 gacl->acl_nace++;
700         }
701         gacl->acl_len = (char *)gpfs_ace_ptr(gacl, gacl->acl_nace)
702                 - (char *)gacl;
703         return gacl;
704 }
705
706 static bool gpfsacl_process_smbacl(vfs_handle_struct *handle,
707                                    files_struct *fsp,
708                                    SMB4ACL_T *smbacl)
709 {
710         int ret;
711         struct gpfs_acl *gacl;
712         TALLOC_CTX *mem_ctx = talloc_tos();
713
714         gacl = vfs_gpfs_smbacl2gpfsacl(mem_ctx, fsp, smbacl, true);
715         if (gacl == NULL) { /* out of memory */
716                 return False;
717         }
718         ret = gpfswrap_putacl(fsp->fsp_name->base_name,
719                               GPFS_PUTACL_STRUCT | GPFS_ACL_SAMBA, gacl);
720
721         if ((ret != 0) && (errno == EINVAL)) {
722                 DEBUG(10, ("Retry without nfs41 control flags\n"));
723                 talloc_free(gacl);
724                 gacl = vfs_gpfs_smbacl2gpfsacl(mem_ctx, fsp, smbacl, false);
725                 if (gacl == NULL) { /* out of memory */
726                         return False;
727                 }
728                 ret = gpfswrap_putacl(fsp->fsp_name->base_name,
729                                       GPFS_PUTACL_STRUCT | GPFS_ACL_SAMBA,
730                                       gacl);
731         }
732
733         if (ret != 0) {
734                 DEBUG(8, ("gpfs_putacl failed with %s\n", strerror(errno)));
735                 gpfs_dumpacl(8, gacl);
736                 return False;
737         }
738
739         DEBUG(10, ("gpfs_putacl succeeded\n"));
740         return True;
741 }
742
743 static NTSTATUS gpfsacl_set_nt_acl_internal(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info_sent, const struct security_descriptor *psd)
744 {
745         struct gpfs_acl *acl;
746         NTSTATUS result = NT_STATUS_ACCESS_DENIED;
747
748         acl = (struct gpfs_acl*) vfs_gpfs_getacl(talloc_tos(),
749                                                  fsp->fsp_name->base_name,
750                                                  false, 0);
751         if (acl == NULL) {
752                 return map_nt_error_from_unix(errno);
753         }
754
755         if (acl->acl_version == GPFS_ACL_VERSION_NFS4) {
756                 if (lp_parm_bool(fsp->conn->params->service, "gpfs",
757                                  "refuse_dacl_protected", false)
758                     && (psd->type&SEC_DESC_DACL_PROTECTED)) {
759                         DEBUG(2, ("Rejecting unsupported ACL with DACL_PROTECTED bit set\n"));
760                         talloc_free(acl);
761                         return NT_STATUS_NOT_SUPPORTED;
762                 }
763
764                 result = smb_set_nt_acl_nfs4(handle,
765                         fsp, security_info_sent, psd,
766                         gpfsacl_process_smbacl);
767         } else { /* assume POSIX ACL - by default... */
768                 result = set_nt_acl(fsp, security_info_sent, psd);
769         }
770
771         talloc_free(acl);
772         return result;
773 }
774
775 static NTSTATUS gpfsacl_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info_sent, const struct security_descriptor *psd)
776 {
777         struct gpfs_config_data *config;
778
779         SMB_VFS_HANDLE_GET_DATA(handle, config,
780                                 struct gpfs_config_data,
781                                 return NT_STATUS_INTERNAL_ERROR);
782
783         if (!config->acl) {
784                 return SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd);
785         }
786
787         return gpfsacl_set_nt_acl_internal(handle, fsp, security_info_sent, psd);
788 }
789
790 static SMB_ACL_T gpfs2smb_acl(const struct gpfs_acl *pacl, TALLOC_CTX *mem_ctx)
791 {
792         SMB_ACL_T result;
793         gpfs_aclCount_t i;
794
795         result = sys_acl_init(mem_ctx);
796         if (result == NULL) {
797                 errno = ENOMEM;
798                 return NULL;
799         }
800
801         result->count = pacl->acl_nace;
802         result->acl = talloc_realloc(result, result->acl, struct smb_acl_entry,
803                                      result->count);
804         if (result->acl == NULL) {
805                 TALLOC_FREE(result);
806                 errno = ENOMEM;
807                 return NULL;
808         }
809
810         for (i=0; i<pacl->acl_nace; i++) {
811                 struct smb_acl_entry *ace = &result->acl[i];
812                 const struct gpfs_ace_v1 *g_ace = &pacl->ace_v1[i];
813
814                 DEBUG(10, ("Converting type %d id %lu perm %x\n",
815                            (int)g_ace->ace_type, (unsigned long)g_ace->ace_who,
816                            (int)g_ace->ace_perm));
817
818                 switch (g_ace->ace_type) {
819                 case GPFS_ACL_USER:
820                         ace->a_type = SMB_ACL_USER;
821                         ace->info.user.uid = (uid_t)g_ace->ace_who;
822                         break;
823                 case GPFS_ACL_USER_OBJ:
824                         ace->a_type = SMB_ACL_USER_OBJ;
825                         break;
826                 case GPFS_ACL_GROUP:
827                         ace->a_type = SMB_ACL_GROUP;
828                         ace->info.group.gid = (gid_t)g_ace->ace_who;
829                         break;
830                 case GPFS_ACL_GROUP_OBJ:
831                         ace->a_type = SMB_ACL_GROUP_OBJ;
832                         break;
833                 case GPFS_ACL_OTHER:
834                         ace->a_type = SMB_ACL_OTHER;
835                         break;
836                 case GPFS_ACL_MASK:
837                         ace->a_type = SMB_ACL_MASK;
838                         break;
839                 default:
840                         DEBUG(10, ("Got invalid ace_type: %d\n",
841                                    g_ace->ace_type));
842                         TALLOC_FREE(result);
843                         errno = EINVAL;
844                         return NULL;
845                 }
846
847                 ace->a_perm = 0;
848                 ace->a_perm |= (g_ace->ace_perm & ACL_PERM_READ) ?
849                         SMB_ACL_READ : 0;
850                 ace->a_perm |= (g_ace->ace_perm & ACL_PERM_WRITE) ?
851                         SMB_ACL_WRITE : 0;
852                 ace->a_perm |= (g_ace->ace_perm & ACL_PERM_EXECUTE) ?
853                         SMB_ACL_EXECUTE : 0;
854
855                 DEBUGADD(10, ("Converted to %d perm %x\n",
856                               ace->a_type, ace->a_perm));
857         }
858
859         return result;
860 }
861
862 static SMB_ACL_T gpfsacl_get_posix_acl(const char *path, gpfs_aclType_t type,
863                                        TALLOC_CTX *mem_ctx)
864 {
865         struct gpfs_acl *pacl;
866         SMB_ACL_T result = NULL;
867
868         pacl = vfs_gpfs_getacl(talloc_tos(), path, false, type);
869
870         if (pacl == NULL) {
871                 DEBUG(10, ("vfs_gpfs_getacl failed for %s with %s\n",
872                            path, strerror(errno)));
873                 if (errno == 0) {
874                         errno = EINVAL;
875                 }
876                 goto done;
877         }
878
879         if (pacl->acl_version != GPFS_ACL_VERSION_POSIX) {
880                 DEBUG(10, ("Got acl version %d, expected %d\n",
881                            pacl->acl_version, GPFS_ACL_VERSION_POSIX));
882                 errno = EINVAL;
883                 goto done;
884         }
885
886         DEBUG(10, ("len: %d, level: %d, version: %d, nace: %d\n",
887                    pacl->acl_len, pacl->acl_level, pacl->acl_version,
888                    pacl->acl_nace));
889
890         result = gpfs2smb_acl(pacl, mem_ctx);
891         if (result != NULL) {
892                 errno = 0;
893         }
894
895  done:
896
897         if (pacl != NULL) {
898                 talloc_free(pacl);
899         }
900         if (errno != 0) {
901                 TALLOC_FREE(result);
902         }
903         return result;
904 }
905
906 static SMB_ACL_T gpfsacl_sys_acl_get_file(vfs_handle_struct *handle,
907                                           const char *path_p,
908                                           SMB_ACL_TYPE_T type,
909                                           TALLOC_CTX *mem_ctx)
910 {
911         gpfs_aclType_t gpfs_type;
912         struct gpfs_config_data *config;
913
914         SMB_VFS_HANDLE_GET_DATA(handle, config,
915                                 struct gpfs_config_data,
916                                 return NULL);
917
918         if (!config->acl) {
919                 return SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, path_p,
920                                                      type, mem_ctx);
921         }
922
923         switch(type) {
924         case SMB_ACL_TYPE_ACCESS:
925                 gpfs_type = GPFS_ACL_TYPE_ACCESS;
926                 break;
927         case SMB_ACL_TYPE_DEFAULT:
928                 gpfs_type = GPFS_ACL_TYPE_DEFAULT;
929                 break;
930         default:
931                 DEBUG(0, ("Got invalid type: %d\n", type));
932                 smb_panic("exiting");
933         }
934
935         return gpfsacl_get_posix_acl(path_p, gpfs_type, mem_ctx);
936 }
937
938 static SMB_ACL_T gpfsacl_sys_acl_get_fd(vfs_handle_struct *handle,
939                                         files_struct *fsp,
940                                         TALLOC_CTX *mem_ctx)
941 {
942         struct gpfs_config_data *config;
943
944         SMB_VFS_HANDLE_GET_DATA(handle, config,
945                                 struct gpfs_config_data,
946                                 return NULL);
947
948         if (!config->acl) {
949                 return SMB_VFS_NEXT_SYS_ACL_GET_FD(handle, fsp, mem_ctx);
950         }
951
952         return gpfsacl_get_posix_acl(fsp->fsp_name->base_name,
953                                      GPFS_ACL_TYPE_ACCESS, mem_ctx);
954 }
955
956 static int gpfsacl_sys_acl_blob_get_file(vfs_handle_struct *handle,
957                                       const char *path_p,
958                                       TALLOC_CTX *mem_ctx,
959                                       char **blob_description,
960                                       DATA_BLOB *blob)
961 {
962         struct gpfs_config_data *config;
963         struct gpfs_opaque_acl *acl = NULL;
964         DATA_BLOB aclblob;
965         int result;
966
967         SMB_VFS_HANDLE_GET_DATA(handle, config,
968                                 struct gpfs_config_data,
969                                 return -1);
970
971         if (!config->acl) {
972                 return SMB_VFS_NEXT_SYS_ACL_BLOB_GET_FILE(handle, path_p,
973                                                           mem_ctx,
974                                                           blob_description,
975                                                           blob);
976         }
977
978         errno = 0;
979         acl = (struct gpfs_opaque_acl *)
980                         vfs_gpfs_getacl(mem_ctx,
981                                         path_p,
982                                         true,
983                                         GPFS_ACL_TYPE_NFS4);
984
985         if (errno) {
986                 DEBUG(5, ("vfs_gpfs_getacl finished with errno %d: %s\n",
987                                         errno, strerror(errno)));
988
989                 /* EINVAL means POSIX ACL, bail out on other cases */
990                 if (errno != EINVAL) {
991                         return -1;
992                 }
993         }
994
995         if (acl != NULL) {
996                 /*
997                  * file has NFSv4 ACL
998                  *
999                  * we only need the actual ACL blob here
1000                  * acl_version will always be NFS4 because we asked
1001                  * for NFS4
1002                  * acl_type is only used for POSIX ACLs
1003                  */
1004                 aclblob.data = (uint8_t*) acl->acl_var_data;
1005                 aclblob.length = acl->acl_buffer_len;
1006
1007                 *blob_description = talloc_strdup(mem_ctx, "gpfs_nfs4_acl");
1008                 if (!*blob_description) {
1009                         talloc_free(acl);
1010                         errno = ENOMEM;
1011                         return -1;
1012                 }
1013
1014                 result = non_posix_sys_acl_blob_get_file_helper(handle, path_p,
1015                                                                 aclblob,
1016                                                                 mem_ctx, blob);
1017
1018                 talloc_free(acl);
1019                 return result;
1020         }
1021
1022         /* fall back to POSIX ACL */
1023         return posix_sys_acl_blob_get_file(handle, path_p, mem_ctx,
1024                                            blob_description, blob);
1025 }
1026
1027 static int gpfsacl_sys_acl_blob_get_fd(vfs_handle_struct *handle,
1028                                       files_struct *fsp,
1029                                       TALLOC_CTX *mem_ctx,
1030                                       char **blob_description,
1031                                       DATA_BLOB *blob)
1032 {
1033         struct gpfs_config_data *config;
1034         struct gpfs_opaque_acl *acl = NULL;
1035         DATA_BLOB aclblob;
1036         int result;
1037
1038         SMB_VFS_HANDLE_GET_DATA(handle, config,
1039                                 struct gpfs_config_data,
1040                                 return -1);
1041
1042         if (!config->acl) {
1043                 return SMB_VFS_NEXT_SYS_ACL_BLOB_GET_FD(handle, fsp, mem_ctx,
1044                                                         blob_description, blob);
1045         }
1046
1047         errno = 0;
1048         acl = (struct gpfs_opaque_acl *) vfs_gpfs_getacl(mem_ctx,
1049                                                 fsp->fsp_name->base_name,
1050                                                 true,
1051                                                 GPFS_ACL_TYPE_NFS4);
1052
1053         if (errno) {
1054                 DEBUG(5, ("vfs_gpfs_getacl finished with errno %d: %s\n",
1055                                         errno, strerror(errno)));
1056
1057                 /* EINVAL means POSIX ACL, bail out on other cases */
1058                 if (errno != EINVAL) {
1059                         return -1;
1060                 }
1061         }
1062
1063         if (acl != NULL) {
1064                 /*
1065                  * file has NFSv4 ACL
1066                  *
1067                  * we only need the actual ACL blob here
1068                  * acl_version will always be NFS4 because we asked
1069                  * for NFS4
1070                  * acl_type is only used for POSIX ACLs
1071                  */
1072                 aclblob.data = (uint8_t*) acl->acl_var_data;
1073                 aclblob.length = acl->acl_buffer_len;
1074
1075                 *blob_description = talloc_strdup(mem_ctx, "gpfs_nfs4_acl");
1076                 if (!*blob_description) {
1077                         talloc_free(acl);
1078                         errno = ENOMEM;
1079                         return -1;
1080                 }
1081
1082                 result = non_posix_sys_acl_blob_get_fd_helper(handle, fsp,
1083                                                               aclblob, mem_ctx,
1084                                                               blob);
1085
1086                 talloc_free(acl);
1087                 return result;
1088         }
1089
1090         /* fall back to POSIX ACL */
1091         return posix_sys_acl_blob_get_fd(handle, fsp, mem_ctx,
1092                                          blob_description, blob);
1093 }
1094
1095 static struct gpfs_acl *smb2gpfs_acl(const SMB_ACL_T pacl,
1096                                      SMB_ACL_TYPE_T type)
1097 {
1098         gpfs_aclLen_t len;
1099         struct gpfs_acl *result;
1100         int i;
1101
1102         DEBUG(10, ("smb2gpfs_acl: Got ACL with %d entries\n", pacl->count));
1103
1104         len = offsetof(gpfs_acl_t, ace_v1) + (pacl->count) *
1105                 sizeof(gpfs_ace_v1_t);
1106
1107         result = (struct gpfs_acl *)SMB_MALLOC(len);
1108         if (result == NULL) {
1109                 errno = ENOMEM;
1110                 return result;
1111         }
1112
1113         result->acl_len = len;
1114         result->acl_level = 0;
1115         result->acl_version = GPFS_ACL_VERSION_POSIX;
1116         result->acl_type = (type == SMB_ACL_TYPE_DEFAULT) ?
1117                 GPFS_ACL_TYPE_DEFAULT : GPFS_ACL_TYPE_ACCESS;
1118         result->acl_nace = pacl->count;
1119
1120         for (i=0; i<pacl->count; i++) {
1121                 const struct smb_acl_entry *ace = &pacl->acl[i];
1122                 struct gpfs_ace_v1 *g_ace = &result->ace_v1[i];
1123
1124                 DEBUG(10, ("Converting type %d perm %x\n",
1125                            (int)ace->a_type, (int)ace->a_perm));
1126
1127                 g_ace->ace_perm = 0;
1128
1129                 switch(ace->a_type) {
1130                 case SMB_ACL_USER:
1131                         g_ace->ace_type = GPFS_ACL_USER;
1132                         g_ace->ace_who = (gpfs_uid_t)ace->info.user.uid;
1133                         break;
1134                 case SMB_ACL_USER_OBJ:
1135                         g_ace->ace_type = GPFS_ACL_USER_OBJ;
1136                         g_ace->ace_perm |= ACL_PERM_CONTROL;
1137                         g_ace->ace_who = 0;
1138                         break;
1139                 case SMB_ACL_GROUP:
1140                         g_ace->ace_type = GPFS_ACL_GROUP;
1141                         g_ace->ace_who = (gpfs_uid_t)ace->info.group.gid;
1142                         break;
1143                 case SMB_ACL_GROUP_OBJ:
1144                         g_ace->ace_type = GPFS_ACL_GROUP_OBJ;
1145                         g_ace->ace_who = 0;
1146                         break;
1147                 case SMB_ACL_MASK:
1148                         g_ace->ace_type = GPFS_ACL_MASK;
1149                         g_ace->ace_perm = 0x8f;
1150                         g_ace->ace_who = 0;
1151                         break;
1152                 case SMB_ACL_OTHER:
1153                         g_ace->ace_type = GPFS_ACL_OTHER;
1154                         g_ace->ace_who = 0;
1155                         break;
1156                 default:
1157                         DEBUG(10, ("Got invalid ace_type: %d\n", ace->a_type));
1158                         errno = EINVAL;
1159                         SAFE_FREE(result);
1160                         return NULL;
1161                 }
1162
1163                 g_ace->ace_perm |= (ace->a_perm & SMB_ACL_READ) ?
1164                         ACL_PERM_READ : 0;
1165                 g_ace->ace_perm |= (ace->a_perm & SMB_ACL_WRITE) ?
1166                         ACL_PERM_WRITE : 0;
1167                 g_ace->ace_perm |= (ace->a_perm & SMB_ACL_EXECUTE) ?
1168                         ACL_PERM_EXECUTE : 0;
1169
1170                 DEBUGADD(10, ("Converted to %d id %d perm %x\n",
1171                               g_ace->ace_type, g_ace->ace_who, g_ace->ace_perm));
1172         }
1173
1174         return result;
1175 }
1176
1177 static int gpfsacl_sys_acl_set_file(vfs_handle_struct *handle,
1178                                     const char *name,
1179                                     SMB_ACL_TYPE_T type,
1180                                     SMB_ACL_T theacl)
1181 {
1182         struct gpfs_acl *gpfs_acl;
1183         int result;
1184         struct gpfs_config_data *config;
1185
1186         SMB_VFS_HANDLE_GET_DATA(handle, config,
1187                                 struct gpfs_config_data,
1188                                 return -1);
1189
1190         if (!config->acl) {
1191                 return SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, name, type, theacl);
1192         }
1193
1194         gpfs_acl = smb2gpfs_acl(theacl, type);
1195         if (gpfs_acl == NULL) {
1196                 return -1;
1197         }
1198
1199         result = gpfswrap_putacl(discard_const_p(char, name),
1200                                  GPFS_PUTACL_STRUCT|GPFS_ACL_SAMBA, gpfs_acl);
1201
1202         SAFE_FREE(gpfs_acl);
1203         return result;
1204 }
1205
1206 static int gpfsacl_sys_acl_set_fd(vfs_handle_struct *handle,
1207                                   files_struct *fsp,
1208                                   SMB_ACL_T theacl)
1209 {
1210         struct gpfs_config_data *config;
1211
1212         SMB_VFS_HANDLE_GET_DATA(handle, config,
1213                                 struct gpfs_config_data,
1214                                 return -1);
1215
1216         if (!config->acl) {
1217                 return SMB_VFS_NEXT_SYS_ACL_SET_FD(handle, fsp, theacl);
1218         }
1219
1220         return gpfsacl_sys_acl_set_file(handle, fsp->fsp_name->base_name,
1221                                         SMB_ACL_TYPE_ACCESS, theacl);
1222 }
1223
1224 static int gpfsacl_sys_acl_delete_def_file(vfs_handle_struct *handle,
1225                                            const char *path)
1226 {
1227         struct gpfs_config_data *config;
1228
1229         SMB_VFS_HANDLE_GET_DATA(handle, config,
1230                                 struct gpfs_config_data,
1231                                 return -1);
1232
1233         if (!config->acl) {
1234                 return SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, path);
1235         }
1236
1237         errno = ENOTSUP;
1238         return -1;
1239 }
1240
1241 /*
1242  * Assumed: mode bits are shiftable and standard
1243  * Output: the new aceMask field for an smb nfs4 ace
1244  */
1245 static uint32 gpfsacl_mask_filter(uint32 aceType, uint32 aceMask, uint32 rwx)
1246 {
1247         const uint32 posix_nfs4map[3] = {
1248                 SMB_ACE4_EXECUTE, /* execute */
1249                 SMB_ACE4_WRITE_DATA | SMB_ACE4_APPEND_DATA, /* write; GPFS specific */
1250                 SMB_ACE4_READ_DATA /* read */
1251         };
1252         int     i;
1253         uint32_t        posix_mask = 0x01;
1254         uint32_t        posix_bit;
1255         uint32_t        nfs4_bits;
1256
1257         for(i=0; i<3; i++) {
1258                 nfs4_bits = posix_nfs4map[i];
1259                 posix_bit = rwx & posix_mask;
1260
1261                 if (aceType==SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE) {
1262                         if (posix_bit)
1263                                 aceMask |= nfs4_bits;
1264                         else
1265                                 aceMask &= ~nfs4_bits;
1266                 } else {
1267                         /* add deny bits when suitable */
1268                         if (!posix_bit)
1269                                 aceMask |= nfs4_bits;
1270                         else
1271                                 aceMask &= ~nfs4_bits;
1272                 } /* other ace types are unexpected */
1273
1274                 posix_mask <<= 1;
1275         }
1276
1277         return aceMask;
1278 }
1279
1280 static int gpfsacl_emu_chmod(vfs_handle_struct *handle,
1281                              const char *path, mode_t mode)
1282 {
1283         SMB4ACL_T *pacl = NULL;
1284         int     result;
1285         bool    haveAllowEntry[SMB_ACE4_WHO_EVERYONE + 1] = {False, False, False, False};
1286         int     i;
1287         files_struct    fake_fsp; /* TODO: rationalize parametrization */
1288         SMB4ACE_T       *smbace;
1289         TALLOC_CTX *frame = talloc_stackframe();
1290
1291         DEBUG(10, ("gpfsacl_emu_chmod invoked for %s mode %o\n", path, mode));
1292
1293         result = gpfs_get_nfs4_acl(frame, path, &pacl);
1294         if (result) {
1295                 TALLOC_FREE(frame);
1296                 return result;
1297         }
1298
1299         if (mode & ~(S_IRWXU | S_IRWXG | S_IRWXO)) {
1300                 DEBUG(2, ("WARNING: cutting extra mode bits %o on %s\n", mode, path));
1301         }
1302
1303         for (smbace=smb_first_ace4(pacl); smbace!=NULL; smbace = smb_next_ace4(smbace)) {
1304                 SMB_ACE4PROP_T  *ace = smb_get_ace4(smbace);
1305                 uint32_t        specid = ace->who.special_id;
1306
1307                 if (ace->flags&SMB_ACE4_ID_SPECIAL &&
1308                     ace->aceType<=SMB_ACE4_ACCESS_DENIED_ACE_TYPE &&
1309                     specid <= SMB_ACE4_WHO_EVERYONE) {
1310
1311                         uint32_t newMask;
1312
1313                         if (ace->aceType==SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE)
1314                                 haveAllowEntry[specid] = True;
1315
1316                         /* mode >> 6 for @owner, mode >> 3 for @group,
1317                          * mode >> 0 for @everyone */
1318                         newMask = gpfsacl_mask_filter(ace->aceType, ace->aceMask,
1319                                                       mode >> ((SMB_ACE4_WHO_EVERYONE - specid) * 3));
1320                         if (ace->aceMask!=newMask) {
1321                                 DEBUG(10, ("ace changed for %s (%o -> %o) id=%d\n",
1322                                            path, ace->aceMask, newMask, specid));
1323                         }
1324                         ace->aceMask = newMask;
1325                 }
1326         }
1327
1328         /* make sure we have at least ALLOW entries
1329          * for all the 3 special ids (@EVERYONE, @OWNER, @GROUP)
1330          * - if necessary
1331          */
1332         for(i = SMB_ACE4_WHO_OWNER; i<=SMB_ACE4_WHO_EVERYONE; i++) {
1333                 SMB_ACE4PROP_T  ace;
1334
1335                 if (haveAllowEntry[i]==True)
1336                         continue;
1337
1338                 ZERO_STRUCT(ace);
1339                 ace.aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE;
1340                 ace.flags |= SMB_ACE4_ID_SPECIAL;
1341                 ace.who.special_id = i;
1342
1343                 if (i==SMB_ACE4_WHO_GROUP) /* not sure it's necessary... */
1344                         ace.aceFlags |= SMB_ACE4_IDENTIFIER_GROUP;
1345
1346                 ace.aceMask = gpfsacl_mask_filter(ace.aceType, ace.aceMask,
1347                                                   mode >> ((SMB_ACE4_WHO_EVERYONE - i) * 3));
1348
1349                 /* don't add unnecessary aces */
1350                 if (!ace.aceMask)
1351                         continue;
1352
1353                 /* we add it to the END - as windows expects allow aces */
1354                 smb_add_ace4(pacl, &ace);
1355                 DEBUG(10, ("Added ALLOW ace for %s, mode=%o, id=%d, aceMask=%x\n",
1356                            path, mode, i, ace.aceMask));
1357         }
1358
1359         /* don't add complementary DENY ACEs here */
1360         ZERO_STRUCT(fake_fsp);
1361         fake_fsp.fsp_name = synthetic_smb_fname(
1362                 frame, path, NULL, NULL);
1363         if (fake_fsp.fsp_name == NULL) {
1364                 errno = ENOMEM;
1365                 TALLOC_FREE(frame);
1366                 return -1;
1367         }
1368         /* put the acl */
1369         if (gpfsacl_process_smbacl(handle, &fake_fsp, pacl) == False) {
1370                 TALLOC_FREE(frame);
1371                 return -1;
1372         }
1373
1374         TALLOC_FREE(frame);
1375         return 0; /* ok for [f]chmod */
1376 }
1377
1378 static int vfs_gpfs_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
1379 {
1380         struct smb_filename *smb_fname_cpath;
1381         int rc;
1382
1383         smb_fname_cpath = synthetic_smb_fname(talloc_tos(), path, NULL, NULL);
1384         if (smb_fname_cpath == NULL) {
1385                 errno = ENOMEM;
1386                 return -1;
1387         }
1388
1389         if (SMB_VFS_NEXT_STAT(handle, smb_fname_cpath) != 0) {
1390                 return -1;
1391         }
1392
1393         /* avoid chmod() if possible, to preserve acls */
1394         if ((smb_fname_cpath->st.st_ex_mode & ~S_IFMT) == mode) {
1395                 return 0;
1396         }
1397
1398         rc = gpfsacl_emu_chmod(handle, path, mode);
1399         if (rc == 1)
1400                 return SMB_VFS_NEXT_CHMOD(handle, path, mode);
1401         return rc;
1402 }
1403
1404 static int vfs_gpfs_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
1405 {
1406                  SMB_STRUCT_STAT st;
1407                  int rc;
1408
1409                  if (SMB_VFS_NEXT_FSTAT(handle, fsp, &st) != 0) {
1410                          return -1;
1411                  }
1412
1413                  /* avoid chmod() if possible, to preserve acls */
1414                  if ((st.st_ex_mode & ~S_IFMT) == mode) {
1415                          return 0;
1416                  }
1417
1418                  rc = gpfsacl_emu_chmod(handle, fsp->fsp_name->base_name,
1419                                         mode);
1420                  if (rc == 1)
1421                          return SMB_VFS_NEXT_FCHMOD(handle, fsp, mode);
1422                  return rc;
1423 }
1424
1425 static int gpfs_set_xattr(struct vfs_handle_struct *handle,  const char *path,
1426                            const char *name, const void *value, size_t size,  int flags){
1427         struct xattr_DOSATTRIB dosattrib;
1428         enum ndr_err_code ndr_err;
1429         DATA_BLOB blob;
1430         unsigned int dosmode=0;
1431         struct gpfs_winattr attrs;
1432         int ret = 0;
1433         struct gpfs_config_data *config;
1434
1435         SMB_VFS_HANDLE_GET_DATA(handle, config,
1436                                 struct gpfs_config_data,
1437                                 return -1);
1438
1439         if (!config->winattr) {
1440                 DEBUG(10, ("gpfs_set_xattr:name is %s -> next\n",name));
1441                 return SMB_VFS_NEXT_SETXATTR(handle,path,name,value,size,flags);
1442         }
1443
1444         DEBUG(10, ("gpfs_set_xattr: %s \n",path));
1445
1446         /* Only handle DOS Attributes */
1447         if (strcmp(name,SAMBA_XATTR_DOS_ATTRIB) != 0){
1448                 DEBUG(5, ("gpfs_set_xattr:name is %s\n",name));
1449                 return SMB_VFS_NEXT_SETXATTR(handle,path,name,value,size,flags);
1450         }
1451
1452         blob.data = discard_const_p(uint8_t, value);
1453         blob.length = size;
1454
1455         ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &dosattrib,
1456                         (ndr_pull_flags_fn_t)ndr_pull_xattr_DOSATTRIB);
1457
1458         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1459                 DEBUG(1, ("gpfs_set_xattr: bad ndr decode "
1460                           "from EA on file %s: Error = %s\n",
1461                           path, ndr_errstr(ndr_err)));
1462                 return false;
1463         }
1464
1465         if (dosattrib.version != 3) {
1466                 DEBUG(1, ("gpfs_set_xattr: expected dosattrib version 3, got "
1467                           "%d\n", (int)dosattrib.version));
1468                 return false;
1469         }
1470         if (!(dosattrib.info.info3.valid_flags & XATTR_DOSINFO_ATTRIB)) {
1471                 DEBUG(10, ("gpfs_set_xattr: XATTR_DOSINFO_ATTRIB not "
1472                            "valid, ignoring\n"));
1473                 return true;
1474         }
1475
1476         dosmode = dosattrib.info.info3.attrib;
1477
1478         attrs.winAttrs = 0;
1479         /*Just map RD_ONLY, ARCHIVE, SYSTEM HIDDEN and SPARSE. Ignore the others*/
1480         if (dosmode & FILE_ATTRIBUTE_ARCHIVE){
1481                 attrs.winAttrs |= GPFS_WINATTR_ARCHIVE;
1482         }
1483         if (dosmode & FILE_ATTRIBUTE_HIDDEN){
1484                         attrs.winAttrs |= GPFS_WINATTR_HIDDEN;
1485                 }
1486         if (dosmode & FILE_ATTRIBUTE_SYSTEM){
1487                         attrs.winAttrs |= GPFS_WINATTR_SYSTEM;
1488                 }
1489         if (dosmode & FILE_ATTRIBUTE_READONLY){
1490                         attrs.winAttrs |= GPFS_WINATTR_READONLY;
1491         }
1492         if (dosmode & FILE_ATTRIBUTE_SPARSE) {
1493                 attrs.winAttrs |= GPFS_WINATTR_SPARSE_FILE;
1494         }
1495
1496
1497         ret = gpfswrap_set_winattrs_path(discard_const_p(char, path),
1498                                          GPFS_WINATTR_SET_ATTRS, &attrs);
1499         if ( ret == -1){
1500                 if (errno == ENOSYS) {
1501                         return SMB_VFS_NEXT_SETXATTR(handle, path, name, value,
1502                                                      size, flags);
1503                 }
1504
1505                 DEBUG(1, ("gpfs_set_xattr:Set GPFS attributes failed %d\n",ret));
1506                 return -1;
1507         }
1508
1509         DEBUG(10, ("gpfs_set_xattr:Set attributes: 0x%x\n",attrs.winAttrs));
1510         return 0;
1511 }
1512
1513 static ssize_t gpfs_get_xattr(struct vfs_handle_struct *handle,  const char *path,
1514                               const char *name, void *value, size_t size){
1515         char *attrstr = value;
1516         unsigned int dosmode = 0;
1517         struct gpfs_winattr attrs;
1518         int ret = 0;
1519         struct gpfs_config_data *config;
1520
1521         SMB_VFS_HANDLE_GET_DATA(handle, config,
1522                                 struct gpfs_config_data,
1523                                 return -1);
1524
1525         if (!config->winattr) {
1526                 DEBUG(10, ("gpfs_get_xattr:name is %s -> next\n",name));
1527                 return SMB_VFS_NEXT_GETXATTR(handle,path,name,value,size);
1528         }
1529
1530         DEBUG(10, ("gpfs_get_xattr: %s \n",path));
1531
1532         /* Only handle DOS Attributes */
1533         if (strcmp(name,SAMBA_XATTR_DOS_ATTRIB) != 0){
1534                 DEBUG(5, ("gpfs_get_xattr:name is %s\n",name));
1535                 return SMB_VFS_NEXT_GETXATTR(handle,path,name,value,size);
1536         }
1537
1538         ret = gpfswrap_get_winattrs_path(discard_const_p(char, path), &attrs);
1539         if ( ret == -1){
1540                 int dbg_lvl;
1541
1542                 if (errno == ENOSYS) {
1543                         return SMB_VFS_NEXT_GETXATTR(handle, path, name, value,
1544                                                      size);
1545                 }
1546
1547                 if (errno != EPERM && errno != EACCES) {
1548                         dbg_lvl = 1;
1549                 } else {
1550                         dbg_lvl = 5;
1551                 }
1552                 DEBUG(dbg_lvl, ("gpfs_get_xattr: Get GPFS attributes failed: "
1553                               "%d (%s)\n", ret, strerror(errno)));
1554                 return -1;
1555         }
1556
1557         DEBUG(10, ("gpfs_get_xattr:Got attributes: 0x%x\n",attrs.winAttrs));
1558
1559         /*Just map RD_ONLY, ARCHIVE, SYSTEM, HIDDEN and SPARSE. Ignore the others*/
1560         if (attrs.winAttrs & GPFS_WINATTR_ARCHIVE){
1561                 dosmode |= FILE_ATTRIBUTE_ARCHIVE;
1562         }
1563         if (attrs.winAttrs & GPFS_WINATTR_HIDDEN){
1564                 dosmode |= FILE_ATTRIBUTE_HIDDEN;
1565         }
1566         if (attrs.winAttrs & GPFS_WINATTR_SYSTEM){
1567                 dosmode |= FILE_ATTRIBUTE_SYSTEM;
1568         }
1569         if (attrs.winAttrs & GPFS_WINATTR_READONLY){
1570                 dosmode |= FILE_ATTRIBUTE_READONLY;
1571         }
1572         if (attrs.winAttrs & GPFS_WINATTR_SPARSE_FILE) {
1573                 dosmode |= FILE_ATTRIBUTE_SPARSE;
1574         }
1575
1576         snprintf(attrstr, size, "0x%2.2x",
1577                  (unsigned int)(dosmode & SAMBA_ATTRIBUTES_MASK));
1578         DEBUG(10, ("gpfs_get_xattr: returning %s\n",attrstr));
1579         return 4;
1580 }
1581
1582 #if defined(HAVE_FSTATAT)
1583 static int stat_with_capability(struct vfs_handle_struct *handle,
1584                                 struct smb_filename *smb_fname, int flag)
1585 {
1586         int fd = -1;
1587         bool b;
1588         char *dir_name;
1589         const char *rel_name = NULL;
1590         struct stat st;
1591         int ret = -1;
1592
1593         b = parent_dirname(talloc_tos(), smb_fname->base_name,
1594                            &dir_name, &rel_name);
1595         if (!b) {
1596                 errno = ENOMEM;
1597                 return -1;
1598         }
1599
1600         fd = open(dir_name, O_RDONLY, 0);
1601         TALLOC_FREE(dir_name);
1602         if (fd == -1) {
1603                 return -1;
1604         }
1605
1606         set_effective_capability(DAC_OVERRIDE_CAPABILITY);
1607         ret = fstatat(fd, rel_name, &st, flag);
1608         drop_effective_capability(DAC_OVERRIDE_CAPABILITY);
1609
1610         close(fd);
1611
1612         if (ret == 0) {
1613                 init_stat_ex_from_stat(
1614                         &smb_fname->st, &st,
1615                         lp_fake_directory_create_times(SNUM(handle->conn)));
1616         }
1617
1618         return ret;
1619 }
1620 #endif
1621
1622 static int vfs_gpfs_stat(struct vfs_handle_struct *handle,
1623                          struct smb_filename *smb_fname)
1624 {
1625         struct gpfs_winattr attrs;
1626         char *fname = NULL;
1627         NTSTATUS status;
1628         int ret;
1629         struct gpfs_config_data *config;
1630
1631         SMB_VFS_HANDLE_GET_DATA(handle, config,
1632                                 struct gpfs_config_data,
1633                                 return -1);
1634
1635         ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
1636 #if defined(HAVE_FSTATAT)
1637         if (ret == -1 && errno == EACCES) {
1638                 DEBUG(10, ("Trying stat with capability for %s\n",
1639                            smb_fname->base_name));
1640                 ret = stat_with_capability(handle, smb_fname, 0);
1641         }
1642 #endif
1643         if (ret == -1) {
1644                 return -1;
1645         }
1646
1647         if (!config->winattr) {
1648                 return 0;
1649         }
1650
1651         status = get_full_smb_filename(talloc_tos(), smb_fname, &fname);
1652         if (!NT_STATUS_IS_OK(status)) {
1653                 errno = map_errno_from_nt_status(status);
1654                 return -1;
1655         }
1656         ret = gpfswrap_get_winattrs_path(discard_const_p(char, fname), &attrs);
1657         TALLOC_FREE(fname);
1658         if (ret == 0) {
1659                 smb_fname->st.st_ex_calculated_birthtime = false;
1660                 smb_fname->st.st_ex_btime.tv_sec = attrs.creationTime.tv_sec;
1661                 smb_fname->st.st_ex_btime.tv_nsec = attrs.creationTime.tv_nsec;
1662         }
1663         return 0;
1664 }
1665
1666 static int vfs_gpfs_fstat(struct vfs_handle_struct *handle,
1667                           struct files_struct *fsp, SMB_STRUCT_STAT *sbuf)
1668 {
1669         struct gpfs_winattr attrs;
1670         int ret;
1671         struct gpfs_config_data *config;
1672
1673         SMB_VFS_HANDLE_GET_DATA(handle, config,
1674                                 struct gpfs_config_data,
1675                                 return -1);
1676
1677         ret = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
1678         if (ret == -1) {
1679                 return -1;
1680         }
1681         if ((fsp->fh == NULL) || (fsp->fh->fd == -1)) {
1682                 return 0;
1683         }
1684         if (!config->winattr) {
1685                 return 0;
1686         }
1687
1688         ret = gpfswrap_get_winattrs(fsp->fh->fd, &attrs);
1689         if (ret == 0) {
1690                 sbuf->st_ex_calculated_birthtime = false;
1691                 sbuf->st_ex_btime.tv_sec = attrs.creationTime.tv_sec;
1692                 sbuf->st_ex_btime.tv_nsec = attrs.creationTime.tv_nsec;
1693         }
1694         return 0;
1695 }
1696
1697 static int vfs_gpfs_lstat(struct vfs_handle_struct *handle,
1698                           struct smb_filename *smb_fname)
1699 {
1700         struct gpfs_winattr attrs;
1701         char *path = NULL;
1702         NTSTATUS status;
1703         int ret;
1704         struct gpfs_config_data *config;
1705
1706         SMB_VFS_HANDLE_GET_DATA(handle, config,
1707                                 struct gpfs_config_data,
1708                                 return -1);
1709
1710         ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
1711 #if defined(HAVE_FSTATAT)
1712         if (ret == -1 && errno == EACCES) {
1713                 DEBUG(10, ("Trying lstat with capability for %s\n",
1714                            smb_fname->base_name));
1715                 ret = stat_with_capability(handle, smb_fname,
1716                                            AT_SYMLINK_NOFOLLOW);
1717         }
1718 #endif
1719
1720         if (ret == -1) {
1721                 return -1;
1722         }
1723         if (!config->winattr) {
1724                 return 0;
1725         }
1726
1727         status = get_full_smb_filename(talloc_tos(), smb_fname, &path);
1728         if (!NT_STATUS_IS_OK(status)) {
1729                 errno = map_errno_from_nt_status(status);
1730                 return -1;
1731         }
1732         ret = gpfswrap_get_winattrs_path(discard_const_p(char, path), &attrs);
1733         TALLOC_FREE(path);
1734         if (ret == 0) {
1735                 smb_fname->st.st_ex_calculated_birthtime = false;
1736                 smb_fname->st.st_ex_btime.tv_sec = attrs.creationTime.tv_sec;
1737                 smb_fname->st.st_ex_btime.tv_nsec = attrs.creationTime.tv_nsec;
1738         }
1739         return 0;
1740 }
1741
1742 static void timespec_to_gpfs_time(struct timespec ts, gpfs_timestruc_t *gt,
1743                                   int idx, int *flags)
1744 {
1745         if (!null_timespec(ts)) {
1746                 *flags |= 1 << idx;
1747                 gt[idx].tv_sec = ts.tv_sec;
1748                 gt[idx].tv_nsec = ts.tv_nsec;
1749                 DEBUG(10, ("Setting GPFS time %d, flags 0x%x\n", idx, *flags));
1750         }
1751 }
1752
1753 static int smbd_gpfs_set_times_path(char *path, struct smb_file_time *ft)
1754 {
1755         gpfs_timestruc_t gpfs_times[4];
1756         int flags = 0;
1757         int rc;
1758
1759         ZERO_ARRAY(gpfs_times);
1760         timespec_to_gpfs_time(ft->atime, gpfs_times, 0, &flags);
1761         timespec_to_gpfs_time(ft->mtime, gpfs_times, 1, &flags);
1762         /* No good mapping from LastChangeTime to ctime, not storing */
1763         timespec_to_gpfs_time(ft->create_time, gpfs_times, 3, &flags);
1764
1765         if (!flags) {
1766                 DEBUG(10, ("nothing to do, return to avoid EINVAL\n"));
1767                 return 0;
1768         }
1769
1770         rc = gpfswrap_set_times_path(path, flags, gpfs_times);
1771
1772         if (rc != 0 && errno != ENOSYS) {
1773                 DEBUG(1,("gpfs_set_times() returned with error %s\n",
1774                         strerror(errno)));
1775         }
1776
1777         return rc;
1778 }
1779
1780 static int vfs_gpfs_ntimes(struct vfs_handle_struct *handle,
1781                         const struct smb_filename *smb_fname,
1782                         struct smb_file_time *ft)
1783 {
1784
1785         struct gpfs_winattr attrs;
1786         int ret;
1787         char *path = NULL;
1788         NTSTATUS status;
1789         struct gpfs_config_data *config;
1790
1791         SMB_VFS_HANDLE_GET_DATA(handle, config,
1792                                 struct gpfs_config_data,
1793                                 return -1);
1794
1795         status = get_full_smb_filename(talloc_tos(), smb_fname, &path);
1796         if (!NT_STATUS_IS_OK(status)) {
1797                 errno = map_errno_from_nt_status(status);
1798                 return -1;
1799         }
1800
1801         /* Try to use gpfs_set_times if it is enabled and available */
1802         if (config->settimes) {
1803                 ret = smbd_gpfs_set_times_path(path, ft);
1804
1805                 if (ret == 0 || (ret == -1 && errno != ENOSYS)) {
1806                         return ret;
1807                 }
1808         }
1809
1810         DEBUG(10,("gpfs_set_times() not available or disabled, "
1811                   "use ntimes and winattr\n"));
1812
1813         ret = SMB_VFS_NEXT_NTIMES(handle, smb_fname, ft);
1814         if(ret == -1){
1815                 /* don't complain if access was denied */
1816                 if (errno != EPERM && errno != EACCES) {
1817                         DEBUG(1,("vfs_gpfs_ntimes: SMB_VFS_NEXT_NTIMES failed:"
1818                                  "%s", strerror(errno)));
1819                 }
1820                 return -1;
1821         }
1822
1823         if(null_timespec(ft->create_time)){
1824                 DEBUG(10,("vfs_gpfs_ntimes:Create Time is NULL\n"));
1825                 return 0;
1826         }
1827
1828         if (!config->winattr) {
1829                 return 0;
1830         }
1831
1832         attrs.winAttrs = 0;
1833         attrs.creationTime.tv_sec = ft->create_time.tv_sec;
1834         attrs.creationTime.tv_nsec = ft->create_time.tv_nsec;
1835
1836         ret = gpfswrap_set_winattrs_path(discard_const_p(char, path),
1837                                          GPFS_WINATTR_SET_CREATION_TIME,
1838                                          &attrs);
1839         if(ret == -1 && errno != ENOSYS){
1840                 DEBUG(1,("vfs_gpfs_ntimes: set GPFS ntimes failed %d\n",ret));
1841                 return -1;
1842         }
1843         return 0;
1844
1845 }
1846
1847 static int vfs_gpfs_fallocate(struct vfs_handle_struct *handle,
1848                        struct files_struct *fsp, enum vfs_fallocate_mode mode,
1849                        off_t offset, off_t len)
1850 {
1851         int ret;
1852         struct gpfs_config_data *config;
1853
1854         SMB_VFS_HANDLE_GET_DATA(handle, config,
1855                                 struct gpfs_config_data,
1856                                 return -1);
1857
1858         if (!config->prealloc) {
1859                 /* you should better not run fallocate() on GPFS at all */
1860                 errno = ENOTSUP;
1861                 return -1;
1862         }
1863
1864         if (mode == VFS_FALLOCATE_KEEP_SIZE) {
1865                 DEBUG(10, ("Unsupported VFS_FALLOCATE_KEEP_SIZE\n"));
1866                 errno = ENOTSUP;
1867                 return -1;
1868         }
1869
1870         ret = gpfswrap_prealloc(fsp->fh->fd, offset, len);
1871
1872         if (ret == -1 && errno != ENOSYS) {
1873                 DEBUG(0, ("GPFS prealloc failed: %s\n", strerror(errno)));
1874         } else if (ret == -1 && errno == ENOSYS) {
1875                 DEBUG(10, ("GPFS prealloc not supported.\n"));
1876         } else {
1877                 DEBUG(10, ("GPFS prealloc succeeded.\n"));
1878         }
1879
1880         return ret;
1881 }
1882
1883 static int vfs_gpfs_ftruncate(vfs_handle_struct *handle, files_struct *fsp,
1884                                 off_t len)
1885 {
1886         int result;
1887         struct gpfs_config_data *config;
1888
1889         SMB_VFS_HANDLE_GET_DATA(handle, config,
1890                                 struct gpfs_config_data,
1891                                 return -1);
1892
1893         if (!config->ftruncate) {
1894                 return SMB_VFS_NEXT_FTRUNCATE(handle, fsp, len);
1895         }
1896
1897         result = gpfswrap_ftruncate(fsp->fh->fd, len);
1898         if ((result == -1) && (errno == ENOSYS)) {
1899                 return SMB_VFS_NEXT_FTRUNCATE(handle, fsp, len);
1900         }
1901         return result;
1902 }
1903
1904 static bool vfs_gpfs_is_offline(struct vfs_handle_struct *handle,
1905                                 const struct smb_filename *fname,
1906                                 SMB_STRUCT_STAT *sbuf)
1907 {
1908         struct gpfs_winattr attrs;
1909         char *path = NULL;
1910         NTSTATUS status;
1911         struct gpfs_config_data *config;
1912         int ret;
1913
1914         SMB_VFS_HANDLE_GET_DATA(handle, config,
1915                                 struct gpfs_config_data,
1916                                 return -1);
1917
1918         if (!config->winattr) {
1919                 return SMB_VFS_NEXT_IS_OFFLINE(handle, fname, sbuf);
1920         }
1921
1922         status = get_full_smb_filename(talloc_tos(), fname, &path);
1923         if (!NT_STATUS_IS_OK(status)) {
1924                 errno = map_errno_from_nt_status(status);
1925                 return -1;
1926         }
1927
1928         ret = gpfswrap_get_winattrs_path(path, &attrs);
1929         if (ret == -1) {
1930                 TALLOC_FREE(path);
1931                 return false;
1932         }
1933
1934         if ((attrs.winAttrs & GPFS_WINATTR_OFFLINE) != 0) {
1935                 DEBUG(10, ("%s is offline\n", path));
1936                 TALLOC_FREE(path);
1937                 return true;
1938         }
1939         DEBUG(10, ("%s is online\n", path));
1940         TALLOC_FREE(path);
1941         return SMB_VFS_NEXT_IS_OFFLINE(handle, fname, sbuf);
1942 }
1943
1944 static bool vfs_gpfs_aio_force(struct vfs_handle_struct *handle,
1945                                struct files_struct *fsp)
1946 {
1947         return vfs_gpfs_is_offline(handle, fsp->fsp_name, &fsp->fsp_name->st);
1948 }
1949
1950 static ssize_t vfs_gpfs_sendfile(vfs_handle_struct *handle, int tofd,
1951                                  files_struct *fsp, const DATA_BLOB *hdr,
1952                                  off_t offset, size_t n)
1953 {
1954         if (SMB_VFS_IS_OFFLINE(handle->conn, fsp->fsp_name, &fsp->fsp_name->st))
1955         {
1956                 errno = ENOSYS;
1957                 return -1;
1958         }
1959         return SMB_VFS_NEXT_SENDFILE(handle, tofd, fsp, hdr, offset, n);
1960 }
1961
1962 static int vfs_gpfs_connect(struct vfs_handle_struct *handle,
1963                             const char *service, const char *user)
1964 {
1965         struct gpfs_config_data *config;
1966         int ret;
1967
1968         gpfswrap_lib_init(0);
1969
1970         config = talloc_zero(handle->conn, struct gpfs_config_data);
1971         if (!config) {
1972                 DEBUG(0, ("talloc_zero() failed\n"));
1973                 errno = ENOMEM;
1974                 return -1;
1975         }
1976
1977         ret = SMB_VFS_NEXT_CONNECT(handle, service, user);
1978         if (ret < 0) {
1979                 TALLOC_FREE(config);
1980                 return ret;
1981         }
1982
1983         config->sharemodes = lp_parm_bool(SNUM(handle->conn), "gpfs",
1984                                         "sharemodes", true);
1985
1986         config->leases = lp_parm_bool(SNUM(handle->conn), "gpfs",
1987                                         "leases", true);
1988
1989         config->hsm = lp_parm_bool(SNUM(handle->conn), "gpfs",
1990                                    "hsm", false);
1991
1992         config->syncio = lp_parm_bool(SNUM(handle->conn), "gpfs",
1993                                       "syncio", false);
1994
1995         config->winattr = lp_parm_bool(SNUM(handle->conn), "gpfs",
1996                                        "winattr", false);
1997
1998         config->ftruncate = lp_parm_bool(SNUM(handle->conn), "gpfs",
1999                                          "ftruncate", true);
2000
2001         config->getrealfilename = lp_parm_bool(SNUM(handle->conn), "gpfs",
2002                                                "getrealfilename", true);
2003
2004         config->dfreequota = lp_parm_bool(SNUM(handle->conn), "gpfs",
2005                                           "dfreequota", false);
2006
2007         config->prealloc = lp_parm_bool(SNUM(handle->conn), "gpfs",
2008                                    "prealloc", true);
2009
2010         config->acl = lp_parm_bool(SNUM(handle->conn), "gpfs", "acl", true);
2011
2012         config->settimes = lp_parm_bool(SNUM(handle->conn), "gpfs",
2013                                         "settimes", true);
2014         config->recalls = lp_parm_bool(SNUM(handle->conn), "gpfs",
2015                                        "recalls", true);
2016
2017         SMB_VFS_HANDLE_SET_DATA(handle, config,
2018                                 NULL, struct gpfs_config_data,
2019                                 return -1);
2020
2021         if (config->leases) {
2022                 /*
2023                  * GPFS lease code is based on kernel oplock code
2024                  * so make sure it is turned on
2025                  */
2026                 if (!lp_kernel_oplocks(SNUM(handle->conn))) {
2027                         DEBUG(5, ("Enabling kernel oplocks for "
2028                                   "gpfs:leases to work\n"));
2029                         lp_do_parameter(SNUM(handle->conn), "kernel oplocks",
2030                                         "true");
2031                 }
2032
2033                 /*
2034                  * as the kernel does not properly support Level II oplocks
2035                  * and GPFS leases code is based on kernel infrastructure, we
2036                  * need to turn off Level II oplocks if gpfs:leases is enabled
2037                  */
2038                 if (lp_level2_oplocks(SNUM(handle->conn))) {
2039                         DEBUG(5, ("gpfs:leases are enabled, disabling "
2040                                   "Level II oplocks\n"));
2041                         lp_do_parameter(SNUM(handle->conn), "level2 oplocks",
2042                                         "false");
2043                 }
2044         }
2045
2046         return 0;
2047 }
2048
2049 static int get_gpfs_fset_id(const char *pathname, int *fset_id)
2050 {
2051         int err, fd, errno_fcntl;
2052
2053         struct {
2054                 gpfsFcntlHeader_t hdr;
2055                 gpfsGetFilesetName_t fsn;
2056         } arg;
2057
2058         arg.hdr.totalLength = sizeof(arg);
2059         arg.hdr.fcntlVersion = GPFS_FCNTL_CURRENT_VERSION;
2060         arg.hdr.fcntlReserved = 0;
2061         arg.fsn.structLen = sizeof(arg.fsn);
2062         arg.fsn.structType = GPFS_FCNTL_GET_FILESETNAME;
2063
2064         fd = open(pathname, O_RDONLY);
2065         if (fd == -1) {
2066                 DEBUG(1, ("Could not open %s: %s\n",
2067                           pathname, strerror(errno)));
2068                 return fd;
2069         }
2070
2071         err = gpfswrap_fcntl(fd, &arg);
2072         errno_fcntl = errno;
2073         close(fd);
2074
2075         if (err) {
2076                 errno = errno_fcntl;
2077                 if (errno != ENOSYS) {
2078                         DEBUG(1, ("GPFS_FCNTL_GET_FILESETNAME for %s failed: "
2079                                   "%s\n", pathname, strerror(errno)));
2080                 }
2081                 return err;
2082         }
2083
2084         err = gpfswrap_getfilesetid(discard_const_p(char, pathname),
2085                                     arg.fsn.buffer, fset_id);
2086         if (err && errno != ENOSYS) {
2087                 DEBUG(1, ("gpfs_getfilesetid for %s failed: %s\n",
2088                           pathname, strerror(errno)));
2089         }
2090         return err;
2091 }
2092
2093 static int get_gpfs_quota(const char *pathname, int type, int id,
2094                           struct gpfs_quotaInfo *qi)
2095 {
2096         int ret;
2097
2098         ZERO_STRUCTP(qi);
2099         ret = gpfswrap_quotactl(discard_const_p(char, pathname),
2100                                 GPFS_QCMD(Q_GETQUOTA, type), id, qi);
2101
2102         if (ret) {
2103                 if (errno == GPFS_E_NO_QUOTA_INST) {
2104                         DEBUG(10, ("Quotas disabled on GPFS filesystem.\n"));
2105                 } else if (errno != ENOSYS) {
2106                         DEBUG(0, ("Get quota failed, type %d, id, %d, "
2107                                   "errno %d.\n", type, id, errno));
2108                 }
2109
2110                 return ret;
2111         }
2112
2113         DEBUG(10, ("quota type %d, id %d, blk u:%lld h:%lld s:%lld gt:%u\n",
2114                    type, id, qi->blockUsage, qi->blockHardLimit,
2115                    qi->blockSoftLimit, qi->blockGraceTime));
2116
2117         return ret;
2118 }
2119
2120 static int vfs_gpfs_get_quotas(const char *path, uid_t uid, gid_t gid,
2121                                int *fset_id,
2122                                struct gpfs_quotaInfo *qi_user,
2123                                struct gpfs_quotaInfo *qi_group,
2124                                struct gpfs_quotaInfo *qi_fset)
2125 {
2126         int err;
2127         char *dir_path;
2128         bool b;
2129
2130         /*
2131          * We want to always use the directory to get the fileset id,
2132          * because files might have a share mode. We also do not want
2133          * to get the parent directory when there is already a
2134          * directory to avoid stepping in a different fileset.  The
2135          * path passed here is currently either "." or a filename, so
2136          * this is ok. The proper solution would be having a way to
2137          * query the fileset id without opening the file.
2138          */
2139         b = parent_dirname(talloc_tos(), path, &dir_path, NULL);
2140         if (!b) {
2141                 errno = ENOMEM;
2142                 return -1;
2143         }
2144
2145         DEBUG(10, ("path %s, directory %s\n", path, dir_path));
2146
2147         err = get_gpfs_fset_id(dir_path, fset_id);
2148         if (err) {
2149                 DEBUG(0, ("Get fset id failed path %s, dir %s, errno %d.\n",
2150                           path, dir_path, errno));
2151                 return err;
2152         }
2153
2154         err = get_gpfs_quota(path, GPFS_USRQUOTA, uid, qi_user);
2155         if (err) {
2156                 return err;
2157         }
2158
2159         err = get_gpfs_quota(path, GPFS_GRPQUOTA, gid, qi_group);
2160         if (err) {
2161                 return err;
2162         }
2163
2164         err = get_gpfs_quota(path, GPFS_FILESETQUOTA, *fset_id, qi_fset);
2165         if (err) {
2166                 return err;
2167         }
2168
2169         return 0;
2170 }
2171
2172 static void vfs_gpfs_disk_free_quota(struct gpfs_quotaInfo qi, time_t cur_time,
2173                                      uint64_t *dfree, uint64_t *dsize)
2174 {
2175         uint64_t usage, limit;
2176
2177         /*
2178          * The quota reporting is done in units of 1024 byte blocks, but
2179          * sys_fsusage uses units of 512 byte blocks, adjust the block number
2180          * accordingly. Also filter possibly negative usage counts from gpfs.
2181          */
2182         usage = qi.blockUsage < 0 ? 0 : (uint64_t)qi.blockUsage * 2;
2183         limit = (uint64_t)qi.blockHardLimit * 2;
2184
2185         /*
2186          * When the grace time for the exceeded soft block quota has been
2187          * exceeded, the soft block quota becomes an additional hard limit.
2188          */
2189         if (qi.blockSoftLimit &&
2190             qi.blockGraceTime && cur_time > qi.blockGraceTime) {
2191                 /* report disk as full */
2192                 *dfree = 0;
2193                 *dsize = MIN(*dsize, usage);
2194         }
2195
2196         if (!qi.blockHardLimit)
2197                 return;
2198
2199         if (usage >= limit) {
2200                 /* report disk as full */
2201                 *dfree = 0;
2202                 *dsize = MIN(*dsize, usage);
2203
2204         } else {
2205                 /* limit has not been reached, determine "free space" */
2206                 *dfree = MIN(*dfree, limit - usage);
2207                 *dsize = MIN(*dsize, limit);
2208         }
2209 }
2210
2211 static uint64_t vfs_gpfs_disk_free(vfs_handle_struct *handle, const char *path,
2212                                    uint64_t *bsize,
2213                                    uint64_t *dfree, uint64_t *dsize)
2214 {
2215         struct security_unix_token *utok;
2216         struct gpfs_quotaInfo qi_user, qi_group, qi_fset;
2217         struct gpfs_config_data *config;
2218         int err, fset_id;
2219         time_t cur_time;
2220
2221         SMB_VFS_HANDLE_GET_DATA(handle, config, struct gpfs_config_data,
2222                                 return (uint64_t)-1);
2223         if (!config->dfreequota) {
2224                 return SMB_VFS_NEXT_DISK_FREE(handle, path,
2225                                               bsize, dfree, dsize);
2226         }
2227
2228         err = sys_fsusage(path, dfree, dsize);
2229         if (err) {
2230                 DEBUG (0, ("Could not get fs usage, errno %d\n", errno));
2231                 return SMB_VFS_NEXT_DISK_FREE(handle, path,
2232                                               bsize, dfree, dsize);
2233         }
2234
2235         /* sys_fsusage returns units of 512 bytes */
2236         *bsize = 512;
2237
2238         DEBUG(10, ("fs dfree %llu, dsize %llu\n",
2239                    (unsigned long long)*dfree, (unsigned long long)*dsize));
2240
2241         utok = handle->conn->session_info->unix_token;
2242         err = vfs_gpfs_get_quotas(path, utok->uid, utok->gid, &fset_id,
2243                                   &qi_user, &qi_group, &qi_fset);
2244         if (err) {
2245                 return SMB_VFS_NEXT_DISK_FREE(handle, path,
2246                                               bsize, dfree, dsize);
2247         }
2248
2249         cur_time = time(NULL);
2250
2251         /* Adjust free space and size according to quota limits. */
2252         vfs_gpfs_disk_free_quota(qi_user, cur_time, dfree, dsize);
2253         vfs_gpfs_disk_free_quota(qi_group, cur_time, dfree, dsize);
2254
2255         /* Id 0 indicates the default quota, not an actual quota */
2256         if (fset_id != 0) {
2257                 vfs_gpfs_disk_free_quota(qi_fset, cur_time, dfree, dsize);
2258         }
2259
2260         disk_norm(bsize, dfree, dsize);
2261         return *dfree;
2262 }
2263
2264 static uint32_t vfs_gpfs_capabilities(struct vfs_handle_struct *handle,
2265                                       enum timestamp_set_resolution *p_ts_res)
2266 {
2267         struct gpfs_config_data *config;
2268         uint32_t next;
2269
2270         next = SMB_VFS_NEXT_FS_CAPABILITIES(handle, p_ts_res);
2271
2272         SMB_VFS_HANDLE_GET_DATA(handle, config,
2273                                 struct gpfs_config_data,
2274                                 return next);
2275
2276         if (config->hsm) {
2277                 next |= FILE_SUPPORTS_REMOTE_STORAGE;
2278         }
2279         return next;
2280 }
2281
2282 static int vfs_gpfs_open(struct vfs_handle_struct *handle,
2283                          struct smb_filename *smb_fname, files_struct *fsp,
2284                          int flags, mode_t mode)
2285 {
2286         struct gpfs_config_data *config;
2287
2288         SMB_VFS_HANDLE_GET_DATA(handle, config,
2289                                 struct gpfs_config_data,
2290                                 return -1);
2291
2292         if (config->hsm && !config->recalls) {
2293                 if (SMB_VFS_IS_OFFLINE(handle->conn, smb_fname, &smb_fname->st))
2294                 {
2295                         DEBUG(10, ("Refusing access to offline file %s\n",
2296                                   fsp_str_dbg(fsp)));
2297                         errno = EACCES;
2298                         return -1;
2299                 }
2300         }
2301
2302         if (config->syncio) {
2303                 flags |= O_SYNC;
2304         }
2305         return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
2306 }
2307
2308 static ssize_t vfs_gpfs_pread(vfs_handle_struct *handle, files_struct *fsp,
2309                               void *data, size_t n, off_t offset)
2310 {
2311         ssize_t ret;
2312         bool was_offline;
2313
2314         was_offline = SMB_VFS_IS_OFFLINE(handle->conn, fsp->fsp_name,
2315                                          &fsp->fsp_name->st);
2316
2317         ret = SMB_VFS_NEXT_PREAD(handle, fsp, data, n, offset);
2318
2319         if ((ret != -1) && was_offline) {
2320                 notify_fname(handle->conn, NOTIFY_ACTION_MODIFIED,
2321                              FILE_NOTIFY_CHANGE_ATTRIBUTES,
2322                              fsp->fsp_name->base_name);
2323         }
2324
2325         return ret;
2326 }
2327
2328 struct vfs_gpfs_pread_state {
2329         struct files_struct *fsp;
2330         ssize_t ret;
2331         int err;
2332         bool was_offline;
2333 };
2334
2335 static void vfs_gpfs_pread_done(struct tevent_req *subreq);
2336
2337 static struct tevent_req *vfs_gpfs_pread_send(struct vfs_handle_struct *handle,
2338                                               TALLOC_CTX *mem_ctx,
2339                                               struct tevent_context *ev,
2340                                               struct files_struct *fsp,
2341                                               void *data, size_t n,
2342                                               off_t offset)
2343 {
2344         struct tevent_req *req, *subreq;
2345         struct vfs_gpfs_pread_state *state;
2346
2347         req = tevent_req_create(mem_ctx, &state, struct vfs_gpfs_pread_state);
2348         if (req == NULL) {
2349                 return NULL;
2350         }
2351         state->was_offline = SMB_VFS_IS_OFFLINE(handle->conn, fsp->fsp_name,
2352                                                 &fsp->fsp_name->st);
2353         state->fsp = fsp;
2354         subreq = SMB_VFS_NEXT_PREAD_SEND(state, ev, handle, fsp, data,
2355                                          n, offset);
2356         if (tevent_req_nomem(subreq, req)) {
2357                 return tevent_req_post(req, ev);
2358         }
2359         tevent_req_set_callback(subreq, vfs_gpfs_pread_done, req);
2360         return req;
2361 }
2362
2363 static void vfs_gpfs_pread_done(struct tevent_req *subreq)
2364 {
2365         struct tevent_req *req = tevent_req_callback_data(
2366                 subreq, struct tevent_req);
2367         struct vfs_gpfs_pread_state *state = tevent_req_data(
2368                 req, struct vfs_gpfs_pread_state);
2369
2370         state->ret = SMB_VFS_PREAD_RECV(subreq, &state->err);
2371         TALLOC_FREE(subreq);
2372         tevent_req_done(req);
2373 }
2374
2375 static ssize_t vfs_gpfs_pread_recv(struct tevent_req *req, int *err)
2376 {
2377         struct vfs_gpfs_pread_state *state = tevent_req_data(
2378                 req, struct vfs_gpfs_pread_state);
2379         struct files_struct *fsp = state->fsp;
2380
2381         if (tevent_req_is_unix_error(req, err)) {
2382                 return -1;
2383         }
2384         *err = state->err;
2385
2386         if ((state->ret != -1) && state->was_offline) {
2387                 DEBUG(10, ("sending notify\n"));
2388                 notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED,
2389                              FILE_NOTIFY_CHANGE_ATTRIBUTES,
2390                              fsp->fsp_name->base_name);
2391         }
2392
2393         return state->ret;
2394 }
2395
2396 static ssize_t vfs_gpfs_pwrite(vfs_handle_struct *handle, files_struct *fsp,
2397                                const void *data, size_t n, off_t offset)
2398 {
2399         ssize_t ret;
2400         bool was_offline;
2401
2402         was_offline = SMB_VFS_IS_OFFLINE(handle->conn, fsp->fsp_name,
2403                                          &fsp->fsp_name->st);
2404
2405         ret = SMB_VFS_NEXT_PWRITE(handle, fsp, data, n, offset);
2406
2407         if ((ret != -1) && was_offline) {
2408                 notify_fname(handle->conn, NOTIFY_ACTION_MODIFIED,
2409                              FILE_NOTIFY_CHANGE_ATTRIBUTES,
2410                              fsp->fsp_name->base_name);
2411         }
2412
2413         return ret;
2414 }
2415
2416 struct vfs_gpfs_pwrite_state {
2417         struct files_struct *fsp;
2418         ssize_t ret;
2419         int err;
2420         bool was_offline;
2421 };
2422
2423 static void vfs_gpfs_pwrite_done(struct tevent_req *subreq);
2424
2425 static struct tevent_req *vfs_gpfs_pwrite_send(
2426         struct vfs_handle_struct *handle,
2427         TALLOC_CTX *mem_ctx,
2428         struct tevent_context *ev,
2429         struct files_struct *fsp,
2430         const void *data, size_t n,
2431         off_t offset)
2432 {
2433         struct tevent_req *req, *subreq;
2434         struct vfs_gpfs_pwrite_state *state;
2435
2436         req = tevent_req_create(mem_ctx, &state, struct vfs_gpfs_pwrite_state);
2437         if (req == NULL) {
2438                 return NULL;
2439         }
2440         state->was_offline = SMB_VFS_IS_OFFLINE(handle->conn, fsp->fsp_name,
2441                                                 &fsp->fsp_name->st);
2442         state->fsp = fsp;
2443         subreq = SMB_VFS_NEXT_PWRITE_SEND(state, ev, handle, fsp, data,
2444                                          n, offset);
2445         if (tevent_req_nomem(subreq, req)) {
2446                 return tevent_req_post(req, ev);
2447         }
2448         tevent_req_set_callback(subreq, vfs_gpfs_pwrite_done, req);
2449         return req;
2450 }
2451
2452 static void vfs_gpfs_pwrite_done(struct tevent_req *subreq)
2453 {
2454         struct tevent_req *req = tevent_req_callback_data(
2455                 subreq, struct tevent_req);
2456         struct vfs_gpfs_pwrite_state *state = tevent_req_data(
2457                 req, struct vfs_gpfs_pwrite_state);
2458
2459         state->ret = SMB_VFS_PWRITE_RECV(subreq, &state->err);
2460         TALLOC_FREE(subreq);
2461         tevent_req_done(req);
2462 }
2463
2464 static ssize_t vfs_gpfs_pwrite_recv(struct tevent_req *req, int *err)
2465 {
2466         struct vfs_gpfs_pwrite_state *state = tevent_req_data(
2467                 req, struct vfs_gpfs_pwrite_state);
2468         struct files_struct *fsp = state->fsp;
2469
2470         if (tevent_req_is_unix_error(req, err)) {
2471                 return -1;
2472         }
2473         *err = state->err;
2474
2475         if ((state->ret != -1) && state->was_offline) {
2476                 DEBUG(10, ("sending notify\n"));
2477                 notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED,
2478                              FILE_NOTIFY_CHANGE_ATTRIBUTES,
2479                              fsp->fsp_name->base_name);
2480         }
2481
2482         return state->ret;
2483 }
2484
2485
2486 static struct vfs_fn_pointers vfs_gpfs_fns = {
2487         .connect_fn = vfs_gpfs_connect,
2488         .disk_free_fn = vfs_gpfs_disk_free,
2489         .fs_capabilities_fn = vfs_gpfs_capabilities,
2490         .kernel_flock_fn = vfs_gpfs_kernel_flock,
2491         .linux_setlease_fn = vfs_gpfs_setlease,
2492         .get_real_filename_fn = vfs_gpfs_get_real_filename,
2493         .fget_nt_acl_fn = gpfsacl_fget_nt_acl,
2494         .get_nt_acl_fn = gpfsacl_get_nt_acl,
2495         .fset_nt_acl_fn = gpfsacl_fset_nt_acl,
2496         .sys_acl_get_file_fn = gpfsacl_sys_acl_get_file,
2497         .sys_acl_get_fd_fn = gpfsacl_sys_acl_get_fd,
2498         .sys_acl_blob_get_file_fn = gpfsacl_sys_acl_blob_get_file,
2499         .sys_acl_blob_get_fd_fn = gpfsacl_sys_acl_blob_get_fd,
2500         .sys_acl_set_file_fn = gpfsacl_sys_acl_set_file,
2501         .sys_acl_set_fd_fn = gpfsacl_sys_acl_set_fd,
2502         .sys_acl_delete_def_file_fn = gpfsacl_sys_acl_delete_def_file,
2503         .chmod_fn = vfs_gpfs_chmod,
2504         .fchmod_fn = vfs_gpfs_fchmod,
2505         .close_fn = vfs_gpfs_close,
2506         .setxattr_fn = gpfs_set_xattr,
2507         .getxattr_fn = gpfs_get_xattr,
2508         .stat_fn = vfs_gpfs_stat,
2509         .fstat_fn = vfs_gpfs_fstat,
2510         .lstat_fn = vfs_gpfs_lstat,
2511         .ntimes_fn = vfs_gpfs_ntimes,
2512         .is_offline_fn = vfs_gpfs_is_offline,
2513         .aio_force_fn = vfs_gpfs_aio_force,
2514         .sendfile_fn = vfs_gpfs_sendfile,
2515         .fallocate_fn = vfs_gpfs_fallocate,
2516         .open_fn = vfs_gpfs_open,
2517         .pread_fn = vfs_gpfs_pread,
2518         .pread_send_fn = vfs_gpfs_pread_send,
2519         .pread_recv_fn = vfs_gpfs_pread_recv,
2520         .pwrite_fn = vfs_gpfs_pwrite,
2521         .pwrite_send_fn = vfs_gpfs_pwrite_send,
2522         .pwrite_recv_fn = vfs_gpfs_pwrite_recv,
2523         .ftruncate_fn = vfs_gpfs_ftruncate
2524 };
2525
2526 NTSTATUS vfs_gpfs_init(void);
2527 NTSTATUS vfs_gpfs_init(void)
2528 {
2529         int ret;
2530
2531         ret = gpfswrap_init();
2532         if (ret != 0) {
2533                 DEBUG(1, ("Could not initialize GPFS library wrapper\n"));
2534         }
2535
2536         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "gpfs",
2537                                 &vfs_gpfs_fns);
2538 }