nwconn: align AFP attribute bits with WebSDK
All checks were successful
Source release / source-package (push) Successful in 46s

The WebSDK/NCP AFP File Information records use a distinct SetInfo request bitmap and attribute word.  The previous smoke-oriented implementation reused the low response-bit positions for Set Attributes, Modify Date/Time, FinderInfo, Hidden/Invisible, System, and Archive.  That made the current tests pass, but it was not faithful to the documented header semantics and risked keeping AFP metadata parallel to existing NetWare attributes.

Switch Set File Information to the documented request bitmap values: 0x0100 for Attributes, 0x1000 for Modify Date/Time, and 0x4000 for FinderInfo.  Switch the AFP attribute word to the documented NetWare-style bits: Hidden 0x0200, System 0x0400, Subdirectory 0x1000, and Archive 0x2000.

Map Hidden, System, and Archive through the existing NetWare attribute store via FILE_ATTR_H, FILE_ATTR_S, and FILE_ATTR_A.  This keeps AFP Set/Get/Scan aligned with mars_nwe's existing attribute helper instead of maintaining duplicate AFP-only xattr state.  FinderInfo remains AFP metadata and still uses the Modify-rights gate added earlier.

Update the Linux smoke helper and suite to use --hidden / --clear-hidden while keeping --invisible / --clear-invisible as compatibility aliases.  Document the corrected WebSDK bit values and the convergence rule that NetWare attributes must use mars_nwe NetWare helpers.

Tests: git diff --check; bash -n tests/linux/afp_smoke_suite.sh; gcc -Iinclude -I/mnt/data/stubs -fsyntax-only tests/linux/afp_set_file_info_smoke.c
This commit is contained in:
OpenAI
2026-05-30 15:46:23 +00:00
committed by Mario Fetka
parent fb4934fddc
commit 55fdf64c8e
6 changed files with 122 additions and 94 deletions

View File

