Pass path and error code to exceptions

This commit is contained in:
Robin Appelman 2014-10-17 14:55:53 +02:00
commit 77c30c698f
4 changed files with 80 additions and 50 deletions

View file

@ -7,4 +7,25 @@
namespace Icewind\SMB\Exception; namespace Icewind\SMB\Exception;
class InvalidRequestException extends Exception {} class InvalidRequestException extends Exception {
/**
* @var string
*/
protected $path;
/**
* @param string $path
* @param int $code
*/
public function __construct($path, $code = 0) {
parent::__construct('Invalid request for ' . $path, $code);
$this->path = $path;
}
/**
* @return string
*/
public function getPath() {
return $this->path;
}
}

View file

@ -27,32 +27,36 @@ class NativeState {
protected $connected = false; protected $connected = false;
protected function handleError() { protected function handleError($path) {
$error = smbclient_state_errno($this->state); $error = smbclient_state_errno($this->state);
switch ($error) { switch ($error) {
// see error.h // see error.h
case 0; case 0;
return; return;
case 1: case 1:
throw new ForbiddenException(); throw new ForbiddenException($path, $error);
case 2: case 2:
throw new NotFoundException(); throw new NotFoundException($path, $error);
case 17: case 17:
throw new AlreadyExistsException(); throw new AlreadyExistsException($path, $error);
case 20: case 20:
throw new InvalidTypeException(); throw new InvalidTypeException($path, $error);
case 21: case 21:
throw new InvalidTypeException(); throw new InvalidTypeException($path, $error);
case 39: case 39:
throw new NotEmptyException(); throw new NotEmptyException($path, $error);
default: default:
throw new Exception('Unknown error (' . $error . ')'); $message = 'Unknown error (' . $error . ')';
if ($path) {
$message .= ' for ' . $path;
}
throw new Exception($message, $error);
} }
} }
protected function testResult($result) { protected function testResult($result, $path) {
if ($result === false or $result === null) { if ($result === false or $result === null) {
$this->handleError(); $this->handleError($path);
} }
} }
@ -69,7 +73,7 @@ class NativeState {
$this->state = smbclient_state_new(); $this->state = smbclient_state_new();
$result = @smbclient_state_init($this->state, $workGroup, $user, $password); $result = @smbclient_state_init($this->state, $workGroup, $user, $password);
$this->testResult($result); $this->testResult($result, '');
$this->connected = true; $this->connected = true;
return $result; return $result;
} }
@ -81,7 +85,7 @@ class NativeState {
public function opendir($uri) { public function opendir($uri) {
$result = @smbclient_opendir($this->state, $uri); $result = @smbclient_opendir($this->state, $uri);
$this->testResult($result); $this->testResult($result, $uri);
return $result; return $result;
} }
@ -92,7 +96,7 @@ class NativeState {
public function readdir($dir) { public function readdir($dir) {
$result = @smbclient_readdir($this->state, $dir); $result = @smbclient_readdir($this->state, $dir);
$this->testResult($result); $this->testResult($result, $dir);
return $result; return $result;
} }
@ -103,7 +107,7 @@ class NativeState {
public function closedir($dir) { public function closedir($dir) {
$result = smbclient_closedir($this->state, $dir); $result = smbclient_closedir($this->state, $dir);
$this->testResult($result); $this->testResult($result, $dir);
return $result; return $result;
} }
@ -115,7 +119,7 @@ class NativeState {
public function rename($old, $new) { public function rename($old, $new) {
$result = @smbclient_rename($this->state, $old, $this->state, $new); $result = @smbclient_rename($this->state, $old, $this->state, $new);
$this->testResult($result); $this->testResult($result, $new);
return $result; return $result;
} }
@ -126,7 +130,7 @@ class NativeState {
public function unlink($uri) { public function unlink($uri) {
$result = @smbclient_unlink($this->state, $uri); $result = @smbclient_unlink($this->state, $uri);
$this->testResult($result); $this->testResult($result, $uri);
return $result; return $result;
} }
@ -138,7 +142,7 @@ class NativeState {
public function mkdir($uri, $mask = 0777) { public function mkdir($uri, $mask = 0777) {
$result = @smbclient_mkdir($this->state, $uri, $mask); $result = @smbclient_mkdir($this->state, $uri, $mask);
$this->testResult($result); $this->testResult($result, $uri);
return $result; return $result;
} }
@ -149,7 +153,7 @@ class NativeState {
public function rmdir($uri) { public function rmdir($uri) {
$result = @smbclient_rmdir($this->state, $uri); $result = @smbclient_rmdir($this->state, $uri);
$this->testResult($result); $this->testResult($result, $uri);
return $result; return $result;
} }
@ -160,7 +164,7 @@ class NativeState {
public function stat($uri) { public function stat($uri) {
$result = @smbclient_stat($this->state, $uri); $result = @smbclient_stat($this->state, $uri);
$this->testResult($result); $this->testResult($result, $uri);
return $result; return $result;
} }
@ -171,7 +175,7 @@ class NativeState {
public function fstat($file) { public function fstat($file) {
$result = @smbclient_fstat($this->state, $file); $result = @smbclient_fstat($this->state, $file);
$this->testResult($result); $this->testResult($result, $file);
return $result; return $result;
} }
@ -184,7 +188,7 @@ class NativeState {
public function open($uri, $mode, $mask = 0666) { public function open($uri, $mode, $mask = 0666) {
$result = @smbclient_open($this->state, $uri, $mode, $mask); $result = @smbclient_open($this->state, $uri, $mode, $mask);
$this->testResult($result); $this->testResult($result, $uri);
return $result; return $result;
} }
@ -196,7 +200,7 @@ class NativeState {
public function create($uri, $mask = 0666) { public function create($uri, $mask = 0666) {
$result = @smbclient_creat($this->state, $uri, $mask); $result = @smbclient_creat($this->state, $uri, $mask);
$this->testResult($result); $this->testResult($result, $uri);
return $result; return $result;
} }
@ -208,7 +212,7 @@ class NativeState {
public function read($file, $bytes) { public function read($file, $bytes) {
$result = @smbclient_read($this->state, $file, $bytes); $result = @smbclient_read($this->state, $file, $bytes);
$this->testResult($result); $this->testResult($result, $file);
return $result; return $result;
} }
@ -221,7 +225,7 @@ class NativeState {
public function write($file, $data, $length = null) { public function write($file, $data, $length = null) {
$result = @smbclient_write($this->state, $file, $data, $length); $result = @smbclient_write($this->state, $file, $data, $length);
$this->testResult($result); $this->testResult($result, $file);
return $result; return $result;
} }
@ -234,7 +238,7 @@ class NativeState {
public function lseek($file, $offset, $whence = SEEK_SET) { public function lseek($file, $offset, $whence = SEEK_SET) {
$result = @smbclient_lseek($this->state, $file, $offset, $whence); $result = @smbclient_lseek($this->state, $file, $offset, $whence);
$this->testResult($result); $this->testResult($result, $file);
return $result; return $result;
} }
@ -246,14 +250,14 @@ class NativeState {
public function ftruncate($file, $size) { public function ftruncate($file, $size) {
$result = @smbclient_ftruncate($this->state, $file, $size); $result = @smbclient_ftruncate($this->state, $file, $size);
$this->testResult($result); $this->testResult($result, $file);
return $result; return $result;
} }
public function close($file) { public function close($file) {
$result = @smbclient_close($this->state, $file); $result = @smbclient_close($this->state, $file);
$this->testResult($result); $this->testResult($result, $file);
return $result; return $result;
} }
@ -265,7 +269,7 @@ class NativeState {
public function getxattr($uri, $key) { public function getxattr($uri, $key) {
$result = @smbclient_getxattr($this->state, $uri, $key); $result = @smbclient_getxattr($this->state, $uri, $key);
$this->testResult($result); $this->testResult($result, $uri);
return $result; return $result;
} }
@ -279,7 +283,7 @@ class NativeState {
public function setxattr($uri, $key, $value, $flags = 0) { public function setxattr($uri, $key, $value, $flags = 0) {
$result = @smbclient_setxattr($this->state, $uri, $key, $value, $flags); $result = @smbclient_setxattr($this->state, $uri, $key, $value, $flags);
$this->testResult($result); $this->testResult($result, $uri);
return $result; return $result;
} }

View file

@ -27,12 +27,12 @@ class Parser {
$this->timeZone = $timeZone; $this->timeZone = $timeZone;
} }
public function checkForError($output) { public function checkForError($output, $path) {
if (count($output) === 0) { if (count($output) === 0) {
return true; return true;
} else { } else {
if (strpos($output[0], 'does not exist')) { if (strpos($output[0], 'does not exist')) {
throw new NotFoundException(); throw new NotFoundException($path);
} }
$parts = explode(' ', $output[0]); $parts = explode(' ', $output[0]);
$error = false; $error = false;
@ -45,18 +45,22 @@ class Parser {
case ErrorCodes::PathNotFound: case ErrorCodes::PathNotFound:
case ErrorCodes::ObjectNotFound: case ErrorCodes::ObjectNotFound:
case ErrorCodes::NoSuchFile: case ErrorCodes::NoSuchFile:
throw new NotFoundException(); throw new NotFoundException($path);
case ErrorCodes::NameCollision: case ErrorCodes::NameCollision:
throw new AlreadyExistsException(); throw new AlreadyExistsException($path);
case ErrorCodes::AccessDenied: case ErrorCodes::AccessDenied:
throw new AccessDeniedException(); throw new AccessDeniedException($path);
case ErrorCodes::DirectoryNotEmpty: case ErrorCodes::DirectoryNotEmpty:
throw new NotEmptyException(); throw new NotEmptyException($path);
case ErrorCodes::FileIsADirectory: case ErrorCodes::FileIsADirectory:
case ErrorCodes::NotADirectory: case ErrorCodes::NotADirectory:
throw new InvalidTypeException(); throw new InvalidTypeException($path);
default: default:
throw new Exception(); $message = 'Unknown error (' . $error . ')';
if ($path) {
$message .= ' for ' . $path;
}
throw new Exception($message);
} }
} }
} }

View file

@ -83,7 +83,7 @@ class Share implements IShare {
$path = $this->escapePath($path); $path = $this->escapePath($path);
$cmd = $command . ' ' . $path; $cmd = $command . ' ' . $path;
$output = $this->execute($cmd); $output = $this->execute($cmd);
return $this->parseOutput($output); return $this->parseOutput($output, $path);
} }
/** /**
@ -99,7 +99,7 @@ class Share implements IShare {
$escapedPath = $this->escapePath($path); $escapedPath = $this->escapePath($path);
$output = $this->execute('cd ' . $escapedPath); $output = $this->execute('cd ' . $escapedPath);
//check output for errors //check output for errors
$this->parseOutput($output); $this->parseOutput($output, $path);
$output = $this->execute('dir'); $output = $this->execute('dir');
$this->execute('cd /'); $this->execute('cd /');
@ -114,7 +114,7 @@ class Share implements IShare {
$escapedPath = $this->escapePath($path); $escapedPath = $this->escapePath($path);
$output = $this->execute('allinfo ' . $escapedPath); $output = $this->execute('allinfo ' . $escapedPath);
if (count($output) < 3) { if (count($output) < 3) {
$this->parseOutput($output); $this->parseOutput($output, $path);
} }
$stat = $this->parser->parseStat($output); $stat = $this->parser->parseStat($output);
return new FileInfo($path, basename($path), $stat['size'], $stat['mtime'], $stat['mode']); return new FileInfo($path, basename($path), $stat['size'], $stat['mtime'], $stat['mode']);
@ -167,7 +167,7 @@ class Share implements IShare {
} catch (NotFoundException $e2) { } catch (NotFoundException $e2) {
throw $e; throw $e;
} catch (\Exception $e2) { } catch (\Exception $e2) {
throw new InvalidTypeException(); throw new InvalidTypeException($path);
} }
throw $e; throw $e;
} }
@ -188,7 +188,7 @@ class Share implements IShare {
$path2 = $this->escapePath($to); $path2 = $this->escapePath($to);
$cmd = 'rename ' . $path1 . ' ' . $path2; $cmd = 'rename ' . $path1 . ' ' . $path2;
$output = $this->execute($cmd); $output = $this->execute($cmd);
return $this->parseOutput($output); return $this->parseOutput($output, $to);
} }
/** /**
@ -205,7 +205,7 @@ class Share implements IShare {
$path1 = $this->escapeLocalPath($source); //first path is local, needs different escaping $path1 = $this->escapeLocalPath($source); //first path is local, needs different escaping
$path2 = $this->escapePath($target); $path2 = $this->escapePath($target);
$output = $this->execute('put ' . $path1 . ' ' . $path2); $output = $this->execute('put ' . $path1 . ' ' . $path2);
return $this->parseOutput($output); return $this->parseOutput($output, $target);
} }
/** /**
@ -222,7 +222,7 @@ class Share implements IShare {
$path1 = $this->escapePath($source); $path1 = $this->escapePath($source);
$path2 = $this->escapeLocalPath($target); //second path is local, needs different escaping $path2 = $this->escapeLocalPath($target); //second path is local, needs different escaping
$output = $this->execute('get ' . $path1 . ' ' . $path2); $output = $this->execute('get ' . $path1 . ' ' . $path2);
return $this->parseOutput($output); return $this->parseOutput($output, $source);
} }
/** /**
@ -308,12 +308,12 @@ class Share implements IShare {
// first reset the mode to normal // first reset the mode to normal
$cmd = 'setmode ' . $path . ' -rsha'; $cmd = 'setmode ' . $path . ' -rsha';
$output = $this->execute($cmd); $output = $this->execute($cmd);
$this->parseOutput($output); $this->parseOutput($output, $path);
// then set the modes we want // then set the modes we want
$cmd = 'setmode ' . $path . ' ' . $modeString; $cmd = 'setmode ' . $path . ' ' . $modeString;
$output = $this->execute($cmd); $output = $this->execute($cmd);
return $this->parseOutput($output); return $this->parseOutput($output, $path);
} }
/** /**
@ -330,7 +330,8 @@ class Share implements IShare {
/** /**
* check output for errors * check output for errors
* *
* @param $lines * @param string[] $lines
* @param string $path
* *
* @throws NotFoundException * @throws NotFoundException
* @throws \Icewind\SMB\Exception\AlreadyExistsException * @throws \Icewind\SMB\Exception\AlreadyExistsException
@ -340,8 +341,8 @@ class Share implements IShare {
* @throws \Icewind\SMB\Exception\Exception * @throws \Icewind\SMB\Exception\Exception
* @return bool * @return bool
*/ */
protected function parseOutput($lines) { protected function parseOutput($lines, $path = '') {
$this->parser->checkForError($lines); $this->parser->checkForError($lines, $path);
} }
/** /**