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