* EPL: add S3 check to FSCK to delete files not in egw_sqlfs table or empty files from S3 buckets

This commit is contained in:
ralf 2024-02-27 14:54:57 +02:00
parent 1f0aef8c96
commit ac54652c33
3 changed files with 80 additions and 4 deletions

View File

@ -130,7 +130,14 @@ class Utils extends StreamWrapper
'check_only' => $check_only) 'check_only' => $check_only)
) as $app_msgs) ) as $app_msgs)
{ {
if ($app_msgs) $msgs = array_merge($msgs, $app_msgs); if ($app_msgs && is_array($app_msgs[0]))
{
$msgs = array_merge($msgs, ...$app_msgs);
}
elseif ($app_msgs)
{
$msgs = array_merge($msgs, $app_msgs);
}
} }
// also run quota recalc as fsck might have (re-)moved files // also run quota recalc as fsck might have (re-)moved files
@ -258,7 +265,7 @@ class Utils extends StreamWrapper
$msgs = array(); $msgs = array();
$limit = 500; $limit = 500;
$offset = 0; $offset = 0;
$select_stmt = self::$pdo->prepare('SELECT fs_id FROM '.self::TABLE. $select_stmt = self::$pdo->prepare('SELECT fs_id,fs_size FROM '.self::TABLE.
" WHERE fs_mime!='httpd/unix-directory' AND fs_content IS NULL AND fs_link IS NULL AND (fs_s3_flags&7)=0". " WHERE fs_mime!='httpd/unix-directory' AND fs_content IS NULL AND fs_link IS NULL AND (fs_s3_flags&7)=0".
" LIMIT $limit OFFSET :offset"); " LIMIT $limit OFFSET :offset");
$select_stmt->setFetchMode(PDO::FETCH_ASSOC); $select_stmt->setFetchMode(PDO::FETCH_ASSOC);
@ -298,13 +305,44 @@ class Utils extends StreamWrapper
} }
} }
} }
// file is empty and NOT in /templates/ or /etemplates/ which use 0-byte files as delete marker
elseif (!$row['fs_size'] && !filesize($phy_path) && !preg_match('#^/e?templates/#', $path))
{
if ($check_only)
{
++$offset;
$msgs[] = lang('File %1 is empty %2!',
$path.' (#'.$row['fs_id'].')',$phy_path);
}
else
{
if (!isset($stmt))
{
$stmt = self::$pdo->prepare('DELETE FROM '.self::TABLE.' WHERE fs_id=:fs_id');
$stmt_props = self::$pdo->prepare('DELETE FROM '.self::PROPS_TABLE.' WHERE fs_id=:fs_id');
}
if ($stmt->execute(array('fs_id' => $row['fs_id'])) &&
$stmt_props->execute(array('fs_id' => $row['fs_id'])))
{
$msgs[] = lang('File %1 is empty %2 --> file removed!',$path,$phy_path);
unlink($phy_path);
}
else
{
++$offset;
$msgs[] = lang('File %1 is empty %2 --> failed to remove file!',
$path.' (#'.$row['fs_id'].')',$phy_path);
}
}
}
} }
} }
while ($num >= $limit); while ($num >= $limit);
if ($check_only && $msgs) if ($check_only && $msgs)
{ {
$msgs[] = lang('Files without content in physical filesystem will be removed.'); $msgs[] = lang('Files without content in physical filesystem or empty files will be removed.');
} }
return $msgs; return $msgs;
} }

38
filemanager/fsck.php Executable file
View File

@ -0,0 +1,38 @@
#!/usr/bin/env php
<?php
/**
* VFS - filesystem check via cli
*
* @link https://www.egroupware.org
* @package filemanager
* @author Ralf Becker <rb-AT-egroupware.org>
* @copyright (c) 2024 by Ralf Becker <rb-AT-egroupware.org>
*/
use EGroupware\api\Vfs\Sqlfs;
if (php_sapi_name() !== 'cli') // security precaution: forbid calling via web
{
die('<h1>fsck.php must NOT be called as web-page --> exiting !!!</h1>');
}
$GLOBALS['egw_info'] = [
'flags' => [
'currentapp' => 'login',
'no_exception_handler' => 'cli',
]
];
require(dirname(__DIR__).'/header.inc.php');
$msgs = Sqlfs\Utils::fsck([
'check_only' => $check_only = ($_SERVER['argv'][1] ?? '') !== '--yes',
]);
echo implode("\n", $msgs)."\n";
if (!$msgs)
{
error_log("fsck found NO problems :)");
}
elseif ($check_only)
{
error_log('Use --yes to fix problems found');
}

View File

@ -339,7 +339,7 @@ class filemanager_admin extends filemanager_ui
$content = '<p>' . implode("</p>\n<p>", (array)$msgs) . "</p>\n"; $content = '<p>' . implode("</p>\n<p>", (array)$msgs) . "</p>\n";
$content .= Api\Html::form('<p>' . ($check_only && is_array($msgs) ? $content .= Api\Html::form('<p>' . ($check_only && is_array($msgs) ?
Api\Html::submit_button('fix', lang('Fix reported problems')) : '') . Api\Html::submit_button('edit', lang('Fix reported problems')) : '') .
Api\Html::submit_button('cancel', lang('Cancel')) . '</p>', Api\Html::submit_button('cancel', lang('Cancel')) . '</p>',
'', '/index.php', array('menuaction' => 'filemanager.filemanager_admin.fsck') '', '/index.php', array('menuaction' => 'filemanager.filemanager_admin.fsck')
); );