/* nwarchive.c - mars_nwe private archive metadata helpers */ #include "net.h" #include "nwarchive.h" #include "nwxattr.h" #if XATTR_SUPPORT #include #endif #define MARS_NWE_ARCHIVE_XATTR "org.mars-nwe.netware.archive" #define MARS_NWE_ARCHIVE_VERSION 1 typedef struct { uint8 version; uint8 flags; uint8 archive_date[2]; uint8 archive_time[2]; uint8 archiver_id[4]; } MARS_NWE_ARCHIVE_XATTR_DATA; static void init_archive_data(MARS_NWE_ARCHIVE_XATTR_DATA *d) { memset(d, 0, sizeof(*d)); d->version = MARS_NWE_ARCHIVE_VERSION; } static void read_archive_data(MARS_NWE_ARCHIVE_XATTR_DATA *d, uint16 *archive_date, uint16 *archive_time, uint32 *archiver_id, uint8 *flags) { if (flags) *flags = d->flags; if (archive_date) *archive_date = (d->flags & MARS_NWE_ARCHIVE_HAS_DATE) ? (uint16)GET_16(d->archive_date) : 0; if (archive_time) *archive_time = (d->flags & MARS_NWE_ARCHIVE_HAS_TIME) ? (uint16)GET_16(d->archive_time) : 0; if (archiver_id) *archiver_id = (d->flags & MARS_NWE_ARCHIVE_HAS_ARCHIVER) ? GET_BE32(d->archiver_id) : 0; } #if XATTR_SUPPORT static int get_archive_data(char *unixname, MARS_NWE_ARCHIVE_XATTR_DATA *d) { ssize_t len; init_archive_data(d); if (!unixname || !*unixname) return(-1); len = mars_nwe_getxattr(unixname, MARS_NWE_ARCHIVE_XATTR, d, sizeof(*d)); if (len != sizeof(*d) || d->version != MARS_NWE_ARCHIVE_VERSION) { init_archive_data(d); return(-1); } return(0); } #endif void mars_nwe_get_archive_info(char *unixname, uint16 *archive_date, uint16 *archive_time, uint32 *archiver_id, uint8 *flags) { MARS_NWE_ARCHIVE_XATTR_DATA d; #if XATTR_SUPPORT (void)get_archive_data(unixname, &d); #else (void)unixname; init_archive_data(&d); #endif read_archive_data(&d, archive_date, archive_time, archiver_id, flags); } int mars_nwe_set_archive_info(char *unixname, int set_date, uint16 archive_date, int set_time, uint16 archive_time, int set_archiver, uint32 archiver_id) { #if XATTR_SUPPORT MARS_NWE_ARCHIVE_XATTR_DATA d; (void)get_archive_data(unixname, &d); if (set_date) { U16_TO_16(archive_date, d.archive_date); if (archive_date) d.flags |= MARS_NWE_ARCHIVE_HAS_DATE; else d.flags &= (uint8)~MARS_NWE_ARCHIVE_HAS_DATE; } if (set_time) { U16_TO_16(archive_time, d.archive_time); if (archive_time) d.flags |= MARS_NWE_ARCHIVE_HAS_TIME; else d.flags &= (uint8)~MARS_NWE_ARCHIVE_HAS_TIME; } if (set_archiver) { U32_TO_BE32(archiver_id, d.archiver_id); if (archiver_id) d.flags |= MARS_NWE_ARCHIVE_HAS_ARCHIVER; else d.flags &= (uint8)~MARS_NWE_ARCHIVE_HAS_ARCHIVER; } if (!unixname || !*unixname) return(0); if (!d.flags) { if (mars_nwe_removexattr(unixname, MARS_NWE_ARCHIVE_XATTR)) { int err = errno; if (err != ENODATA #ifdef ENOATTR && err != ENOATTR #endif ) XDPRINTF((5,0,"mars_nwe archive xattr remove ignored for %s errno=%d", unixname, err)); } return(0); } if (mars_nwe_setxattr(unixname, MARS_NWE_ARCHIVE_XATTR, &d, sizeof(d), 0)) { int err = errno; /* Compatibility rule: NetWare archive metadata has no POSIX field. * If Linux xattrs are unavailable or rejected, keep the NCP call * successful and only log that the extra metadata was not stored. */ XDPRINTF((5,0,"mars_nwe archive xattr ignored for %s errno=%d", unixname, err)); } #else (void)unixname; (void)set_date; (void)archive_date; (void)set_time; (void)archive_time; (void)set_archiver; (void)archiver_id; #endif return(0); } #define MARS_NWE_FILEINFO_XATTR "org.mars-nwe.netware.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]; 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)); 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, uint32 *modifier_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 (modifier_id) *modifier_id = (d->flags & MARS_NWE_FILEINFO_HAS_MODIFIER) ? GET_BE32(d->modifier_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 = mars_nwe_getxattr(unixname, MARS_NWE_FILEINFO_XATTR, d, sizeof(*d)); if ((len != sizeof(*d) && len != MARS_NWE_FILEINFO_XATTR_V1_SIZE) || 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, 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, 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 (mars_nwe_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 (mars_nwe_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); } 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 (mars_nwe_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 (mars_nwe_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); }