今年三月份去腾讯面试过。笔试题有一题是,PHP 中的 is_writable 函数不可信,请写一个函数来替代这个函数。
拿到这个题目,我便想起之前读 CI 框架实现的时候看到 CI 里面写了个 is_really_writable 函数,当时没有注意,只看这个函数的功能,至于 CI 为什么要自己实现一个 is_writable 函数的功能没有去深究。当时,我的解题思路是这样的,既然 is_writable 不可信,那么我就实实在在的尝试去那个文件夹里进行写入,如果可以写则返回 true,否则返回 false,思路是对的,但代码并不是完全无误,有瑕疵。
回到家后我便开始搜索,同时重新仔细查看 CI 的那个函数实现以及说明,原来是因为在 Windows 服务器上如果一个文件夹有只读属性,is_writable 这个函数还是会返回 true,而实际上 php 是不能进行写入的,另外一种情况是,在 unix 服务器上,如果 safe_mode 选项打开,那么 is_writable 函数也是不可信的。
这个事情提醒我,当遇到一个问题时,一定要追查到底,搞明白它的原理以及那样做的理由。
附上 CI 里面 is_really_writable 函数的实现:
function is_really_writable($file) { // If we're on a Unix server with safe_mode off we call is_writable if (DIRECTORY_SEPARATOR == '/' AND @ini_get("safe_mode") == false) { return is_writable($file); } // For windows servers and safe_mode "on" installations we'll actually // write a file then read it. Bah... if (is_dir($file)) { $file = rtrim($file, '/') . '/' . md5(mt_rand(1, 100) . mt_rand(1, 100)); if (($fp = @fopen($file, FOPEN_WRITE_CREATE)) === false) { return false; } fclose($fp); @chmod($file, DIR_WRITE_MODE); @unlink($file); return true; } elseif (!is_file($file) OR ($fp = @fopen($file, FOPEN_WRITE_CREATE)) === false) { return false; } fclose($fp); return true; }