diff --git a/inc/functions/fs.php b/inc/functions/fs.php index 0c43d66a..5f9ed463 100644 --- a/inc/functions/fs.php +++ b/inc/functions/fs.php @@ -4,65 +4,71 @@ namespace Vichan\Functions; class FsUtils { - public const ATOMIC_MULTI_ERR_NONE = 0; - public const ATOMIC_MULTI_ERR_SRC_BAD = 1; - public const ATOMIC_MULTI_ERR_SRC_NO_PERM = 2; - public const ATOMIC_MULTI_ERR_TARGET_BAD = 3; - public const ATOMIC_MULTI_ERR_TARGET_NO_PERM = 4; - public const ATOMIC_MULTI_ERR_ACTION_ERROR = 5; + public const MULTI_ERR_NONE = 0; + public const MULTI_ERR_SRC_BAD = 1; + public const MULTI_ERR_SRC_NO_PERM = 2; + public const MULTI_ERR_TARGET_BAD = 3; + public const MULTI_ERR_TARGET_NO_PERM = 4; + public const MULTI_ERR_ACTION_FAILED = 5; - private static function atomic_multi(array $config, string $src_dir, string $target_dir, iterable $src_file_names, callable $action, callable $action_rollback): int { + private static function multiAction(array $config, string $src_dir, string $target_dir, iterable $src_file_names, callable $action, callable $action_rollback): int { if (!is_dir($src_dir)) { - return self::ATOMIC_MULTI_ERR_SRC_BAD; + return self::MULTI_ERR_SRC_BAD; } if (!is_readable($src_dir)) { - return self::ATOMIC_MULTI_ERR_SRC_NO_PERM; + return self::MULTI_ERR_SRC_NO_PERM; } if (!is_dir($target_dir)) { - return self::ATOMIC_MULTI_ERR_TARGET_BAD; + return self::MULTI_ERR_TARGET_BAD; } if (!is_writable($target_dir)) { - return self::ATOMIC_MULTI_ERR_TARGET_NO_PERM; + return self::MULTI_ERR_TARGET_NO_PERM; } - $src_dir = self::ensure_end_path_separator($src_dir); - $target_dir = self::ensure_end_path_separator($target_dir); + $src_dir = self::ensureEndPathSeparator($src_dir); + $target_dir = self::ensureEndPathSeparator($target_dir); $linked = []; foreach ($src_file_names as $file_name) { $src_path = $src_dir . $file_name; $target_path = $target_dir . $file_name; - $success = $action($src_path, $target_path); - - if ($success) { - $linked[] = $file_name; - } - // Rollback. - else { + if (!file_exists($src_path)) { if ($config['syslog']) { - $l_count = count($linked); - _syslog(LOG_ERR, "Failed to link $src_path in $target_dir, rolling back $l_count linked files."); + _syslog(LOG_WARNING, "Attempting to operate on non-exiting file $src_path"); + } + } else { + $success = $action($src_path, $target_path); + + if ($success) { + $linked[] = $file_name; } + // Rollback. + else { + if ($config['syslog']) { + $l_count = count($linked); + _syslog(LOG_ERR, "Failed to link $src_path in $target_dir, rolling back $l_count linked files."); + } - foreach ($linked as $file_name) { - $src_path = $src_dir . $file_name; - $target_path = $target_dir . $file_name; + foreach ($linked as $file_name) { + $src_path = $src_dir . $file_name; + $target_path = $target_dir . $file_name; - // Already falling back, ignore eventual errors and just log them. - $success = $action_rollback($src_path, $target_path); - if (!$success && $config['syslog']) { - _syslog(LOG_ERR, "Failed to rollback $target_path in $src_dir."); + // Already falling back, ignore eventual errors and just log them. + $success = $action_rollback($src_path, $target_path); + if (!$success && $config['syslog']) { + _syslog(LOG_ERR, "Failed to rollback $target_path in $src_dir."); + } } - } - return self::ATOMIC_MULTI_ERR_ACTION_ERROR; + return self::MULTI_ERR_ACTION_FAILED; + } } } - return self::ATOMIC_MULTI_ERR_NONE; + return self::MULTI_ERR_NONE; } @@ -70,7 +76,7 @@ class FsUtils { * Appends a '/' to the given path if not already present. * @return string Returns the directory path terminating with a path separator. */ - public static function ensure_end_path_separator(string $dir): string { + public static function ensureEndPathSeparator(string $dir): string { if ($dir[strlen($dir) - 1] !== '/') { return "$dir/"; } @@ -84,11 +90,11 @@ class FsUtils { * @param string $src_dir The directory from which to fetch the files. * @param string $target_dir The directory to which the files should be copied to. * @param iterable $src_file_names The names of the files in $src_dir to be copied into $target_dir. The file names - * must NOT begin with a path separator. - * @return int Returns one of the class's ATOMIC_MULTI_ERR_* constants. + * may be path fragments, but must NOT begin with a path separator. + * @return int Returns one of the class's MULTI_ERR_* constants. */ - public function atomic_multi_copy(array $config, string $src_dir, string $target_dir, iterable $src_file_names) { - self::atomic_multi($config, $src_dir, $target_dir, $src_file_names, 'link', function($src_path, $target_path) { + public static function multiCopy(array $config, string $src_dir, string $target_dir, iterable $src_file_names) { + self::multiAction($config, $src_dir, $target_dir, $src_file_names, 'link', function($src_path, $target_path) { // Delete the hard links. \unlink($target_path); }); @@ -101,11 +107,11 @@ class FsUtils { * @param string $src_dir The directory from which to fetch the files. * @param string $target_dir The directory to which the files should be copied to. * @param iterable $src_file_names The names of the files in $src_dir to be copied into $target_dir. The file names - * must NOT begin with a path separator. - * @return int Returns one of the class's ATOMIC_MULTI_ERR_* constants. + * may be path fragments, but must NOT begin with a path separator. + * @return int Returns one of the class's MULTI_ERR_* constants. */ - public function atomic_multi_move(array $config, string $src_dir, string $target_dir, iterable $src_file_names) { - self::atomic_multi($config, $src_dir, $target_dir, $src_file_names, 'rename', function ($src_path, $target_path) { + public static function multiMove(array $config, string $src_dir, string $target_dir, iterable $src_file_names) { + self::multiAction($config, $src_dir, $target_dir, $src_file_names, 'rename', function ($src_path, $target_path) { // Move the files back into the source directory. \rename($target_path, $src_path); }); @@ -119,8 +125,8 @@ class FsUtils { * with a path separator. * @return int Returns the number of deleted files. */ - public function multi_delete(array $config, string $dir, iterable $file_names): int { - $dir = self::ensure_end_path_separator($dir); + public function multiDelete(array $config, string $dir, iterable $file_names): int { + $dir = self::ensureEndPathSeparator($dir); $deleted = 0; foreach ($file_names as $file_name) {