Browse Source

FileCache: rebuild cache file before touch when different file owner (#16120)

* Test Travis envs

* The fix

* posix_geteuid only exists on Linux

* Added PR to changelog
tags/2.0.16
Filippo Tessarotto 7 years ago committed by Dmitry Naumenko
parent
commit
4f41d1118c
  1. 4
      .travis.yml
  2. 1
      framework/CHANGELOG.md
  3. 6
      framework/caching/FileCache.php
  4. 35
      tests/framework/caching/FileCacheTest.php

4
.travis.yml

@ -32,6 +32,7 @@ env:
- TASK_TESTS_PHP=1 - TASK_TESTS_PHP=1
- TASK_TESTS_JS=0 - TASK_TESTS_JS=0
- TASK_TESTS_COVERAGE=0 - TASK_TESTS_COVERAGE=0
- TRAVIS_SECOND_USER=travis_two
services: services:
@ -147,6 +148,9 @@ install:
travis_retry npm install travis_retry npm install
fi fi
# Needed for FileCacheTest
- sudo useradd $TRAVIS_SECOND_USER --gid $(id -g) -M
before_script: before_script:
# #
# Disable: # Disable:

1
framework/CHANGELOG.md

@ -10,6 +10,7 @@ Yii Framework 2 Change Log
- Bug #15988: Fixed bash completion (alekciy) - Bug #15988: Fixed bash completion (alekciy)
- Bug #15117: Fixed `yii\db\Schema::getTableMetadata` cache refreshing (boboldehampsink) - Bug #15117: Fixed `yii\db\Schema::getTableMetadata` cache refreshing (boboldehampsink)
- Bug #16073: Fixed regression in Oracle `IN` condition builder for more than 1000 items (cebe) - Bug #16073: Fixed regression in Oracle `IN` condition builder for more than 1000 items (cebe)
- Bug #16120: FileCache: rebuild cache file before touch when different file owner (Slamdunk)
2.0.15.1 March 21, 2018 2.0.15.1 March 21, 2018

6
framework/caching/FileCache.php

@ -141,6 +141,12 @@ class FileCache extends Cache
if ($this->directoryLevel > 0) { if ($this->directoryLevel > 0) {
@FileHelper::createDirectory(dirname($cacheFile), $this->dirMode, true); @FileHelper::createDirectory(dirname($cacheFile), $this->dirMode, true);
} }
// If ownership differs the touch call will fail, so we try to
// rebuild the file from scratch by deleting it first
// https://github.com/yiisoft/yii2/pull/16120
if (is_file($cacheFile) && function_exists('posix_geteuid') && fileowner($cacheFile) !== posix_geteuid()) {
@unlink($cacheFile);
}
if (@file_put_contents($cacheFile, $value, LOCK_EX) !== false) { if (@file_put_contents($cacheFile, $value, LOCK_EX) !== false) {
if ($this->fileMode !== null) { if ($this->fileMode !== null) {
@chmod($cacheFile, $this->fileMode); @chmod($cacheFile, $this->fileMode);

35
tests/framework/caching/FileCacheTest.php

@ -52,4 +52,39 @@ class FileCacheTest extends CacheTestCase
static::$time++; static::$time++;
$this->assertFalse($cache->get('expire_testa')); $this->assertFalse($cache->get('expire_testa'));
} }
public function testCacheRenewalOnDifferentOwnership()
{
$TRAVIS_SECOND_USER = getenv('TRAVIS_SECOND_USER');
if (empty($TRAVIS_SECOND_USER)) {
$this->markTestSkipped('Travis second user not found');
}
$cache = $this->getCacheInstance();
$cacheValue = uniqid('value_');
$cachePublicKey = uniqid('key_');
$cacheInternalKey = $cache->buildKey($cachePublicKey);
static::$time = \time();
$this->assertTrue($cache->set($cachePublicKey, $cacheValue, 2));
$this->assertSame($cacheValue, $cache->get($cachePublicKey));
$refClass = new \ReflectionClass($cache);
$refMethodGetCacheFile = $refClass->getMethod('getCacheFile');
$refMethodGetCacheFile->setAccessible(true);
$cacheFile = $refMethodGetCacheFile->invoke($cache, $cacheInternalKey);
$refMethodGetCacheFile->setAccessible(false);
$output = array();
$returnVar = null;
exec(sprintf('sudo chown %s %s',
escapeshellarg($TRAVIS_SECOND_USER),
escapeshellarg($cacheFile)
), $output, $returnVar);
$this->assertSame(0, $returnVar, 'Cannot change ownership of cache file to test cache renewal');
$this->assertTrue($cache->set($cachePublicKey, uniqid('value_2_'), 2), 'Cannot rebuild cache on different file ownership');
}
} }

Loading…
Cancel
Save