symlink: view symlinks in cygwin
handles the query for NfsSymlinkTargetName EA by making a symlink upcall. adds a trailing null for 'ls -l' in cygwin Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
This commit is contained in:
parent
0afc5ebb4d
commit
1a5f3cb3a1
1 changed files with 64 additions and 2 deletions
|
|
@ -4557,6 +4557,7 @@ NTSTATUS map_setea_error(
|
|||
case ERROR_NETNAME_DELETED: return STATUS_NETWORK_NAME_DELETED;
|
||||
case ERROR_FILE_TOO_LARGE: return STATUS_EA_TOO_LARGE;
|
||||
case ERROR_BUFFER_OVERFLOW: return STATUS_BUFFER_OVERFLOW;
|
||||
case STATUS_BUFFER_TOO_SMALL:
|
||||
case ERROR_INSUFFICIENT_BUFFER: return STATUS_BUFFER_TOO_SMALL;
|
||||
case ERROR_INVALID_EA_HANDLE: return STATUS_NONEXISTENT_EA_ENTRY;
|
||||
case ERROR_NO_MORE_FILES: return STATUS_NO_MORE_EAS;
|
||||
|
|
@ -4734,6 +4735,63 @@ out:
|
|||
return status;
|
||||
}
|
||||
|
||||
static NTSTATUS QueryCygwinSymlink(
|
||||
IN OUT PRX_CONTEXT RxContext,
|
||||
IN PFILE_GET_EA_INFORMATION query,
|
||||
OUT PFILE_FULL_EA_INFORMATION info)
|
||||
{
|
||||
__notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
|
||||
__notnull PNFS41_V_NET_ROOT_EXTENSION VNetRootContext =
|
||||
NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
|
||||
__notnull PNFS41_NETROOT_EXTENSION NetRootContext =
|
||||
NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
|
||||
__notnull PNFS41_FOBX Fobx = NFS41GetFobxExtension(RxContext->pFobx);
|
||||
nfs41_updowncall_entry *entry;
|
||||
UNICODE_STRING TargetName;
|
||||
const USHORT HeaderLen = FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName) +
|
||||
query->EaNameLength + 1;
|
||||
NTSTATUS status;
|
||||
|
||||
if (RxContext->Info.LengthRemaining < HeaderLen) {
|
||||
status = STATUS_BUFFER_TOO_SMALL;
|
||||
RxContext->InformationToReturn = HeaderLen;
|
||||
goto out;
|
||||
}
|
||||
|
||||
TargetName.Buffer = (PWCH)(info->EaName + query->EaNameLength + 1);
|
||||
TargetName.MaximumLength = (USHORT)min(RxContext->Info.LengthRemaining -
|
||||
HeaderLen, 0xFFFF);
|
||||
|
||||
status = nfs41_UpcallCreate(NFS41_SYMLINK, &Fobx->sec_ctx,
|
||||
VNetRootContext->session, Fobx->nfs41_open_state,
|
||||
NetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
|
||||
if (status) goto out;
|
||||
|
||||
entry->u.Symlink.filename = SrvOpen->pAlreadyPrefixedName;
|
||||
entry->u.Symlink.target = &TargetName;
|
||||
entry->u.Symlink.set = FALSE;
|
||||
|
||||
status = nfs41_UpcallWaitForReply(entry, VNetRootContext->timeout);
|
||||
if (status) goto out;
|
||||
|
||||
status = map_setea_error(entry->status);
|
||||
if (status == STATUS_SUCCESS) {
|
||||
info->NextEntryOffset = 0;
|
||||
info->Flags = 0;
|
||||
info->EaNameLength = query->EaNameLength;
|
||||
info->EaValueLength = TargetName.Length - sizeof(UNICODE_NULL);
|
||||
TargetName.Buffer[TargetName.Length/sizeof(WCHAR)] = UNICODE_NULL;
|
||||
RtlCopyMemory(info->EaName, query->EaName, query->EaNameLength);
|
||||
RxContext->Info.LengthRemaining = HeaderLen + info->EaValueLength;
|
||||
} else if (status == STATUS_BUFFER_TOO_SMALL) {
|
||||
RxContext->InformationToReturn = HeaderLen +
|
||||
entry->u.Symlink.target->Length;
|
||||
}
|
||||
RxFreePool(entry);
|
||||
out:
|
||||
return status;
|
||||
}
|
||||
|
||||
static NTSTATUS QueryCygwinEA(
|
||||
IN OUT PRX_CONTEXT RxContext,
|
||||
IN PFILE_GET_EA_INFORMATION query,
|
||||
|
|
@ -4744,6 +4802,11 @@ static NTSTATUS QueryCygwinEA(
|
|||
if (query == NULL)
|
||||
goto out;
|
||||
|
||||
if (AnsiStrEq(&NfsSymlinkTargetName, query->EaName, query->EaNameLength)) {
|
||||
status = QueryCygwinSymlink(RxContext, query, info);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (AnsiStrEq(&NfsV3Attributes, query->EaName, query->EaNameLength)) {
|
||||
nfs3_attrs attrs;
|
||||
|
||||
|
|
@ -4773,8 +4836,7 @@ static NTSTATUS QueryCygwinEA(
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (AnsiStrEq(&NfsActOnLink, query->EaName, query->EaNameLength) ||
|
||||
AnsiStrEq(&NfsSymlinkTargetName, query->EaName, query->EaNameLength)) {
|
||||
if (AnsiStrEq(&NfsActOnLink, query->EaName, query->EaNameLength)) {
|
||||
|
||||
const LONG LengthRequired = sizeof(FILE_FULL_EA_INFORMATION) +
|
||||
query->EaNameLength - sizeof(CHAR);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue