11use crate :: defs:: { KSU_MOUNT_SOURCE , MODULE_DIR , SKIP_MOUNT_FILE_NAME , TEMP_DIR } ;
2- use crate :: magic_mount:: NodeFileType :: { Directory , RegularFile , Symlink } ;
2+ use crate :: magic_mount:: NodeFileType :: { Directory , RegularFile , Symlink , Whiteout } ;
33use crate :: restorecon:: { lgetfilecon, lsetfilecon} ;
44use anyhow:: { bail, Context , Result } ;
55use extattr:: lgetxattr;
@@ -14,7 +14,7 @@ use std::collections::hash_map::Entry;
1414use std:: collections:: HashMap ;
1515use std:: fs;
1616use std:: fs:: { create_dir, create_dir_all, read_dir, DirEntry , FileType } ;
17- use std:: os:: unix:: fs:: symlink;
17+ use std:: os:: unix:: fs:: { symlink, FileTypeExt } ;
1818use std:: path:: { Path , PathBuf } ;
1919
2020const REPLACE_DIR_XATTR : & str = "trusted.overlay.opaque" ;
@@ -24,6 +24,7 @@ enum NodeFileType {
2424 RegularFile ,
2525 Directory ,
2626 Symlink ,
27+ Whiteout ,
2728}
2829
2930impl NodeFileType {
@@ -63,13 +64,9 @@ impl Node {
6364 }
6465 }
6566
66- let file_type = entry. file_type ( ) ?;
67-
6867 let node = match self . children . entry ( name. clone ( ) ) {
6968 Entry :: Occupied ( o) => Some ( o. into_mut ( ) ) ,
70- Entry :: Vacant ( v) => {
71- Self :: new_module ( & name, file_type, & path) . map ( |it| v. insert ( it) )
72- }
69+ Entry :: Vacant ( v) => Self :: new_module ( & name, & entry, & path) . map ( |it| v. insert ( it) ) ,
7370 } ;
7471
7572 if let Some ( node) = node {
@@ -96,18 +93,30 @@ impl Node {
9693
9794 fn new_module < T : ToString , P : AsRef < Path > > (
9895 name : T ,
99- file_type : FileType ,
96+ entry : & DirEntry ,
10097 module_path : P ,
10198 ) -> Option < Self > {
102- let file_type = NodeFileType :: from_file_type ( file_type) ?;
99+ if let Ok ( metadata) = entry. metadata ( ) {
100+ let file_type = if metadata. file_type ( ) . is_char_device ( )
101+ && metadata. dev ( ) == 0
102+ && metadata. ino ( ) == 0
103+ {
104+ Some ( Whiteout )
105+ } else {
106+ NodeFileType :: from_file_type ( metadata. file_type ( ) )
107+ } ;
108+ if let Some ( file_type) = file_type {
109+ return Some ( Node {
110+ name : name. to_string ( ) ,
111+ file_type,
112+ children : Default :: default ( ) ,
113+ module_path : Some ( PathBuf :: from ( module_path. as_ref ( ) ) ) ,
114+ replace : false ,
115+ } ) ;
116+ }
117+ }
103118
104- Some ( Node {
105- name : name. to_string ( ) ,
106- file_type,
107- children : Default :: default ( ) ,
108- module_path : Some ( PathBuf :: from ( module_path. as_ref ( ) ) ) ,
109- replace : false ,
110- } )
119+ None
111120 }
112121}
113122
@@ -251,13 +260,19 @@ fn do_magic_mount<P: AsRef<Path>, WP: AsRef<Path>>(
251260 if !has_tmpfs {
252261 for ( name, node) in & current. children {
253262 let real_path = path. join ( name) ;
254- let need = if node. file_type == Symlink || !real_path. exists ( ) {
255- true
256- } else {
257- let file_type = real_path. metadata ( ) ?. file_type ( ) ;
258- let file_type =
259- NodeFileType :: from_file_type ( file_type) . unwrap_or ( RegularFile ) ;
260- file_type != node. file_type || file_type == Symlink
263+ let need = match node. file_type {
264+ Symlink => true ,
265+ Whiteout => real_path. exists ( ) ,
266+ _ => {
267+ if let Ok ( metadata) = real_path. metadata ( ) {
268+ let file_type = NodeFileType :: from_file_type ( metadata. file_type ( ) )
269+ . unwrap_or ( Whiteout ) ;
270+ file_type != node. file_type || file_type == Symlink
271+ } else {
272+ // real path not exists
273+ true
274+ }
275+ }
261276 } ;
262277 if need {
263278 create_tmpfs = need;
@@ -333,6 +348,7 @@ fn do_magic_mount<P: AsRef<Path>, WP: AsRef<Path>>(
333348 move_mount ( & work_dir_path, & path) ?;
334349 }
335350 }
351+ Whiteout => { }
336352 }
337353
338354 Ok ( ( ) )
0 commit comments