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:
Casey Bodley 2012-05-07 14:51:30 -04:00 committed by Olga Kornievskaia
parent 0afc5ebb4d
commit 1a5f3cb3a1

View file

@ -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);