Apply chattr "F" directly after mkdir, "C" directly after open(), "i" when finalizing implicitely created directories
This commit is contained in:
parent
c142b7b58f
commit
1a5e356d85
@ -381,16 +381,21 @@ int Xorriso_restore_chattr_i(struct XorrisO *xorriso, IsoNode *node,
|
|||||||
char *disk_path, int flag)
|
char *disk_path, int flag)
|
||||||
{
|
{
|
||||||
int ret, max_bit;
|
int ret, max_bit;
|
||||||
uint64_t lfa_flags;
|
uint64_t lfa_flags, mask;
|
||||||
static uint64_t lfa_i= 0xffffffff;
|
static uint64_t lfa_i= 0xffffffff;
|
||||||
|
|
||||||
if(lfa_i == 0xffffffff)
|
if(lfa_i == 0xffffffff)
|
||||||
lfa_i= Xorriso__lfa_bits("i");
|
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);
|
ret= iso_node_get_lfa_flags(node, &lfa_flags, &max_bit, 0);
|
||||||
if(ret > 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);
|
ret= Xorriso_set_local_chattr_i(xorriso, disk_path, 0);
|
||||||
if(ret <= 0)
|
if(ret <= 0)
|
||||||
return(ret);
|
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
|
/* @param flag bit0= minimal transfer: access permissions only
|
||||||
bit1= keep directory open: keep owner, allow rwx for owner
|
bit1= keep directory open: keep owner, allow rwx for owner
|
||||||
and push directory onto xorriso->perm_stack
|
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;
|
size_t num_attrs= 0, *value_lengths= NULL;
|
||||||
char **names= NULL, **values= NULL;
|
char **names= NULL, **values= NULL;
|
||||||
int *errnos= NULL;
|
int *errnos= NULL;
|
||||||
uint64_t lfa_flags, mask;
|
uint64_t lfa_flags= 0, mask= 0, push_mask= 0;
|
||||||
int max_bit, os_errno;
|
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) {
|
if(lfa_C == 0xffffffff) {
|
||||||
lfa_C= Xorriso__lfa_bits("C");
|
lfa_C= Xorriso__lfa_bits("C");
|
||||||
|
lfa_F= Xorriso__lfa_bits("F");
|
||||||
lfa_i= Xorriso__lfa_bits("i");
|
lfa_i= Xorriso__lfa_bits("i");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -499,12 +550,41 @@ cannot_set_xattr:;
|
|||||||
if(!(xorriso->do_aaip & 2))
|
if(!(xorriso->do_aaip & 2))
|
||||||
mode= iso_node_get_perms_wo_acl(node);
|
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)) {
|
if(is_dir && (flag&2)) {
|
||||||
ret= Xorriso_fake_stbuf(xorriso, "", &stbuf, &node,
|
ret= Xorriso_fake_stbuf(xorriso, "", &stbuf, &node,
|
||||||
1 | ((!!(xorriso->do_aaip & 2)) << 3));
|
1 | ((!!(xorriso->do_aaip & 2)) << 3));
|
||||||
if(ret<=0)
|
if(ret<=0)
|
||||||
{ret= 0; goto ex;}
|
{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) {
|
if(ret<=0) {
|
||||||
Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0);
|
Xorriso_msgs_submit(xorriso, 0, disk_path, 0, "ERRFILE", 0);
|
||||||
strcpy(xorriso->info_text,
|
strcpy(xorriso->info_text,
|
||||||
@ -570,37 +650,18 @@ cannot_set_perm:;
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(xorriso->do_aaip & (1 << 12)) {
|
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) {
|
if(mask != 0) {
|
||||||
ret= iso_local_set_lfa_flags(disk_path, lfa_flags, max_bit, mask,
|
ret= iso_local_set_lfa_flags(disk_path, lfa_flags, max_bit, mask,
|
||||||
&os_errno,
|
&os_errno, 0);
|
||||||
(!!(xorriso->do_aaip & (1 << 13))) |
|
|
||||||
((!!(xorriso->do_aaip & (1 << 14))) << 1));
|
|
||||||
|
|
||||||
/* >>> Need adjustable graceful error handling */;
|
/* >>> Need adjustable graceful error handling */;
|
||||||
|
|
||||||
ret= Xorriso_report_chattr_outcome(xorriso, disk_path,
|
ret= Xorriso_report_chattr_outcome(xorriso, disk_path, lfa_flags,
|
||||||
lfa_flags,
|
mask, ret, os_errno, 0);
|
||||||
xorriso->lfa_restore_mask & ~lfa_C,
|
|
||||||
ret, os_errno, 0);
|
|
||||||
if(ret <= 0)
|
if(ret <= 0)
|
||||||
goto ex;
|
goto ex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ret= 1;
|
ret= 1;
|
||||||
ex:;
|
ex:;
|
||||||
@ -981,24 +1042,23 @@ int Xorriso_tree_restore_node(struct XorrisO *xorriso, IsoNode *node,
|
|||||||
off_t catsize, iso_node_size, wanted_size, cap;
|
off_t catsize, iso_node_size, wanted_size, cap;
|
||||||
char disk_md5[16], iso_md5[16];
|
char disk_md5[16], iso_md5[16];
|
||||||
void *ctx= NULL;
|
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;
|
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(buf, char, buf_size);
|
||||||
Xorriso_alloc_meM(temp_path, char, SfileadrL);
|
Xorriso_alloc_meM(temp_path, char, SfileadrL);
|
||||||
|
|
||||||
if(lfa_C == 0xffffffff)
|
|
||||||
lfa_C= Xorriso__lfa_bits("C");
|
|
||||||
|
|
||||||
if(!(flag & 2))
|
if(!(flag & 2))
|
||||||
img_offset= bytes= 0;
|
img_offset= bytes= 0;
|
||||||
if(LIBISO_ISDIR(node)) {
|
if(LIBISO_ISDIR(node)) {
|
||||||
what= "directory";
|
what= "directory";
|
||||||
ret= mkdir(disk_path, 0777);
|
ret= mkdir(disk_path, 0777);
|
||||||
l_errno= errno;
|
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)) {
|
} else if(LIBISO_ISREG(node) || ISO_NODE_IS_BOOTCAT(node)) {
|
||||||
if(ISO_NODE_IS_BOOTCAT(node)) {
|
if(ISO_NODE_IS_BOOTCAT(node)) {
|
||||||
what= "boot catalog";
|
what= "boot catalog";
|
||||||
@ -1096,23 +1156,11 @@ int Xorriso_tree_restore_node(struct XorrisO *xorriso, IsoNode *node,
|
|||||||
goto cannot_restore;
|
goto cannot_restore;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(new_empty) {
|
if(new_empty && open_path_pt != NULL) {
|
||||||
/* If chattr 'C' "no copy-on-write" is present on node and enabled for
|
ret= Xorriso_early_chattr_CF(xorriso, node, open_path_pt, &l_errno, 0);
|
||||||
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)
|
if(ret <= 0)
|
||||||
goto cannot_restore;
|
goto cannot_restore;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ISO_NODE_IS_BOOTCAT(node)) {
|
if(ISO_NODE_IS_BOOTCAT(node)) {
|
||||||
ret= Xorriso_get_volume(xorriso, &volume, 0);
|
ret= Xorriso_get_volume(xorriso, &volume, 0);
|
||||||
@ -2122,7 +2170,7 @@ int Xorriso_restore(struct XorrisO *xorriso,
|
|||||||
char *path= NULL, *apt, *npt;
|
char *path= NULL, *apt, *npt;
|
||||||
IsoNode *node= NULL;
|
IsoNode *node= NULL;
|
||||||
int done= 0, is_dir= 0, ret, source_is_dir, stbuf_ret, hret;
|
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;
|
int leaf_is_split= 0, source_is_split= 0, new_dir_made= 0, no_props;
|
||||||
struct stat stbuf;
|
struct stat stbuf;
|
||||||
struct PermiteM *perm_stack_mem;
|
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);
|
Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE",0);
|
||||||
{ret= 0; goto ex;}
|
{ret= 0; goto ex;}
|
||||||
}
|
}
|
||||||
if(!done) {
|
if(done) {
|
||||||
/* keep rwx for the owner */
|
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,
|
Xorriso_restore_implicit_properties(xorriso, disk_path, path,
|
||||||
img_path, 4);
|
img_path, 4);
|
||||||
}
|
}
|
||||||
|
@ -1 +1 @@
|
|||||||
#define Xorriso_timestamP "2024.08.07.132513"
|
#define Xorriso_timestamP "2024.08.18.153958"
|
||||||
|
Loading…
Reference in New Issue
Block a user