diff --git a/includes/file.inc b/includes/file.inc
index 1e256c6..28cf04c 100644
--- a/includes/file.inc
+++ b/includes/file.inc
@@ -441,8 +441,8 @@ function file_prepare_directory(&$directory, $options = FILE_MODIFY_PERMISSIONS)
   if (!is_dir($directory)) {
     // Let mkdir() recursively create directories and use the default directory
     // permissions.
-    if (($options & FILE_CREATE_DIRECTORY) && @drupal_mkdir($directory, NULL, TRUE)) {
-      return drupal_chmod($directory);
+    if ($options & FILE_CREATE_DIRECTORY) {
+      return @drupal_mkdir($directory, NULL, TRUE);
     }
     return FALSE;
   }
@@ -2334,7 +2334,52 @@ function drupal_mkdir($uri, $mode = NULL, $recursive = FALSE, $context = NULL) {
     $mode = variable_get('file_chmod_directory', 0775);
   }
 
-  if (!isset($context)) {
+  // If the URI has a scheme, don't override the umask - schemes can handle this
+  // issue in their own implementation.
+  if (file_uri_scheme($uri)) {
+    return _drupal_mkdir_call($uri, $mode, $recursive, $context);
+  }
+
+  // If recursive, create each missing component of the parent directory
+  // individually and set the mode explicitly to override the umask.
+  if ($recursive) {
+    $components = explode(DIRECTORY_SEPARATOR, $uri);
+    array_pop($components);
+    $recursive_path = '';
+    foreach ($components as $component) {
+      $recursive_path .= $component;
+
+      if (!file_exists($recursive_path)) {
+        if (!_drupal_mkdir_call($recursive_path, $mode, FALSE, $context)) {
+          return FALSE;
+        }
+        // Not necessary to use drupal_chmod() as there is no scheme.
+        if (!chmod($recursive_path, $mode)) {
+          return FALSE;
+        }
+      }
+
+      $recursive_path .= DIRECTORY_SEPARATOR;
+    }
+  }
+
+  // Do not check if the top-level directory already exists, as this condition
+  // must cause this function to fail.
+  if (!_drupal_mkdir_call($uri, $mode, FALSE, $context)) {
+    return FALSE;
+  }
+  // Not necessary to use drupal_chmod() as there is no scheme.
+  return chmod($uri, $mode);
+}
+
+/**
+ * Helper function. Ensures we don't pass a NULL as a context resource to
+ * mkdir().
+ *
+ * @see drupal_mkdir()
+ */
+function _drupal_mkdir_call($uri, $mode, $recursive, $context) {
+  if (is_null($context)) {
     return mkdir($uri, $mode, $recursive);
   }
   else {
diff --git a/includes/stream_wrappers.inc b/includes/stream_wrappers.inc
index fa401c6..d446194 100644
--- a/includes/stream_wrappers.inc
+++ b/includes/stream_wrappers.inc
@@ -553,7 +553,7 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
    * Support for unlink().
    *
    * @param $uri
-   *   A string containing the URI to the resource to delete.
+   *   A string containing the uri to the resource to delete.
    *
    * @return
    *   TRUE if resource was successfully deleted.
@@ -569,9 +569,9 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
    * Support for rename().
    *
    * @param $from_uri,
-   *   The URI to the file to rename.
+   *   The uri to the file to rename.
    * @param $to_uri
-   *   The new URI for file.
+   *   The new uri for file.
    *
    * @return
    *   TRUE if file was successfully renamed.
@@ -636,10 +636,10 @@ abstract class DrupalLocalStreamWrapper implements DrupalStreamWrapperInterface
       $localpath = $this->getLocalPath($uri);
     }
     if ($options & STREAM_REPORT_ERRORS) {
-      return mkdir($localpath, $mode, $recursive);
+      return drupal_mkdir($localpath, $mode, $recursive);
     }
     else {
-      return @mkdir($localpath, $mode, $recursive);
+      return @drupal_mkdir($localpath, $mode, $recursive);
     }
   }
 
