diff --git a/daemon/nfs41_const.h b/daemon/nfs41_const.h index 0a74cad..27bb361 100644 --- a/daemon/nfs41_const.h +++ b/daemon/nfs41_const.h @@ -41,10 +41,6 @@ #define UPCALL_BUF_SIZE 1024 -/* FileSystemName reported for FileFsAttributeInformation */ -#define NFS41_FILESYSTEM_NAME L"NFS" -#define NFS41_FILESYSTEM_NAME_LEN (sizeof(NFS41_FILESYSTEM_NAME)-sizeof(WCHAR)) - /* MaximumComponentNameLength reported for FileFsAttributeInformation */ #define NFS41_MAX_COMPONENT_LEN 64 #define NFS41_MAX_PATH_LEN MAX_PATH diff --git a/daemon/upcall.h b/daemon/upcall.h index 40f62f9..45fb941 100644 --- a/daemon/upcall.h +++ b/daemon/upcall.h @@ -141,12 +141,6 @@ typedef struct __volume_upcall_args { FILE_FS_SIZE_INFORMATION size; FILE_FS_FULL_SIZE_INFORMATION fullsize; FILE_FS_ATTRIBUTE_INFORMATION attribute; - - /* attribute.FileSystemName is WCHAR[1], so even though there's - * some extra space in the union from other members, reserve - * enough space for an arbitrary NFS41_FILESYSTEM_NAME_LEN */ - unsigned char buffer[sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + - NFS41_FILESYSTEM_NAME_LEN]; } info; } volume_upcall_args; diff --git a/daemon/volume.c b/daemon/volume.c index 064b95d..508309b 100644 --- a/daemon/volume.c +++ b/daemon/volume.c @@ -98,7 +98,6 @@ static int handle_volume_attributes( bitmap4 attr_request = { 1, { FATTR4_WORD0_CASE_INSENSITIVE | FATTR4_WORD0_CASE_PRESERVING } }; PFILE_FS_ATTRIBUTE_INFORMATION attr = &args->info.attribute; - size_t max_length; int status = NO_ERROR; status = nfs41_getattr(session, NULL, &attr_request, &info); @@ -117,27 +116,14 @@ static int handle_volume_attributes( attr->MaximumComponentNameLength = NFS41_MAX_COMPONENT_LEN; - /* calculate how much space we have for FileSystemName; args.info.buffer - * should guarantee us enough room for NFS41_FILESYSTEM_NAME */ - max_length = sizeof(args->info) - - FIELD_OFFSET(FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName); + /* let the driver fill in FileSystemName/Len */ - if (FAILED(StringCbCopyNW(attr->FileSystemName, max_length, - NFS41_FILESYSTEM_NAME, NFS41_FILESYSTEM_NAME_LEN))) { - status = ERROR_BUFFER_OVERFLOW; - eprintf("FileSystemName '%S' truncated to '%S'! returning %d\n", - NFS41_FILESYSTEM_NAME, attr->FileSystemName, status); - goto out; - } - - attr->FileSystemNameLength = NFS41_FILESYSTEM_NAME_LEN; - args->len = sizeof(args->info.attribute) + NFS41_FILESYSTEM_NAME_LEN; + args->len = sizeof(args->info.attribute); dprintf(2, "FileFsAttributeInformation: case_preserving %u, " - "case_insensitive %u, max component %u, name '%S', length %u\n", + "case_insensitive %u, max component %u\n", info.case_preserving, info.case_insensitive, - attr->MaximumComponentNameLength, - attr->FileSystemName, attr->FileSystemNameLength); + attr->MaximumComponentNameLength); out: return status; } diff --git a/sys/nfs41_driver.c b/sys/nfs41_driver.c index 8887117..67ce84e 100644 --- a/sys/nfs41_driver.c +++ b/sys/nfs41_driver.c @@ -278,10 +278,17 @@ typedef struct _NFS41_NETROOT_EXTENSION { #define NFS41GetNetRootExtension(pNetRoot) \ (((pNetRoot) == NULL) ? NULL : (PNFS41_NETROOT_EXTENSION)((pNetRoot)->Context)) +/* FileSystemName as reported by FileFsAttributeInfo query */ +#define FS_NAME L"NFS" +#define FS_NAME_LEN (sizeof(FS_NAME) - sizeof(WCHAR)) +#define FS_ATTR_LEN (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + FS_NAME_LEN) + typedef struct _NFS41_V_NET_ROOT_EXTENSION { NODE_TYPE_CODE NodeTypeCode; NODE_BYTE_SIZE NodeByteSize; HANDLE session; + BYTE FsAttrs[FS_ATTR_LEN]; + LONG FsAttrsLen; } NFS41_V_NET_ROOT_EXTENSION, *PNFS41_V_NET_ROOT_EXTENSION; #define NFS41GetVNetRootExtension(pVNetRoot) \ (((pVNetRoot) == NULL) ? NULL : \ @@ -3039,8 +3046,23 @@ NTSTATUS nfs41_QueryVolumeInformation ( goto out; } - case FileFsSizeInformation: case FileFsAttributeInformation: + /* used cached fs attributes if available */ + if (pVNetRootContext->FsAttrsLen) { + const LONG len = pVNetRootContext->FsAttrsLen; + if (RxContext->Info.LengthRemaining < len) { + RxContext->InformationToReturn = len; + status = STATUS_BUFFER_TOO_SMALL; + goto out; + } + RtlCopyMemory(RxContext->Info.Buffer, + pVNetRootContext->FsAttrs, len); + RxContext->Info.LengthRemaining -= len; + status = STATUS_SUCCESS; + goto out; + } + /* else fall through and send the upcall */ + case FileFsSizeInformation: case FileFsFullSizeInformation: break; @@ -3067,6 +3089,28 @@ NTSTATUS nfs41_QueryVolumeInformation ( RxContext->InformationToReturn = entry->u.Volume.buf_len; status = STATUS_BUFFER_TOO_SMALL; } else if (entry->status == STATUS_SUCCESS) { + if (InfoClass == FileFsAttributeInformation) { + /* fill in the FileSystemName */ + PFILE_FS_ATTRIBUTE_INFORMATION attrs = + (PFILE_FS_ATTRIBUTE_INFORMATION)RxContext->Info.Buffer; + DECLARE_CONST_UNICODE_STRING(FsName, FS_NAME); + entry->u.Volume.buf_len += FsName.Length; + if (entry->u.Volume.buf_len > RxContext->Info.LengthRemaining) { + RxContext->InformationToReturn = entry->u.Volume.buf_len; + status = STATUS_BUFFER_TOO_SMALL; + goto out; + } + RtlCopyMemory(attrs->FileSystemName, FsName.Buffer, + FsName.MaximumLength); /* 'MaximumLength' to include null */ + attrs->FileSystemNameLength = FsName.Length; + + /* save fs attributes with the vnetroot */ + if (entry->u.Volume.buf_len <= FS_ATTR_LEN) { + RtlCopyMemory(&pVNetRootContext->FsAttrs, + RxContext->Info.Buffer, entry->u.Volume.buf_len); + pVNetRootContext->FsAttrsLen = entry->u.Volume.buf_len; + } + } RxContext->Info.LengthRemaining -= entry->u.Volume.buf_len; status = STATUS_SUCCESS; } else {