@@ -944,17 +944,19 @@ function move($file1, $file2) {
944944 function rmdir ($ dir , $ recursive =false ) {
945945 $ dir = rtrim ($ dir , '/ ' );
946946 if (is_dir ($ dir )) {
947- $ objects = scandir ($ dir );
947+ $ objects = array_diff ( scandir ($ dir), array ( ' . ' , ' .. ' ) );
948948 foreach ($ objects as $ object ) {
949- if ($ object != ". " && $ object != ".. " && $ recursive ) {
950- if (filetype ($ dir .'/ ' .$ object ) == 'dir ' )
951- $ this ->rmdir ($ dir .'/ ' .$ object , $ recursive );
952- else unlink ($ dir .'/ ' .$ object );
949+ if ($ recursive ) {
950+ if (is_dir ("$ dir/ $ object " )) {
951+ $ this ->rmdir ("$ dir/ $ object " , $ recursive );
952+ } else {
953+ unlink ("$ dir/ $ object " );
954+ }
953955 }
954956 }
955- reset ($ objects );
956- rmdir ($ dir );
957+ return rmdir ($ dir );
957958 }
959+ return false ;
958960 }
959961
960962 function touch ($ file , $ allow_symlink = false ){
@@ -2241,7 +2243,7 @@ public function create_jailkit_user($username, $home_dir, $user_home_dir, $shell
22412243
22422244 public function create_jailkit_chroot ($ home_dir , $ app_sections = array (), $ options = array ()) {
22432245 if (!is_dir ($ home_dir )) {
2244- $ app ->log ("Jail directory does not exist: $ homedir " , LOGLEVEL_WARN );
2246+ $ app ->log ("create_jailkit_chroot: jail directory does not exist: $ homedir " , LOGLEVEL_WARN );
22452247 return false ;
22462248 }
22472249 if (empty ($ app_sections )) {
@@ -2291,7 +2293,7 @@ public function create_jailkit_chroot($home_dir, $app_sections = array(), $optio
22912293
22922294 public function create_jailkit_programs ($ home_dir , $ programs = array (), $ options = array ()) {
22932295 if (!is_dir ($ home_dir )) {
2294- $ app ->log ("Jail directory does not exist: $ homedir " , LOGLEVEL_WARN );
2296+ $ app ->log ("create_jailkit_programs: jail directory does not exist: $ homedir " , LOGLEVEL_WARN );
22952297 return false ;
22962298 }
22972299 if (empty ($ programs )) {
@@ -2311,6 +2313,7 @@ public function create_jailkit_programs($home_dir, $programs = array(), $options
23112313 '|^/tmp/?$| ' ,
23122314 '|^/run/?$| ' ,
23132315 '|^/boot/?$| ' ,
2316+ '|^/var(/?|/backups?/?)?$| ' ,
23142317 );
23152318
23162319 $ program_args = '' ;
@@ -2350,16 +2353,19 @@ public function create_jailkit_programs($home_dir, $programs = array(), $options
23502353
23512354 public function update_jailkit_chroot ($ home_dir , $ sections = array (), $ programs = array (), $ options = array ()) {
23522355 if (!is_dir ($ home_dir )) {
2353- $ app ->log ("Jail directory does not exist: $ homedir " , LOGLEVEL_WARN );
2356+ $ app ->log ("update_jailkit_chroot: jail directory does not exist: $ homedir " , LOGLEVEL_WARN );
23542357 return false ;
23552358 }
23562359
2357- $ opts = array (' force ' );
2360+ $ opts = array ();
23582361 foreach ($ options as $ opt ) {
23592362 switch ($ opt ) {
23602363 case '-k|hardlink ' :
23612364 $ opts [] = 'hardlink ' ;
23622365 break ;
2366+ case '-f|force ' :
2367+ $ opts [] = 'force ' ;
2368+ break ;
23632369 }
23642370 }
23652371
@@ -2380,17 +2386,21 @@ public function update_jailkit_chroot($home_dir, $sections = array(), $programs
23802386 'var ' ,
23812387 );
23822388
2389+ $ skips = '' ;
2390+ $ multiple_links = array ();
23832391 foreach ($ jailkit_directories as $ dir ) {
23842392 $ root_dir = '/ ' .$ dir ;
23852393 $ jail_dir = rtrim ($ home_dir , '/ ' ) . '/ ' .$ dir ;
23862394
23872395 if (!is_dir ($ jail_dir )) {
2396+ $ skips .= " --skip=/ $ dir " ;
23882397 continue ;
23892398 }
23902399
23912400 // if directory exists in jail but not in root, remove it
23922401 if (is_dir ($ jail_dir ) && !is_dir ($ root_dir )) {
23932402 $ this ->rmdir ($ jail_dir , true );
2403+ $ skips .= " --skip=/ $ dir " ;
23942404 continue ;
23952405 }
23962406
@@ -2401,6 +2411,51 @@ public function update_jailkit_chroot($home_dir, $sections = array(), $programs
24012411 if (!in_array ($ opts , 'hardlink ' ) && !in_array ($ options , 'allow_hardlink ' )) {
24022412 $ app ->log ("TODO: search for and remove hardlinked files " , LOGLEVEL_DEBUG );
24032413 // search for and save list of files
2414+
2415+ $ find_multiple_links = function ( $ path ) use ( &$ find_multiple_links ) {
2416+ $ found = array ();
2417+ if (is_dir ($ path )) {
2418+ $ objects = array_diff (scandir ($ path ), array ('. ' , '.. ' ));
2419+ foreach ($ objects as $ object ) {
2420+ $ ret = $ find_multiple_links ( "$ path/ $ object " );
2421+ if (count ($ ret ) > 0 ) {
2422+ $ found = array_merge ($ found , $ ret );
2423+ }
2424+ }
2425+ } else {
2426+ $ stat = stat ($ path );
2427+ if ($ stat ['nlink ' ] > 1 ) {
2428+ $ found [$ path ] = $ path ;
2429+ }
2430+ }
2431+ return $ found ;
2432+ };
2433+
2434+ $ ret = $ find_multiple_links ( $ jail_dir );
2435+ if (count ($ ret ) > 0 ) {
2436+ $ multiple_links = array_merge ($ multiple_links , $ ret );
2437+ }
2438+ }
2439+ }
2440+
2441+
2442+ $ cmd = 'jk_update --jail= ' .escapeshellarg ($ home_dir ) . $ skips ;
2443+ exec ($ cmd , $ out , $ ret );
2444+ foreach ($ out as $ line ) {
2445+ if (substr ( $ line , 0 , 4 ) === "skip " )) {
2446+ continue ;
2447+ }
2448+ if (preg_match ('|^(? [^ ]+){6}(.+)$ ' .preg_quote ($ home_dir , '| ' ).'| ' , $ line , $ matches )) {
2449+ # remove deprecated files that jk_update failed to remove
2450+ if (is_file ($ matches [1 ])) {
2451+ $ app ->log ("removing deprecated file which jk_update failed to remove: " .$ matches [1 ], LOGLEVEL_DEBUG );
2452+ unlink ($ matches [1 ]);
2453+ } elseif (is_dir ($ matches [1 ])) {
2454+ $ app ->log ("removing deprecated directory which jk_update failed to remove: " .$ matches [1 ], LOGLEVEL_DEBUG );
2455+ $ this ->rmdir ($ matches [1 ], true );
2456+ }
2457+ # unhandled error
2458+ $ app ->log ("jk_update error for jail $ home_dir: " .$ matches [1 ], LOGLEVEL_DEBUG );
24042459 }
24052460 }
24062461
@@ -2417,9 +2472,24 @@ public function update_jailkit_chroot($home_dir, $sections = array(), $programs
24172472 $ this ->chmod ($ home_dir . '/tmp ' , 0770 , true );
24182473 }
24192474
2420- // search for and remove hardlinked
2475+ // search for any hardlinked files which are now missing
24212476 if (!in_array ($ opts , 'hardlink ' ) && !in_array ($ options , 'allow_hardlink ' )) {
2422- $ app ->log ("TODO: search for hardlinked files now missing and add back " , LOGLEVEL_DEBUG );
2477+ foreach ($ multiple_links as $ file ) {
2478+ if (!is_file ($ file )) {
2479+ // strip $home_dir from $file
2480+ if (substr ($ file , 0 , strlen (rtrim ($ home_dir , '/ ' ))) == strlen (rtrim ($ home_dir , '/ ' ))) {
2481+ $ file = substr ($ file , strlen (rtrim ($ home_dir , '/ ' )));
2482+ }
2483+ if (is_file ($ file )) { // file exists in root
2484+ $ app ->log ("file with multiple links still missing, running jk_cp to restore: $ file " , LOGLEVEL_DEBUG );
2485+ $ cmd = 'jk_cp -j ? ' . escapeshellarg ($ file );
2486+ $ this ->exec_safe ($ cmd , $ home_dir );
2487+ } else {
2488+ // not necessarily an error
2489+ $ app ->log ("previously hardlinked file was not found to restore: $ file " , LOGLEVEL_DEBUG );
2490+ }
2491+ }
2492+ }
24232493 }
24242494
24252495 // Fix permissions of the root firectory
@@ -2428,6 +2498,51 @@ public function update_jailkit_chroot($home_dir, $sections = array(), $programs
24282498 return true ;
24292499 }
24302500
2501+ public function delete_jailkit_chroot ($ home_dir , $ options = array ()) {
2502+ if (!is_dir ($ home_dir )) {
2503+ $ app ->log ("delete_jailkit_chroot: jail directory does not exist: $ homedir " , LOGLEVEL_DEBUG );
2504+ return false ;
2505+ }
2506+
2507+ $ jailkit_directories = array (
2508+ 'bin ' ,
2509+ 'dev ' ,
2510+ 'etc ' ,
2511+ 'lib ' ,
2512+ 'lib32 ' ,
2513+ 'lib64 ' ,
2514+ 'opt ' ,
2515+ 'sys ' ,
2516+ 'usr ' ,
2517+ 'var ' ,
2518+ );
2519+
2520+ $ removed = '' ;
2521+ foreach ($ jailkit_directories as $ dir ) {
2522+ $ jail_dir = rtrim ($ home_dir , '/ ' ) . '/ ' .$ dir ;
2523+
2524+ if (is_dir ($ jail_dir )) {
2525+ $ this ->rmdir ($ jail_dir , true );
2526+ $ removed .= ' / ' .$ dir ;
2527+ }
2528+
2529+ }
2530+
2531+ $ app ->log ("delete_jailkit_chroot: removed from jail $ homedir: $ removed " , LOGLEVEL_DEBUG );
2532+
2533+ // handle etc and home special
2534+ $ home = rtrim ($ home_dir , '/ ' ) . '/home ' ;
2535+ @rmdir ($ home ); # ok to fail if non-empty
2536+
2537+ $ private = rtrim ($ home_dir , '/ ' ) . '/private ' ;
2538+ if (is_dir ($ home ) && is_dir ($ private )) {
2539+ $ archive = $ private .'/home- ' .date ('c ' );
2540+ rename ($ home , $ archive );
2541+ }
2542+
2543+ return true ;
2544+ }
2545+
24312546
24322547 public function pipe_exec ($ cmd , $ stdin , &$ retval = null , &$ stderr = null ) {
24332548 $ descriptors = array (
0 commit comments