bool c_XSLTProcessor::t_setprofiling(const String& filename) { if (filename.length() > 0) { String translated = File::TranslatePath(filename); Stream::Wrapper* w = Stream::getWrapperFromURI(translated); if (!w) return false; if (w->access(translated, W_OK)) { m_profile = translated; return true; } } return false; }
static bool findFileWrapper(const String& file, void* ctx) { ResolveIncludeContext* context = (ResolveIncludeContext*)ctx; assert(context->path.isNull()); Stream::Wrapper* w = Stream::getWrapperFromURI(file); if (!dynamic_cast<FileStreamWrapper*>(w)) { if (w->stat(file, context->s) == 0) { context->path = file; return true; } } // handle file:// if (file.substr(0, 7) == s_file_url) { return findFileWrapper(file.substr(7), ctx); } // TranslatePath() will canonicalize the path and also check // whether the file is in an allowed directory. String translatedPath = File::TranslatePathKeepRelative(file); if (file[0] != '/') { if (HPHP::Eval::FileRepository::findFile(translatedPath.get(), context->s)) { context->path = translatedPath; return true; } return false; } if (RuntimeOption::SandboxMode || !RuntimeOption::AlwaysUseRelativePath) { if (HPHP::Eval::FileRepository::findFile(translatedPath.get(), context->s)) { context->path = translatedPath; return true; } } string server_root(SourceRootInfo::GetCurrentSourceRoot()); if (server_root.empty()) { server_root = string(g_vmContext->getCwd()->data()); if (server_root.empty() || server_root[server_root.size() - 1] != '/') { server_root += "/"; } } String rel_path(Util::relativePath(server_root, translatedPath.data())); if (HPHP::Eval::FileRepository::findFile(rel_path.get(), context->s)) { context->path = rel_path; return true; } return false; }
Resource File::Open(const String& filename, const String& mode, int options /* = 0 */, const Variant& context /* = null */) { Stream::Wrapper *wrapper = Stream::getWrapperFromURI(filename); if (!wrapper) return Resource(); Resource rcontext = context.isNull() ? g_context->getStreamContext() : context.toResource(); File *file = wrapper->open(filename, mode, options, rcontext); if (file != nullptr) { file->m_name = filename.data(); file->m_mode = mode.data(); file->m_streamContext = rcontext; } return Resource(file); }
static bool HHVM_METHOD(XSLTProcessor, setProfiling, const String& filename) { auto data = Native::data<XSLTProcessorData>(this_); if (filename.length() > 0) { String translated = File::TranslatePath(filename); Stream::Wrapper* w = Stream::getWrapperFromURI(translated); if (!w) return false; if (w->access(translated, W_OK)) { data->m_profile = translated; return true; } } return false; }
PhpFile *FileRepository::checkoutFile(StringData *rname, const struct stat &s) { FileInfo fileInfo; PhpFile *ret = nullptr; String name(rname); bool isPlainFile = File::IsPlainFilePath(name); if (isPlainFile) { if (rname->data()[0] != '/') { name = String(SourceRootInfo::GetCurrentSourceRoot()) + name; } // Get the common fast path out of the way with as little locking // as possible: it's in the map and has not changed on disk ParsedFilesMap::const_accessor acc; if (s_files.find(acc, name.get()) && !acc->second->isChanged(s)) { TRACE(1, "FR fast path hit %s\n", rname->data()); ret = acc->second->getPhpFile(); return ret; } } else { // Do the read before we get the repo lock, since it will call into the // stream library and will needs its own locks. if (isAuthoritativeRepo()) { throw FatalErrorException( "including urls doesn't work in RepoAuthoritative mode" ); } Stream::Wrapper* w = Stream::getWrapperFromURI(name); File* f = w->open(name, "r", 0, null_variant); if (!f) return nullptr; StringBuffer sb; sb.read(f); fileInfo.m_inputString = sb.detach(); computeMd5(name.get(), fileInfo); } TRACE(1, "FR fast path miss: %s\n", rname->data()); const StringData *n = makeStaticString(name.get()); PhpFile* toKill = nullptr; SCOPE_EXIT { // run this after acc is destroyed (and its lock released) if (toKill) toKill->decRefAndDelete(); }; ParsedFilesMap::accessor acc; bool isNew = s_files.insert(acc, n); PhpFileWrapper* old = acc->second; SCOPE_EXIT { // run this just before acc is released if (old && old != acc->second) { if (old->getPhpFile() != acc->second->getPhpFile()) { toKill = old->getPhpFile(); } delete old; } if (!acc->second) s_files.erase(acc); }; assert(isNew || old); // We don't leave null entries around. bool isChanged = !isNew && old->isChanged(s); if (isNew || isChanged) { if (isPlainFile && !readFile(n, s, fileInfo)) { TRACE(1, "File disappeared between stat and FR::readNewFile: %s\n", rname->data()); return nullptr; } ret = fileInfo.m_phpFile; if (isChanged && ret == old->getPhpFile()) { // The file changed but had the same contents. if (debug && md5Enabled()) { ReadLock lock(s_md5Lock); assert(s_md5Files.find(ret->getMd5())->second == ret); } return ret; } } else if (!isNew) { // Somebody might have loaded the file between when we dropped // our read lock and got the write lock ret = old->getPhpFile(); return ret; } // If we get here the file was not in s_files or has changed on disk if (!ret) { // Try to read Unit from .hhbc repo. ret = readHhbc(n->data(), fileInfo); } if (!ret) { if (isAuthoritativeRepo()) { raise_error("Tried to parse %s in repo authoritative mode", n->data()); } ret = parseFile(n->data(), fileInfo); if (!ret) return nullptr; } assert(ret != nullptr); if (isNew) { acc->second = new PhpFileWrapper(s, ret); ret->incRef(); ret->setId(Transl::TargetCache::allocBit()); } else { PhpFile *f = old->getPhpFile(); if (f != ret) { ret->setId(f->getId()); ret->incRef(); } acc->second = new PhpFileWrapper(s, ret); } if (md5Enabled()) { WriteLock lock(s_md5Lock); s_md5Files[ret->getMd5()] = ret; } return ret; }
bool findFileWrapper(const String& file, void* ctx) { auto const context = static_cast<ResolveIncludeContext*>(ctx); assertx(context->path.isNull()); Stream::Wrapper* w = Stream::getWrapperFromURI(file); if (w && !w->isNormalFileStream()) { // Stream wrappers can reenter PHP via user defined callbacks. Roll this // operation into a single event rqtrace::EventGuard trace{"STREAM_WRAPPER_STAT"}; rqtrace::DisableTracing disable; if (w->stat(file, context->s) == 0) { context->path = file; return true; } } // handle file:// if (StringUtil::IsFileUrl(file)) { return findFileWrapper(file.substr(7), ctx); } if (!w) return false; auto passW = RuntimeOption::RepoAuthoritative || dynamic_cast<FileStreamWrapper*>(w) || !w->isNormalFileStream() ? nullptr : w; // TranslatePath() will canonicalize the path and also check // whether the file is in an allowed directory. String translatedPath = File::TranslatePathKeepRelative(file); if (!FileUtil::isAbsolutePath(file.toCppString())) { if (findFile(translatedPath.get(), context->s, context->allow_dir, passW, context->nativeFuncs)) { context->path = translatedPath; return true; } return false; } if (RuntimeOption::SandboxMode || !RuntimeOption::AlwaysUseRelativePath) { if (findFile(translatedPath.get(), context->s, context->allow_dir, passW, context->nativeFuncs)) { context->path = translatedPath; return true; } } std::string server_root(SourceRootInfo::GetCurrentSourceRoot()); if (server_root.empty()) { server_root = std::string(g_context->getCwd().data()); if (server_root.empty() || FileUtil::isDirSeparator(server_root[server_root.size() - 1])) { server_root += FileUtil::getDirSeparator(); } } String rel_path(FileUtil::relativePath(server_root, translatedPath.data())); if (findFile(rel_path.get(), context->s, context->allow_dir, passW, context->nativeFuncs)) { context->path = rel_path; return true; } return false; }