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