@@ -22,11 +22,11 @@
#define MARS_NWE_AFP_ENTRY_ID_VERSION 1
#define MARS_NWE_AFP_ATTRIBUTES_VERSION 1
#define NWATALK_AFP_ATTR_INVISIBLE 0x0001
#define NWATALK_AFP_ATTR_SYSTEM 0x0004
#define NWATALK_AFP_ATTR_SETCLR 0x8000
#define NWATALK_AFP_ATTR_HIDDEN 0x0200
#define NWATALK_AFP_ATTR_SYSTEM 0x0400
#define NWATALK_AFP_ATTR_SETCLR 0x8000
#define NWATALK_AFP_ATTR_STORED_MASK \
(NWATALK_AFP_ATTR_INVISIBLE | NWATALK_AFP_ATTR_SYSTEM)
(NWATALK_AFP_ATTR_HIDDEN | NWATALK_AFP_ATTR_SYSTEM)
typedef struct {
uint8 version;

View File

@@ -1112,34 +1112,34 @@ static void afp_leaf_name_from_path(uint8 *dst, int dst_len,
afp_copy_fixed_name(dst, dst_len, path + start, end - start);
}
#define AFP_FILE_BITMAP_ATTRIBUTES 0x0001
#define AFP_FILE_BITMAP_MODIFY_DATE 0x0010
#define AFP_FILE_BITMAP_FINDER_INFO 0x0020
#define AFP_ATTR_INVISIBLE 0x0001
#define AFP_ATTR_SYSTEM 0x0004
#define AFP_ATTR_ARCHIVE 0x0040
#define AFP_FILE_BITMAP_ATTRIBUTES 0x0100
#define AFP_FILE_BITMAP_MODIFY_DATE 0x1000
#define AFP_FILE_BITMAP_FINDER_INFO 0x4000
#define AFP_ATTR_HIDDEN 0x0200
#define AFP_ATTR_SYSTEM 0x0400
#define AFP_ATTR_SUBDIRECTORY 0x1000
#define AFP_ATTR_ARCHIVE 0x2000
#define AFP_ATTR_SETCLR 0x8000
#define AFP_ATTR_STORED_MASK \
(AFP_ATTR_INVISIBLE | AFP_ATTR_SYSTEM | AFP_ATTR_ARCHIVE)
#define AFP_ATTR_XATTR_MASK \
(AFP_ATTR_INVISIBLE | AFP_ATTR_SYSTEM)
#define AFP_ATTR_NETWARE_MASK \
(AFP_ATTR_HIDDEN | AFP_ATTR_SYSTEM | AFP_ATTR_ARCHIVE)
static uint16 afp_basic_attributes(int volume, const char *unixname, const struct stat *stb)
{
uint16 attributes = 0;
if (S_ISDIR(stb->st_mode))
attributes |= 0x0400; /* AFP_SA_SUBDIR */
attributes |= AFP_ATTR_SUBDIRECTORY;
if (!S_ISDIR(stb->st_mode)) {
uint16 stored_attrs = 0;
uint32 nw_attrs = get_nw_attrib_dword(volume, (char *)unixname,
(struct stat *)stb);
if (nw_attrs & FILE_ATTR_H)
attributes |= AFP_ATTR_HIDDEN;
if (nw_attrs & FILE_ATTR_S)
attributes |= AFP_ATTR_SYSTEM;
if (nw_attrs & FILE_ATTR_A)
attributes |= AFP_ATTR_ARCHIVE;
if (!nwatalk_get_afp_attributes(unixname, &stored_attrs))
attributes |= stored_attrs;
}
return(attributes);
@@ -1290,18 +1290,29 @@ static int afp_get_file_information(uint8 *afp_req, int afp_len,
}
static int afp_set_netware_archive_attribute(int volume, char *unixname,
struct stat *stb,
uint16 requested_attrs)
static int afp_set_netware_attributes(int volume, char *unixname,
struct stat *stb,
uint16 requested_attrs)
{
uint32 nw_attrs;
uint16 requested_bits;
uint32 mapped_bits = 0;
if (!unixname || !stb) return(-0x9c);
requested_bits = requested_attrs & ~AFP_ATTR_SETCLR;
if (requested_bits & AFP_ATTR_HIDDEN) mapped_bits |= FILE_ATTR_H;
if (requested_bits & AFP_ATTR_SYSTEM) mapped_bits |= FILE_ATTR_S;
if (requested_bits & AFP_ATTR_ARCHIVE) mapped_bits |= FILE_ATTR_A;
if (!mapped_bits) return(0);
nw_attrs = get_nw_attrib_dword(volume, unixname, stb);
if (requested_attrs & AFP_ATTR_SETCLR)
nw_attrs |= FILE_ATTR_A;
nw_attrs |= mapped_bits;
else
nw_attrs &= ~FILE_ATTR_A;
nw_attrs &= ~mapped_bits;
return(set_nw_attrib_word(volume, unixname, stb, (int)(nw_attrs & 0xffff)));
}
@@ -1400,13 +1411,13 @@ static int afp_set_file_information(uint8 *afp_req, int afp_len,
if (request_mask & AFP_FILE_BITMAP_ATTRIBUTES) {
uint16 requested_attrs = GET_BE16(afp_req + data_off);
uint16 requested_bits = requested_attrs & ~AFP_ATTR_SETCLR;
if (requested_bits & ~AFP_ATTR_STORED_MASK) {
if (requested_bits & ~AFP_ATTR_NETWARE_MASK) {
XDPRINTF((2,0, "%s rejected: unsupported AFP attributes attrs=0x%04x path='%s'",
call_name, requested_attrs, visable_data(afp_req + 9, path_len)));
return(-0x9c);
}
if (requested_bits & AFP_ATTR_XATTR_MASK)
needs_afp_metadata_modify = 1;
/* Attribute writes are routed through set_nw_attrib_word(), which performs
* the NetWare Modify-rights check. FinderInfo remains AFP metadata. */
data_off += 2;
}
if ((request_mask & AFP_FILE_BITMAP_MODIFY_DATE) && afp_len < data_off + 4) {
@@ -1461,17 +1472,12 @@ static int afp_set_file_information(uint8 *afp_req, int afp_len,
uint16 requested_attrs = GET_BE16(afp_req + data_off);
uint16 requested_set_bits = requested_attrs & ~AFP_ATTR_SETCLR;
log_attrs = requested_attrs;
if (requested_set_bits & AFP_ATTR_ARCHIVE) {
result = afp_set_netware_archive_attribute(path_volume, unixname,
&stbuff, requested_attrs);
if (result < 0)
return(result);
}
if (requested_set_bits & AFP_ATTR_XATTR_MASK) {
uint16 xattr_attrs = requested_attrs & (AFP_ATTR_SETCLR | AFP_ATTR_XATTR_MASK);
result = nwatalk_set_afp_attributes(unixname, xattr_attrs);
if (requested_set_bits & AFP_ATTR_NETWARE_MASK) {
result = afp_set_netware_attributes(path_volume, unixname,
&stbuff, requested_attrs);
if (result < 0)
return(result);
if (!stat(unixname, &stbuff)) {}
}
data_off += 2;
}