diff --git a/core/includes/file.inc b/core/includes/file.inc
index baaf6547ef85c906e42b0646fc765de0a0c56b2a..f141cc81d714afd354f17f076ffaed2c91981d84 100644
--- a/core/includes/file.inc
+++ b/core/includes/file.inc
@@ -1344,18 +1344,8 @@ function drupal_chmod($uri, $mode = NULL) {
     }
   }
 
-  // If this URI is a stream, pass it off to the appropriate stream wrapper.
-  // Otherwise, attempt PHP's chmod. This allows use of drupal_chmod even
-  // for unmanaged files outside of the stream wrapper interface.
-  if ($wrapper = file_stream_wrapper_get_instance_by_uri($uri)) {
-    if ($wrapper->chmod($mode)) {
-      return TRUE;
-    }
-  }
-  else {
-    if (@chmod($uri, $mode)) {
-      return TRUE;
-    }
+  if (@chmod($uri, $mode)) {
+    return TRUE;
   }
 
   watchdog('file', 'The file permissions could not be set on %uri.', array('%uri' => $uri), WATCHDOG_ERROR);
diff --git a/core/lib/Drupal/Core/StreamWrapper/LocalReadOnlyStream.php b/core/lib/Drupal/Core/StreamWrapper/LocalReadOnlyStream.php
index 2a549eab0413d09cf7be367a3eef631e1c32f351..b4aede327d8ecf9c45c12b30103ea150a6948620 100644
--- a/core/lib/Drupal/Core/StreamWrapper/LocalReadOnlyStream.php
+++ b/core/lib/Drupal/Core/StreamWrapper/LocalReadOnlyStream.php
@@ -127,6 +127,16 @@ public function stream_flush() {
     return FALSE;
   }
 
+  /**
+   * {@inheritdoc}
+   *
+   * Does not change meta data as this is a read-only stream wrapper.
+   */
+  public function stream_metadata($uri, $option, $value) {
+    trigger_error('stream_metadata() not supported for read-only stream wrappers', E_USER_WARNING);
+    return FALSE;
+  }
+
   /**
    * Support for unlink().
    *
@@ -209,19 +219,4 @@ public function rmdir($uri, $options) {
     return FALSE;
   }
 
-  /**
-   * Support for chmod().
-   *
-   * Does not change file permissions as this is a read-only stream wrapper.
-   *
-   * @param int $mode
-   *   Permission flags - see chmod().
-   *
-   * @return bool
-   *   FALSE as the permission change will never be allowed.
-   */
-  public function chmod($mode) {
-    trigger_error('chmod() not supported for read-only stream wrappers', E_USER_WARNING);
-    return FALSE;
-  }
 }
diff --git a/core/lib/Drupal/Core/StreamWrapper/LocalStream.php b/core/lib/Drupal/Core/StreamWrapper/LocalStream.php
index 5c1ee6f43e9f31dacfb014a399e748418746a32b..86d0e63c97218e950ec76ed19976c358e20f7482 100644
--- a/core/lib/Drupal/Core/StreamWrapper/LocalStream.php
+++ b/core/lib/Drupal/Core/StreamWrapper/LocalStream.php
@@ -125,17 +125,6 @@ static function getMimeType($uri, $mapping = NULL) {
     return 'application/octet-stream';
   }
 
-  /**
-   * Implements Drupal\Core\StreamWrapper\StreamWrapperInterface::chmod().
-   */
-  function chmod($mode) {
-    $output = @chmod($this->getLocalPath(), $mode);
-    // We are modifying the underlying file here, so we have to clear the stat
-    // cache so that PHP understands that URI has changed too.
-    clearstatcache(TRUE, $this->getLocalPath());
-    return $output;
-  }
-
   /**
    * Implements Drupal\Core\StreamWrapper\StreamWrapperInterface::realpath().
    */
