- From 5ece03478f48a34d4a21ac2a1c42f1e53cca524a Mon Sep 17 00:00:00 2001
- From: Roland Mainz <roland.mainz@nrubsig.org>
- Date: Tue, 6 Jan 2026 11:27:56 +0100
- Subject: [PATCH 1/6] daemon: Fix namecache updates for Windows streams
- Fix namecache updates for Windows streams.
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- daemon/nfs41_ops.c | 25 ++++++++++++++++++-------
- 1 file changed, 18 insertions(+), 7 deletions(-)
- diff --git a/daemon/nfs41_ops.c b/daemon/nfs41_ops.c
- index cc650e9..066c036 100644
- --- a/daemon/nfs41_ops.c
- +++ b/daemon/nfs41_ops.c
- @@ -864,13 +864,18 @@ int nfs41_close(
- if (compound_error(status = compound.res.status))
- goto out;
- - if (info.type == NF4NAMEDATTR)
- - goto out;
- + bool update_cache = true;
- + if ((info.type == NF4NAMEDATTR) && (is_stream_path_fh(file) == false)) {
- + /* This should only happen for Windows EAs */
- + update_cache = false;
- + }
- - /* update the attributes of the parent directory */
- - bitmap4_cpy(&info.attrmask, &getattr_res.obj_attributes.attrmask);
- - nfs41_attr_cache_update(session_name_cache(session),
- - file->fh.fileid, &info);
- + if (update_cache) {
- + /* update the attributes of the parent directory */
- + bitmap4_cpy(&info.attrmask, &getattr_res.obj_attributes.attrmask);
- + nfs41_attr_cache_update(session_name_cache(session),
- + file->fh.fileid, &info);
- + }
- out:
- return status;
- }
- @@ -947,7 +952,13 @@ int nfs41_write(
- if (compound_error(status = compound.res.status))
- goto out;
- - if (stable != UNSTABLE4 && pinfo->type != NF4NAMEDATTR) {
- + bool update_cache = (stable != UNSTABLE4);
- + if ((pinfo->type == NF4NAMEDATTR) && (is_stream_path_fh(file) == false)) {
- + /* This should only happen for Windows EAs */
- + update_cache = false;
- + }
- +
- + if (update_cache) {
- /* update the attribute cache */
- bitmap4_cpy(&pinfo->attrmask, &getattr_res.obj_attributes.attrmask);
- nfs41_attr_cache_update(session_name_cache(session),
- --
- 2.51.0
- From 7e479297b7b17217b48e80f31824873da2424066 Mon Sep 17 00:00:00 2001
- From: Roland Mainz <roland.mainz@nrubsig.org>
- Date: Tue, 6 Jan 2026 12:06:01 +0100
- Subject: [PATCH 2/6] daemon: Unify |read_entire_dir()| implementations and
- move it to util.c
- Unify |read_entire_dir()| implementations and move it to daemon/util.c.
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- daemon/ea.c | 95 +++-----------------------------------
- daemon/util.c | 92 ++++++++++++++++++++++++++++++++++++-
- daemon/util.h | 14 +++++-
- daemon/winstreams.c | 108 ++++++--------------------------------------
- 4 files changed, 124 insertions(+), 185 deletions(-)
- diff --git a/daemon/ea.c b/daemon/ea.c
- index be5ecac..b9c94c1 100644
- --- a/daemon/ea.c
- +++ b/daemon/ea.c
- @@ -1,6 +1,6 @@
- /* NFSv4.1 client for Windows
- * Copyright (C) 2012 The Regents of the University of Michigan
- - * Copyright (C) 2024-2025 Roland Mainz <roland.mainz@nrubsig.org>
- + * Copyright (C) 2024-2026 Roland Mainz <roland.mainz@nrubsig.org>
- *
- * Olga Kornievskaia <aglo@umich.edu>
- * Casey Bodley <cbodley@umich.edu>
- @@ -302,91 +302,6 @@ out:
- return status;
- }
- -#define READDIR_LEN_INITIAL 8192
- -#define READDIR_LEN_MIN 2048
- -
- -/* call readdir repeatedly to get a complete list of entries */
- -static int read_entire_dir(
- - IN nfs41_session *session,
- - IN nfs41_path_fh *eadir,
- - OUT unsigned char **buffer_out,
- - OUT uint32_t *length_out)
- -{
- - nfs41_readdir_cookie cookie = { 0 };
- - bitmap4 attr_request;
- - nfs41_readdir_entry *last_entry;
- - unsigned char *buffer;
- - uint32_t buffer_len, len, total_len;
- - bool_t eof;
- - int status = NO_ERROR;
- -
- - attr_request.count = 0; /* don't request attributes */
- -
- - /* allocate the buffer for readdir entries */
- - buffer_len = READDIR_LEN_INITIAL;
- - buffer = calloc(1, buffer_len);
- - if (buffer == NULL) {
- - status = GetLastError();
- - goto out;
- - }
- -
- - last_entry = NULL;
- - total_len = 0;
- - eof = FALSE;
- -
- - while (!eof) {
- - len = buffer_len - total_len;
- - if (len < READDIR_LEN_MIN) {
- - const ptrdiff_t diff = (unsigned char*)last_entry - buffer;
- - /* realloc the buffer to fit more entries */
- - unsigned char *tmp = realloc(buffer, (size_t)buffer_len * 2L);
- - if (tmp == NULL) {
- - status = GetLastError();
- - goto out_free;
- - }
- -
- - if (last_entry) /* fix last_entry pointer */
- - last_entry = (nfs41_readdir_entry*)(tmp + diff);
- - buffer = tmp;
- - buffer_len *= 2;
- - len = buffer_len - total_len;
- - }
- -
- - /* fetch the next group of entries */
- - status = nfs41_readdir(session, eadir, &attr_request,
- - &cookie, buffer + total_len, &len, &eof);
- - if (status)
- - goto out_free;
- -
- - if (last_entry == NULL) {
- - /* initialize last_entry to the front of the list */
- - last_entry = (nfs41_readdir_entry*)(buffer + total_len);
- - } else if (len) {
- - /* link the previous list to the new one */
- - last_entry->next_entry_offset = (uint32_t)FIELD_OFFSET(
- - nfs41_readdir_entry, name) + last_entry->name_len;
- - }
- -
- - /* find the new last entry */
- - while (last_entry->next_entry_offset) {
- - last_entry = (nfs41_readdir_entry*)((char*)last_entry +
- - last_entry->next_entry_offset);
- - }
- -
- - cookie.cookie = last_entry->cookie;
- - total_len += len;
- - }
- -
- - *buffer_out = buffer;
- - *length_out = total_len;
- -out:
- - return status;
- -
- -out_free:
- - free(buffer);
- - goto out;
- -}
- -
- #define ALIGNED_EASIZE(len) \
- (align4(sizeof(FILE_GET_EA_INFORMATION) + (len)))
- @@ -481,6 +396,9 @@ static int get_ea_list(
- PFILE_GET_EA_INFORMATION ea_list;
- uint32_t entry_len, ea_size;
- int status = NO_ERROR;
- + bitmap4 attr_request = {
- + .count = 0 /* don't request attributes */
- + };
- EnterCriticalSection(&state->ea.lock);
- @@ -492,7 +410,8 @@ static int get_ea_list(
- }
- /* read the entire directory into a nfs41_readdir_entry buffer */
- - status = read_entire_dir(state->session, eadir, &entry_list, &entry_len);
- + status = read_entire_dir(state->session, eadir, &attr_request,
- + &entry_list, &entry_len);
- if (status)
- goto out;
- @@ -512,7 +431,7 @@ static int get_ea_list(
- *ealist_out = state->ea.list = ea_list;
- *eaindex_out = state->ea.index;
- out_free:
- - free(entry_list); /* allocated by read_entire_dir() */
- + free_entire_dir(entry_list); /* allocated by read_entire_dir() */
- out:
- LeaveCriticalSection(&state->ea.lock);
- return status;
- diff --git a/daemon/util.c b/daemon/util.c
- index 8d7f950..7029bb6 100644
- --- a/daemon/util.c
- +++ b/daemon/util.c
- @@ -1,6 +1,6 @@
- /* NFSv4.1 client for Windows
- * Copyright (C) 2012 The Regents of the University of Michigan
- - * Copyright (C) 2023-2025 Roland Mainz <roland.mainz@nrubsig.org>
- + * Copyright (C) 2023-2026 Roland Mainz <roland.mainz@nrubsig.org>
- *
- * Olga Kornievskaia <aglo@umich.edu>
- * Casey Bodley <cbodley@umich.edu>
- @@ -922,3 +922,93 @@ create_symlink_chgrp_out:
- return chgrp_status;
- }
- #endif /* NFS41_DRIVER_SETGID_NEWGRP_SUPPORT */
- +
- +
- +#define READDIR_LEN_INITIAL 8192
- +#define READDIR_LEN_MIN 2048
- +
- +/* call readdir repeatedly to get a complete list of entries */
- +int read_entire_dir(
- + IN nfs41_session *session,
- + IN nfs41_path_fh *dir,
- + IN bitmap4 *attr_request,
- + OUT unsigned char **restrict buffer_out,
- + OUT uint32_t *restrict length_out)
- +{
- + nfs41_readdir_cookie cookie = { 0 };
- + nfs41_readdir_entry *last_entry;
- + unsigned char *buffer;
- + uint32_t buffer_len, len, total_len;
- + bool_t eof;
- + int status = NO_ERROR;
- +
- + /* Allocate the buffer for readdir entries */
- + buffer_len = READDIR_LEN_INITIAL;
- + buffer = calloc(1, buffer_len);
- + if (buffer == NULL) {
- + status = GetLastError();
- + goto out;
- + }
- +
- + last_entry = NULL;
- + total_len = 0;
- + eof = FALSE;
- +
- + while (!eof) {
- + len = buffer_len - total_len;
- + if (len < READDIR_LEN_MIN) {
- + const ptrdiff_t diff = (unsigned char*)last_entry - buffer;
- + /* Reallocate the buffer to fit more entries */
- + unsigned char *tmp = realloc(buffer, (size_t)buffer_len * 2L);
- + if (tmp == NULL) {
- + status = GetLastError();
- + goto out_free;
- + }
- +
- + if (last_entry) /* Fix last_entry pointer */
- + last_entry = (nfs41_readdir_entry *)(tmp + diff);
- + buffer = tmp;
- + buffer_len *= 2;
- + len = buffer_len - total_len;
- + }
- +
- + /* Fetch the next group of entries */
- + status = nfs41_readdir(session, dir, attr_request,
- + &cookie, buffer + total_len, &len, &eof);
- + if (status)
- + goto out_free;
- +
- + if (last_entry == NULL) {
- + /* Initialize last_entry to the front of the list */
- + last_entry = (nfs41_readdir_entry *)(buffer + total_len);
- + } else if (len) {
- + /* Link the previous list to the new one */
- + last_entry->next_entry_offset = (uint32_t)FIELD_OFFSET(
- + nfs41_readdir_entry, name) + last_entry->name_len;
- + }
- +
- + /* Find the new last entry */
- + while (last_entry->next_entry_offset) {
- + last_entry = (nfs41_readdir_entry*)((char*)last_entry +
- + last_entry->next_entry_offset);
- + }
- +
- + cookie.cookie = last_entry->cookie;
- + total_len += len;
- + }
- +
- + *buffer_out = buffer;
- + *length_out = total_len;
- +out:
- + return status;
- +
- +out_free:
- + free_entire_dir(buffer);
- + goto out;
- +}
- +
- +void free_entire_dir(
- + unsigned char *restrict buffer)
- +{
- + free(buffer);
- +}
- diff --git a/daemon/util.h b/daemon/util.h
- index dc0ea07..362df4c 100644
- --- a/daemon/util.h
- +++ b/daemon/util.h
- @@ -1,6 +1,6 @@
- /* NFSv4.1 client for Windows
- * Copyright (C) 2012 The Regents of the University of Michigan
- - * Copyright (C) 2023-2025 Roland Mainz <roland.mainz@nrubsig.org>
- + * Copyright (C) 2023-2026 Roland Mainz <roland.mainz@nrubsig.org>
- *
- * Olga Kornievskaia <aglo@umich.edu>
- * Casey Bodley <cbodley@umich.edu>
- @@ -458,4 +458,16 @@ int chgrp_to_primarygroup(
- IN nfs41_open_state *state);
- #endif /* NFS41_DRIVER_SETGID_NEWGRP_SUPPORT */
- +typedef struct __bitmap4 bitmap4;
- +typedef struct __nfs41_path_fh nfs41_path_fh;
- +typedef struct __nfs41_session nfs41_session;
- +
- +int read_entire_dir(
- + IN nfs41_session *session,
- + IN nfs41_path_fh *dir,
- + IN bitmap4 *attr_request,
- + OUT unsigned char **restrict buffer_out,
- + OUT uint32_t *restrict length_out);
- +void free_entire_dir(
- + unsigned char *restrict buffer);
- #endif /* !__NFS41_DAEMON_UTIL_H__ */
- diff --git a/daemon/winstreams.c b/daemon/winstreams.c
- index 0770131..1478fbe 100644
- --- a/daemon/winstreams.c
- +++ b/daemon/winstreams.c
- @@ -206,100 +206,6 @@ int parse_win32stream_name(
- return NO_ERROR;
- }
- -#define READDIR_LEN_INITIAL 8192
- -#define READDIR_LEN_MIN 2048
- -
- -/* call readdir repeatedly to get a complete list of entries */
- -static
- -int read_entire_dir(
- - IN nfs41_session *session,
- - IN nfs41_path_fh *dir,
- - OUT unsigned char **restrict buffer_out,
- - OUT uint32_t *restrict length_out)
- -{
- - nfs41_readdir_cookie cookie = { 0 };
- - nfs41_readdir_entry *last_entry;
- - unsigned char *buffer;
- - uint32_t buffer_len, len, total_len;
- - bool_t eof;
- - int status = NO_ERROR;
- - /* Attributes for stream */
- - bitmap4 attr_request = {
- - .count = 2,
- - .arr = {
- - [0] = FATTR4_WORD0_TYPE | FATTR4_WORD0_CHANGE |
- - FATTR4_WORD0_SIZE | FATTR4_WORD0_FSID |
- - FATTR4_WORD0_FILEID,
- - [1] = FATTR4_WORD1_SPACE_USED,
- - [2] = 0
- - }
- - };
- -
- - /* allocate the buffer for readdir entries */
- - buffer_len = READDIR_LEN_INITIAL;
- - buffer = calloc(1, buffer_len);
- - if (buffer == NULL) {
- - status = GetLastError();
- - goto out;
- - }
- -
- - last_entry = NULL;
- - total_len = 0;
- - eof = FALSE;
- -
- - while (!eof) {
- - len = buffer_len - total_len;
- - if (len < READDIR_LEN_MIN) {
- - const ptrdiff_t diff = (unsigned char*)last_entry - buffer;
- - /* realloc the buffer to fit more entries */
- - unsigned char *tmp = realloc(buffer, (size_t)buffer_len * 2L);
- - if (tmp == NULL) {
- - status = GetLastError();
- - goto out_free;
- - }
- -
- - if (last_entry) /* Fix last_entry pointer */
- - last_entry = (nfs41_readdir_entry *)(tmp + diff);
- - buffer = tmp;
- - buffer_len *= 2;
- - len = buffer_len - total_len;
- - }
- -
- - /* Fetch the next group of entries */
- - status = nfs41_readdir(session, dir, &attr_request,
- - &cookie, buffer + total_len, &len, &eof);
- - if (status)
- - goto out_free;
- -
- - if (last_entry == NULL) {
- - /* Initialize last_entry to the front of the list */
- - last_entry = (nfs41_readdir_entry *)(buffer + total_len);
- - } else if (len) {
- - /* Link the previous list to the new one */
- - last_entry->next_entry_offset = (uint32_t)FIELD_OFFSET(
- - nfs41_readdir_entry, name) + last_entry->name_len;
- - }
- -
- - /* Find the new last entry */
- - while (last_entry->next_entry_offset) {
- - last_entry = (nfs41_readdir_entry*)((char*)last_entry +
- - last_entry->next_entry_offset);
- - }
- -
- - cookie.cookie = last_entry->cookie;
- - total_len += len;
- - }
- -
- - *buffer_out = buffer;
- - *length_out = total_len;
- -out:
- - return status;
- -
- -out_free:
- - free(buffer);
- - goto out;
- -}
- -
- #define ALIGNED_STREAMINFOSIZE(namebytelen) \
- (align8(sizeof(FILE_STREAM_INFORMATION) + (namebytelen)))
- @@ -488,9 +394,21 @@ int get_stream_list(
- PFILE_STREAM_INFORMATION stream_list;
- uint32_t entry_len, stream_list_size;
- int status = NO_ERROR;
- + /* Attributes for stream */
- + bitmap4 attr_request = {
- + .count = 2,
- + .arr = {
- + [0] = FATTR4_WORD0_TYPE | FATTR4_WORD0_CHANGE |
- + FATTR4_WORD0_SIZE | FATTR4_WORD0_FSID |
- + FATTR4_WORD0_FILEID,
- + [1] = FATTR4_WORD1_SPACE_USED,
- + [2] = 0
- + }
- + };
- /* read the entire directory into a |nfs41_readdir_entry| buffer */
- status = read_entire_dir(state->session, streamfile,
- + &attr_request,
- &entry_list, &entry_len);
- if (status)
- goto out;
- @@ -517,7 +435,7 @@ int get_stream_list(
- *streamlist_out = stream_list;
- *streamlist_out_size = stream_list_size;
- out_free:
- - free(entry_list); /* allocated by |read_entire_dir()| */
- + free_entire_dir(entry_list); /* allocated by |read_entire_dir()| */
- out:
- return status;
- }
- --
- 2.51.0
- From 1eb19df3bca78c808536a81611e3c54ba4afd8dc Mon Sep 17 00:00:00 2001
- From: Roland Mainz <roland.mainz@nrubsig.org>
- Date: Tue, 6 Jan 2026 12:10:00 +0100
- Subject: [PATCH 3/6] daemon: Clarify comment that we use NFS named attributes
- for Windows EA, not RFC8726 XATTRs
- Clarify comment that we use NFSv4 named attributes for Windows EA
- and not the RFC8726 XATTRs extension.
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- daemon/ea.c | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
- diff --git a/daemon/ea.c b/daemon/ea.c
- index b9c94c1..edae48e 100644
- --- a/daemon/ea.c
- +++ b/daemon/ea.c
- @@ -41,11 +41,11 @@
- #endif
- /*
- - * |WIN_NFS4_EA_NAME_PREFIX| - Prefix for Windows EA in NFSv4
- - * XATTR (extended attributes) namespace
- + * |WIN_NFS4_EA_NAME_PREFIX| - Prefix for Windows EAs in NFSv4
- + * named attribute namespace
- *
- * We need such a prefix to avoid colliding with other users
- - * in the NFSv4 XATTR namespace - for example SUN Microsystrems
- + * in the NFSv4 named attribute namespace - for example SUN Microsystrems
- * (Solaris, Illumos, ...) uses "SUNWattr_" as prefix, and setting
- * such attributes can cause data corruption (or in case of
- * "SUNWattr_ro" will fail, because the attribute file is
- --
- 2.51.0
- From 01a08d5d037bd496291fa1b532ae3f1c202bcee5 Mon Sep 17 00:00:00 2001
- From: Roland Mainz <roland.mainz@nrubsig.org>
- Date: Tue, 6 Jan 2026 12:24:36 +0100
- Subject: [PATCH 4/6] daemon: Rename |nfs41_superblock.ea_support| to
- |nfs41_superblock.nfs_namedattr_support|
- Rename |nfs41_superblock.ea_support| to |nfs41_superblock.nfs_namedattr_support|.
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- daemon/acl.c | 6 +++---
- daemon/aclutil.c | 28 ++++++++++++++--------------
- daemon/nfs41.h | 4 ++--
- daemon/nfs41_superblock.c | 8 ++++----
- daemon/winstreams.c | 2 +-
- 5 files changed, 24 insertions(+), 24 deletions(-)
- diff --git a/daemon/acl.c b/daemon/acl.c
- index 2d7546b..4dfcb8a 100644
- --- a/daemon/acl.c
- +++ b/daemon/acl.c
- @@ -1,6 +1,6 @@
- /* NFSv4.1 client for Windows
- * Copyright (C) 2012 The Regents of the University of Michigan
- - * Copyright (C) 2023-2025 Roland Mainz <roland.mainz@nrubsig.org>
- + * Copyright (C) 2023-2026 Roland Mainz <roland.mainz@nrubsig.org>
- *
- * Olga Kornievskaia <aglo@umich.edu>
- * Casey Bodley <cbodley@umich.edu>
- @@ -168,7 +168,7 @@ static int handle_getacl(void *daemon_context, nfs41_upcall *upcall)
- DPRINTF(ACLLVL2, ("handle_getacl: DACL_SECURITY_INFORMATION\n"));
- status = convert_nfs4acl_2_dacl(nfs41dg,
- info.acl, state->type, &dacl, &sids,
- - state->file.fh.superblock->ea_support?true:false);
- + state->file.fh.superblock->nfs_namedattr_support?true:false);
- if (status)
- goto out;
- status = SetSecurityDescriptorDacl(&sec_desc, TRUE, dacl, TRUE);
- @@ -369,7 +369,7 @@ static int handle_setacl(void *daemon_context, nfs41_upcall *upcall)
- }
- status = map_dacl_2_nfs4acl(acl, sid, gsid, &nfs4_acl,
- state->type,
- - state->file.fh.superblock->ea_support?true:false,
- + state->file.fh.superblock->nfs_namedattr_support?true:false,
- nfs41dg->localdomain_name);
- if (status)
- goto out;
- diff --git a/daemon/aclutil.c b/daemon/aclutil.c
- index 6724543..1163a02 100644
- --- a/daemon/aclutil.c
- +++ b/daemon/aclutil.c
- @@ -43,9 +43,9 @@
- static void map_winace2nfs4aceflags(BYTE win_aceflags, uint32_t *nfs4_aceflags);
- static void map_nfs4aceflags2winaceflags(uint32_t nfs4_aceflags, DWORD *win_aceflags);
- static void map_winaccessmask2nfs4acemask(ACCESS_MASK win_mask,
- - int file_type, bool named_attr_support, uint32_t *nfs4_mask);
- + int file_type, bool nfs_namedattr_support, uint32_t *nfs4_mask);
- static void map_nfs4acemask2winaccessmask(uint32_t nfs4_mask,
- - int file_type, bool named_attr_support, ACCESS_MASK *win_mask);
- + int file_type, bool nfs_namedattr_support, ACCESS_MASK *win_mask);
- void convert_nfs4name_2_user_domain(LPSTR nfs4name,
- LPSTR *domain)
- @@ -116,7 +116,7 @@ static int check_4_special_identifiers(const char *restrict who,
- int convert_nfs4acl_2_dacl(nfs41_daemon_globals *nfs41dg,
- nfsacl41 *acl, int file_type, PACL *dacl_out, PSID **sids_out,
- - bool named_attr_support)
- + bool nfs_namedattr_support)
- {
- int status = ERROR_NOT_SUPPORTED, size = 0;
- uint32_t nfs_i = 0, win_i = 0;
- @@ -127,9 +127,9 @@ int convert_nfs4acl_2_dacl(nfs41_daemon_globals *nfs41dg,
- BOOLEAN flag;
- DPRINTF(ACLLVL2, ("--> convert_nfs4acl_2_dacl(acl=0x%p,"
- - "file_type='%s'(=%d), named_attr_support=%d)\n",
- + "file_type='%s'(=%d), nfs_namedattr_support=%d)\n",
- acl, map_nfs_ftype2str(file_type), file_type,
- - (int)named_attr_support));
- + (int)nfs_namedattr_support));
- bool *skip_aces = _alloca(acl->count * sizeof(bool));
- @@ -231,7 +231,7 @@ int convert_nfs4acl_2_dacl(nfs41_daemon_globals *nfs41dg,
- map_nfs4aceflags2winaceflags(curr_nfsace->aceflag,
- &win_aceflags);
- map_nfs4acemask2winaccessmask(curr_nfsace->acemask,
- - file_type, named_attr_support, &mask);
- + file_type, nfs_namedattr_support, &mask);
- if (DPRINTF_LEVEL_ENABLED(ACLLVL1)) {
- dprintf_out("nfs2win: acl->aces[%d].who='%s': "
- @@ -444,7 +444,7 @@ static void map_nfs4aceflags2winaceflags(uint32_t nfs4_aceflags, DWORD *win_acef
- static
- void map_winaccessmask2nfs4acemask(ACCESS_MASK win_mask,
- - int file_type, bool named_attr_support, uint32_t *nfs4_mask)
- + int file_type, bool nfs_namedattr_support, uint32_t *nfs4_mask)
- {
- *nfs4_mask = 0;
- @@ -458,7 +458,7 @@ void map_winaccessmask2nfs4acemask(ACCESS_MASK win_mask,
- uint32_t ace4_all_dir_filt = ACE4_ALL_DIR;
- #ifdef MAP_WIN32GENERIC2ACE4GENERIC
- - if (!named_attr_support) {
- + if (!nfs_namedattr_support) {
- /*
- * Filter out unsupported features for
- * |GENERIC_*| --> |ACE_*ATTR| conversion.
- @@ -568,7 +568,7 @@ void map_winaccessmask2nfs4acemask(ACCESS_MASK win_mask,
- static
- void map_nfs4acemask2winaccessmask(uint32_t nfs4_mask,
- - int file_type, bool named_attr_support, ACCESS_MASK *win_mask)
- + int file_type, bool nfs_namedattr_support, ACCESS_MASK *win_mask)
- {
- *win_mask = 0;
- @@ -582,7 +582,7 @@ void map_nfs4acemask2winaccessmask(uint32_t nfs4_mask,
- uint32_t ace4_all_file_filt = ACE4_ALL_FILE;
- uint32_t ace4_all_dir_filt = ACE4_ALL_DIR;
- - if (!named_attr_support) {
- + if (!nfs_namedattr_support) {
- /*
- * Filter out unsupported features for
- * |ACE_*ATTR| --> |GENERIC_*| conversion.
- @@ -974,7 +974,7 @@ out:
- }
- int map_dacl_2_nfs4acl(PACL acl, PSID sid, PSID gsid, nfsacl41 *nfs4_acl,
- - int file_type, bool named_attr_support, char *domain)
- + int file_type, bool nfs_namedattr_support, char *domain)
- {
- int status;
- if (acl == NULL) {
- @@ -993,7 +993,7 @@ int map_dacl_2_nfs4acl(PACL acl, PSID sid, PSID gsid, nfsacl41 *nfs4_acl,
- uint32_t ace4_all_dir_filt = ACE4_ALL_DIR;
- #ifdef MAP_WIN32GENERIC2ACE4GENERIC
- /* Filter out unsupported features */
- - if (!named_attr_support) {
- + if (!nfs_namedattr_support) {
- ace4_all_dir_filt &= ~ACE4_RW_NAMED_ATTRS;
- }
- #endif /* MAP_WIN32GENERIC2ACE4GENERIC */
- @@ -1003,7 +1003,7 @@ int map_dacl_2_nfs4acl(PACL acl, PSID sid, PSID gsid, nfsacl41 *nfs4_acl,
- uint32_t ace4_all_file_filt = ACE4_ALL_FILE;
- #ifdef MAP_WIN32GENERIC2ACE4GENERIC
- /* Filter out unsupported features */
- - if (!named_attr_support) {
- + if (!nfs_namedattr_support) {
- ace4_all_file_filt &= ~ACE4_RW_NAMED_ATTRS;
- }
- #endif /* MAP_WIN32GENERIC2ACE4GENERIC */
- @@ -1099,7 +1099,7 @@ int map_dacl_2_nfs4acl(PACL acl, PSID sid, PSID gsid, nfsacl41 *nfs4_acl,
- map_winace2nfs4aceflags(ace->AceFlags,
- &curr_nfsace->aceflag);
- map_winaccessmask2nfs4acemask(win_mask,
- - file_type, named_attr_support,
- + file_type, nfs_namedattr_support,
- &curr_nfsace->acemask);
- /*
- diff --git a/daemon/nfs41.h b/daemon/nfs41.h
- index e016d77..953750f 100644
- --- a/daemon/nfs41.h
- +++ b/daemon/nfs41.h
- @@ -1,6 +1,6 @@
- /* NFSv4.1 client for Windows
- * Copyright (C) 2012 The Regents of the University of Michigan
- - * Copyright (C) 2024-2025 Roland Mainz <roland.mainz@nrubsig.org>
- + * Copyright (C) 2024-2026 Roland Mainz <roland.mainz@nrubsig.org>
- *
- * Olga Kornievskaia <aglo@umich.edu>
- * Casey Bodley <cbodley@umich.edu>
- @@ -57,7 +57,7 @@ typedef struct __nfs41_superblock {
- unsigned int cansettime : 1;
- unsigned int link_support : 1;
- unsigned int symlink_support : 1;
- - unsigned int ea_support : 1;
- + unsigned int nfs_namedattr_support : 1;
- unsigned int case_preserving : 1;
- unsigned int case_insensitive : 1;
- unsigned int sparse_file_support : 1;
- diff --git a/daemon/nfs41_superblock.c b/daemon/nfs41_superblock.c
- index 1a767d3..4095ca0 100644
- --- a/daemon/nfs41_superblock.c
- +++ b/daemon/nfs41_superblock.c
- @@ -125,7 +125,7 @@ static int get_superblock_attrs(
- superblock->aclsupport = info.aclsupport;
- superblock->link_support = info.link_support;
- superblock->symlink_support = info.symlink_support;
- - superblock->ea_support = supports_named_attrs;
- + superblock->nfs_namedattr_support = supports_named_attrs;
- #ifdef NFS41_DRIVER_HACK_FORCE_FILENAME_CASE_MOUNTOPTIONS
- if (root->force_case_preserving == TRISTATE_BOOL_NOT_SET) {
- @@ -303,7 +303,7 @@ void nfs41_superblock_fs_attributes(
- FsAttrs->FileSystemAttributes |= FILE_SUPPORTS_HARD_LINKS;
- if (superblock->symlink_support)
- FsAttrs->FileSystemAttributes |= FILE_SUPPORTS_REPARSE_POINTS;
- - if (superblock->ea_support) {
- + if (superblock->nfs_namedattr_support) {
- FsAttrs->FileSystemAttributes |= FILE_SUPPORTS_EXTENDED_ATTRIBUTES;
- #ifdef NFS41_WINSTREAMS_SUPPORT
- FsAttrs->FileSystemAttributes |= FILE_NAMED_STREAMS;
- @@ -335,7 +335,7 @@ void nfs41_superblock_fs_attributes(
- DPRINTF(SBLVL, ("FileFsAttributeInformation: "
- "link_support=%u, "
- "symlink_support=%u, "
- - "ea_support=%u, "
- + "nfs_namedattr_support=%u, "
- "case_preserving=%u, "
- "case_insensitive=%u, "
- "aclsupport=%u, "
- @@ -343,7 +343,7 @@ void nfs41_superblock_fs_attributes(
- "FileSystemAttributes=0x%lx\n",
- superblock->link_support,
- superblock->symlink_support,
- - superblock->ea_support,
- + superblock->nfs_namedattr_support,
- (int)superblock->case_preserving,
- (int)superblock->case_insensitive,
- superblock->aclsupport,
- diff --git a/daemon/winstreams.c b/daemon/winstreams.c
- index 1478fbe..929fb81 100644
- --- a/daemon/winstreams.c
- +++ b/daemon/winstreams.c
- @@ -449,7 +449,7 @@ int get_streaminformation(
- int status;
- nfs41_path_fh parent = { 0 };
- - if (!state->file.fh.superblock->ea_support) {
- + if (!state->file.fh.superblock->nfs_namedattr_support) {
- return ERROR_NOT_SUPPORTED;
- }
- --
- 2.51.0
- From 5f50588ec8fd04b7d7c46f027f02490ab3c21391 Mon Sep 17 00:00:00 2001
- From: Roland Mainz <roland.mainz@nrubsig.org>
- Date: Tue, 6 Jan 2026 12:37:02 +0100
- Subject: [PATCH 5/6] README.md,docs: Document Windows names streams support
- Document Windows names streams support.
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- README.md | 8 ++++++++
- docs/README.xml | 12 ++++++++++++
- 2 files changed, 20 insertions(+)
- diff --git a/README.md b/README.md
- index 2bbb83d..df37c7b 100644
- --- a/README.md
- +++ b/README.md
- @@ -139,6 +139,14 @@ NFSv4.2/NFSv4.1 filesystem driver for Windows 10/11 & Windows Server
- sparse files. Requires on Win11 \>= 22H2 because it relies on
- `|CopyFile2()|` flag `|COPY_FILE_ENABLE_SPARSE_COPY|`.
- +- Windows "named streams"/[Alternate Data
- + Stream](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/c54dec26-1551-4d3a-a0ea-4fa40f848eb3)
- + support
- +
- + - Supports Win32 APIs `|FileStreamInformation|`
- +
- + - Requires NFSv4.1 server which supports the NFSv4.1 named attributes.
- +
- - Case-insensitive filesystem support
- - Requires NFSv4.1 server which supports the
- diff --git a/docs/README.xml b/docs/README.xml
- index e7f3a6c..39e1fdf 100644
- --- a/docs/README.xml
- +++ b/docs/README.xml
- @@ -141,6 +141,18 @@
- </itemizedlist>
- </para>
- </listitem>
- + <listitem>
- + <para>Windows "named streams"/<link xl:href="https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/c54dec26-1551-4d3a-a0ea-4fa40f848eb3">Alternate Data Stream</link> support
- + <itemizedlist>
- + <listitem>
- + <para>Supports Win32 APIs <literal>|<link xl:href="https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_file_stream_information">FileStreamInformation</link>|</literal></para>
- + </listitem>
- + <listitem>
- + <para>Requires NFSv4.1 server which supports the NFSv4.1 named attributes.</para>
- + </listitem>
- + </itemizedlist>
- + </para>
- + </listitem>
- <listitem>
- <para>Case-insensitive filesystem support
- <itemizedlist>
- --
- 2.51.0
- From 83cbc2adb01d0003991859ed039827f17a15adcf Mon Sep 17 00:00:00 2001
- From: Dan Shelton <dan.f.shelton@gmail.com>
- Date: Tue, 6 Jan 2026 13:41:14 +0100
- Subject: [PATCH 6/6] daemon: Fix printf()-style&co format argument warning
- Fix printf()-style&co format argument warning.
- Signed-off-by: Cedric Blancher <cedric.blancher@gmail.com>
- ---
- daemon/acl.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
- diff --git a/daemon/acl.c b/daemon/acl.c
- index 4dfcb8a..0b97538 100644
- --- a/daemon/acl.c
- +++ b/daemon/acl.c
- @@ -51,7 +51,7 @@ static int parse_getacl(
- EASSERT(length == 0);
- - DPRINTF(1, ("parsing NFS41_SYSOP_ACL_QUERY: secinfo=0xlx\n",
- + DPRINTF(1, ("parsing NFS41_SYSOP_ACL_QUERY: secinfo=0x%lx\n",
- (long)args->query_secinfo));
- out:
- return status;
- --
- 2.51.0
msnfs41client: Patchs for Win32 named streams, cleanup, docs+misc, 2026-01-06
Posted by Anonymous on Tue 6th Jan 2026 13:25
raw | new post
Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.
rovema.kpaste.net RSS