Merge pull request #386 from terrafrost/symlink

SFTP: add readlink and symlink functions

* terrafrost/symlink:
  SFTP: return $sftp object in unit tests
  SFTP: fix unit test
  SFTP: syntax error in unit test
  SFTP: add unit tests for symlinks
  SFTP: add readlink and symlink functions
This commit is contained in:
Andreas Fischer 2014-06-23 16:37:55 +02:00
commit 949cfcc867
2 changed files with 107 additions and 0 deletions

View File

@ -312,6 +312,8 @@ class Net_SFTP extends Net_SSH2
SFTPv5+: http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.3 SFTPv5+: http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.3
pre-SFTPv5 : http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-6.5 */ pre-SFTPv5 : http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-6.5 */
18 => 'NET_SFTP_RENAME', 18 => 'NET_SFTP_RENAME',
19 => 'NET_SFTP_READLINK',
20 => 'NET_SFTP_SYMLINK',
101=> 'NET_SFTP_STATUS', 101=> 'NET_SFTP_STATUS',
102=> 'NET_SFTP_HANDLE', 102=> 'NET_SFTP_HANDLE',
@ -1557,6 +1559,86 @@ class Net_SFTP extends Net_SSH2
return true; return true;
} }
/**
* Return the target of a symbolic link
*
* @param String $link
* @return Mixed
* @access public
*/
function readlink($link)
{
if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) {
return false;
}
$link = $this->_realpath($link);
if (!$this->_send_sftp_packet(NET_SFTP_READLINK, pack('Na*', strlen($link), $link))) {
return false;
}
$response = $this->_get_sftp_packet();
switch ($this->packet_type) {
case NET_SFTP_NAME:
break;
case NET_SFTP_STATUS:
$this->_logError($response);
return false;
default:
user_error('Expected SSH_FXP_NAME or SSH_FXP_STATUS');
return false;
}
extract(unpack('Ncount', $this->_string_shift($response, 4)));
// the file isn't a symlink
if (!$count) {
return false;
}
extract(unpack('Nlength', $this->_string_shift($response, 4)));
return $this->_string_shift($response, $length);
}
/**
* Create a symlink
*
* symlink() creates a symbolic link to the existing target with the specified name link.
*
* @param String $target
* @param String $link
* @return Boolean
* @access public
*/
function symlink($target, $link)
{
if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) {
return false;
}
$target = $this->_realpath($target);
$link = $this->_realpath($link);
$packet = pack('Na*Na*', strlen($target), $target, strlen($link), $link);
if (!$this->_send_sftp_packet(NET_SFTP_SYMLINK, $packet)) {
return false;
}
$response = $this->_get_sftp_packet();
if ($this->packet_type != NET_SFTP_STATUS) {
user_error('Expected SSH_FXP_STATUS');
return false;
}
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
if ($status != NET_SFTP_STATUS_OK) {
$this->_logError($response, $status);
return false;
}
return true;
}
/** /**
* Creates a directory. * Creates a directory.
* *

View File

@ -316,6 +316,31 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase
return $sftp; return $sftp;
} }
/**
* @depends testSortOrder
*/
public function testSymlink($sftp)
{
$this->assertTrue(
$sftp->symlink('file3.txt', 'symlink'),
'Failed asserting that a symlink could be created'
);
return $sftp;
}
/**
* @depends testSymlink
*/
public function testReadlink($sftp)
{
$this->assertInternalType('string', $sftp->readlink('symlink'),
'Failed asserting that a symlink\'s target could be read'
);
return $sftp;
}
/** /**
* @depends testSortOrder * @depends testSortOrder
*/ */