Skip to content

Commit

Permalink
Hooked stream_metadata(..) on touch(..)
Browse files Browse the repository at this point in the history
Summary: #3687

When `touch(..)` is passed a path that denotes a user file, call `stream_metadata(..)` (if implemented) in the registered class.

Reviewed By: @ptarjan

Differential Revision: D1550205
  • Loading branch information
AlphaStream authored and hhvm-bot committed Sep 17, 2014
1 parent abfcbff commit 1f55a08
Show file tree
Hide file tree
Showing 9 changed files with 117 additions and 0 deletions.
26 changes: 26 additions & 0 deletions hphp/runtime/base/user-file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ StaticString s_stream_flush("stream_flush");
StaticString s_stream_truncate("stream_truncate");
StaticString s_stream_lock("stream_lock");
StaticString s_stream_stat("stream_stat");
StaticString s_stream_metadata("stream_metadata");
StaticString s_url_stat("url_stat");
StaticString s_unlink("unlink");
StaticString s_rename("rename");
Expand All @@ -69,6 +70,8 @@ UserFile::UserFile(Class *cls, const Variant& context /*= null */) : UserFSNode(
m_Rename = lookupMethod(s_rename.get());
m_Mkdir = lookupMethod(s_mkdir.get());
m_Rmdir = lookupMethod(s_rmdir.get());
m_StreamMetadata = lookupMethod(s_stream_metadata.get());

m_isLocal = true;

// UserFile, to match Zend, should not call stream_close() unless it was ever
Expand Down Expand Up @@ -492,5 +495,28 @@ bool UserFile::rmdir(const String& filename, int options) {
return false;
}

bool UserFile::touch(const String& path, int64_t mtime, int64_t atime) {
if (atime == 0) {
atime = mtime;
}
bool invoked = false;
Variant ret = invoke(
m_StreamMetadata,
s_stream_metadata,
PackedArrayInit(3)
.append(path)
.append(1) // STREAM_META_TOUCH
.append(atime ? make_packed_array(mtime, atime) : Array::Create())
.toArray(),
invoked
);
if (invoked && (ret.toBoolean() == true)) {
return true;
}

raise_warning("\"%s::touch\" call failed", m_cls->name()->data());
return false;
}

///////////////////////////////////////////////////////////////////////////////
}
2 changes: 2 additions & 0 deletions hphp/runtime/base/user-file.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class UserFile : public File, public UserFSNode {
bool rename(const String& oldname, const String& newname);
bool mkdir(const String& path, int mode, int options);
bool rmdir(const String& path, int options);
bool touch(const String& path, int64_t mtime, int64_t atime);

private:
int urlStat(const String& path, struct stat* stat_sb, int flags = 0);
Expand All @@ -78,6 +79,7 @@ class UserFile : public File, public UserFSNode {
const Func* m_StreamTruncate;
const Func* m_StreamLock;
const Func* m_StreamStat;
const Func* m_StreamMetadata;
const Func* m_UrlStat;
const Func* m_Unlink;
const Func* m_Rename;
Expand Down
7 changes: 7 additions & 0 deletions hphp/runtime/base/user-stream-wrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,5 +92,12 @@ Directory* UserStreamWrapper::opendir(const String& path) {
return dir;
}

bool UserStreamWrapper::touch(const String& path,
int64_t mtime, int64_t atime) {
auto file = NEWOBJ(UserFile)(m_cls);
Resource wrapper(file);
return file->touch(path, mtime, atime);
}

///////////////////////////////////////////////////////////////////////////////
}
1 change: 1 addition & 0 deletions hphp/runtime/base/user-stream-wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ struct UserStreamWrapper final : Stream::Wrapper {
int mkdir(const String& path, int mode, int options) override;
int rmdir(const String& path, int options) override;
Directory* opendir(const String& path) override;
bool touch(const String& path, int64_t mtime, int64_t atime);

private:
String m_name;
Expand Down
10 changes: 10 additions & 0 deletions hphp/runtime/ext/ext_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "hphp/runtime/base/thread-info.h"
#include "hphp/runtime/base/stat-cache.h"
#include "hphp/runtime/base/string-util.h"
#include "hphp/runtime/base/user-stream-wrapper.h"
#include "hphp/system/constants.h"
#include "hphp/system/systemlib.h"
#include "hphp/util/logger.h"
Expand All @@ -58,6 +59,7 @@
#include <boost/algorithm/string/predicate.hpp>
#include <vector>


#define CHECK_HANDLE_BASE(handle, f, ret) \
File *f = handle.getTyped<File>(true, true); \
if (f == nullptr || f->isClosed()) { \
Expand Down Expand Up @@ -1172,6 +1174,14 @@ bool f_lchgrp(const String& filename, const Variant& group) {
bool f_touch(const String& filename, int64_t mtime /* = 0 */,
int64_t atime /* = 0 */) {
CHECK_PATH_FALSE(filename, 1);

// If filename points to a user file, invoke UserStreamWrapper::touch(..)
Stream::Wrapper* w = Stream::getWrapperFromURI(filename);
auto usw = dynamic_cast<UserStreamWrapper*>(w);
if (usw != nullptr) {
return usw->touch(filename, mtime, atime);
}

String translated = File::TranslatePath(filename);

/* create the file if it doesn't exist already */
Expand Down
4 changes: 4 additions & 0 deletions hphp/test/slow/streams/stream_wrapper_register.php
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,11 @@ public function url_stat($path, $flags) {
unlink('abc://d');
is_file('abc://e');
is_link('abc://f');

touch('abc://g');
touch('abc://g', 15);
touch('abc://g', 15, 25);

mkdir('abc://dir', 0755, true);
rmdir('abc://dir');
rename('abc://dir', 'abc://dir2');
56 changes: 56 additions & 0 deletions hphp/test/slow/streams/stream_wrapper_register.php.expect
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,62 @@ array(0) {
string(11) "__construct"
array(0) {
}
string(15) "stream_metadata"
array(3) {
[0]=>
string(7) "abc://g"
[1]=>
int(1)
[2]=>
array(0) {
}
}
string(10) "__destruct"
array(0) {
}
string(11) "__construct"
array(0) {
}
string(15) "stream_metadata"
array(3) {
[0]=>
string(7) "abc://g"
[1]=>
int(1)
[2]=>
array(2) {
[0]=>
int(15)
[1]=>
int(15)
}
}
string(10) "__destruct"
array(0) {
}
string(11) "__construct"
array(0) {
}
string(15) "stream_metadata"
array(3) {
[0]=>
string(7) "abc://g"
[1]=>
int(1)
[2]=>
array(2) {
[0]=>
int(15)
[1]=>
int(25)
}
}
string(10) "__destruct"
array(0) {
}
string(11) "__construct"
array(0) {
}
string(5) "mkdir"
array(3) {
[0]=>
Expand Down
9 changes: 9 additions & 0 deletions hphp/test/slow/streams/stream_wrapper_register_2.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

class B {

}

stream_wrapper_register("cde", "B") or die("Failed to register protocol");

touch('cde://g');
2 changes: 2 additions & 0 deletions hphp/test/slow/streams/stream_wrapper_register_2.php.expectf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

Warning: "B::touch" call failed in %s on line %d

0 comments on commit 1f55a08

Please sign in to comment.