From 99700ac94b3ee9a4468fd0d765463aea8d7a6ff3 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Fri, 19 Jul 2024 22:24:02 +0200 Subject: [PATCH] New API call iso_util_get_lfa_masks() --- libisofs/fs_local.c | 38 +++++++++++++++++++++++--------------- libisofs/libisofs.h | 39 ++++++++++++++++++++++++++++++++++++--- libisofs/libisofs.ver | 1 + libisofs/util.c | 17 ++++++++++++++++- 4 files changed, 76 insertions(+), 19 deletions(-) diff --git a/libisofs/fs_local.c b/libisofs/fs_local.c index f195d19..96ed736 100644 --- a/libisofs/fs_local.c +++ b/libisofs/fs_local.c @@ -975,7 +975,7 @@ int iso_local_get_lfa_flags(char *disk_path, uint64_t *lfa_flags, int *max_bit, } if ((stbuf.st_mode & S_IFMT) == S_IFLNK && !(flag & 32)) return 3; - ret= aaip_get_lfa_flags(disk_path, lfa_flags, max_bit, os_errno, 0); + ret = aaip_get_lfa_flags(disk_path, lfa_flags, max_bit, os_errno, 0); if(ret == 0) return ISO_AAIP_NOT_ENABLED; if (ret < 0) @@ -986,8 +986,8 @@ int iso_local_get_lfa_flags(char *disk_path, uint64_t *lfa_flags, int *max_bit, /* * @param flag Bitfield for control purposes - * bit0= do not try to set known superuser flags - * bit1= set only known chattr settable flags + * bit0= do not try to change known superuser flags + * bit1= change only known chattr settable flags * bit5= in case of symbolic link: inquire link target * @return * 1 = ok, all lfa_flags bits were written @@ -996,18 +996,14 @@ int iso_local_get_lfa_flags(char *disk_path, uint64_t *lfa_flags, int *max_bit, * <0 = error */ int iso_local_set_lfa_flags(char *disk_path, uint64_t lfa_flags, int max_bit, - int *os_errno, int flag) + uint64_t change_mask, int *os_errno, int flag) { - int ret; + int ret, old_max_bit; struct stat stbuf; + uint64_t known_user_mask, known_su_mask, non_settable, unknown, eff_flags; - /* chattr letters: User: sucSdAmtDTCxPF - Superuser: iaj - Non-settable: Z(9)EI(13)heV(21)(22)N(31) - */ - static uint64_t known_user_mask = 0x628384cf; - static uint64_t known_su_mask = 0x00004030; - + iso_util_get_lfa_masks(&known_user_mask, &known_su_mask, &non_settable, + &unknown); *os_errno = 0; if (flag & 32) ret = stat(disk_path, &stbuf); @@ -1020,10 +1016,22 @@ int iso_local_set_lfa_flags(char *disk_path, uint64_t lfa_flags, int max_bit, if ((stbuf.st_mode & S_IFMT) == S_IFLNK && !(flag & 32)) return 3; if (flag & 1) - lfa_flags &= ~known_su_mask; + change_mask &= ~known_su_mask; if (flag & 2) - lfa_flags &= known_user_mask | known_su_mask; - ret= aaip_set_lfa_flags(disk_path, lfa_flags, max_bit, os_errno, 0); + change_mask &= (known_user_mask | known_su_mask); + if (change_mask == ~((uint64_t) 0)) { + eff_flags = lfa_flags; + } else { + ret = aaip_get_lfa_flags(disk_path, &eff_flags, &old_max_bit, os_errno, + 0); + if (ret == 0) + return ISO_AAIP_NOT_ENABLED; + if (ret < 0) + return ISO_AAIP_NO_GET_LOCAL; + eff_flags &= ~change_mask; + eff_flags |= (lfa_flags & change_mask); + } + ret= aaip_set_lfa_flags(disk_path, eff_flags, max_bit, os_errno, 0); if(ret == 0) return ISO_AAIP_NOT_ENABLED; if(ret < 0) diff --git a/libisofs/libisofs.h b/libisofs/libisofs.h index cd35cc7..2ea4c6c 100644 --- a/libisofs/libisofs.h +++ b/libisofs/libisofs.h @@ -8089,10 +8089,15 @@ int iso_local_get_lfa_flags(char *disk_path, uint64_t *lfa_flags, int *max_bit, * @param os_errno * Will get filled with errno if a system call fails. * Else it will be filled with 0. + * @param change_mask + * Tells which bits of lfa_flags are meant to change attribute flags + * of the file. Submit ~((uint64_t) 0) if all bits may cause changes. + * The set of changeable bits may further be restricted by bit0 and bit1 + * of parameter flag. * @param flag * Bitfield for control purposes - * bit0= do not try to set known chattr superuser flags: iaj - * bit1= set only known chattr settable flags: sucSiadAmjtDTCxPF + * bit0= do not try to change known chattr superuser flags: iaj + * bit1= change only known chattr settable flags: sucSiadAmjtDTCxPF * bit5= in case of symbolic link: operate on link target * @return * 1 = ok, all lfa_flags bits were written @@ -8103,7 +8108,7 @@ int iso_local_get_lfa_flags(char *disk_path, uint64_t *lfa_flags, int *max_bit, * @since 1.5.8 */ int iso_local_set_lfa_flags(char *disk_path, uint64_t lfa_flags, int max_bit, - int *os_errno, int flag); + uint64_t change_mask, int *os_errno, int flag); /** @@ -8152,6 +8157,34 @@ int iso_util_encode_lfa_flags(uint64_t lfa_flags, char **flags_text, int flag); int iso_util_decode_lfa_flags(char *flags_text, uint64_t *lfa_flags, int flag); +/** + * Return the bit patterns of four classes of Linux-like file attribute flags. + * They were determined according to man 1 chattr and the source of lsattr + * in juli 2024. The symbolic strings and bit numbers are given here only + * for convenience. Decisive are the returned bit patterns. + * + * @param user_settable + * The flag bits which are known to be user settable with chattr: + * sucSdAmtDTCxPF + * @param su_settable + * The flag bits which are known to be settable with chattr only by + * bearers of various superuser powers: + * iaj + * @param non_settable + * The flags bits which are known to be not settable or not clearable + * by chattr or only known to lsattr: + * ZEIheVN + * @param unknown + * The flags bits for which no symbolic letter is known. Some of them are + * defined in with sparse info, some not even that: + * 9, 13, 21, 22, 24, 26, 27, 31 + * + * @since 1.5.8 + */ +void iso_util_get_lfa_masks(uint64_t *user_settable, uint64_t *su_settable, + uint64_t *non_settable, uint64_t *unknown); + + /* Default in case that the compile environment has no macro PATH_MAX. */ #define Libisofs_default_path_maX 4096 diff --git a/libisofs/libisofs.ver b/libisofs/libisofs.ver index 5097e5d..7c4dee9 100644 --- a/libisofs/libisofs.ver +++ b/libisofs/libisofs.ver @@ -392,5 +392,6 @@ iso_node_get_lfa_flags; iso_node_set_lfa_flags; iso_util_decode_lfa_flags; iso_util_encode_lfa_flags; +iso_util_get_lfa_masks; } LIBISOFS6; diff --git a/libisofs/util.c b/libisofs/util.c index c71d226..130998f 100644 --- a/libisofs/util.c +++ b/libisofs/util.c @@ -2555,7 +2555,7 @@ int iso_util_encode_lfa_flags(uint64_t lfa_flags, char **flags_text, int flag) (*flags_text)[w++] = lfa_flag_letters[i]; } } - flags_text[w] = 0; + (*flags_text)[w] = 0; if (was_unknown) return ISO_LFA_UNKNOWN_BIT; return ISO_SUCCESS; @@ -2610,3 +2610,18 @@ int iso_util_decode_lfa_flags(char *flags_text, uint64_t *lfa_flags, int flag) return 1; } + +void iso_util_get_lfa_masks(uint64_t *user_settable, uint64_t *su_settable, + uint64_t *non_settable, uint64_t *unknown) +{ + /* chattr letters: User settable : sucSdAmtDTCxPF + Superuser settable: iaj + Non-settable : ZEIheVN + unknown : 9, 13, 21, 22, 24, 26, 27, >= 31 + */ + *user_settable = 0x628384cf; + *su_settable = 0x00004030; + *non_settable = 0x101c1900; + *unknown = 0xffffffff8d602200; +} +