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