fixing open for FILE_SUPERSEDE
http://www.osronline.com/showThread.cfm?link=27213 clarifies that unless open for overwrite_if the old file should be deleted and then created again.
This commit is contained in:
parent
c6ee60b362
commit
4418ba8b69
1 changed files with 25 additions and 10 deletions
|
|
@ -324,22 +324,20 @@ static int map_disposition_2_nfsopen(ULONG disposition, int in_status, bool_t pe
|
||||||
{
|
{
|
||||||
int status = NO_ERROR;
|
int status = NO_ERROR;
|
||||||
if (disposition == FILE_SUPERSEDE) {
|
if (disposition == FILE_SUPERSEDE) {
|
||||||
if (in_status == NFS4ERR_NOENT) {
|
if (in_status == NFS4ERR_NOENT)
|
||||||
*create = OPEN4_CREATE;
|
|
||||||
*last_error = ERROR_FILE_NOT_FOUND;
|
*last_error = ERROR_FILE_NOT_FOUND;
|
||||||
}
|
//remove and recreate the file
|
||||||
else // we need to truncate the file file then open it
|
*create = OPEN4_CREATE;
|
||||||
*create = OPEN4_NOCREATE;
|
if (persistent) *createhowmode = GUARDED4;
|
||||||
|
else *createhowmode = EXCLUSIVE4_1;
|
||||||
} else if (disposition == FILE_CREATE) {
|
} else if (disposition == FILE_CREATE) {
|
||||||
// if lookup succeeded which means the file exist, return an error
|
// if lookup succeeded which means the file exist, return an error
|
||||||
if (!in_status)
|
if (!in_status)
|
||||||
status = ERROR_FILE_EXISTS;
|
status = ERROR_FILE_EXISTS;
|
||||||
else {
|
else {
|
||||||
*create = OPEN4_CREATE;
|
*create = OPEN4_CREATE;
|
||||||
if (persistent)
|
if (persistent) *createhowmode = GUARDED4;
|
||||||
*createhowmode = GUARDED4;
|
else *createhowmode = EXCLUSIVE4_1;
|
||||||
else
|
|
||||||
*createhowmode = EXCLUSIVE4_1;
|
|
||||||
}
|
}
|
||||||
} else if (disposition == FILE_OPEN) {
|
} else if (disposition == FILE_OPEN) {
|
||||||
if (in_status == NFS4ERR_NOENT)
|
if (in_status == NFS4ERR_NOENT)
|
||||||
|
|
@ -584,7 +582,7 @@ static int handle_open(nfs41_upcall *upcall)
|
||||||
args->mode = info.mode;
|
args->mode = info.mode;
|
||||||
args->changeattr = info.change;
|
args->changeattr = info.change;
|
||||||
} else {
|
} else {
|
||||||
uint32_t create = 0, createhowmode = 0;
|
uint32_t create = 0, createhowmode = 0, lookup_status = status;
|
||||||
|
|
||||||
map_access_2_allowdeny(args->access_mask, args->access_mode,
|
map_access_2_allowdeny(args->access_mask, args->access_mode,
|
||||||
args->disposition, &state->share_access, &state->share_deny);
|
args->disposition, &state->share_access, &state->share_deny);
|
||||||
|
|
@ -600,6 +598,21 @@ static int handle_open(nfs41_upcall *upcall)
|
||||||
goto out_free_state;
|
goto out_free_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
supersede_retry:
|
||||||
|
// XXX file exists and we have to remove it first
|
||||||
|
if (args->disposition == FILE_SUPERSEDE && lookup_status == NO_ERROR) {
|
||||||
|
nfs41_component *name = &state->file.name;
|
||||||
|
if (!(args->create_opts & FILE_DIRECTORY_FILE))
|
||||||
|
nfs41_delegation_return(state->session, &state->file,
|
||||||
|
OPEN_DELEGATE_WRITE, TRUE);
|
||||||
|
|
||||||
|
dprintf(1, "open for FILE_SUPERSEDE removing %s first\n", name->name);
|
||||||
|
status = nfs41_remove(state->session, &state->parent,
|
||||||
|
name, state->file.fh.fileid);
|
||||||
|
if (status)
|
||||||
|
goto out_free_state;
|
||||||
|
}
|
||||||
|
|
||||||
if (create == OPEN4_CREATE && (args->create_opts & FILE_DIRECTORY_FILE)) {
|
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, args->mode, NULL,
|
||||||
&state->parent, &state->file);
|
&state->parent, &state->file);
|
||||||
|
|
@ -621,6 +634,8 @@ static int handle_open(nfs41_upcall *upcall)
|
||||||
dprintf(1, "%s failed with %s\n", (create == OPEN4_CREATE &&
|
dprintf(1, "%s failed with %s\n", (create == OPEN4_CREATE &&
|
||||||
(args->create_opts & FILE_DIRECTORY_FILE))?"nfs41_create":"nfs41_open",
|
(args->create_opts & FILE_DIRECTORY_FILE))?"nfs41_create":"nfs41_open",
|
||||||
nfs_error_string(status));
|
nfs_error_string(status));
|
||||||
|
if (args->disposition == FILE_SUPERSEDE && status == NFS4ERR_EXIST)
|
||||||
|
goto supersede_retry;
|
||||||
status = nfs_to_windows_error(status, ERROR_FILE_NOT_FOUND);
|
status = nfs_to_windows_error(status, ERROR_FILE_NOT_FOUND);
|
||||||
goto out_free_state;
|
goto out_free_state;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue