Skip to content

Commit

Permalink
Various bug fixes
Browse files Browse the repository at this point in the history
- Fix DirScan::stat Fatal error
- Fix stdout/stderr
- Fix lstat failed (skip scan)
- Fix empty row readlink failed
- Fix Windows volume root double backslash
- Fix Windows volume root name
- Add uniquepath failover
  • Loading branch information
vincepare committed Dec 11, 2015
1 parent c94a7dd commit ab306d4
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 28 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ DirScan is bundled with a text reporter, but you can customize its output by cre
Download dirscan.phar, make it executable (chmod +x dirscan.phar) and rename it if you want. On Linux, store it to `/usr/local/bin` to make it available everywhere :

```
wget -O dirscan https://github.com/vincepare/DirScan/releases/download/1.1.0/dirscan.phar
wget -O dirscan https://github.com/vincepare/DirScan/releases/download/1.1.1/dirscan.phar
chmod +x dirscan
sudo mv dirscan /usr/local/bin/dirscan
```
Expand Down Expand Up @@ -66,4 +66,4 @@ Format tokens to customize output (`--format`) :

### About windows

DirScan is designed to work a Unix environment (Linux or Mac OS) but you can also use it on Windows. In this case, beware of NTFS junction points and symbolic links that are not handled properly by old php releases (see [readlink](http://php.net/manual/en/function.readlink.php) & [is_link](http://php.net/manual/en/function.is-link.php)). But you'd better use other tools like [WhereIsIt](http://www.whereisit-soft.com/).
DirScan is designed to work on a Unix environment (Linux or Mac OS) but you can also use it on Windows. In this case, beware of NTFS junction points and symbolic links that are not handled properly by old php releases (see [readlink](http://php.net/manual/en/function.readlink.php) & [is_link](http://php.net/manual/en/function.is-link.php)). But you'd better use other tools like [WhereIsIt](http://www.whereisit-soft.com/).
20 changes: 16 additions & 4 deletions src/CliReporter.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ public function __construct($settings)
*/
public function header($target, $argv)
{
$targetStat = DirScan::stat($target);
$targetStat = lstat($target);
$targetStat['realpath'] = realpath($target);
$header = !empty($this->format) ? $this->getRowFormatHeader($this->format) : $this->getRowHeader();
echo "date: ".date('r (U)')."\n";
echo "getenv(TZ): ".getenv('TZ')."\n";
Expand Down Expand Up @@ -198,7 +199,7 @@ protected function getRowFormatHeader($format)
protected function getRow($node, $meta)
{
$row = array(
$node['uniquepath'],
self::getPath($node),
$meta['type'],
$node['size'],
);
Expand Down Expand Up @@ -242,7 +243,7 @@ protected function getRow($node, $meta)
protected function getRowFormat($format, $node, $meta)
{
$statMapping = array(
'%u' => $node['uniquepath'],
'%u' => self::getPath($node),
'%t' => $meta['type'],
'%s' => $node['size'],
'%c' => $node['ctime'],
Expand Down Expand Up @@ -278,6 +279,17 @@ protected function getRowFormat($format, $node, $meta)
return $row;
}

/**
* Returns either node uniquepath, or path as failover if uniquepath is not available
*
* @param array $node Data returned by DirScan::stat
* @return string
*/
protected static function getPath($node)
{
return !empty($node['uniquepath']) ? $node['uniquepath'] : $node['path'].' *UNIQUEPATH_FAILOVER';
}

/**
* Print error messages to stderr
*
Expand All @@ -286,6 +298,6 @@ protected function getRowFormat($format, $node, $meta)
*/
public function error($msg, $code = null)
{
fwrite(STDERR, $msg.PHP_EOL);
fwrite(STDERR, "[dirscan] ".$msg.PHP_EOL);
}
}
25 changes: 18 additions & 7 deletions src/DirScan.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,13 @@ public function __construct($settings, Reporter $reporter)
*/
public function scan($path, $pathstack = array())
{
$stat = self::stat($path);
// Get node metadata
$stat = $this->stat($path);
if ($stat === false) {
$msg = "lstat failed on `".$path."`";
call_user_func(array($this->reporter, 'error'), $msg, self::ERR_DIR_LOOP);
return;
}
call_user_func(array($this->reporter, 'push'), $stat, $this);

// Saving start directory device
Expand All @@ -61,7 +67,7 @@ public function scan($path, $pathstack = array())
return;
}

// Do not explore direcotry content if it's not on the start device
// Do not explore directory content if it's not on the start device
if ($this->sameDevice && $stat['dev'] != $this->startDevice) {
return;
}
Expand Down Expand Up @@ -101,7 +107,7 @@ public function scan($path, $pathstack = array())
* @param string $path File system path of the node
* @return array
*/
public static function stat($path)
public function stat($path)
{
$lstat = lstat($path);
if ($lstat === false) {
Expand Down Expand Up @@ -135,11 +141,10 @@ public static function stat($path)
$target = @readlink($path);
if ($target === false) {
$error = error_get_last();
$msg = $error['message']." (".$uniquepath.")";
$msg = $error['message']." (path: ".$path.", uniquepath: ".$uniquepath.")";
call_user_func(array($this->reporter, 'error'), $msg, self::ERR_READLINK);
return;
} else {
$result['target'] = readlink($path);
$result['target'] = $target;
}
}

Expand All @@ -158,10 +163,16 @@ public static function uniquepath($path)
if (!file_exists($path)) {
return false;
}

// Special handling of volume roots on Windows
if (PHP_OS === 'WINNT' && preg_match('#^\w:\\\\$#', $path)) {
return $path;
}
$info = pathinfo($path);
clearstatcache(true);
$parent = realpath($info['dirname']);
$uniquepath = rtrim($parent, '/').DIRECTORY_SEPARATOR.$info['basename'];
$uniquepath = rtrim($parent, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$info['basename'];
return $uniquepath;
}

Expand Down
7 changes: 5 additions & 2 deletions src/dirscan
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@
* @copyright © 2015 Vincent Paré
* @license http://opensource.org/licenses/Apache-2.0
* @package DirScan
* @version 1.1.0 (2015-06-27)
* @version 1.1.1 (2015-12-11)
*/

const DIRSCAN_VERSION = '1.1.0';
ini_set('log_errors', 0);
ini_set('display_errors', 'stderr');

const DIRSCAN_VERSION = '1.1.1';

require __DIR__.'/DirScan.php';
require __DIR__.'/Reporter.php';
Expand Down
52 changes: 39 additions & 13 deletions src/legacy/dirscan
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@
* @copyright © 2015 Vincent Paré
* @license http://opensource.org/licenses/Apache-2.0
* @package DirScan
* @version 1.1.0-legacy (2015-06-27)
* @version 1.1.1-legacy (2015-12-11)
*/

define('DIRSCAN_VERSION', '1.1.0-legacy');
ini_set('log_errors', 0);
ini_set('display_errors', 'stderr');

define('DIRSCAN_VERSION', '1.1.1-legacy');

// Disabling realpath cache on php <= 5.2
ini_set('realpath_cache_size', '0');
Expand Down Expand Up @@ -151,7 +154,13 @@ class DirScan
*/
public function scan($path, $pathstack = array())
{
$stat = self::stat($path);
// Get node metadata
$stat = $this->stat($path);
if ($stat === false) {
$msg = "lstat failed on `".$path."`";
call_user_func(array($this->reporter, 'error'), $msg, self::ERR_DIR_LOOP);
return;
}
call_user_func(array($this->reporter, 'push'), $stat, $this);

// Saving start directory device
Expand All @@ -169,7 +178,7 @@ class DirScan
return;
}

// Do not explore direcotry content if it's not on the start device
// Do not explore directory content if it's not on the start device
if ($this->sameDevice && $stat['dev'] != $this->startDevice) {
return;
}
Expand Down Expand Up @@ -209,7 +218,7 @@ class DirScan
* @param string $path File system path of the node
* @return array
*/
public static function stat($path)
public function stat($path)
{
$lstat = lstat($path);
if ($lstat === false) {
Expand Down Expand Up @@ -242,11 +251,10 @@ class DirScan
$target = @readlink($path);
if ($target === false) {
$error = error_get_last();
$msg = $error['message']." (".$uniquepath.")";
$msg = $error['message']." (path: ".$path.", uniquepath: ".$uniquepath.")";
call_user_func(array($this->reporter, 'error'), $msg, self::ERR_READLINK);
return;
} else {
$result['target'] = readlink($path);
$result['target'] = $target;
}
}

Expand All @@ -265,9 +273,15 @@ class DirScan
if (!file_exists($path)) {
return false;
}

// Special handling of volume roots on Windows
if (PHP_OS === 'WINNT' && preg_match('#^\w:\\\\$#', $path)) {
return $path;
}
$info = pathinfo($path);
$parent = realpath($info['dirname']);
$uniquepath = rtrim($parent, '/').DIRECTORY_SEPARATOR.$info['basename'];
$uniquepath = rtrim($parent, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$info['basename'];
return $uniquepath;
}

Expand Down Expand Up @@ -376,7 +390,8 @@ class CliReporter extends Reporter
*/
public function header($target, $argv)
{
$targetStat = DirScan::stat($target);
$targetStat = lstat($target);
$targetStat['realpath'] = realpath($target);
$header = !empty($this->format) ? $this->getRowFormatHeader($this->format) : $this->getRowHeader();
echo "date: ".date('r (U)')."\n";
echo "getenv(TZ): ".getenv('TZ')."\n";
Expand Down Expand Up @@ -500,7 +515,7 @@ class CliReporter extends Reporter
protected function getRow($node, $meta)
{
$row = array(
$node['uniquepath'],
self::getPath($node),
$meta['type'],
$node['size'],
);
Expand Down Expand Up @@ -544,7 +559,7 @@ class CliReporter extends Reporter
protected function getRowFormat($format, $node, $meta)
{
$statMapping = array(
'%u' => $node['uniquepath'],
'%u' => self::getPath($node),
'%t' => $meta['type'],
'%s' => $node['size'],
'%c' => $node['ctime'],
Expand Down Expand Up @@ -580,6 +595,17 @@ class CliReporter extends Reporter
return $row;
}

/**
* Returns either node uniquepath, or path as failover if uniquepath is not available
*
* @param array $node Data returned by DirScan::stat
* @return string
*/
protected static function getPath($node)
{
return !empty($node['uniquepath']) ? $node['uniquepath'] : $node['path'].' *UNIQUEPATH_FAILOVER';
}

/**
* Print error messages to stderr
*
Expand All @@ -588,6 +614,6 @@ class CliReporter extends Reporter
*/
public function error($msg, $code = null)
{
fwrite(STDERR, $msg.PHP_EOL);
fwrite(STDERR, "[dirscan] ".$msg.PHP_EOL);
}
}
Empty file modified tests/setup.sh
100644 → 100755
Empty file.

0 comments on commit ab306d4

Please sign in to comment.