diff --git a/change_log.txt b/change_log.txt index 8c94f131..863bb7a7 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,4 +1,7 @@ ===== trunk ===== +24.05.2012 +- bugfix Smarty_Internal_Write_File::writeFile() could cause race-conditions on linux systems (Issue 101) + 22.05.2012 - bugfix recursive {include} within {section} did fail (Smarty developer group) diff --git a/libs/Smarty.class.php b/libs/Smarty.class.php index e65f4920..9b46a0da 100644 --- a/libs/Smarty.class.php +++ b/libs/Smarty.class.php @@ -190,6 +190,10 @@ class Smarty extends Smarty_Internal_TemplateBase { */ public static $_UTF8_MODIFIER = 'u'; + /** + * Flag denoting if operating system is windows + */ + public static $_IS_WINDOWS = false; /**#@+ * variables @@ -1464,6 +1468,9 @@ class Smarty extends Smarty_Internal_TemplateBase { } } +// Check if we're running on windows +Smarty::$_IS_WINDOWS = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN'; + // let PCRE (preg_*) treat strings as ISO-8859-1 if we're not dealing with UTF-8 if (Smarty::$_CHARSET !== 'UTF-8') { Smarty::$_UTF8_MODIFIER = ''; diff --git a/libs/sysplugins/smarty_internal_write_file.php b/libs/sysplugins/smarty_internal_write_file.php index 2dfb4757..e5d19ce8 100644 --- a/libs/sysplugins/smarty_internal_write_file.php +++ b/libs/sysplugins/smarty_internal_write_file.php @@ -44,12 +44,30 @@ class Smarty_Internal_Write_File { throw new SmartyException("unable to write file {$_tmp_file}"); return false; } + + /* + * Windows' rename() fails if the destination exists, + * Linux' rename() properly handles the overwrite. + * Simply unlink()ing a file might cause other processes + * currently reading that file to fail, but linux' rename() + * seems to be smart enough to handle that for us. + */ + if (Smarty::$_IS_WINDOWS) { + // remove original file + @unlink($_filepath); + // rename tmp file + $success = @rename($_tmp_file, $_filepath); + } else { + // rename tmp file + $success = @rename($_tmp_file, $_filepath); + if (!$success) { + // remove original file + @unlink($_filepath); + // rename tmp file + $success = @rename($_tmp_file, $_filepath); + } + } - // remove original file - @unlink($_filepath); - - // rename tmp file - $success = rename($_tmp_file, $_filepath); if (!$success) { error_reporting($_error_reporting); throw new SmartyException("unable to write file {$_filepath}");