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 <cbodley@citi.umich.edu>
This commit is contained in:
parent
b51bd2f9d1
commit
80d979ace6
3 changed files with 68 additions and 0 deletions
|
|
@ -579,6 +579,7 @@ const char *opcode2string(int opcode)
|
||||||
case NFS41_FILE_QUERY: return "NFS41_FILE_QUERY";
|
case NFS41_FILE_QUERY: return "NFS41_FILE_QUERY";
|
||||||
case NFS41_FILE_SET: return "NFS41_FILE_SET";
|
case NFS41_FILE_SET: return "NFS41_FILE_SET";
|
||||||
case NFS41_EA_SET: return "NFS41_EA_SET";
|
case NFS41_EA_SET: return "NFS41_EA_SET";
|
||||||
|
case NFS41_SYMLINK: return "NFS41_SYMLINK";
|
||||||
case NFS41_VOLUME_QUERY: return "NFS41_VOLUME_QUERY";
|
case NFS41_VOLUME_QUERY: return "NFS41_VOLUME_QUERY";
|
||||||
default: return "UNKNOWN";
|
default: return "UNKNOWN";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -198,6 +198,13 @@ typedef struct _updowncall_entry {
|
||||||
HANDLE session;
|
HANDLE session;
|
||||||
DWORD mode;
|
DWORD mode;
|
||||||
} SetEa;
|
} SetEa;
|
||||||
|
struct {
|
||||||
|
HANDLE open_state;
|
||||||
|
HANDLE session;
|
||||||
|
PUNICODE_STRING filename;
|
||||||
|
PUNICODE_STRING target;
|
||||||
|
BOOLEAN set;
|
||||||
|
} Symlink;
|
||||||
struct {
|
struct {
|
||||||
HANDLE session;
|
HANDLE session;
|
||||||
FS_INFORMATION_CLASS query;
|
FS_INFORMATION_CLASS query;
|
||||||
|
|
@ -968,6 +975,49 @@ out:
|
||||||
return status;
|
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,
|
NTSTATUS marshal_nfs41_volume(nfs41_updowncall_entry *entry,
|
||||||
unsigned char *buf,
|
unsigned char *buf,
|
||||||
ULONG buf_len,
|
ULONG buf_len,
|
||||||
|
|
@ -1086,6 +1136,9 @@ handle_upcall(
|
||||||
case NFS41_EA_SET:
|
case NFS41_EA_SET:
|
||||||
status = marshal_nfs41_easet(entry, pbOut, cbOut, len);
|
status = marshal_nfs41_easet(entry, pbOut, cbOut, len);
|
||||||
break;
|
break;
|
||||||
|
case NFS41_SYMLINK:
|
||||||
|
status = marshal_nfs41_symlink(entry, pbOut, cbOut, len);
|
||||||
|
break;
|
||||||
case NFS41_VOLUME_QUERY:
|
case NFS41_VOLUME_QUERY:
|
||||||
status = marshal_nfs41_volume(entry, pbOut, cbOut, len);
|
status = marshal_nfs41_volume(entry, pbOut, cbOut, len);
|
||||||
break;
|
break;
|
||||||
|
|
@ -1370,6 +1423,19 @@ nfs41_downcall (
|
||||||
RtlCopyMemory(&cur->u.QueryFile.readdir_cookie, buf, sizeof(HANDLE));
|
RtlCopyMemory(&cur->u.QueryFile.readdir_cookie, buf, sizeof(HANDLE));
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case NFS41_VOLUME_QUERY:
|
||||||
RtlCopyMemory(&tmp->u.Volume.buf_len, buf, sizeof(LONG));
|
RtlCopyMemory(&tmp->u.Volume.buf_len, buf, sizeof(LONG));
|
||||||
buf += sizeof(LONG);
|
buf += sizeof(LONG);
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@ typedef enum _nfs41_opcodes {
|
||||||
NFS41_FILE_QUERY,
|
NFS41_FILE_QUERY,
|
||||||
NFS41_FILE_SET,
|
NFS41_FILE_SET,
|
||||||
NFS41_EA_SET,
|
NFS41_EA_SET,
|
||||||
|
NFS41_SYMLINK,
|
||||||
NFS41_VOLUME_QUERY,
|
NFS41_VOLUME_QUERY,
|
||||||
NFS41_SHUTDOWN,
|
NFS41_SHUTDOWN,
|
||||||
INVALID_OPCODE
|
INVALID_OPCODE
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue