From 80d979ace62bd9adcd8d65f0c026963792f0c53a Mon Sep 17 00:00:00 2001 From: Casey Bodley Date: Thu, 23 Sep 2010 12:19:21 -0400 Subject: [PATCH] symlink: driver marshalls new SYMLINK upcall new NFS41_SYMLINK upcall and associated data in nfs41_updowncall_entry.u.Symlink supports both setting and querying the symlink target. if Symlink.set is TRUE, Symlink.target is marshalled into the upcall. if Symlink.set is FALSE, Symlink.target is read from the downcall Signed-off-by: Casey Bodley --- sys/nfs41_debug.c | 1 + sys/nfs41_driver.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++ sys/nfs41_driver.h | 1 + 3 files changed, 68 insertions(+) diff --git a/sys/nfs41_debug.c b/sys/nfs41_debug.c index 6e7b27a..a753e68 100644 --- a/sys/nfs41_debug.c +++ b/sys/nfs41_debug.c @@ -579,6 +579,7 @@ const char *opcode2string(int opcode) case NFS41_FILE_QUERY: return "NFS41_FILE_QUERY"; case NFS41_FILE_SET: return "NFS41_FILE_SET"; case NFS41_EA_SET: return "NFS41_EA_SET"; + case NFS41_SYMLINK: return "NFS41_SYMLINK"; case NFS41_VOLUME_QUERY: return "NFS41_VOLUME_QUERY"; default: return "UNKNOWN"; } diff --git a/sys/nfs41_driver.c b/sys/nfs41_driver.c index 08f3964..61d0119 100644 --- a/sys/nfs41_driver.c +++ b/sys/nfs41_driver.c @@ -198,6 +198,13 @@ typedef struct _updowncall_entry { HANDLE session; DWORD mode; } SetEa; + struct { + HANDLE open_state; + HANDLE session; + PUNICODE_STRING filename; + PUNICODE_STRING target; + BOOLEAN set; + } Symlink; struct { HANDLE session; FS_INFORMATION_CLASS query; @@ -968,6 +975,49 @@ out: return status; } +NTSTATUS marshal_nfs41_symlink(nfs41_updowncall_entry *entry, + unsigned char *buf, + ULONG buf_len, + ULONG *len) +{ + NTSTATUS status = STATUS_SUCCESS; + ULONG header_len = 0; + unsigned char *tmp = buf; + + DbgEn(); + status = marshal_nfs41_header(entry, tmp, buf_len, len); + if (status == STATUS_INSUFFICIENT_RESOURCES) + goto out; + else + tmp += *len; + header_len = *len + 2 * sizeof(HANDLE) + sizeof(BOOLEAN) + + length_as_ansi(entry->u.Symlink.filename); + if (entry->u.Symlink.set) + header_len += length_as_ansi(entry->u.Symlink.target); + if (header_len > buf_len) { + status = STATUS_INSUFFICIENT_RESOURCES; + goto out; + } + + RtlCopyMemory(tmp, &entry->u.Symlink.session, sizeof(HANDLE)); + tmp += sizeof(HANDLE); + RtlCopyMemory(tmp, &entry->u.Symlink.open_state, sizeof(HANDLE)); + tmp += sizeof(HANDLE); + marshall_unicode_as_ansi(&tmp, entry->u.Symlink.filename); + RtlCopyMemory(tmp, &entry->u.Symlink.set, sizeof(BOOLEAN)); + tmp += sizeof(BOOLEAN); + if (entry->u.Symlink.set) + marshall_unicode_as_ansi(&tmp, entry->u.Symlink.target); + + *len = header_len; + + DbgP("session=0x%x open_state=0x%x set=0x%x\n", + entry->u.SetEa.session, entry->u.SetEa.open_state, entry->u.SetEa.mode); +out: + DbgEx(); + return status; +} + NTSTATUS marshal_nfs41_volume(nfs41_updowncall_entry *entry, unsigned char *buf, ULONG buf_len, @@ -1086,6 +1136,9 @@ handle_upcall( case NFS41_EA_SET: status = marshal_nfs41_easet(entry, pbOut, cbOut, len); break; + case NFS41_SYMLINK: + status = marshal_nfs41_symlink(entry, pbOut, cbOut, len); + break; case NFS41_VOLUME_QUERY: status = marshal_nfs41_volume(entry, pbOut, cbOut, len); break; @@ -1370,6 +1423,19 @@ nfs41_downcall ( RtlCopyMemory(&cur->u.QueryFile.readdir_cookie, buf, sizeof(HANDLE)); } break; + case NFS41_SYMLINK: + if (cur->u.Symlink.set) + break; + RtlCopyMemory(&cur->u.Symlink.target->Length, buf, sizeof(USHORT)); + buf += sizeof(USHORT); + if (cur->u.Symlink.target->Length > cur->u.Symlink.target->MaximumLength) { + cur->status = STATUS_BUFFER_TOO_SMALL; + break; + } + RtlCopyMemory(cur->u.Symlink.target->Buffer, buf, + cur->u.Symlink.target->Length); + cur->u.Symlink.target->Length -= sizeof(UNICODE_NULL); + break; case NFS41_VOLUME_QUERY: RtlCopyMemory(&tmp->u.Volume.buf_len, buf, sizeof(LONG)); buf += sizeof(LONG); diff --git a/sys/nfs41_driver.h b/sys/nfs41_driver.h index 30b0153..0614662 100644 --- a/sys/nfs41_driver.h +++ b/sys/nfs41_driver.h @@ -64,6 +64,7 @@ typedef enum _nfs41_opcodes { NFS41_FILE_QUERY, NFS41_FILE_SET, NFS41_EA_SET, + NFS41_SYMLINK, NFS41_VOLUME_QUERY, NFS41_SHUTDOWN, INVALID_OPCODE