diff --git a/daemon/delegation.c b/daemon/delegation.c index ecb0bcb..e26c2af 100644 --- a/daemon/delegation.c +++ b/daemon/delegation.c @@ -441,19 +441,14 @@ static int delegation_truncate( IN nfs41_delegation_state *deleg, IN nfs41_client *client, IN stateid_arg *stateid, - IN uint32_t mode, IN nfs41_file_info *info) { nfs41_superblock *superblock = deleg->file.fh.superblock; /* use SETATTR to truncate the file */ - info->attrmask.arr[0] = FATTR4_WORD0_SIZE; - info->attrmask.arr[1] = FATTR4_WORD1_MODE | - FATTR4_WORD1_TIME_CREATE | FATTR4_WORD1_TIME_MODIFY_SET; - info->attrmask.count = 2; + info->attrmask.arr[1] |= FATTR4_WORD1_TIME_CREATE | + FATTR4_WORD1_TIME_MODIFY_SET; - info->size = 0; - info->mode = mode; get_nfs_time(&info->time_create); get_nfs_time(&info->time_modify); info->time_delta = &superblock->time_delta; @@ -467,7 +462,7 @@ static int delegation_truncate( int nfs41_delegate_open( IN nfs41_open_state *state, IN uint32_t create, - IN uint32_t mode, + IN OPTIONAL nfs41_file_info *createattrs, OUT nfs41_file_info *info) { nfs41_client *client = state->session->client; @@ -518,8 +513,10 @@ int nfs41_delegate_open( goto out_deleg; if (create == OPEN4_CREATE) { + memcpy(info, createattrs, sizeof(nfs41_file_info)); + /* write delegations allow us to simulate OPEN4_CREATE with SETATTR */ - status = delegation_truncate(deleg, client, &stateid, mode, info); + status = delegation_truncate(deleg, client, &stateid, info); if (status) goto out_deleg; } @@ -585,7 +582,7 @@ int nfs41_delegation_to_open( status = nfs41_open(open->session, &open->parent, &open->file, &open->owner, &claim, open->share_access, open->share_deny, - OPEN4_NOCREATE, 0, 0, try_recovery, &open_stateid, &ignore, NULL); + OPEN4_NOCREATE, 0, NULL, try_recovery, &open_stateid, &ignore, NULL); AcquireSRWLockExclusive(&open->lock); if (status == NFS4_OK) { diff --git a/daemon/delegation.h b/daemon/delegation.h index bd1f653..517dc32 100644 --- a/daemon/delegation.h +++ b/daemon/delegation.h @@ -52,7 +52,7 @@ int nfs41_delegation_granted( int nfs41_delegate_open( IN nfs41_open_state *state, IN uint32_t create, - IN uint32_t mode, + IN OPTIONAL nfs41_file_info *createattrs, OUT nfs41_file_info *info); int nfs41_delegation_to_open( diff --git a/daemon/nfs41_ops.c b/daemon/nfs41_ops.c index efb2e32..c4bc4e3 100644 --- a/daemon/nfs41_ops.c +++ b/daemon/nfs41_ops.c @@ -375,7 +375,7 @@ int nfs41_open( IN uint32_t deny, IN uint32_t create, IN uint32_t how_mode, - IN uint32_t mode, + IN OPTIONAL nfs41_file_info *createattrs, IN bool_t try_recovery, OUT stateid4 *stateid, OUT open_delegation4 *delegation, @@ -462,11 +462,7 @@ int nfs41_open( open_args.owner = owner; open_args.openhow.opentype = create; open_args.openhow.how.mode = how_mode; - open_args.openhow.how.createattrs.info.attrmask.count = 2; - open_args.openhow.how.createattrs.info.attrmask.arr[0] = FATTR4_WORD0_SIZE; - open_args.openhow.how.createattrs.info.attrmask.arr[1] = FATTR4_WORD1_MODE; - open_args.openhow.how.createattrs.info.mode = mode; - open_args.openhow.how.createattrs.info.size = 0; + open_args.openhow.how.createattrs = createattrs; if (how_mode == EXCLUSIVE4_1) { DWORD tid = GetCurrentThreadId(); time((time_t*)open_args.openhow.how.createverf); @@ -529,7 +525,7 @@ out: int nfs41_create( IN nfs41_session *session, IN uint32_t type, - IN uint32_t mode, + IN nfs41_file_info *createattrs, IN OPTIONAL const char *symlink, IN nfs41_path_fh *parent, OUT nfs41_path_fh *file, @@ -575,10 +571,7 @@ int nfs41_create( create_args.objtype.u.lnk.linkdata_len = (uint32_t)strlen(symlink); } create_args.name = &file->name; - create_args.createattrs.info.attrmask.count = 2; - create_args.createattrs.info.attrmask.arr[0] = 0; - create_args.createattrs.info.attrmask.arr[1] = FATTR4_WORD1_MODE; - create_args.createattrs.info.mode = mode; //511; // 0777 + create_args.createattrs = createattrs; compound_add_op(&compound, OP_GETFH, NULL, &getfh_res); getfh_res.fh = &file->fh; diff --git a/daemon/nfs41_ops.h b/daemon/nfs41_ops.h index d8cccce..7217942 100644 --- a/daemon/nfs41_ops.h +++ b/daemon/nfs41_ops.h @@ -352,14 +352,10 @@ typedef struct __createtype4 { } u; } createtype4; -typedef struct __createattrs4 { - nfs41_file_info info; -} createattrs4; - typedef struct __nfs41_create_args { createtype4 objtype; const nfs41_component *name; - createattrs4 createattrs; + nfs41_file_info *createattrs; } nfs41_create_args; typedef struct __nfs41_create_res { @@ -549,7 +545,7 @@ enum createmode4 { typedef struct __createhow4 { uint32_t mode; - createattrs4 createattrs; + nfs41_file_info *createattrs; unsigned char createverf[NFS4_VERIFIER_SIZE]; } createhow4; @@ -1045,7 +1041,7 @@ int nfs41_open( IN uint32_t deny, IN uint32_t create, IN uint32_t how_mode, - IN uint32_t mode, + IN OPTIONAL nfs41_file_info *createattrs, IN bool_t try_recovery, OUT stateid4 *stateid, OUT open_delegation4 *delegation, @@ -1054,7 +1050,7 @@ int nfs41_open( int nfs41_create( IN nfs41_session *session, IN uint32_t type, - IN uint32_t mode, + IN nfs41_file_info *createattrs, IN OPTIONAL const char *symlink, IN nfs41_path_fh *parent, OUT nfs41_path_fh *file, diff --git a/daemon/nfs41_xdr.c b/daemon/nfs41_xdr.c index 9462033..990c648 100644 --- a/daemon/nfs41_xdr.c +++ b/daemon/nfs41_xdr.c @@ -1338,13 +1338,13 @@ static bool_t encode_createtype4( static bool_t encode_createattrs4( XDR *xdr, - createattrs4* createattrs) + nfs41_file_info* createattrs) { fattr4 attrs; /* encode attribute values from createattrs->info into attrs.attr_vals */ attrs.attr_vals_len = NFS4_OPAQUE_LIMIT; - if (!encode_file_attrs(&attrs, &createattrs->info)) + if (!encode_file_attrs(&attrs, createattrs)) return FALSE; return xdr_fattr4(xdr, &attrs); @@ -1365,7 +1365,7 @@ static bool_t encode_op_create( if (!encode_component(xdr, args->name)) return FALSE; - return encode_createattrs4(xdr, &args->createattrs); + return encode_createattrs4(xdr, args->createattrs); } static bool_t xdr_change_info4( @@ -1896,7 +1896,7 @@ static bool_t encode_createhow4( { case UNCHECKED4: case GUARDED4: - result = encode_createattrs4(xdr, &ch->createattrs); + result = encode_createattrs4(xdr, ch->createattrs); break; case EXCLUSIVE4: result = xdr_opaque(xdr, (char *)ch->createverf, NFS4_VERIFIER_SIZE); @@ -1904,7 +1904,7 @@ static bool_t encode_createhow4( case EXCLUSIVE4_1: if (!xdr_opaque(xdr, (char *)ch->createverf, NFS4_VERIFIER_SIZE)) return FALSE; - if (!encode_createattrs4(xdr, &ch->createattrs)) + if (!encode_createattrs4(xdr, ch->createattrs)) return FALSE; break; } diff --git a/daemon/open.c b/daemon/open.c index 4197fce..7198cef 100644 --- a/daemon/open.c +++ b/daemon/open.c @@ -184,7 +184,7 @@ static int do_open( IN OUT nfs41_open_state *state, IN uint32_t create, IN uint32_t createhow, - IN uint32_t mode, + IN nfs41_file_info *createattrs, IN bool_t try_recovery, OUT nfs41_file_info *info) { @@ -199,7 +199,8 @@ static int do_open( status = nfs41_open(state->session, &state->parent, &state->file, &state->owner, &claim, state->share_access, state->share_deny, - create, createhow, mode, TRUE, &open_stateid, &delegation, info); + create, createhow, createattrs, TRUE, &open_stateid, + &delegation, info); if (status) goto out; @@ -226,18 +227,19 @@ static int open_or_delegate( IN OUT nfs41_open_state *state, IN uint32_t create, IN uint32_t createhow, - IN uint32_t mode, + IN nfs41_file_info *createattrs, IN bool_t try_recovery, OUT nfs41_file_info *info) { int status; /* check for existing delegation */ - status = nfs41_delegate_open(state, create, mode, info); + status = nfs41_delegate_open(state, create, createattrs, info); /* get an open stateid if we have no delegation stateid */ if (status) - status = do_open(state, create, createhow, mode, try_recovery, info); + status = do_open(state, create, createhow, + createattrs, try_recovery, info); state->pnfs_last_offset = info->size ? info->size - 1 : 0; @@ -582,8 +584,14 @@ static int handle_open(nfs41_upcall *upcall) args->mode = info.mode; args->changeattr = info.change; } else { + nfs41_file_info createattrs; uint32_t create = 0, createhowmode = 0, lookup_status = status; + createattrs.attrmask.count = 2; + createattrs.attrmask.arr[0] = 0; + createattrs.attrmask.arr[1] = FATTR4_WORD1_MODE; + createattrs.mode = args->mode; + map_access_2_allowdeny(args->access_mask, args->access_mode, args->disposition, &state->share_access, &state->share_deny); status = map_disposition_2_nfsopen(args->disposition, status, @@ -614,11 +622,13 @@ supersede_retry: } if (create == OPEN4_CREATE && (args->create_opts & FILE_DIRECTORY_FILE)) { - status = nfs41_create(state->session, NF4DIR, args->mode, NULL, + status = nfs41_create(state->session, NF4DIR, &createattrs, NULL, &state->parent, &state->file, &info); args->created = status == NFS4_OK ? TRUE : FALSE; } else { - status = open_or_delegate(state, create, createhowmode, args->mode, + createattrs.attrmask.arr[0] = FATTR4_WORD0_SIZE; + createattrs.size = 0; + status = open_or_delegate(state, create, createhowmode, &createattrs, TRUE, &info); if (status == NFS4_OK && state->delegation.state) args->deleg_type = state->delegation.state->state.type; diff --git a/daemon/recovery.c b/daemon/recovery.c index 7713602..82af5a0 100644 --- a/daemon/recovery.c +++ b/daemon/recovery.c @@ -151,7 +151,7 @@ static int recover_open_grace( claim.u.prev.delegate_type = delegation->type; return nfs41_open(session, parent, file, owner, &claim, access, deny, - OPEN4_NOCREATE, 0, 0, FALSE, stateid, delegation, NULL); + OPEN4_NOCREATE, 0, NULL, FALSE, stateid, delegation, NULL); } static int recover_open_no_grace( @@ -173,7 +173,7 @@ static int recover_open_no_grace( claim.u.deleg_prev.filename = &file->name; status = nfs41_open(session, parent, file, owner, - &claim, access, deny, OPEN4_NOCREATE, 0, 0, FALSE, + &claim, access, deny, OPEN4_NOCREATE, 0, NULL, FALSE, stateid, delegation, NULL); if (status == NFS4_OK || status == NFS4ERR_BADSESSION) goto out; @@ -193,7 +193,7 @@ static int recover_open_no_grace( access |= OPEN4_SHARE_ACCESS_WANT_WRITE_DELEG; status = nfs41_open(session, parent, file, owner, - &claim, access, deny, OPEN4_NOCREATE, 0, 0, FALSE, + &claim, access, deny, OPEN4_NOCREATE, 0, NULL, FALSE, stateid, delegation, NULL); out: return status; diff --git a/daemon/setattr.c b/daemon/setattr.c index 863551f..c5855f8 100644 --- a/daemon/setattr.c +++ b/daemon/setattr.c @@ -521,7 +521,7 @@ static int handle_setexattr(nfs41_upcall *upcall) setexattr_upcall_args *args = &upcall->args.setexattr; nfs41_open_state *state = upcall->state_ref; stateid_arg stateid; - nfs41_file_info info = { 0 }; + nfs41_file_info createattrs, info = { 0 }; PFILE_FULL_EA_INFORMATION eainfo = (PFILE_FULL_EA_INFORMATION)args->buf, prev = NULL; nfs41_path_fh parent, file; @@ -533,6 +533,12 @@ static int handle_setexattr(nfs41_upcall *upcall) UCHAR *buf; open_delegation4 delegation = { 0 }; + createattrs.attrmask.count = 2; + createattrs.attrmask.arr[0] = FATTR4_WORD0_SIZE; + createattrs.attrmask.arr[1] = FATTR4_WORD1_MODE; + createattrs.size = 0; + createattrs.mode = 0664; + /* break read delegations before SETATTR */ nfs41_delegation_return(state->session, &state->file, OPEN_DELEGATE_READ, FALSE); @@ -577,7 +583,7 @@ static int handle_setexattr(nfs41_upcall *upcall) claim.u.null.filename = &dst_name; status = nfs41_open(state->session, &parent, &file, &state->owner, &claim, OPEN4_SHARE_ACCESS_WRITE, OPEN4_SHARE_DENY_BOTH, OPEN4_CREATE, - UNCHECKED4, 0664, TRUE, &open_stateid, &delegation, NULL); + UNCHECKED4, &createattrs, TRUE, &open_stateid, &delegation, NULL); if (status) { dprintf(1, "handle_setexattr: nfs41_rpc_open() failed with error %s.\n", nfs_error_string(status)); diff --git a/daemon/symlink.c b/daemon/symlink.c index 61ccc0d..0a33e3f 100644 --- a/daemon/symlink.c +++ b/daemon/symlink.c @@ -227,7 +227,8 @@ static int handle_symlink(nfs41_upcall *upcall) int status = NO_ERROR; if (args->set) { - nfs41_file_info info; + nfs41_file_info info, createattrs; + /* don't send windows slashes to the server */ char *p; for (p = args->target_set; *p; p++) if (*p == '\\') *p = '/'; @@ -249,7 +250,11 @@ static int handle_symlink(nfs41_upcall *upcall) } /* create the symlink */ - status = nfs41_create(state->session, NF4LNK, 0777, + createattrs.attrmask.count = 1; + createattrs.attrmask.arr[0] = 0; + createattrs.attrmask.arr[1] = FATTR4_WORD1_MODE; + createattrs.mode = 0777; + status = nfs41_create(state->session, NF4LNK, &createattrs, args->target_set, &state->parent, &state->file, &info); if (status) { eprintf("nfs41_create() for symlink=%s failed with %s\n",