Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 71 additions & 38 deletions apps/files/command/scan.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ class Scan extends Command {
protected $filesCounter = 0;
/** @var bool */
protected $interrupted = false;
/** @var bool */
protected $php_pcntl_signal = true;



public function __construct(\OC\User\Manager $userManager) {
Expand Down Expand Up @@ -93,15 +96,22 @@ protected function configure() {

protected function scanFiles($user, $path, $verbose, OutputInterface $output) {
$scanner = new \OC\Files\Utils\Scanner($user, \OC::$server->getDatabaseConnection(), \OC::$server->getLogger());
# check on each file/folder if there was a user interrupt (ctrl-c) and throw an exeption
# printout and count
if ($verbose) {
$scanner->listen('\OC\Files\Utils\Scanner', 'scanFile', function ($path) use ($output) {
$output->writeln("Scanning file <info>$path</info>");
$output->writeln("\tFile <info>$path</info>");
$this->filesCounter += 1;
if ($this->hasBeenInterrupted()) {
throw new \Exception('ctrl-c');
}
});
$scanner->listen('\OC\Files\Utils\Scanner', 'scanFolder', function ($path) use ($output) {
$output->writeln("Scanning folder <info>$path</info>");
$output->writeln("\tFolder <info>$path</info>");
$this->foldersCounter += 1;
if ($this->hasBeenInterrupted()) {
throw new \Exception('ctrl-c');
}
});
$scanner->listen('\OC\Files\Utils\Scanner', 'StorageNotAvailable', function (StorageNotAvailableException $e) use ($output) {
$output->writeln("Error while scanning, storage not available (" . $e->getMessage() . ")");
Expand All @@ -110,9 +120,15 @@ protected function scanFiles($user, $path, $verbose, OutputInterface $output) {
} else {
$scanner->listen('\OC\Files\Utils\Scanner', 'scanFile', function ($path) use ($output) {
$this->filesCounter += 1;
if ($this->hasBeenInterrupted()) {
throw new \Exception('ctrl-c');
}
});
$scanner->listen('\OC\Files\Utils\Scanner', 'scanFolder', function ($path) use ($output) {
$this->foldersCounter += 1;
if ($this->hasBeenInterrupted()) {
throw new \Exception('ctrl-c');
}
});
}

Expand All @@ -121,6 +137,9 @@ protected function scanFiles($user, $path, $verbose, OutputInterface $output) {
} catch (ForbiddenException $e) {
$output->writeln("<error>Home storage for user $user not writable</error>");
$output->writeln("Make sure you're running the scan command only as the user the web server runs as");
} catch (\Exception $e) {
# exit the function if ctrl-c has been pressed
return;
}
}

Expand All @@ -137,11 +156,6 @@ protected function execute(InputInterface $input, OutputInterface $output) {
$users = $input->getArgument('user_id');
}

if (count($users) === 0) {
$output->writeln("<error>Please specify the user id to scan, \"--all\" to scan for all users or \"--path=...\"</error>");
return;
}

# no messaging level option means: no full printout but statistics
# $quiet means no print at all
# $verbose means full printout including statistics
Expand All @@ -159,18 +173,38 @@ protected function execute(InputInterface $input, OutputInterface $output) {
$verbose = false;
}

# check quantity of users to be process and show it on the command line
$users_total = count($users);
if ($users_total === 0) {
$output->writeln("<error>Please specify the user id to scan, \"--all\" to scan for all users or \"--path=...\"</error>");
return;
} else {
if ($users_total > 1) {
$output->writeln("\nScanning files for $users_total users");
}
}

$this->initTools();

$user_count = 0;
foreach ($users as $user) {
if (is_object($user)) {
$user = $user->getUID();
}
$path = $inputPath ? $inputPath : '/' . $user;
$user_count += 1;
if ($this->userManager->userExists($user)) {
# add an extra line when verbose is set to optical seperate users
if ($verbose) {$output->writeln(""); }
$output->writeln("Starting scan for user $user_count out of $users_total ($user)");
# full: printout data if $verbose was set
$this->scanFiles($user, $path, $verbose, $output);
} else {
$output->writeln("<error>Unknown user $user</error>");
$output->writeln("<error>Unknown user $user_count $user</error>");
}
# check on each user if there was a user interrupt (ctrl-c) and exit foreach
if ($this->hasBeenInterrupted()) {
break;
}
}

Expand All @@ -182,17 +216,6 @@ protected function execute(InputInterface $input, OutputInterface $output) {
}


/**
* Checks if the command was interrupted by ctrl-c
*/
protected function checkForInterruption($output) {
if ($this->hasBeenInterrupted()) {
$this->presentResults($output);
exit;
}
}


/**
* Initialises some useful tools for the Command
*/
Expand All @@ -202,14 +225,19 @@ protected function initTools() {
// Convert PHP errors to exceptions
set_error_handler([$this, 'exceptionErrorHandler'], E_ALL);

// Collect interrupts and notify the running command
pcntl_signal(SIGTERM, [$this, 'cancelOperation']);
pcntl_signal(SIGINT, [$this, 'cancelOperation']);
// check if the php pcntl_signal functions are accessible
if (function_exists('pcntl_signal')) {
// Collect interrupts and notify the running command
pcntl_signal(SIGTERM, [$this, 'cancelOperation']);
pcntl_signal(SIGINT, [$this, 'cancelOperation']);
} else {
$this->php_pcntl_signal = false;
}
}


/**
* Changes the status of the command to "interrupted"
* Changes the status of the command to "interrupted" if ctrl-c has been pressed
*
* Gives a chance to the command to properly terminate what it's doing
*/
Expand All @@ -218,6 +246,24 @@ private function cancelOperation() {
}


/**
* @return bool
*/
protected function hasBeenInterrupted() {
// return always false if pcntl_signal functions are not accessible
if ($this->php_pcntl_signal) {
pcntl_signal_dispatch();
if ($this->interrupted) {
return true;
} else {
return false;
}
} else {
return false;
}
}


/**
* Processes PHP errors as exceptions in order to be able to keep track of problems
*
Expand All @@ -239,20 +285,6 @@ public function exceptionErrorHandler($severity, $message, $file, $line) {
}


/**
* @return bool
*/
protected function hasBeenInterrupted() {
$cancelled = false;
pcntl_signal_dispatch();
if ($this->interrupted) {
$cancelled = true;
}

return $cancelled;
}


/**
* @param OutputInterface $output
*/
Expand Down Expand Up @@ -300,7 +332,8 @@ protected function showSummary($headers, $rows, OutputInterface $output) {
*/
protected function formatExecTime() {
list($secs, $tens) = explode('.', sprintf("%.1f", ($this->execTime)));
$niceDate = date('H:i:s', $secs) . '.' . $tens;
# add the following to $niceDate if you want to have microsecons added: . '.' . $tens;
$niceDate = date('H:i:s', $secs);

return $niceDate;
}
Expand Down