NCP22/25 Create-Date/Create-Time/Creator-ID über xattr speichern
All checks were successful
Source release / source-package (push) Successful in 35s

This commit is contained in:
Mario Fetka
2026-05-25 22:13:48 +02:00
parent 9aa2a6eee3
commit cc144f60d0
4 changed files with 283 additions and 20 deletions

View File

@@ -8,6 +8,10 @@
#define MARS_NWE_ARCHIVE_HAS_TIME 0x02
#define MARS_NWE_ARCHIVE_HAS_ARCHIVER 0x04
#define MARS_NWE_FILEINFO_HAS_CREATE_DATE 0x01
#define MARS_NWE_FILEINFO_HAS_CREATE_TIME 0x02
#define MARS_NWE_FILEINFO_HAS_CREATOR 0x04
void mars_nwe_get_archive_info(char *unixname,
uint16 *archive_date,
uint16 *archive_time,
@@ -19,4 +23,15 @@ int mars_nwe_set_archive_info(char *unixname,
int set_time, uint16 archive_time,
int set_archiver, uint32 archiver_id);
void mars_nwe_get_file_info(char *unixname,
uint16 *create_date,
uint16 *create_time,
uint32 *creator_id,
uint8 *flags);
int mars_nwe_set_file_info(char *unixname,
int set_create_date, uint16 create_date,
int set_create_time, uint16 create_time,
int set_creator, uint32 creator_id);
#endif

View File

@@ -1296,7 +1296,8 @@ static time_t nw_2_un_time_parts(uint16 xdate, uint16 xtime)
#define DM_NCP22_25_ARCHIVE_BITS \
(DM_ARCHIVE_DATE | DM_ARCHIVE_TIME | DM_ARCHIVER_ID)
#define DM_NCP22_25_SUPPORTED_BITS \
(DM_ATTRIBUTES | DM_NCP22_25_ARCHIVE_BITS | DM_NCP22_25_TIME_BITS | \
(DM_ATTRIBUTES | DM_CREATE_DATE | DM_CREATE_TIME | DM_CREATOR_ID | \
DM_NCP22_25_ARCHIVE_BITS | DM_NCP22_25_TIME_BITS | \
DM_INHERITED_RIGHTS_MASK)
static int set_ncp22_25_times(int volume, char *unixname, struct stat *stb,
@@ -1392,6 +1393,40 @@ static int set_ncp22_25_archive_info(char *unixname,
!!(change_mask & DM_ARCHIVER_ID), aid));
}
static int set_ncp22_25_file_info(char *unixname,
NW_SET_DIR_INFO *f,
uint32 change_mask,
int is_dir)
{
uint16 cdate = 0;
uint16 ctime = 0;
uint32 cid = 0;
if (!(change_mask & (DM_CREATE_DATE | DM_CREATE_TIME | DM_CREATOR_ID)))
return(0);
if (is_dir) {
if (change_mask & DM_CREATE_DATE)
cdate = (uint16)GET_16(f->u.d.created.date);
if (change_mask & DM_CREATE_TIME)
ctime = (uint16)GET_16(f->u.d.created.time);
if (change_mask & DM_CREATOR_ID)
cid = GET_BE32(f->u.d.created.id);
} else {
if (change_mask & DM_CREATE_DATE)
cdate = (uint16)GET_16(f->u.f.created.date);
if (change_mask & DM_CREATE_TIME)
ctime = (uint16)GET_16(f->u.f.created.time);
if (change_mask & DM_CREATOR_ID)
cid = GET_BE32(f->u.f.created.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));
}
static void log_ncp22_25_change_bits(uint32 change_mask)
{
uint32 unsupported = change_mask & ~DM_NCP22_25_SUPPORTED_BITS;
@@ -1404,14 +1439,10 @@ static void log_ncp22_25_change_bits(uint32 change_mask)
if (unsupported) {
XDPRINTF((5,0,
"NCP22/25 unsupported change bits ignored: create=%d creator=%d modifier=%d maxspace=%d other=0x%08lx",
!!(change_mask & (DM_CREATE_DATE | DM_CREATE_TIME)),
!!(change_mask & DM_CREATOR_ID),
"NCP22/25 unsupported change bits ignored: modifier=%d maxspace=%d other=0x%08lx",
!!(change_mask & DM_MODIFIER_ID),
!!(change_mask & DM_MAXIMUM_SPACE),
(unsigned long)(unsupported & ~(DM_CREATE_DATE | DM_CREATE_TIME |
DM_CREATOR_ID | DM_MODIFIER_ID |
DM_MAXIMUM_SPACE))));
(unsigned long)(unsupported & ~(DM_MODIFIER_ID | DM_MAXIMUM_SPACE))));
}
}
@@ -1428,7 +1459,15 @@ static int get_file_attrib(NW_FILE_INFO *f, char *unixname, struct stat *stb,
dwattrib = get_nw_attrib_dword(nwpath->volume, unixname, stb);
U16_TO_16(dwattrib, f->attrib);
un_date_2_nw(stb->st_mtime, f->create_date, 1);
{
uint16 create_date = 0;
uint8 meta_flags = 0;
mars_nwe_get_file_info(unixname, &create_date, NULL, NULL, &meta_flags);
if (meta_flags & MARS_NWE_FILEINFO_HAS_CREATE_DATE)
U16_TO_BE16(create_date, f->create_date);
else
un_date_2_nw(stb->st_mtime, f->create_date, 1);
}
un_date_2_nw(stb->st_atime, f->acces_date, 1);
un_date_2_nw(stb->st_mtime, f->modify_date, 1);
un_time_2_nw(stb->st_mtime, f->modify_time, 1);
@@ -1451,9 +1490,26 @@ static int get_dir_attrib(NW_DIR_INFO *d, char *unixname, struct stat *stb,
dwattrib = get_nw_attrib_dword(nwpath->volume, unixname, stb);
U16_TO_16(dwattrib, d->attrib);
un_date_2_nw(stb->st_mtime, d->create_date, 1);
un_time_2_nw(stb->st_mtime, d->create_time, 1);
U32_TO_BE32(get_file_owner(stb), d->owner_id);
{
uint16 create_date = 0;
uint16 create_time = 0;
uint32 creator_id = 0;
uint8 meta_flags = 0;
mars_nwe_get_file_info(unixname, &create_date, &create_time,
&creator_id, &meta_flags);
if (meta_flags & MARS_NWE_FILEINFO_HAS_CREATE_DATE)
U16_TO_BE16(create_date, d->create_date);
else
un_date_2_nw(stb->st_mtime, d->create_date, 1);
if (meta_flags & MARS_NWE_FILEINFO_HAS_CREATE_TIME)
U16_TO_BE16(create_time, d->create_time);
else
un_time_2_nw(stb->st_mtime, d->create_time, 1);
if (meta_flags & MARS_NWE_FILEINFO_HAS_CREATOR)
U32_TO_BE32(creator_id, d->owner_id);
else
U32_TO_BE32(get_file_owner(stb), d->owner_id);
}
d->access_right_mask = 0;
d->reserved = 0;
U16_TO_BE16(0, d->next_search);
@@ -2930,9 +2986,26 @@ void get_dos_file_attrib(NW_DOS_FILE_INFO *f,
U32_TO_32(get_nw_attrib_dword(volume, unixname, stb), f->attributes);
U16_TO_16(tru_get_inherited_mask(volume, unixname, stb),
f->inherited_rights_mask);
un_date_2_nw(stb->st_mtime, f->created.date, 0);
un_time_2_nw(stb->st_mtime, f->created.time, 0);
U32_TO_BE32(nw_owner, f->created.id);
{
uint16 create_date = 0;
uint16 create_time = 0;
uint32 creator_id = 0;
uint8 meta_flags = 0;
mars_nwe_get_file_info(unixname, &create_date, &create_time,
&creator_id, &meta_flags);
if (meta_flags & MARS_NWE_FILEINFO_HAS_CREATE_DATE)
U16_TO_16(create_date, f->created.date);
else
un_date_2_nw(stb->st_mtime, f->created.date, 0);
if (meta_flags & MARS_NWE_FILEINFO_HAS_CREATE_TIME)
U16_TO_16(create_time, f->created.time);
else
un_time_2_nw(stb->st_mtime, f->created.time, 0);
if (meta_flags & MARS_NWE_FILEINFO_HAS_CREATOR)
U32_TO_BE32(creator_id, f->created.id);
else
U32_TO_BE32(nw_owner, f->created.id);
}
{
uint16 archive_date = 0;
@@ -2969,9 +3042,26 @@ void get_dos_dir_attrib(NW_DOS_DIR_INFO *f,
f->attributes);
U16_TO_16(tru_get_inherited_mask(volume, unixname, stb),
f->inherited_rights_mask);
un_date_2_nw(stb->st_mtime, f->created.date,0);
un_time_2_nw(stb->st_mtime, f->created.time,0);
U32_TO_BE32(get_file_owner(stb), f->created.id);
{
uint16 create_date = 0;
uint16 create_time = 0;
uint32 creator_id = 0;
uint8 meta_flags = 0;
mars_nwe_get_file_info(unixname, &create_date, &create_time,
&creator_id, &meta_flags);
if (meta_flags & MARS_NWE_FILEINFO_HAS_CREATE_DATE)
U16_TO_16(create_date, f->created.date);
else
un_date_2_nw(stb->st_mtime, f->created.date, 0);
if (meta_flags & MARS_NWE_FILEINFO_HAS_CREATE_TIME)
U16_TO_16(create_time, f->created.time);
else
un_time_2_nw(stb->st_mtime, f->created.time, 0);
if (meta_flags & MARS_NWE_FILEINFO_HAS_CREATOR)
U32_TO_BE32(creator_id, f->created.id);
else
U32_TO_BE32(get_file_owner(stb), f->created.id);
}
{
uint16 archive_date = 0;
uint16 archive_time = 0;
@@ -3094,6 +3184,10 @@ int nw_set_a_directory_entry(int dirhandle,
completition=set_ncp22_25_archive_info(unixname, f, change_mask,
S_ISDIR(stbuff.st_mode));
}
if (!completition) {
completition=set_ncp22_25_file_info(unixname, f, change_mask,
S_ISDIR(stbuff.st_mode));
}
if (S_ISDIR(stbuff.st_mode)) {
if (change_mask & DM_INHERITED_RIGHTS_MASK) {
int result=tru_set_inherited_mask(nwpath.volume, unixname,

View File

@@ -1096,11 +1096,26 @@ static int build_dir_info(DIR_BASE_ENTRY *dbe,
} else p+=6;
if (infomask & INFO_MSK_CREAT_INFO) {
un_time_2_nw(stb->st_mtime, p, 0);
uint16 create_date = 0;
uint16 create_time = 0;
uint32 creator_id = 0;
uint8 meta_flags = 0;
mars_nwe_get_file_info(unixname, &create_date, &create_time,
&creator_id, &meta_flags);
if (meta_flags & MARS_NWE_FILEINFO_HAS_CREATE_TIME)
U16_TO_16(create_time, p);
else
un_time_2_nw(stb->st_mtime, p, 0);
p +=2;
un_date_2_nw(stb->st_mtime, p, 0);
if (meta_flags & MARS_NWE_FILEINFO_HAS_CREATE_DATE)
U16_TO_16(create_date, p);
else
un_date_2_nw(stb->st_mtime, p, 0);
p +=2;
U32_TO_BE32(owner, p); /* HI-LOW ! */
if (meta_flags & MARS_NWE_FILEINFO_HAS_CREATOR)
U32_TO_BE32(creator_id, p); /* HI-LOW ! */
else
U32_TO_BE32(owner, p); /* HI-LOW ! */
p +=4;
} else p+=8;

View File

@@ -146,3 +146,142 @@ int mars_nwe_set_archive_info(char *unixname,
#endif
return(0);
}
#define MARS_NWE_FILEINFO_XATTR "user.mars_nwe.fileinfo"
#define MARS_NWE_FILEINFO_VERSION 1
typedef struct {
uint8 version;
uint8 flags;
uint8 create_date[2];
uint8 create_time[2];
uint8 creator_id[4];
} MARS_NWE_FILEINFO_XATTR_DATA;
static void init_file_info_data(MARS_NWE_FILEINFO_XATTR_DATA *d)
{
memset(d, 0, sizeof(*d));
d->version = MARS_NWE_FILEINFO_VERSION;
}
static void read_file_info_data(MARS_NWE_FILEINFO_XATTR_DATA *d,
uint16 *create_date,
uint16 *create_time,
uint32 *creator_id,
uint8 *flags)
{
if (flags)
*flags = d->flags;
if (create_date)
*create_date = (d->flags & MARS_NWE_FILEINFO_HAS_CREATE_DATE)
? (uint16)GET_16(d->create_date) : 0;
if (create_time)
*create_time = (d->flags & MARS_NWE_FILEINFO_HAS_CREATE_TIME)
? (uint16)GET_16(d->create_time) : 0;
if (creator_id)
*creator_id = (d->flags & MARS_NWE_FILEINFO_HAS_CREATOR)
? GET_BE32(d->creator_id) : 0;
}
#if XATTR_SUPPORT
static int get_file_info_data(char *unixname, MARS_NWE_FILEINFO_XATTR_DATA *d)
{
ssize_t len;
init_file_info_data(d);
if (!unixname || !*unixname)
return(-1);
len = getxattr(unixname, MARS_NWE_FILEINFO_XATTR, d, sizeof(*d));
if (len != sizeof(*d) || d->version != MARS_NWE_FILEINFO_VERSION) {
init_file_info_data(d);
return(-1);
}
return(0);
}
#endif
void mars_nwe_get_file_info(char *unixname,
uint16 *create_date,
uint16 *create_time,
uint32 *creator_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, create_date, create_time, creator_id, flags);
}
int mars_nwe_set_file_info(char *unixname,
int set_create_date, uint16 create_date,
int set_create_time, uint16 create_time,
int set_creator, uint32 creator_id)
{
#if XATTR_SUPPORT
MARS_NWE_FILEINFO_XATTR_DATA d;
(void)get_file_info_data(unixname, &d);
if (set_create_date) {
U16_TO_16(create_date, d.create_date);
if (create_date)
d.flags |= MARS_NWE_FILEINFO_HAS_CREATE_DATE;
else
d.flags &= (uint8)~MARS_NWE_FILEINFO_HAS_CREATE_DATE;
}
if (set_create_time) {
U16_TO_16(create_time, d.create_time);
if (create_time)
d.flags |= MARS_NWE_FILEINFO_HAS_CREATE_TIME;
else
d.flags &= (uint8)~MARS_NWE_FILEINFO_HAS_CREATE_TIME;
}
if (set_creator) {
U32_TO_BE32(creator_id, d.creator_id);
if (creator_id)
d.flags |= MARS_NWE_FILEINFO_HAS_CREATOR;
else
d.flags &= (uint8)~MARS_NWE_FILEINFO_HAS_CREATOR;
}
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: creator 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_create_date;
(void)create_date;
(void)set_create_time;
(void)create_time;
(void)set_creator;
(void)creator_id;
#endif
return(0);
}