@@ -354,6 +343,34 @@ public function stream_cast($cast_as) {
     return false;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function stream_metadata($uri, $option, $value) {
+    $target = $this->getLocalPath($uri);
+    $return = FALSE;
+    switch ($option) {
+      case STREAM_META_TOUCH:
+        if (!empty($value)) {
+          $return = touch($target, $value[0], $value[1]);
+        }
+        else {
+          $return = touch($target);
+        }
+        break;
+
+      case STREAM_META_ACCESS:
+        $return = chmod($target, $value);
+        break;
+    }
+    if ($return) {
+      // For convenience clear the file status cache of the underlying file,
+      // since metadata operations are often followed by file status checks.
+      clearstatcache(TRUE, $target);
+    }
+    return $return;
+  }
+
   /**
    * Support for unlink().
    *
diff --git a/core/lib/Drupal/Core/StreamWrapper/PhpStreamWrapperInterface.php b/core/lib/Drupal/Core/StreamWrapper/PhpStreamWrapperInterface.php
index fad393fb00119e2d6f1ca39227fd80e12701f4fe..ba19159c0916a31230877bc14bc3b5e99d0c6a3d 100644
--- a/core/lib/Drupal/Core/StreamWrapper/PhpStreamWrapperInterface.php
+++ b/core/lib/Drupal/Core/StreamWrapper/PhpStreamWrapperInterface.php
@@ -23,6 +23,39 @@ public function stream_seek($offset, $whence);
   public function stream_flush();
   public function stream_tell();
   public function stream_stat();
+
+  /**
+   * Sets metadata on the stream.
+   *
+   * @param string $uri
+   *   A string containing the URI to the file to set metadata on.
+   * @param int $option
+   *   One of:
+   *   - STREAM_META_TOUCH: The method was called in response to touch().
+   *   - STREAM_META_OWNER_NAME: The method was called in response to chown()
+   *     with string parameter.
+   *   - STREAM_META_OWNER: The method was called in response to chown().
+   *   - STREAM_META_GROUP_NAME: The method was called in response to chgrp().
+   *   - STREAM_META_GROUP: The method was called in response to chgrp().
+   *   - STREAM_META_ACCESS: The method was called in response to chmod().
+   * @param mixed $value
+   *   If option is:
+   *   - STREAM_META_TOUCH: Array consisting of two arguments of the touch()
+   *     function.
+   *   - STREAM_META_OWNER_NAME or STREAM_META_GROUP_NAME: The name of the owner
+   *     user/group as string.
+   *   - STREAM_META_OWNER or STREAM_META_GROUP: The value of the owner
+   *     user/group as integer.
+   *   - STREAM_META_ACCESS: The argument of the chmod() as integer.
+   *
+   * @return bool
+   *   Returns TRUE on success or FALSE on failure. If $option is not
+   *   implemented, FALSE should be returned.
+   *
+   * @see http://www.php.net/manual/streamwrapper.stream-metadata.php
+   */
+  public function stream_metadata($uri, $option, $value);
+
   public function unlink($uri);
   public function rename($from_uri, $to_uri);
   public function mkdir($uri, $mode, $options);
diff --git a/core/lib/Drupal/Core/StreamWrapper/ReadOnlyStream.php b/core/lib/Drupal/Core/StreamWrapper/ReadOnlyStream.php
index 612545549b64dda856cdfc9d48f465a90f437877..c45ef6ecaac99d16ef2f1e888d1dc75d1004b067 100644
--- a/core/lib/Drupal/Core/StreamWrapper/ReadOnlyStream.php
+++ b/core/lib/Drupal/Core/StreamWrapper/ReadOnlyStream.php
@@ -161,6 +161,16 @@ public function stream_flush() {
     return FALSE;
   }
 
+  /**
+   * {@inheritdoc}
+   *
+   * Does not change meta data as this is a read-only stream wrapper.
+   */
+  public function stream_metadata($uri, $option, $value) {
+    trigger_error('stream_metadata() not supported for read-only stream wrappers', E_USER_WARNING);
+    return FALSE;
+  }
+
   /**
    * Support for unlink().
    *
@@ -243,19 +253,4 @@ public function rmdir($uri, $options) {
     return FALSE;
   }
 
-  /**
-   * Support for chmod().
-   *
-   * Does not change file permissions as this is a read-only stream wrapper.
-   *
-   * @param int $mode
-   *   Permission flags - see chmod().
-   *
-   * @return bool
-   *   FALSE as the permission change will never be allowed.
-   */
-  public function chmod($mode) {
-    trigger_error('chmod() not supported for read-only stream wrappers', E_USER_WARNING);
-    return FALSE;
-  }
 }
diff --git a/core/lib/Drupal/Core/StreamWrapper/StreamWrapperInterface.php b/core/lib/Drupal/Core/StreamWrapper/StreamWrapperInterface.php
index 9830a012a1b07fd1062d7dcb5e7c0df7d52cdc7d..11ad30d9175bfb4e9b179dd135eb90b93d418828 100644
--- a/core/lib/Drupal/Core/StreamWrapper/StreamWrapperInterface.php
+++ b/core/lib/Drupal/Core/StreamWrapper/StreamWrapperInterface.php
@@ -77,21 +77,6 @@ public function getExternalUrl();
    */
   public static function getMimeType($uri, $mapping = NULL);
 
-  /**
-   * Changes permissions of the resource.
-   *
-   * PHP lacks this functionality and it is not part of the official stream
-   * wrapper interface. This is a custom implementation for Drupal.
-   *
-   * @param int $mode
-   *   Integer value for the permissions. Consult PHP chmod() documentation
-   *   for more information.
-   *
-   * @return bool
-   *   Returns TRUE on success or FALSE on failure.
-   */
-  public function chmod($mode);
-
   /**
    * Returns canonical, absolute path of the resource.
    *