From 3bf16d1e42e955d97519a47c95c75b51cf346772 Mon Sep 17 00:00:00 2001 From: Mario Fetka Date: Mon, 25 May 2026 22:46:37 +0200 Subject: [PATCH] NCP22/25 modifierID --- include/nwarchive.h | 8 +++++ src/connect.c | 35 +++++++++++++++------ src/namspace.c | 11 ++++++- src/nwarchive.c | 75 +++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 117 insertions(+), 12 deletions(-) diff --git a/include/nwarchive.h b/include/nwarchive.h index 5387890..1e40bc7 100644 --- a/include/nwarchive.h +++ b/include/nwarchive.h @@ -11,6 +11,7 @@ #define MARS_NWE_FILEINFO_HAS_CREATE_DATE 0x01 #define MARS_NWE_FILEINFO_HAS_CREATE_TIME 0x02 #define MARS_NWE_FILEINFO_HAS_CREATOR 0x04 +#define MARS_NWE_FILEINFO_HAS_MODIFIER 0x08 void mars_nwe_get_archive_info(char *unixname, uint16 *archive_date, @@ -34,4 +35,11 @@ int mars_nwe_set_file_info(char *unixname, int set_create_time, uint16 create_time, int set_creator, uint32 creator_id); +void mars_nwe_get_file_modifier_info(char *unixname, + uint32 *modifier_id, + uint8 *flags); + +int mars_nwe_set_file_modifier_info(char *unixname, + int set_modifier, uint32 modifier_id); + #endif diff --git a/src/connect.c b/src/connect.c index dfa7f35..bb4041b 100644 --- a/src/connect.c +++ b/src/connect.c @@ -1401,8 +1401,11 @@ static int set_ncp22_25_file_info(char *unixname, uint16 cdate = 0; uint16 ctime = 0; uint32 cid = 0; + uint32 mid = 0; + int result; - if (!(change_mask & (DM_CREATE_DATE | DM_CREATE_TIME | DM_CREATOR_ID))) + if (!(change_mask & (DM_CREATE_DATE | DM_CREATE_TIME | DM_CREATOR_ID | + DM_MODIFIER_ID))) return(0); if (is_dir) { @@ -1419,12 +1422,18 @@ static int set_ncp22_25_file_info(char *unixname, ctime = (uint16)GET_16(f->u.f.created.time); if (change_mask & DM_CREATOR_ID) cid = GET_BE32(f->u.f.created.id); + if (change_mask & DM_MODIFIER_ID) + mid = GET_BE32(f->u.f.updated.id); } - return(mars_nwe_set_file_info(unixname, - !!(change_mask & DM_CREATE_DATE), cdate, - !!(change_mask & DM_CREATE_TIME), ctime, - !!(change_mask & DM_CREATOR_ID), cid)); + result = mars_nwe_set_file_info(unixname, + !!(change_mask & DM_CREATE_DATE), cdate, + !!(change_mask & DM_CREATE_TIME), ctime, + !!(change_mask & DM_CREATOR_ID), cid); + if (!result && !is_dir) + result = mars_nwe_set_file_modifier_info(unixname, + !!(change_mask & DM_MODIFIER_ID), mid); + return(result); } static void log_ncp22_25_change_bits(uint32 change_mask) @@ -1439,10 +1448,9 @@ static void log_ncp22_25_change_bits(uint32 change_mask) if (unsupported) { XDPRINTF((5,0, - "NCP22/25 unsupported change bits ignored: modifier=%d maxspace=%d other=0x%08lx", - !!(change_mask & DM_MODIFIER_ID), + "NCP22/25 unsupported change bits ignored: maxspace=%d other=0x%08lx", !!(change_mask & DM_MAXIMUM_SPACE), - (unsigned long)(unsupported & ~(DM_MODIFIER_ID | DM_MAXIMUM_SPACE)))); + (unsigned long)(unsupported & ~DM_MAXIMUM_SPACE))); } } @@ -3027,7 +3035,16 @@ void get_dos_file_attrib(NW_DOS_FILE_INFO *f, un_date_2_nw(stb->st_mtime, f->updated.date, 0); un_time_2_nw(stb->st_mtime, f->updated.time, 0); - U32_TO_BE32(nw_owner, f->updated.id); + { + uint32 modifier_id = 0; + uint8 mod_flags = 0; + mars_nwe_get_file_modifier_info(unixname, &modifier_id, &mod_flags); + if (mod_flags & MARS_NWE_FILEINFO_HAS_MODIFIER) { + U32_TO_BE32(modifier_id, f->updated.id); + } else { + U32_TO_BE32(nw_owner, f->updated.id); + } + } un_date_2_nw(stb->st_atime, f->last_access_date, 0); U32_TO_32(stb->st_size, f->size); diff --git a/src/namspace.c b/src/namspace.c index 1595db4..1cb2fc7 100644 --- a/src/namspace.c +++ b/src/namspace.c @@ -1127,7 +1127,16 @@ static int build_dir_info(DIR_BASE_ENTRY *dbe, p +=2; un_date_2_nw(stb->st_mtime, p, 0); p +=2; - U32_TO_BE32(owner, p); /* HI-LOW ! */ + { + uint32 modifier_id = 0; + uint8 mod_flags = 0; + mars_nwe_get_file_modifier_info(unixname, &modifier_id, &mod_flags); + if (mod_flags & MARS_NWE_FILEINFO_HAS_MODIFIER) { + U32_TO_BE32(modifier_id, p); /* HI-LOW ! */ + } else { + U32_TO_BE32(owner, p); /* HI-LOW ! */ + } + } p +=4; un_date_2_nw(stb->st_atime, p, 0); /* access date */ p +=2; diff --git a/src/nwarchive.c b/src/nwarchive.c index e10c67b..7d8a394 100644 --- a/src/nwarchive.c +++ b/src/nwarchive.c @@ -157,8 +157,11 @@ typedef struct { uint8 create_date[2]; uint8 create_time[2]; uint8 creator_id[4]; + uint8 modifier_id[4]; } MARS_NWE_FILEINFO_XATTR_DATA; +#define MARS_NWE_FILEINFO_XATTR_V1_SIZE 10 + static void init_file_info_data(MARS_NWE_FILEINFO_XATTR_DATA *d) { memset(d, 0, sizeof(*d)); @@ -169,6 +172,7 @@ static void read_file_info_data(MARS_NWE_FILEINFO_XATTR_DATA *d, uint16 *create_date, uint16 *create_time, uint32 *creator_id, + uint32 *modifier_id, uint8 *flags) { if (flags) @@ -182,6 +186,9 @@ static void read_file_info_data(MARS_NWE_FILEINFO_XATTR_DATA *d, if (creator_id) *creator_id = (d->flags & MARS_NWE_FILEINFO_HAS_CREATOR) ? GET_BE32(d->creator_id) : 0; + if (modifier_id) + *modifier_id = (d->flags & MARS_NWE_FILEINFO_HAS_MODIFIER) + ? GET_BE32(d->modifier_id) : 0; } #if XATTR_SUPPORT @@ -194,7 +201,8 @@ static int get_file_info_data(char *unixname, MARS_NWE_FILEINFO_XATTR_DATA *d) return(-1); len = getxattr(unixname, MARS_NWE_FILEINFO_XATTR, d, sizeof(*d)); - if (len != sizeof(*d) || d->version != MARS_NWE_FILEINFO_VERSION) { + if ((len != sizeof(*d) && len != MARS_NWE_FILEINFO_XATTR_V1_SIZE) || + d->version != MARS_NWE_FILEINFO_VERSION) { init_file_info_data(d); return(-1); } @@ -216,7 +224,22 @@ void mars_nwe_get_file_info(char *unixname, (void)unixname; init_file_info_data(&d); #endif - read_file_info_data(&d, create_date, create_time, creator_id, flags); + read_file_info_data(&d, create_date, create_time, creator_id, NULL, flags); +} + +void mars_nwe_get_file_modifier_info(char *unixname, + uint32 *modifier_id, + uint8 *flags) +{ + MARS_NWE_FILEINFO_XATTR_DATA d; + +#if XATTR_SUPPORT + (void)get_file_info_data(unixname, &d); +#else + (void)unixname; + init_file_info_data(&d); +#endif + read_file_info_data(&d, NULL, NULL, NULL, modifier_id, flags); } int mars_nwe_set_file_info(char *unixname, @@ -285,3 +308,51 @@ int mars_nwe_set_file_info(char *unixname, #endif return(0); } + + +int mars_nwe_set_file_modifier_info(char *unixname, + int set_modifier, uint32 modifier_id) +{ +#if XATTR_SUPPORT + MARS_NWE_FILEINFO_XATTR_DATA d; + + (void)get_file_info_data(unixname, &d); + + if (set_modifier) { + U32_TO_BE32(modifier_id, d.modifier_id); + if (modifier_id) + d.flags |= MARS_NWE_FILEINFO_HAS_MODIFIER; + else + d.flags &= (uint8)~MARS_NWE_FILEINFO_HAS_MODIFIER; + } + + if (!unixname || !*unixname) + return(0); + + if (!d.flags) { + if (removexattr(unixname, MARS_NWE_FILEINFO_XATTR)) { + int err = errno; +#if defined(ENOATTR) + if (err != ENODATA && err != ENOATTR) +#else + if (err != ENODATA) +#endif + XDPRINTF((5,0,"mars_nwe fileinfo xattr remove ignored for %s errno=%d", unixname, err)); + } + return(0); + } + + if (setxattr(unixname, MARS_NWE_FILEINFO_XATTR, &d, sizeof(d), 0)) { + int err = errno; + /* Compatibility rule: modifier metadata has no portable POSIX field. + * Keep the NCP call successful and only log the missing persistence. + */ + XDPRINTF((5,0,"mars_nwe fileinfo xattr ignored for %s errno=%d", unixname, err)); + } +#else + (void)unixname; + (void)set_modifier; + (void)modifier_id; +#endif + return(0); +}