delegate some syscalls to the stream wrappers

Needed for phars. People are doing

  file_exists('phar://a.phar/b.php');

I didn't do all syscalls like `chmod` or `symlink`. Think I should bite the bullet, or do it piecemeal when needed?
Esse commit está contido em:
Paul Tarjan
2013-07-22 23:30:49 -07:00
commit de Sara Golemon
commit 15b04a6097
6 arquivos alterados com 97 adições e 38 exclusões
+2 -1
Ver Arquivo
@@ -123,7 +123,8 @@ bool File::IsPlainFilePath(CStrRef filename) {
Variant File::Open(CStrRef filename, CStrRef mode,
int options /* = 0 */,
CVarRef context /* = null */) {
File *file = Stream::open(filename, mode, options, context);
Stream::Wrapper *wrapper = Stream::getWrapperFromURI(filename);
File *file = wrapper->open(filename, mode, options, context);
if (file != nullptr) {
file->m_name = filename.data();
file->m_mode = mode.data();
+9
Ver Arquivo
@@ -31,6 +31,15 @@ class FileStreamWrapper : public Stream::Wrapper {
static MemFile* openFromCache(CStrRef filename, CStrRef mode);
virtual File* open(CStrRef filename, CStrRef mode,
int options, CVarRef context);
virtual int access(CStrRef path, int mode) {
return ::access(File::TranslatePath(path).data(), mode);
}
virtual int stat(CStrRef path, struct stat* buf) {
return ::stat(File::TranslatePath(path).data(), buf);
}
virtual int lstat(CStrRef path, struct stat* buf) {
return ::lstat(File::TranslatePath(path).data(), buf);
}
};
///////////////////////////////////////////////////////////////////////////////
+9
Ver Arquivo
@@ -33,6 +33,15 @@ class Wrapper : boost::noncopyable {
virtual File* open(CStrRef filename, CStrRef mode,
int options, CVarRef context) = 0;
virtual int access(CStrRef path, int mode) {
return -1;
}
virtual int lstat(CStrRef path, struct stat* buf) {
return -1;
}
virtual int stat(CStrRef path, struct stat* buf) {
return -1;
}
virtual ~Wrapper() {}
};
+14 -12
Ver Arquivo
@@ -176,26 +176,28 @@ Wrapper* getWrapper(CStrRef scheme) {
return nullptr;
}
File* open(CStrRef uri, CStrRef mode, int options, CVarRef context) {
StaticString
s_compress_zlib("compress.zlib"),
s_file("file");
Wrapper* getWrapperFromURI(CStrRef uri) {
const char *uri_string = uri.data();
Wrapper *wrapper = nullptr;
/* Special case for PHP4 Backward Compatability */
if (!strncasecmp(uri_string, "zlib:", sizeof("zlib:") - 1)) {
wrapper = getWrapper("compress.zlib");
} else {
const char *colon = strstr(uri_string, "://");
if (colon) {
wrapper = getWrapper(String(uri_string, colon - uri_string, CopyString));
}
return getWrapper(s_compress_zlib);
}
if (wrapper == nullptr) {
wrapper = getWrapper("file");
const char *colon = strstr(uri_string, "://");
if (!colon) {
return getWrapper(s_file);
}
assert(wrapper);
return wrapper->open(uri, mode, options, context);
int len = colon - uri_string;
if (Wrapper *w = getWrapper(String(uri_string, len, CopyString))) {
return w;
}
return getWrapper(s_file);
}
static FileStreamWrapper s_file_stream_wrapper;
+1 -1
Ver Arquivo
@@ -35,7 +35,7 @@ bool restoreWrapper(CStrRef scheme);
bool registerRequestWrapper(CStrRef scheme, std::unique_ptr<Wrapper> wrapper);
Array enumWrappers();
Wrapper* getWrapper(CStrRef scheme);
File* open(CStrRef uri, CStrRef mode, int options, CVarRef context);
Wrapper* getWrapperFromURI(CStrRef uri);
/* Called during process init to register core wrappers */
void RegisterCoreWrappers();
+62 -24
Ver Arquivo
@@ -29,6 +29,8 @@
#include "hphp/runtime/server/static_content_cache.h"
#include "hphp/runtime/base/zend_scanf.h"
#include "hphp/runtime/base/pipe.h"
#include "hphp/runtime/base/stream_wrapper_registry.h"
#include "hphp/runtime/base/file_stream_wrapper.h"
#include "hphp/system/systemlib.h"
#include "hphp/util/logger.h"
#include "hphp/util/util.h"
@@ -95,6 +97,42 @@ static bool check_error(const char *function, int line, bool ret) {
return ret;
}
static int accessSyscall(
CStrRef path,
int mode,
bool useFileCache = false) {
Stream::Wrapper* w = Stream::getWrapperFromURI(path);
if (useFileCache && dynamic_cast<FileStreamWrapper*>(w)) {
// This if block is needed for useFileCache
return ::access(File::TranslatePath(path, useFileCache).data(), mode);
}
return w->access(path, mode);
}
static int statSyscall(
CStrRef path,
struct stat* buf,
bool useFileCache = false) {
Stream::Wrapper* w = Stream::getWrapperFromURI(path);
if (useFileCache && dynamic_cast<FileStreamWrapper*>(w)) {
// This if block is needed for useFileCache
return ::stat(File::TranslatePath(path, useFileCache).data(), buf);
}
return w->stat(path, buf);
}
static int lstatSyscall(
CStrRef path,
struct stat* buf,
bool useFileCache = false) {
Stream::Wrapper* w = Stream::getWrapperFromURI(path);
if (useFileCache && dynamic_cast<FileStreamWrapper*>(w)) {
// This if block is needed for useFileCache
return ::lstat(File::TranslatePath(path, useFileCache).data(), buf);
}
return w->lstat(path, buf);
}
const StaticString
s_dev("dev"),
s_ino("ino"),
@@ -580,13 +618,13 @@ Variant f_sha1_file(CStrRef filename, bool raw_output /* = false */) {
Variant f_fileperms(CStrRef filename) {
struct stat sb;
CHECK_SYSTEM(stat(File::TranslatePath(filename, true).data(), &sb));
CHECK_SYSTEM(statSyscall(filename, &sb, true));
return (int64_t)sb.st_mode;
}
Variant f_fileinode(CStrRef filename) {
struct stat sb;
CHECK_SYSTEM(stat(File::TranslatePath(filename).data(), &sb));
CHECK_SYSTEM(statSyscall(filename, &sb));
return (int64_t)sb.st_ino;
}
@@ -598,43 +636,43 @@ Variant f_filesize(CStrRef filename) {
if (size >= 0) return size;
}
struct stat sb;
CHECK_SYSTEM(stat(File::TranslatePath(filename, true).data(), &sb));
CHECK_SYSTEM(statSyscall(filename, &sb, true));
return (int64_t)sb.st_size;
}
Variant f_fileowner(CStrRef filename) {
struct stat sb;
CHECK_SYSTEM(stat(File::TranslatePath(filename, true).data(), &sb));
CHECK_SYSTEM(statSyscall(filename, &sb, true));
return (int64_t)sb.st_uid;
}
Variant f_filegroup(CStrRef filename) {
struct stat sb;
CHECK_SYSTEM(stat(File::TranslatePath(filename, true).data(), &sb));
CHECK_SYSTEM(statSyscall(filename, &sb, true));
return (int64_t)sb.st_gid;
}
Variant f_fileatime(CStrRef filename) {
struct stat sb;
CHECK_SYSTEM(stat(File::TranslatePath(filename, true).data(), &sb));
CHECK_SYSTEM(statSyscall(filename, &sb, true));
return (int64_t)sb.st_atime;
}
Variant f_filemtime(CStrRef filename) {
struct stat sb;
CHECK_SYSTEM(stat(File::TranslatePath(filename, true).data(), &sb));
CHECK_SYSTEM(statSyscall(filename, &sb, true));
return (int64_t)sb.st_mtime;
}
Variant f_filectime(CStrRef filename) {
struct stat sb;
CHECK_SYSTEM(stat(File::TranslatePath(filename, true).data(), &sb));
CHECK_SYSTEM(statSyscall(filename, &sb, true));
return (int64_t)sb.st_ctime;
}
Variant f_filetype(CStrRef filename) {
struct stat sb;
CHECK_SYSTEM(lstat(File::TranslatePath(filename).data(), &sb));
CHECK_SYSTEM(lstatSyscall(filename, &sb));
switch (sb.st_mode & S_IFMT) {
case S_IFLNK: return "link";
@@ -650,16 +688,16 @@ Variant f_filetype(CStrRef filename) {
Variant f_linkinfo(CStrRef filename) {
struct stat sb;
CHECK_SYSTEM(stat(File::TranslatePath(filename).data(), &sb));
CHECK_SYSTEM(statSyscall(filename, &sb));
return (int64_t)sb.st_dev;
}
bool f_is_writable(CStrRef filename) {
struct stat sb;
if (stat(File::TranslatePath(filename).data(), &sb)) {
if (statSyscall(filename, &sb)) {
return false;
}
CHECK_SYSTEM(access(File::TranslatePath(filename).data(), W_OK));
CHECK_SYSTEM(accessSyscall(filename, W_OK));
return true;
/*
int mask = S_IWOTH;
@@ -691,8 +729,8 @@ bool f_is_writeable(CStrRef filename) {
bool f_is_readable(CStrRef filename) {
struct stat sb;
CHECK_SYSTEM(stat(File::TranslatePath(filename, true).data(), &sb));
CHECK_SYSTEM(access(File::TranslatePath(filename, true).data(), R_OK));
CHECK_SYSTEM(statSyscall(filename, &sb, true));
CHECK_SYSTEM(accessSyscall(filename, R_OK, true));
return true;
/*
int mask = S_IROTH;
@@ -720,8 +758,8 @@ bool f_is_readable(CStrRef filename) {
bool f_is_executable(CStrRef filename) {
struct stat sb;
CHECK_SYSTEM(stat(File::TranslatePath(filename).data(), &sb));
CHECK_SYSTEM(access(File::TranslatePath(filename).data(), X_OK));
CHECK_SYSTEM(statSyscall(filename, &sb));
CHECK_SYSTEM(accessSyscall(filename, X_OK));
return true;
/*
int mask = S_IXOTH;
@@ -749,7 +787,7 @@ bool f_is_executable(CStrRef filename) {
bool f_is_file(CStrRef filename) {
struct stat sb;
CHECK_SYSTEM(stat(File::TranslatePath(filename, true).data(), &sb));
CHECK_SYSTEM(statSyscall(filename, &sb, true));
return (sb.st_mode & S_IFMT) == S_IFREG;
}
@@ -767,13 +805,13 @@ bool f_is_dir(CStrRef filename) {
}
struct stat sb;
CHECK_SYSTEM(stat(File::TranslatePath(filename).data(), &sb));
CHECK_SYSTEM(statSyscall(filename, &sb));
return (sb.st_mode & S_IFMT) == S_IFDIR;
}
bool f_is_link(CStrRef filename) {
struct stat sb;
CHECK_SYSTEM(lstat(File::TranslatePath(filename).data(), &sb));
CHECK_SYSTEM(lstatSyscall(filename, &sb));
return (sb.st_mode & S_IFMT) == S_IFLNK;
}
@@ -787,7 +825,7 @@ bool f_is_uploaded_file(CStrRef filename) {
bool f_file_exists(CStrRef filename) {
if (filename.empty() ||
(access(File::TranslatePath(filename, true).data(), F_OK)) < 0) {
(accessSyscall(filename, F_OK, true)) < 0) {
return false;
}
return true;
@@ -795,13 +833,13 @@ bool f_file_exists(CStrRef filename) {
Variant f_stat(CStrRef filename) {
struct stat sb;
CHECK_SYSTEM(stat(File::TranslatePath(filename, true).data(), &sb));
CHECK_SYSTEM(statSyscall(filename, &sb, true));
return stat_impl(&sb);
}
Variant f_lstat(CStrRef filename) {
struct stat sb;
CHECK_SYSTEM(lstat(File::TranslatePath(filename, true).data(), &sb));
CHECK_SYSTEM(lstatSyscall(filename, &sb, true));
return stat_impl(&sb);
}
@@ -837,7 +875,7 @@ Variant f_realpath(CStrRef path) {
StaticContentCache::TheFileCache->exists(translated.data(), false)) {
return translated;
}
if (access(translated.c_str(), F_OK) == 0) {
if (accessSyscall(path, F_OK) == 0) {
char resolved_path[PATH_MAX];
if (!realpath(translated.c_str(), resolved_path)) {
return false;
@@ -1005,7 +1043,7 @@ bool f_touch(CStrRef filename, int64_t mtime /* = 0 */, int64_t atime /* = 0 */)
String translated = File::TranslatePath(filename);
/* create the file if it doesn't exist already */
if (access(translated.data(), F_OK)) {
if (accessSyscall(translated, F_OK)) {
FILE *f = fopen(translated.data(), "w");
if (f == NULL) {
Logger::Verbose("%s/%d: Unable to create file %s because %s",