diff --git a/daemon/open.c b/daemon/open.c index c5008b7..8fcba8c 100644 --- a/daemon/open.c +++ b/daemon/open.c @@ -236,6 +236,17 @@ int handle_open(nfs41_upcall *upcall) status = nfs41_lookup(args->root, nfs41_root_session(args->root), &state->path, &state->parent, &state->file, &info, &state->session); + if (status == ERROR_REPARSE) { + /* one of the parent components was a symlink */ + upcall->last_error = ERROR_REPARSE; + args->symlink_embedded = TRUE; + + /* replace the path with the symlink target */ + status = nfs41_symlink_follow(state->session, + &state->parent, &args->symlink); + goto out_free_state; + } + // now if file/dir exists, use type returned by lookup if (status == NO_ERROR) { if (info.type == NF4DIR) { @@ -263,10 +274,11 @@ int handle_open(nfs41_upcall *upcall) } else { /* tell the driver to call RxPrepareToReparseSymbolicLink() */ upcall->last_error = ERROR_REPARSE; + args->symlink_embedded = FALSE; /* replace the path with the symlink target */ status = nfs41_symlink_follow(state->session, - &state->parent, &state->file, &args->symlink); + &state->file, &args->symlink); goto out_free_state; } } else @@ -375,6 +387,8 @@ int marshall_open(unsigned char *buffer, uint32_t *length, nfs41_upcall *upcall) if (status) goto out; if (upcall->last_error == ERROR_REPARSE) { unsigned short len = (args->symlink.len + 1) * sizeof(WCHAR); + status = safe_write(&buffer, length, &args->symlink_embedded, sizeof(BOOLEAN)); + if (status) goto out; status = safe_write(&buffer, length, &len, sizeof(len)); if (status) goto out; /* convert args->symlink to wchar */ diff --git a/daemon/upcall.h b/daemon/upcall.h index 1b45de3..4215e75 100644 --- a/daemon/upcall.h +++ b/daemon/upcall.h @@ -55,6 +55,7 @@ typedef struct __open_upcall_args { DWORD mode; LONGLONG changeattr; BOOLEAN created; + BOOLEAN symlink_embedded; } open_upcall_args; typedef struct __close_upcall_args { diff --git a/sys/nfs41_driver.c b/sys/nfs41_driver.c index 669ab7c..7d3b807 100644 --- a/sys/nfs41_driver.c +++ b/sys/nfs41_driver.c @@ -162,6 +162,7 @@ typedef struct _updowncall_entry { ULONG open_owner_id; DWORD mode; LONGLONG changeattr; + BOOLEAN symlink_embedded; } Open; struct { HANDLE open_state; @@ -1398,6 +1399,8 @@ nfs41_downcall ( RtlCopyMemory(&cur->u.Open.changeattr, buf, sizeof(LONGLONG)); buf += sizeof(LONGLONG); if (tmp->errno == ERROR_REPARSE) { + RtlCopyMemory(&cur->u.Open.symlink_embedded, buf, sizeof(BOOLEAN)); + buf += sizeof(BOOLEAN); RtlCopyMemory(&cur->u.Open.symlink.MaximumLength, buf, sizeof(USHORT)); buf += sizeof(USHORT); cur->u.Open.symlink.Length = cur->u.Open.symlink.MaximumLength - sizeof(WCHAR); @@ -2666,9 +2669,9 @@ NTSTATUS nfs41_Create( RtlCopyMemory(buf, entry->u.Open.symlink.Buffer, entry->u.Open.symlink.Length); status = RxPrepareToReparseSymbolicLink(RxContext, - FALSE, &AbsPath, TRUE, &ReparseRequired); - DbgP("RxPrepareToReparseSymbolicLink('%wZ') returned %08lX, " - "FileName is '%wZ'\n", + entry->u.Open.symlink_embedded, &AbsPath, TRUE, &ReparseRequired); + DbgP("RxPrepareToReparseSymbolicLink(%u, '%wZ') returned %08lX, " + "FileName is '%wZ'\n", entry->u.Open.symlink_embedded, &AbsPath, status, &RxContext->CurrentIrpSp->FileObject->FileName); if (status == STATUS_SUCCESS) status = ReparseRequired ? STATUS_REPARSE :