2
Unix SMB/CIFS implementation.
3
Wrap gpfs calls in vfs functions.
5
Copyright (C) Christian Ambach <cambach1@de.ibm.com> 2006
7
Major code contributions by Chetan Shringarpure <chetan.sh@in.ibm.com>
8
and Gomati Mohanan <gomati.mohanan@in.ibm.com>
10
This program is free software; you can redistribute it and/or modify
11
it under the terms of the GNU General Public License as published by
12
the Free Software Foundation; either version 3 of the License, or
13
(at your option) any later version.
15
This program is distributed in the hope that it will be useful,
16
but WITHOUT ANY WARRANTY; without even the implied warranty of
17
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
GNU General Public License for more details.
20
You should have received a copy of the GNU General Public License
21
along with this program. If not, see <http://www.gnu.org/licenses/>.
27
#define DBGC_CLASS DBGC_VFS
30
#include "nfs4_acls.h"
33
static int vfs_gpfs_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
37
START_PROFILE(syscall_kernel_flock);
39
kernel_flock(fsp->fh->fd, share_mode);
41
if (!set_gpfs_sharemode(fsp, fsp->access_mask, fsp->share_access)) {
47
END_PROFILE(syscall_kernel_flock);
52
static int vfs_gpfs_close(vfs_handle_struct *handle, files_struct *fsp)
54
if ((fsp->fh != NULL) && (fsp->fh->fd != -1)) {
55
set_gpfs_sharemode(fsp, 0, 0);
58
return SMB_VFS_NEXT_CLOSE(handle, fsp);
61
static int vfs_gpfs_setlease(vfs_handle_struct *handle, files_struct *fsp,
66
START_PROFILE(syscall_linux_setlease);
68
if ( linux_set_lease_sighandler(fsp->fh->fd) == -1)
71
ret = set_gpfs_lease(fsp->fh->fd,leasetype);
74
/* This must have come from GPFS not being available */
75
/* or some other error, hence call the default */
76
ret = linux_setlease(fsp->fh->fd, leasetype);
79
END_PROFILE(syscall_linux_setlease);
84
static int vfs_gpfs_get_real_filename(struct vfs_handle_struct *handle,
92
char real_pathname[PATH_MAX+1];
95
full_path = talloc_asprintf(talloc_tos(), "%s/%s", path, name);
96
if (full_path == NULL) {
101
buflen = sizeof(real_pathname) - 1;
103
result = smbd_gpfs_get_realfilename_path(full_path, real_pathname,
106
TALLOC_FREE(full_path);
108
if ((result == -1) && (errno == ENOSYS)) {
109
return SMB_VFS_NEXT_GET_REAL_FILENAME(
110
handle, path, name, mem_ctx, found_name);
114
DEBUG(10, ("smbd_gpfs_get_realfilename_path returned %s\n",
120
* GPFS does not necessarily null-terminate the returned path
121
* but instead returns the buffer length in buflen.
124
if (buflen < sizeof(real_pathname)) {
125
real_pathname[buflen] = '\0';
127
real_pathname[sizeof(real_pathname)-1] = '\0';
130
DEBUG(10, ("smbd_gpfs_get_realfilename_path: %s/%s -> %s\n",
131
path, name, real_pathname));
133
name = strrchr_m(real_pathname, '/');
139
*found_name = talloc_strdup(mem_ctx, name+1);
140
if (*found_name == NULL) {
148
static void gpfs_dumpacl(int level, struct gpfs_acl *gacl)
153
DEBUG(0, ("gpfs acl is NULL\n"));
157
DEBUG(level, ("gpfs acl: nace: %d, type:%d, version:%d, level:%d, len:%d\n",
158
gacl->acl_nace, gacl->acl_type, gacl->acl_version, gacl->acl_level, gacl->acl_len));
159
for(i=0; i<gacl->acl_nace; i++)
161
struct gpfs_ace_v4 *gace = gacl->ace_v4 + i;
162
DEBUG(level, ("\tace[%d]: type:%d, flags:0x%x, mask:0x%x, iflags:0x%x, who:%u\n",
163
i, gace->aceType, gace->aceFlags, gace->aceMask,
164
gace->aceIFlags, gace->aceWho));
168
static struct gpfs_acl *gpfs_getacl_alloc(const char *fname, gpfs_aclType_t type)
170
struct gpfs_acl *acl;
173
TALLOC_CTX *mem_ctx = talloc_tos();
175
acl = (struct gpfs_acl *)TALLOC_SIZE(mem_ctx, len);
183
acl->acl_version = 0;
184
acl->acl_type = type;
186
ret = smbd_gpfs_getacl((char *)fname, GPFS_GETACL_STRUCT | GPFS_ACL_SAMBA, acl);
187
if ((ret != 0) && (errno == ENOSPC)) {
188
struct gpfs_acl *new_acl = (struct gpfs_acl *)TALLOC_SIZE(
189
mem_ctx, acl->acl_len + sizeof(struct gpfs_acl));
190
if (new_acl == NULL) {
195
new_acl->acl_len = acl->acl_len;
196
new_acl->acl_level = acl->acl_level;
197
new_acl->acl_version = acl->acl_version;
198
new_acl->acl_type = acl->acl_type;
201
ret = smbd_gpfs_getacl((char *)fname, GPFS_GETACL_STRUCT | GPFS_ACL_SAMBA, acl);
205
DEBUG(8, ("smbd_gpfs_getacl failed with %s\n",strerror(errno)));
212
/* Tries to get nfs4 acls and returns SMB ACL allocated.
213
* On failure returns 1 if it got non-NFSv4 ACL to prompt
214
* retry with POSIX ACL checks.
215
* On failure returns -1 if there is system (GPFS) error, check errno.
216
* Returns 0 on success
218
static int gpfs_get_nfs4_acl(const char *fname, SMB4ACL_T **ppacl)
221
struct gpfs_acl *gacl = NULL;
222
DEBUG(10, ("gpfs_get_nfs4_acl invoked for %s\n", fname));
224
/* First get the real acl length */
225
gacl = gpfs_getacl_alloc(fname, 0);
227
DEBUG(9, ("gpfs_getacl failed for %s with %s\n",
228
fname, strerror(errno)));
232
if (gacl->acl_type != GPFS_ACL_TYPE_NFS4) {
233
DEBUG(10, ("Got non-nfsv4 acl\n"));
234
/* Retry with POSIX ACLs check */
238
*ppacl = smb_create_smb4acl();
240
DEBUG(10, ("len: %d, level: %d, version: %d, nace: %d\n",
241
gacl->acl_len, gacl->acl_level, gacl->acl_version,
244
for (i=0; i<gacl->acl_nace; i++) {
245
struct gpfs_ace_v4 *gace = &gacl->ace_v4[i];
246
SMB_ACE4PROP_T smbace;
247
DEBUG(10, ("type: %d, iflags: %x, flags: %x, mask: %x, "
248
"who: %d\n", gace->aceType, gace->aceIFlags,
249
gace->aceFlags, gace->aceMask, gace->aceWho));
252
if (gace->aceIFlags & ACE4_IFLAG_SPECIAL_ID) {
253
smbace.flags |= SMB_ACE4_ID_SPECIAL;
254
switch (gace->aceWho) {
255
case ACE4_SPECIAL_OWNER:
256
smbace.who.special_id = SMB_ACE4_WHO_OWNER;
258
case ACE4_SPECIAL_GROUP:
259
smbace.who.special_id = SMB_ACE4_WHO_GROUP;
261
case ACE4_SPECIAL_EVERYONE:
262
smbace.who.special_id = SMB_ACE4_WHO_EVERYONE;
265
DEBUG(8, ("invalid special gpfs id %d "
266
"ignored\n", gace->aceWho));
267
continue; /* don't add it */
270
if (gace->aceFlags & ACE4_FLAG_GROUP_ID)
271
smbace.who.gid = gace->aceWho;
273
smbace.who.uid = gace->aceWho;
276
/* remove redundent deny entries */
277
if (i > 0 && gace->aceType == SMB_ACE4_ACCESS_DENIED_ACE_TYPE) {
278
struct gpfs_ace_v4 *prev = &gacl->ace_v4[i-1];
279
if (prev->aceType == SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE &&
280
prev->aceFlags == gace->aceFlags &&
281
prev->aceIFlags == gace->aceIFlags &&
282
(gace->aceMask & prev->aceMask) == 0 &&
283
gace->aceWho == prev->aceWho) {
284
/* its redundent - skip it */
289
smbace.aceType = gace->aceType;
290
smbace.aceFlags = gace->aceFlags;
291
smbace.aceMask = gace->aceMask;
292
smb_add_ace4(*ppacl, &smbace);
298
static NTSTATUS gpfsacl_fget_nt_acl(vfs_handle_struct *handle,
299
files_struct *fsp, uint32 security_info,
302
SMB4ACL_T *pacl = NULL;
306
result = gpfs_get_nfs4_acl(fsp->fsp_name, &pacl);
309
return smb_fget_nt_acl_nfs4(fsp, security_info, ppdesc, pacl);
312
DEBUG(10, ("retrying with posix acl...\n"));
313
return posix_fget_nt_acl(fsp, security_info, ppdesc);
316
/* GPFS ACL was not read, something wrong happened, error code is set in errno */
317
return map_nt_error_from_unix(errno);
320
static NTSTATUS gpfsacl_get_nt_acl(vfs_handle_struct *handle,
322
uint32 security_info, SEC_DESC **ppdesc)
324
SMB4ACL_T *pacl = NULL;
328
result = gpfs_get_nfs4_acl(name, &pacl);
331
return smb_get_nt_acl_nfs4(handle->conn, name, security_info, ppdesc, pacl);
334
DEBUG(10, ("retrying with posix acl...\n"));
335
return posix_get_nt_acl(handle->conn, name, security_info, ppdesc);
338
/* GPFS ACL was not read, something wrong happened, error code is set in errno */
339
return map_nt_error_from_unix(errno);
342
static bool gpfsacl_process_smbacl(files_struct *fsp, SMB4ACL_T *smbacl)
345
gpfs_aclLen_t gacl_len;
347
struct gpfs_acl *gacl;
348
TALLOC_CTX *mem_ctx = talloc_tos();
350
gacl_len = sizeof(struct gpfs_acl) +
351
(smb_get_naces(smbacl)-1)*sizeof(gpfs_ace_v4_t);
353
gacl = (struct gpfs_acl *)TALLOC_SIZE(mem_ctx, gacl_len);
355
DEBUG(0, ("talloc failed\n"));
360
gacl->acl_len = gacl_len;
362
gacl->acl_version = GPFS_ACL_VERSION_NFS4;
363
gacl->acl_type = GPFS_ACL_TYPE_NFS4;
364
gacl->acl_nace = 0; /* change later... */
366
for (smbace=smb_first_ace4(smbacl); smbace!=NULL; smbace = smb_next_ace4(smbace)) {
367
struct gpfs_ace_v4 *gace = &gacl->ace_v4[gacl->acl_nace];
368
SMB_ACE4PROP_T *aceprop = smb_get_ace4(smbace);
370
gace->aceType = aceprop->aceType;
371
gace->aceFlags = aceprop->aceFlags;
372
gace->aceMask = aceprop->aceMask;
375
* GPFS can't distinguish between WRITE and APPEND on
376
* files, so one being set without the other is an
377
* error. Sorry for the many ()'s :-)
380
if (!fsp->is_directory
382
((((gace->aceMask & ACE4_MASK_WRITE) == 0)
383
&& ((gace->aceMask & ACE4_MASK_APPEND) != 0))
385
(((gace->aceMask & ACE4_MASK_WRITE) != 0)
386
&& ((gace->aceMask & ACE4_MASK_APPEND) == 0)))
388
lp_parm_bool(fsp->conn->params->service, "gpfs",
389
"merge_writeappend", True)) {
390
DEBUG(2, ("vfs_gpfs.c: file [%s]: ACE contains "
391
"WRITE^APPEND, setting WRITE|APPEND\n",
393
gace->aceMask |= ACE4_MASK_WRITE|ACE4_MASK_APPEND;
396
gace->aceIFlags = (aceprop->flags&SMB_ACE4_ID_SPECIAL) ? ACE4_IFLAG_SPECIAL_ID : 0;
398
if (aceprop->flags&SMB_ACE4_ID_SPECIAL)
400
switch(aceprop->who.special_id)
402
case SMB_ACE4_WHO_EVERYONE:
403
gace->aceWho = ACE4_SPECIAL_EVERYONE;
405
case SMB_ACE4_WHO_OWNER:
406
gace->aceWho = ACE4_SPECIAL_OWNER;
408
case SMB_ACE4_WHO_GROUP:
409
gace->aceWho = ACE4_SPECIAL_GROUP;
412
DEBUG(8, ("unsupported special_id %d\n", aceprop->who.special_id));
413
continue; /* don't add it !!! */
416
/* just only for the type safety... */
417
if (aceprop->aceFlags&SMB_ACE4_IDENTIFIER_GROUP)
418
gace->aceWho = aceprop->who.gid;
420
gace->aceWho = aceprop->who.uid;
426
ret = smbd_gpfs_putacl(fsp->fsp_name, GPFS_PUTACL_STRUCT | GPFS_ACL_SAMBA, gacl);
428
DEBUG(8, ("gpfs_putacl failed with %s\n", strerror(errno)));
429
gpfs_dumpacl(8, gacl);
433
DEBUG(10, ("gpfs_putacl succeeded\n"));
437
static NTSTATUS gpfsacl_set_nt_acl_internal(files_struct *fsp, uint32 security_info_sent, const SEC_DESC *psd)
439
struct gpfs_acl *acl;
440
NTSTATUS result = NT_STATUS_ACCESS_DENIED;
442
acl = gpfs_getacl_alloc(fsp->fsp_name, 0);
446
if (acl->acl_version&GPFS_ACL_VERSION_NFS4)
448
result = smb_set_nt_acl_nfs4(
449
fsp, security_info_sent, psd,
450
gpfsacl_process_smbacl);
451
} else { /* assume POSIX ACL - by default... */
452
result = set_nt_acl(fsp, security_info_sent, psd);
458
static NTSTATUS gpfsacl_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info_sent, const SEC_DESC *psd)
460
return gpfsacl_set_nt_acl_internal(fsp, security_info_sent, psd);
463
static SMB_ACL_T gpfs2smb_acl(const struct gpfs_acl *pacl)
468
result = sys_acl_init(pacl->acl_nace);
469
if (result == NULL) {
474
result->count = pacl->acl_nace;
476
for (i=0; i<pacl->acl_nace; i++) {
477
struct smb_acl_entry *ace = &result->acl[i];
478
const struct gpfs_ace_v1 *g_ace = &pacl->ace_v1[i];
480
DEBUG(10, ("Converting type %d id %lu perm %x\n",
481
(int)g_ace->ace_type, (unsigned long)g_ace->ace_who,
482
(int)g_ace->ace_perm));
484
switch (g_ace->ace_type) {
486
ace->a_type = SMB_ACL_USER;
487
ace->uid = (uid_t)g_ace->ace_who;
489
case GPFS_ACL_USER_OBJ:
490
ace->a_type = SMB_ACL_USER_OBJ;
493
ace->a_type = SMB_ACL_GROUP;
494
ace->gid = (gid_t)g_ace->ace_who;
496
case GPFS_ACL_GROUP_OBJ:
497
ace->a_type = SMB_ACL_GROUP_OBJ;
500
ace->a_type = SMB_ACL_OTHER;
503
ace->a_type = SMB_ACL_MASK;
506
DEBUG(10, ("Got invalid ace_type: %d\n",
514
ace->a_perm |= (g_ace->ace_perm & ACL_PERM_READ) ?
516
ace->a_perm |= (g_ace->ace_perm & ACL_PERM_WRITE) ?
518
ace->a_perm |= (g_ace->ace_perm & ACL_PERM_EXECUTE) ?
521
DEBUGADD(10, ("Converted to %d perm %x\n",
522
ace->a_type, ace->a_perm));
528
static SMB_ACL_T gpfsacl_get_posix_acl(const char *path, gpfs_aclType_t type)
530
struct gpfs_acl *pacl;
531
SMB_ACL_T result = NULL;
533
pacl = gpfs_getacl_alloc(path, type);
536
DEBUG(10, ("gpfs_getacl failed for %s with %s\n",
537
path, strerror(errno)));
544
if (pacl->acl_version != GPFS_ACL_VERSION_POSIX) {
545
DEBUG(10, ("Got acl version %d, expected %d\n",
546
pacl->acl_version, GPFS_ACL_VERSION_POSIX));
551
DEBUG(10, ("len: %d, level: %d, version: %d, nace: %d\n",
552
pacl->acl_len, pacl->acl_level, pacl->acl_version,
555
result = gpfs2smb_acl(pacl);
556
if (result == NULL) {
568
static SMB_ACL_T gpfsacl_sys_acl_get_file(vfs_handle_struct *handle,
572
gpfs_aclType_t gpfs_type;
575
case SMB_ACL_TYPE_ACCESS:
576
gpfs_type = GPFS_ACL_TYPE_ACCESS;
578
case SMB_ACL_TYPE_DEFAULT:
579
gpfs_type = GPFS_ACL_TYPE_DEFAULT;
582
DEBUG(0, ("Got invalid type: %d\n", type));
583
smb_panic("exiting");
586
return gpfsacl_get_posix_acl(path_p, gpfs_type);
589
static SMB_ACL_T gpfsacl_sys_acl_get_fd(vfs_handle_struct *handle,
592
return gpfsacl_get_posix_acl(fsp->fsp_name, GPFS_ACL_TYPE_ACCESS);
595
static struct gpfs_acl *smb2gpfs_acl(const SMB_ACL_T pacl,
599
struct gpfs_acl *result;
603
gpfs_ace_v1_t ace_v1[1]; /* when GPFS_ACL_VERSION_POSIX */
604
gpfs_ace_v4_t ace_v4[1]; /* when GPFS_ACL_VERSION_NFS4 */
607
DEBUG(10, ("smb2gpfs_acl: Got ACL with %d entries\n", pacl->count));
609
len = sizeof(struct gpfs_acl) - sizeof(union gpfs_ace_union) +
610
(pacl->count)*sizeof(gpfs_ace_v1_t);
612
result = (struct gpfs_acl *)SMB_MALLOC(len);
613
if (result == NULL) {
618
result->acl_len = len;
619
result->acl_level = 0;
620
result->acl_version = GPFS_ACL_VERSION_POSIX;
621
result->acl_type = (type == SMB_ACL_TYPE_DEFAULT) ?
622
GPFS_ACL_TYPE_DEFAULT : GPFS_ACL_TYPE_ACCESS;
623
result->acl_nace = pacl->count;
625
for (i=0; i<pacl->count; i++) {
626
const struct smb_acl_entry *ace = &pacl->acl[i];
627
struct gpfs_ace_v1 *g_ace = &result->ace_v1[i];
629
DEBUG(10, ("Converting type %d perm %x\n",
630
(int)ace->a_type, (int)ace->a_perm));
634
switch(ace->a_type) {
636
g_ace->ace_type = GPFS_ACL_USER;
637
g_ace->ace_who = (gpfs_uid_t)ace->uid;
639
case SMB_ACL_USER_OBJ:
640
g_ace->ace_type = GPFS_ACL_USER_OBJ;
641
g_ace->ace_perm |= ACL_PERM_CONTROL;
645
g_ace->ace_type = GPFS_ACL_GROUP;
646
g_ace->ace_who = (gpfs_uid_t)ace->gid;
648
case SMB_ACL_GROUP_OBJ:
649
g_ace->ace_type = GPFS_ACL_GROUP_OBJ;
653
g_ace->ace_type = GPFS_ACL_MASK;
654
g_ace->ace_perm = 0x8f;
658
g_ace->ace_type = GPFS_ACL_OTHER;
662
DEBUG(10, ("Got invalid ace_type: %d\n", ace->a_type));
668
g_ace->ace_perm |= (ace->a_perm & SMB_ACL_READ) ?
670
g_ace->ace_perm |= (ace->a_perm & SMB_ACL_WRITE) ?
672
g_ace->ace_perm |= (ace->a_perm & SMB_ACL_EXECUTE) ?
673
ACL_PERM_EXECUTE : 0;
675
DEBUGADD(10, ("Converted to %d id %d perm %x\n",
676
g_ace->ace_type, g_ace->ace_who, g_ace->ace_perm));
682
static int gpfsacl_sys_acl_set_file(vfs_handle_struct *handle,
687
struct gpfs_acl *gpfs_acl;
690
gpfs_acl = smb2gpfs_acl(theacl, type);
691
if (gpfs_acl == NULL) {
695
result = smbd_gpfs_putacl((char *)name, GPFS_PUTACL_STRUCT | GPFS_ACL_SAMBA, gpfs_acl);
701
static int gpfsacl_sys_acl_set_fd(vfs_handle_struct *handle,
705
return gpfsacl_sys_acl_set_file(handle, fsp->fsp_name, SMB_ACL_TYPE_ACCESS, theacl);
708
static int gpfsacl_sys_acl_delete_def_file(vfs_handle_struct *handle,
716
* Assumed: mode bits are shiftable and standard
717
* Output: the new aceMask field for an smb nfs4 ace
719
static uint32 gpfsacl_mask_filter(uint32 aceType, uint32 aceMask, uint32 rwx)
721
const uint32 posix_nfs4map[3] = {
722
SMB_ACE4_EXECUTE, /* execute */
723
SMB_ACE4_WRITE_DATA | SMB_ACE4_APPEND_DATA, /* write; GPFS specific */
724
SMB_ACE4_READ_DATA /* read */
727
uint32_t posix_mask = 0x01;
732
nfs4_bits = posix_nfs4map[i];
733
posix_bit = rwx & posix_mask;
735
if (aceType==SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE) {
737
aceMask |= nfs4_bits;
739
aceMask &= ~nfs4_bits;
741
/* add deny bits when suitable */
743
aceMask |= nfs4_bits;
745
aceMask &= ~nfs4_bits;
746
} /* other ace types are unexpected */
754
static int gpfsacl_emu_chmod(const char *path, mode_t mode)
756
SMB4ACL_T *pacl = NULL;
758
bool haveAllowEntry[SMB_ACE4_WHO_EVERYONE + 1] = {False, False, False, False};
760
files_struct fake_fsp; /* TODO: rationalize parametrization */
763
DEBUG(10, ("gpfsacl_emu_chmod invoked for %s mode %o\n", path, mode));
765
result = gpfs_get_nfs4_acl(path, &pacl);
769
if (mode & ~(S_IRWXU | S_IRWXG | S_IRWXO)) {
770
DEBUG(2, ("WARNING: cutting extra mode bits %o on %s\n", mode, path));
773
for (smbace=smb_first_ace4(pacl); smbace!=NULL; smbace = smb_next_ace4(smbace)) {
774
SMB_ACE4PROP_T *ace = smb_get_ace4(smbace);
775
uint32_t specid = ace->who.special_id;
777
if (ace->flags&SMB_ACE4_ID_SPECIAL &&
778
ace->aceType<=SMB_ACE4_ACCESS_DENIED_ACE_TYPE &&
779
specid <= SMB_ACE4_WHO_EVERYONE) {
783
if (ace->aceType==SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE)
784
haveAllowEntry[specid] = True;
786
/* mode >> 6 for @owner, mode >> 3 for @group,
787
* mode >> 0 for @everyone */
788
newMask = gpfsacl_mask_filter(ace->aceType, ace->aceMask,
789
mode >> ((SMB_ACE4_WHO_EVERYONE - specid) * 3));
790
if (ace->aceMask!=newMask) {
791
DEBUG(10, ("ace changed for %s (%o -> %o) id=%d\n",
792
path, ace->aceMask, newMask, specid));
794
ace->aceMask = newMask;
798
/* make sure we have at least ALLOW entries
799
* for all the 3 special ids (@EVERYONE, @OWNER, @GROUP)
802
for(i = SMB_ACE4_WHO_OWNER; i<=SMB_ACE4_WHO_EVERYONE; i++) {
805
if (haveAllowEntry[i]==True)
809
ace.aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE;
810
ace.flags |= SMB_ACE4_ID_SPECIAL;
811
ace.who.special_id = i;
813
if (i==SMB_ACE4_WHO_GROUP) /* not sure it's necessary... */
814
ace.aceFlags |= SMB_ACE4_IDENTIFIER_GROUP;
816
ace.aceMask = gpfsacl_mask_filter(ace.aceType, ace.aceMask,
817
mode >> ((SMB_ACE4_WHO_EVERYONE - i) * 3));
819
/* don't add unnecessary aces */
823
/* we add it to the END - as windows expects allow aces */
824
smb_add_ace4(pacl, &ace);
825
DEBUG(10, ("Added ALLOW ace for %s, mode=%o, id=%d, aceMask=%x\n",
826
path, mode, i, ace.aceMask));
829
/* don't add complementary DENY ACEs here */
830
ZERO_STRUCT(fake_fsp);
831
fake_fsp.fsp_name = (char *)path; /* no file_new is needed here */
834
if (gpfsacl_process_smbacl(&fake_fsp, pacl) == False)
836
return 0; /* ok for [f]chmod */
839
static int vfs_gpfs_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
844
if (SMB_VFS_NEXT_STAT(handle, path, &st) != 0) {
848
/* avoid chmod() if possible, to preserve acls */
849
if ((st.st_mode & ~S_IFMT) == mode) {
853
rc = gpfsacl_emu_chmod(path, mode);
855
return SMB_VFS_NEXT_CHMOD(handle, path, mode);
859
static int vfs_gpfs_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mode)
864
if (SMB_VFS_NEXT_FSTAT(handle, fsp, &st) != 0) {
868
/* avoid chmod() if possible, to preserve acls */
869
if ((st.st_mode & ~S_IFMT) == mode) {
873
rc = gpfsacl_emu_chmod(fsp->fsp_name, mode);
875
return SMB_VFS_NEXT_FCHMOD(handle, fsp, mode);
879
/* VFS operations structure */
881
static vfs_op_tuple gpfs_op_tuples[] = {
883
{ SMB_VFS_OP(vfs_gpfs_kernel_flock),
884
SMB_VFS_OP_KERNEL_FLOCK,
885
SMB_VFS_LAYER_OPAQUE },
887
{ SMB_VFS_OP(vfs_gpfs_setlease),
888
SMB_VFS_OP_LINUX_SETLEASE,
889
SMB_VFS_LAYER_OPAQUE },
891
{ SMB_VFS_OP(vfs_gpfs_get_real_filename),
892
SMB_VFS_OP_GET_REAL_FILENAME,
893
SMB_VFS_LAYER_OPAQUE },
895
{ SMB_VFS_OP(gpfsacl_fget_nt_acl),
896
SMB_VFS_OP_FGET_NT_ACL,
897
SMB_VFS_LAYER_TRANSPARENT },
899
{ SMB_VFS_OP(gpfsacl_get_nt_acl),
900
SMB_VFS_OP_GET_NT_ACL,
901
SMB_VFS_LAYER_TRANSPARENT },
903
{ SMB_VFS_OP(gpfsacl_fset_nt_acl),
904
SMB_VFS_OP_FSET_NT_ACL,
905
SMB_VFS_LAYER_TRANSPARENT },
907
{ SMB_VFS_OP(gpfsacl_sys_acl_get_file),
908
SMB_VFS_OP_SYS_ACL_GET_FILE,
909
SMB_VFS_LAYER_TRANSPARENT },
911
{ SMB_VFS_OP(gpfsacl_sys_acl_get_fd),
912
SMB_VFS_OP_SYS_ACL_GET_FD,
913
SMB_VFS_LAYER_TRANSPARENT },
915
{ SMB_VFS_OP(gpfsacl_sys_acl_set_file),
916
SMB_VFS_OP_SYS_ACL_SET_FILE,
917
SMB_VFS_LAYER_TRANSPARENT },
919
{ SMB_VFS_OP(gpfsacl_sys_acl_set_fd),
920
SMB_VFS_OP_SYS_ACL_SET_FD,
921
SMB_VFS_LAYER_TRANSPARENT },
923
{ SMB_VFS_OP(gpfsacl_sys_acl_delete_def_file),
924
SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE,
925
SMB_VFS_LAYER_TRANSPARENT },
927
{ SMB_VFS_OP(vfs_gpfs_chmod),
929
SMB_VFS_LAYER_TRANSPARENT },
931
{ SMB_VFS_OP(vfs_gpfs_fchmod),
933
SMB_VFS_LAYER_TRANSPARENT },
935
{ SMB_VFS_OP(vfs_gpfs_close),
937
SMB_VFS_LAYER_TRANSPARENT },
939
{ SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP }
944
NTSTATUS vfs_gpfs_init(void);
945
NTSTATUS vfs_gpfs_init(void)
949
return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "gpfs",