SFTP: stat cache updates

This commit is contained in:
terrafrost 2015-07-14 15:23:04 -05:00 committed by Andreas Fischer
parent 12ccc402b1
commit 862b63e9e5
2 changed files with 55 additions and 2 deletions

View File

@ -901,7 +901,7 @@ class Net_SFTP extends Net_SSH2
} else { } else {
$temp = $dir . '/' . $shortname; $temp = $dir . '/' . $shortname;
} }
$this->_update_stat_cache($temp, (object) array('stat' => $attributes)); $this->_update_stat_cache($temp, (object) array('lstat' => $attributes));
} }
// SFTPv6 has an optional boolean end-of-list field, but we'll ignore that, since the // SFTPv6 has an optional boolean end-of-list field, but we'll ignore that, since the
// final SSH_FXP_STATUS packet should tell us that, already. // final SSH_FXP_STATUS packet should tell us that, already.
@ -1072,6 +1072,12 @@ class Net_SFTP extends Net_SSH2
$temp = &$this->stat_cache; $temp = &$this->stat_cache;
$max = count($dirs) - 1; $max = count($dirs) - 1;
foreach ($dirs as $i=>$dir) { foreach ($dirs as $i=>$dir) {
// if $temp is an object that means one of two things.
// 1. a file was deleted and changed to a directory behind phpseclib's back
// 2. it's a symlink. when lstat is done it's unclear what it's a symlink to
if (is_object($temp)) {
$temp = array();
}
if (!isset($temp[$dir])) { if (!isset($temp[$dir])) {
$temp[$dir] = array(); $temp[$dir] = array();
} }
@ -1161,7 +1167,7 @@ class Net_SFTP extends Net_SSH2
if ($this->use_stat_cache) { if ($this->use_stat_cache) {
$result = $this->_query_stat_cache($filename); $result = $this->_query_stat_cache($filename);
if (is_array($result) && isset($result['.'])) { if (is_array($result) && isset($result['.']) && isset($result['.']->stat)) {
return $result['.']->stat; return $result['.']->stat;
} }
if (is_object($result) && isset($result->stat)) { if (is_object($result) && isset($result->stat)) {

View File

@ -594,5 +594,52 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase
$sftp->stat(self::$scratchDir), $sftp->stat(self::$scratchDir),
'Failed asserting that stat on a deleted directory returns false' 'Failed asserting that stat on a deleted directory returns false'
); );
return $sftp;
}
/**
* @depends testDeleteEmptyDir
* @group github735
*/
public function testStatVsLstat($sftp)
{
$this->assertTrue($sftp->mkdir(self::$scratchDir));
$this->assertTrue($sftp->chdir(self::$scratchDir));
$this->assertTrue($sftp->put('text.txt', 'zzzzz'));
$this->assertTrue($sftp->symlink('text.txt', 'link.txt'));
$this->assertTrue($sftp->mkdir('subdir'));
$this->assertTrue($sftp->symlink('subdir', 'linkdir'));
$sftp->clearStatCache();
// pre-populate the stat cache
$sftp->nlist();
$stat = $sftp->stat('link.txt');
$this->assertSame($stat['type'], NET_SFTP_TYPE_REGULAR);
$stat = $sftp->lstat('link.txt');
$this->assertSame($stat['type'], NET_SFTP_TYPE_SYMLINK);
$stat = $sftp->stat('linkdir');
$this->assertSame($stat['type'], NET_SFTP_TYPE_DIRECTORY);
$stat = $sftp->lstat('link.txt');
$this->assertSame($stat['type'], NET_SFTP_TYPE_SYMLINK);
$sftp->disableStatCache();
$sftp->nlist();
$stat = $sftp->stat('link.txt');
$this->assertSame($stat['type'], NET_SFTP_TYPE_REGULAR);
$stat = $sftp->lstat('link.txt');
$this->assertSame($stat['type'], NET_SFTP_TYPE_SYMLINK);
$stat = $sftp->stat('linkdir');
$this->assertSame($stat['type'], NET_SFTP_TYPE_DIRECTORY);
$stat = $sftp->lstat('link.txt');
$this->assertSame($stat['type'], NET_SFTP_TYPE_SYMLINK);
$sftp->enableStatCache();
} }
} }