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