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