diff --git a/doc/streams-tutorial.md b/doc/streams-tutorial.md
index 09b21a3..80d1235 100644
--- a/doc/streams-tutorial.md
+++ b/doc/streams-tutorial.md
@@ -220,6 +220,28 @@ The main difference is the creation of `$cxt` using PHP's
take a look at the [PHP documentation](http://us3.php.net/manual/en/book.stream.php)
for streams.
+## Stream Wrapper As A File System
+As it was noted earlier in this tutorial, swift does not support directories.
+Instead the names of a file can be path like with a separator. For example,
+`swiftfs://Example/path/to/my_file.txt` has a name of `path/to/my_file.txt`.
+
+To enable applications to use swift in a more directlry like manner there is a
+second stream wrapper with a prefix `swiftfs://`. swiftfs stands for swift file
+system. It works in a similar manner to to the standard stream wrappers with a
+few key differences:
+
+- mkdir will return TRUE is no objects start with the directory you are trying
+ to crate. Otherwise it will return FALSE.
+- rmdir will return FALSE if any objects start with the directory prefix you are
+ trying to remove. rmdir does not allow you to remove directories with files
+ in them.
+- Running stat on a directory that is a prefix for some objects (e.g.,
+ `swiftfs://Example/path/to/`) will see this is a prefix for a file and treat
+ it as if it were a directory.
+
+To use this stream wrapper instead of the standard swift one simple replace the
+usage of `swift://` with `swiftfs://`.
+
## Summary
This tutorial is focused on using stream wrappers to interact with your
diff --git a/src/HPCloud/Storage/ObjectStorage/StreamWrapperFS.php b/src/HPCloud/Storage/ObjectStorage/StreamWrapperFS.php
index a046256..a9ec5f7 100644
--- a/src/HPCloud/Storage/ObjectStorage/StreamWrapperFS.php
+++ b/src/HPCloud/Storage/ObjectStorage/StreamWrapperFS.php
@@ -23,8 +23,45 @@ SOFTWARE.
* @file
* Contains the stream wrapper for `swiftfs://` URLs.
*
+ * Note, this stream wrapper is in early testing.
+ *
* The stream wrapper implemented in HPCloud\Storage\ObjectStorage\StreamWrapper
- * only supports the elements of a stream
+ * only supports the elements of a stream that are implemented by object
+ * storage. This is how the PHP documentation states a stream wrapper should be
+ * created. Because some features do not exist, attempting to treat a stream
+ * wrapper as if it were a file system will not entirely work. For example,
+ * while there are not directories objects have pathy names (with / separators).
+ * Directory calls to object storage with the default stream wrappers will not
+ * operate how they would for a file system.
+ *
+ * StreamWrapperFS is an attempt to make a filesystem like stream wrapper.
+ * Hence the protocol is swiftfs standing for swift file system.
+ *
+ * To understand how this stream wrapper works start by first reading the
+ * documentation on the HPCloud::Storage::ObjectStorage::StreamWrapper.
+ *
+ * DIRECTORIES
+ *
+ * Because OpenStack Swift does not support directories the swift:// stream
+ * wrapper does not support them. This stream wrapper attempts to fake them by
+ * faking directory stats, mkdir, and rmdir. By default (see the options below
+ * for how to change these) directories have permissions of 777, timestamps
+ * close to that of the request, and the user and group called by php. We mock
+ * these on the fly though information is stored in the PHP stat cache.
+ *
+ * In addition to the parameters supported by StreamWrapper, the following
+ * parameters may be set either in the stream context or through
+ * HPCloud::Bootstrap::setConfiguration():
+ * - swiftfs_fake_stat_mode: Directories don't exist in swift. When stat() is
+ * is called on a directory we mock the stat information so functions like
+ * is_dir will work. The default file permissions is 0777. Though this
+ * parameter you can pass is a different set of file permissions to use
+ * for these mock stats.
+ * - swiftfs_fake_isdir_true: Directory functions like mkdir and is_dir (stat)
+ * check to see if there are objects with the the passed in directory as a
+ * prefix to see if it already exists. If you want is_dir to always return
+ * true even if it is not an existing prefix set this to TRUE. Defaults to
+ * FALSE.
*/
namespace HPCloud\Storage\ObjectStorage;
@@ -55,7 +92,7 @@ class StreamWrapperFS extends StreamWrapper {
*/
public function mkdir($uri, $mode, $options) {
- return !($this->testDirectoryExists($uri));
+ return ($this->cxt('swiftfs_fake_isdir_true', FALSE) || !($this->testDirectoryExists($uri)));
}
@@ -85,7 +122,7 @@ class StreamWrapperFS extends StreamWrapper {
// When FALSE is returned there is no file to stat. So, we attempt to handle
// it like a directory.
else {
- if ($this->testDirectoryExists($path)) {
+ if ($this->cxt('swiftfs_fake_isdir_true', FALSE) || $this->testDirectoryExists($path)) {
// The directory prefix exists. Fake the directory file permissions.
return $this->fakeStat(TRUE);
}
@@ -159,7 +196,7 @@ class StreamWrapperFS extends StreamWrapper {
// Set inode type to directory or file.
$type = $dir ? 040000 : 0100000;
// Fake world-readible
- $mode = $type + 0777;
+ $mode = $type + $this->cxt('swiftfs_fake_stat_mode', 0777);
$values = array(
'dev' => 0,
diff --git a/test/Tests/StreamWrapperFSTest.php b/test/Tests/StreamWrapperFSTest.php
index b239d04..3639e14 100644
--- a/test/Tests/StreamWrapperFSTest.php
+++ b/test/Tests/StreamWrapperFSTest.php
@@ -647,5 +647,4 @@ class StreamWrapperFSTest extends \HPCloud\Tests\TestCase {
$this->assertFalse(rmdir($url, $this->basicSwiftContext()));
}
-
}