From 1a5e356d85153be7864b486de0f5c71c72514133 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Sun, 18 Aug 2024 17:41:01 +0200 Subject: [PATCH] Apply chattr "F" directly after mkdir, "C" directly after open(), "i" when finalizing implicitely created directories --- xorriso/read_run.c | 174 +++++++++++++++++++++++------------- xorriso/xorriso_timestamp.h | 2 +- 2 files changed, 115 insertions(+), 61 deletions(-) diff --git a/xorriso/read_run.c b/xorriso/read_run.c index f469a6d0..fc4b29e3 100644 --- a/xorriso/read_run.c +++ b/xorriso/read_run.c @@ -381,16 +381,21 @@ int Xorriso_restore_chattr_i(struct XorrisO *xorriso, IsoNode *node, char *disk_path, int flag) { int ret, max_bit; - uint64_t lfa_flags; + uint64_t lfa_flags, mask; static uint64_t lfa_i= 0xffffffff; if(lfa_i == 0xffffffff) lfa_i= Xorriso__lfa_bits("i"); - if((xorriso->do_aaip & (1 << 12)) && !(xorriso->do_aaip & (1 << 13))) { + if((xorriso->do_aaip & (1 << 12))) { + mask= iso_util_get_effective_lfa_mask(xorriso->lfa_restore_mask, + (!!(xorriso->do_aaip & (1 << 13))) | + ((!!(xorriso->do_aaip & (1 << 14))) << 1)); + if(!(mask & lfa_i)) + return(2); ret= iso_node_get_lfa_flags(node, &lfa_flags, &max_bit, 0); if(ret > 0) { - if(lfa_flags & lfa_i & xorriso->lfa_restore_mask) { + if(lfa_flags & lfa_i) { ret= Xorriso_set_local_chattr_i(xorriso, disk_path, 0); if(ret <= 0) return(ret); @@ -402,6 +407,51 @@ int Xorriso_restore_chattr_i(struct XorrisO *xorriso, IsoNode *node, } +int Xorriso_early_chattr_CF(struct XorrisO *xorriso, IsoNode *node, + char *disk_path, int *os_errno, int flag) +{ + int ret, max_bit; + uint64_t lfa_flags, xorriso_mask, set_mask; + static uint64_t lfa_C= 0xffffffff, lfa_F= 0; + + if(lfa_C == 0xffffffff) { + lfa_C= Xorriso__lfa_bits("C"); + lfa_F= Xorriso__lfa_bits("F"); + } + + *os_errno= 0; + if(!(xorriso->lfa_flags_setting & (1 << 12))) + return(2); + + ret= iso_node_get_lfa_flags(node, &lfa_flags, &max_bit, 0); + if(ret <= 0) + return(3); + xorriso_mask= iso_util_get_effective_lfa_mask(xorriso->lfa_restore_mask, + (!!(xorriso->do_aaip & (1 << 13))) | + ((!!(xorriso->do_aaip & (1 << 14))) << 1)); + set_mask= 0; + /* C must be set on empty regular files. + But if it would be set for a directory, all its files would get set C, + even if their IsoNode does not have it. + */ + if(!LIBISO_ISDIR(node)) + set_mask|= lfa_C; + /* F must be set on empty directories. (It is undefined for regular files) */ + if(LIBISO_ISDIR(node)) + set_mask|= lfa_F; + set_mask&= xorriso_mask; + if(set_mask == 0) + return(4); + ret= iso_local_set_lfa_flags(disk_path, lfa_flags, max_bit, set_mask, + os_errno, 0); + ret= Xorriso_report_chattr_outcome(xorriso, disk_path, lfa_flags, set_mask, + ret, *os_errno, 0); + if(ret <= 0) + return(ret); + return(1); +} + + /* @param flag bit0= minimal transfer: access permissions only bit1= keep directory open: keep owner, allow rwx for owner and push directory onto xorriso->perm_stack @@ -418,12 +468,13 @@ int Xorriso_restore_properties(struct XorrisO *xorriso, char *disk_path, size_t num_attrs= 0, *value_lengths= NULL; char **names= NULL, **values= NULL; int *errnos= NULL; - uint64_t lfa_flags, mask; + uint64_t lfa_flags= 0, mask= 0, push_mask= 0; int max_bit, os_errno; - static uint64_t lfa_C= 0xffffffff, lfa_i= 0xffffffff; + static uint64_t lfa_C= 0xffffffff, lfa_i= 0, lfa_F= 0; if(lfa_C == 0xffffffff) { lfa_C= Xorriso__lfa_bits("C"); + lfa_F= Xorriso__lfa_bits("F"); lfa_i= Xorriso__lfa_bits("i"); } @@ -499,12 +550,41 @@ cannot_set_xattr:; if(!(xorriso->do_aaip & 2)) mode= iso_node_get_perms_wo_acl(node); + /* Need to assess lfa_flags early because 'i' might need to be pushed to + the perm stack */ + if(xorriso->do_aaip & (1 << 12)) { + ret= iso_node_get_lfa_flags(node, &lfa_flags, &max_bit, 0); + if (ret < 0) { + Xorriso_process_msg_queues(xorriso, 0); + strcpy(xorriso->info_text, + "Error with obtaining file attribut flags for "); + Text_shellsafe(disk_path, xorriso->info_text, 1); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + {ret= 0; goto ex;} + } else if(ret > 0) { + mask= iso_util_get_effective_lfa_mask(xorriso->lfa_restore_mask, + (!!(xorriso->do_aaip & (1 << 13))) | + ((!!(xorriso->do_aaip & (1 << 14))) << 1)); + /* Do not set 'C' of non-directories or 'F' of directories here. + It would be too late. */ + if(!is_dir) + mask&= ~lfa_C; + if(is_dir) + mask&= ~lfa_F; + push_mask= mask; + /* Do not set lfa_flag 'i' of a directory here. It would be too early. */ + if(is_dir) + mask&= ~lfa_i; + } + } + if(is_dir && (flag&2)) { ret= Xorriso_fake_stbuf(xorriso, "", &stbuf, &node, 1 | ((!!(xorriso->do_aaip & 2)) << 3)); if(ret<=0) {ret= 0; goto ex;} - ret= Permstack_push(&(xorriso->perm_stack), disk_path, &stbuf, 0); + ret= Permstack_push(&(xorriso->perm_stack), disk_path, &stbuf, + !!(lfa_flags & push_mask & lfa_i)); if(ret<=0) { Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0); strcpy(xorriso->info_text, @@ -570,36 +650,17 @@ cannot_set_perm:; } if(xorriso->do_aaip & (1 << 12)) { - ret= iso_node_get_lfa_flags(node, &lfa_flags, &max_bit, 0); - if (ret < 0) { - Xorriso_process_msg_queues(xorriso, 0); - strcpy(xorriso->info_text, - "Error with obtaining file attribut flags for "); - Text_shellsafe(disk_path, xorriso->info_text, 1); - Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); - {ret= 0; goto ex;} - } else if(ret > 0) { - /* Do not set lfa_flag 'C' here. It would be too late. */ - mask= xorriso->lfa_restore_mask & ~lfa_C; - /* Do not set lfa_flag 'i' of a directory here. It would be too early. */ - if(is_dir) - mask&= ~lfa_i; - if(mask != 0) { - ret= iso_local_set_lfa_flags(disk_path, lfa_flags, max_bit, mask, - &os_errno, - (!!(xorriso->do_aaip & (1 << 13))) | - ((!!(xorriso->do_aaip & (1 << 14))) << 1)); + if(mask != 0) { + ret= iso_local_set_lfa_flags(disk_path, lfa_flags, max_bit, mask, + &os_errno, 0); - /* >>> Need adjustable graceful error handling */; + /* >>> Need adjustable graceful error handling */; - ret= Xorriso_report_chattr_outcome(xorriso, disk_path, - lfa_flags, - xorriso->lfa_restore_mask & ~lfa_C, - ret, os_errno, 0); - if(ret <= 0) - goto ex; - } - } + ret= Xorriso_report_chattr_outcome(xorriso, disk_path, lfa_flags, + mask, ret, os_errno, 0); + if(ret <= 0) + goto ex; + } } ret= 1; @@ -981,24 +1042,23 @@ int Xorriso_tree_restore_node(struct XorrisO *xorriso, IsoNode *node, off_t catsize, iso_node_size, wanted_size, cap; char disk_md5[16], iso_md5[16]; void *ctx= NULL; - int use_md5= 0, i, sparse_ret= 3, max_bit, os_errno; + int use_md5= 0, i, sparse_ret= 3; struct Xorriso_sparse_statE *sparse_state= NULL; - uint64_t lfa_flags; - static uint64_t lfa_C= 0xffffffff; Xorriso_alloc_meM(buf, char, buf_size); Xorriso_alloc_meM(temp_path, char, SfileadrL); - if(lfa_C == 0xffffffff) - lfa_C= Xorriso__lfa_bits("C"); - if(!(flag & 2)) img_offset= bytes= 0; if(LIBISO_ISDIR(node)) { what= "directory"; ret= mkdir(disk_path, 0777); l_errno= errno; - + if(ret == 0) { + ret= Xorriso_early_chattr_CF(xorriso, node, disk_path, &l_errno, 0); + if(ret <= 0) + goto cannot_restore; + } } else if(LIBISO_ISREG(node) || ISO_NODE_IS_BOOTCAT(node)) { if(ISO_NODE_IS_BOOTCAT(node)) { what= "boot catalog"; @@ -1096,22 +1156,10 @@ int Xorriso_tree_restore_node(struct XorrisO *xorriso, IsoNode *node, goto cannot_restore; } - if(new_empty) { - /* If chattr 'C' "no copy-on-write" is present on node and enabled for - restoring, then set it as long as the file is empty, because man chattr - says so for btrfs. - */ - ret= iso_node_get_lfa_flags(node, &lfa_flags, &max_bit, 0); - if(ret > 0) { - if(lfa_flags & lfa_C & xorriso->lfa_restore_mask) { - ret= iso_local_set_lfa_flags(open_path_pt, lfa_C, max_bit, lfa_C, - &os_errno, 0); - ret= Xorriso_report_chattr_outcome(xorriso, open_path_pt, - lfa_C, lfa_C, ret, os_errno, 0); - if(ret <= 0) - goto cannot_restore; - } - } + if(new_empty && open_path_pt != NULL) { + ret= Xorriso_early_chattr_CF(xorriso, node, open_path_pt, &l_errno, 0); + if(ret <= 0) + goto cannot_restore; } if(ISO_NODE_IS_BOOTCAT(node)) { @@ -2122,7 +2170,7 @@ int Xorriso_restore(struct XorrisO *xorriso, char *path= NULL, *apt, *npt; IsoNode *node= NULL; int done= 0, is_dir= 0, ret, source_is_dir, stbuf_ret, hret; - int dir_create= 0, node_count= 0, node_register= 0, path_size; + int dir_create= 0, node_count= 0, node_register= 0, path_size, l_errno= 0; int leaf_is_split= 0, source_is_split= 0, new_dir_made= 0, no_props; struct stat stbuf; struct PermiteM *perm_stack_mem; @@ -2248,8 +2296,14 @@ int Xorriso_restore(struct XorrisO *xorriso, Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0); {ret= 0; goto ex;} } - if(!done) { - /* keep rwx for the owner */ + if(done) { + if(node != NULL) { + ret= Xorriso_early_chattr_CF(xorriso, node, disk_path, &l_errno, 0); + if(ret <= 0) + goto ex; + } + } else { + /* keep rwx for the owner, delay lfa_flags 'i' if present */ Xorriso_restore_implicit_properties(xorriso, disk_path, path, img_path, 4); } diff --git a/xorriso/xorriso_timestamp.h b/xorriso/xorriso_timestamp.h index e62b8975..a17f785b 100644 --- a/xorriso/xorriso_timestamp.h +++ b/xorriso/xorriso_timestamp.h @@ -1 +1 @@ -#define Xorriso_timestamP "2024.08.07.132513" +#define Xorriso_timestamP "2024.08.18.153958"