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