 core/includes/common.inc                           |    8 +-
 core/includes/file.inc                             |  431 +++++++-------------
 core/modules/color/color.module                    |    2 +-
 .../lib/Drupal/image/Tests/ImageDimensionsTest.php |    2 +-
 .../image/Tests/ImageStylesPathAndUrlTest.php      |    2 +-
 .../Drupal/image/Tests/ImageThemeFunctionTest.php  |    4 +-
 core/modules/system/image.gd.inc                   |    2 +-
 .../lib/Drupal/system/Tests/File/CopyTest.php      |   73 ++--
 .../lib/Drupal/system/Tests/File/DirectoryTest.php |   52 +--
 .../lib/Drupal/system/Tests/File/DownloadTest.php  |    2 +-
 .../lib/Drupal/system/Tests/File/MoveTest.php      |  146 +++----
 .../lib/Drupal/system/Tests/File/SaveDataTest.php  |   29 +-
 .../Drupal/system/Tests/File/SaveUploadTest.php    |   59 +--
 .../Drupal/system/Tests/File/UnmanagedCopyTest.php |   35 +-
 .../Drupal/system/Tests/File/UnmanagedMoveTest.php |   32 +-
 .../system/Tests/File/UnmanagedSaveDataTest.php    |    2 +-
 .../lib/Drupal/system/Tests/Image/FileMoveTest.php |    7 +-
 core/modules/system/system.module                  |   21 +-
 .../tests/modules/file_test/file_test.module       |   12 +-
 core/modules/update/update.manager.inc             |    4 +-
 .../user/lib/Drupal/user/UserStorageController.php |    2 +-
 core/modules/user/user.module                      |   16 -
 22 files changed, 364 insertions(+), 579 deletions(-)

diff --git a/core/includes/common.inc b/core/includes/common.inc
index 838f228..1d07497 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -3260,7 +3260,7 @@ function drupal_build_css_cache($css) {
     $uri = $csspath . '/' . $filename;
     // Create the CSS file.
     file_prepare_directory($csspath, FILE_CREATE_DIRECTORY);
-    if (!file_exists($uri) && !file_unmanaged_save_data($data, $uri, FILE_EXISTS_REPLACE)) {
+    if (!file_exists($uri) && !file_unmanaged_save_data($data, $uri, FILE_CHECK_EXISTS_FALSE)) {
       return FALSE;
     }
     // If CSS gzip compression is enabled and the zlib extension is available
@@ -3272,7 +3272,7 @@ function drupal_build_css_cache($css) {
     // aren't working can set css_gzip_compression to FALSE in order to skip
     // generating a file that won't be used.
     if (variable_get('css_gzip_compression', TRUE) && extension_loaded('zlib')) {
-      if (!file_exists($uri . '.gz') && !file_unmanaged_save_data(gzencode($data, 9, FORCE_GZIP), $uri . '.gz', FILE_EXISTS_REPLACE)) {
+      if (!file_exists($uri . '.gz') && !file_unmanaged_save_data(gzencode($data, 9, FORCE_GZIP), $uri . '.gz', FILE_CHECK_EXISTS_FALSE)) {
         return FALSE;
       }
     }
@@ -4767,7 +4767,7 @@ function drupal_build_js_cache($files) {
     $uri = $jspath . '/' . $filename;
     // Create the JS file.
     file_prepare_directory($jspath, FILE_CREATE_DIRECTORY);
-    if (!file_exists($uri) && !file_unmanaged_save_data($contents, $uri, FILE_EXISTS_REPLACE)) {
+    if (!file_exists($uri) && !file_unmanaged_save_data($contents, $uri, FILE_CHECK_EXISTS_FALSE)) {
       return FALSE;
     }
     // If JS gzip compression is enabled and the zlib extension is available
@@ -4779,7 +4779,7 @@ function drupal_build_js_cache($files) {
     // aren't working can set js_gzip_compression to FALSE in order to skip
     // generating a file that won't be used.
     if (variable_get('js_gzip_compression', TRUE) && extension_loaded('zlib')) {
-      if (!file_exists($uri . '.gz') && !file_unmanaged_save_data(gzencode($contents, 9, FORCE_GZIP), $uri . '.gz', FILE_EXISTS_REPLACE)) {
+      if (!file_exists($uri . '.gz') && !file_unmanaged_save_data(gzencode($contents, 9, FORCE_GZIP), $uri . '.gz', FILE_CHECK_EXISTS_FALSE)) {
         return FALSE;
       }
     }
diff --git a/core/includes/file.inc b/core/includes/file.inc
index 133d64f..82c79d1 100644
--- a/core/includes/file.inc
+++ b/core/includes/file.inc
@@ -8,6 +8,7 @@
 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
 use Symfony\Component\HttpFoundation\StreamedResponse;
+use Drupal\entity\EntityFieldQuery;
 use Drupal\Core\StreamWrapper\LocalStream;
 use Drupal\Core\File\File;
 
@@ -114,19 +115,19 @@ const FILE_CREATE_DIRECTORY = 1;
 const FILE_MODIFY_PERMISSIONS = 2;
 
 /**
- * Flag for dealing with existing files: Appends number until name is unique.
+ * Flag for dealing with existing files: Don't check.
  */
-const FILE_EXISTS_RENAME = 0;
+const FILE_CHECK_EXISTS_FALSE = 0;
 
 /**
- * Flag for dealing with existing files: Replace the existing file.
+ * Flag for dealing with existing files: Only check filesystem.
  */
-const FILE_EXISTS_REPLACE = 1;
+const FILE_CHECK_EXISTS_FS = 1;
 
 /**
- * Flag for dealing with existing files: Do nothing and return FALSE.
+ * Flag for dealing with existing files: Check database, then filesystem.
  */
-const FILE_EXISTS_ERROR = 2;
+const FILE_CHECK_EXISTS_DB_FS = 2;
 
 /**
  * Indicates that the file is permanent and should not be deleted.
@@ -758,8 +759,6 @@ function file_usage_delete(File $file, $module, $type = NULL, $id = NULL, $count
  * - Checks if $source and $destination are valid and readable/writable.
  * - Checks that $source is not equal to $destination; if they are an error
  *   is reported.
- * - If file already exists in $destination either the call will error out,
- *   replace the file or rename the file based on the $replace parameter.
  * - Adds the new file to the files database. If the source file is a
  *   temporary file, the resulting file will also be a temporary file. See
  *   file_save_upload() for details on temporary files.
@@ -768,15 +767,6 @@ function file_usage_delete(File $file, $module, $type = NULL, $id = NULL, $count
  *   A file entity.
  * @param $destination
  *   A string containing the destination that $source should be copied to.
- *   This must be a stream wrapper URI.
- * @param $replace
- *   Replace behavior when the destination file already exists:
- *   - FILE_EXISTS_REPLACE - Replace the existing file. If a managed file with
- *       the destination name exists then its database entry will be updated. If
- *       no database entry is found then a new one will be created.
- *   - FILE_EXISTS_RENAME - Append _{incrementing number} until the filename is
- *       unique.
- *   - FILE_EXISTS_ERROR - Do nothing and return FALSE.
  *
  * @return
  *   File object if the copy is successful, or FALSE in the event of an error.
@@ -784,44 +774,19 @@ function file_usage_delete(File $file, $module, $type = NULL, $id = NULL, $count
  * @see file_unmanaged_copy()
  * @see hook_file_copy()
  */
-function file_copy(File $source, $destination = NULL, $replace = FILE_EXISTS_RENAME) {
-  if (!file_valid_uri($destination)) {
-    if (($realpath = drupal_realpath($source->uri)) !== FALSE) {
-      watchdog('file', 'File %file (%realpath) could not be copied because the destination %destination is invalid. This is often caused by improper use of file_copy() or a missing stream wrapper.', array('%file' => $source->uri, '%realpath' => $realpath, '%destination' => $destination));
-    }
-    else {
-      watchdog('file', 'File %file could not be copied because the destination %destination is invalid. This is often caused by improper use of file_copy() or a missing stream wrapper.', array('%file' => $source->uri, '%destination' => $destination));
-    }
-    drupal_set_message(t('The specified file %file could not be copied because the destination is invalid. More information is available in the system log.', array('%file' => $source->uri)), 'error');
-    return FALSE;
-  }
-
-  if ($uri = file_unmanaged_copy($source->uri, $destination, $replace)) {
-    $file = clone $source;
-    $file->fid = NULL;
-    $file->uri = $uri;
-    $file->filename = drupal_basename($uri);
-    // If we are replacing an existing file re-use its database record.
-    if ($replace == FILE_EXISTS_REPLACE) {
-      $existing_files = file_load_multiple(array(), array('uri' => $uri));
-      if (count($existing_files)) {
-        $existing = reset($existing_files);
-        $file->fid = $existing->fid;
-        $file->filename = $existing->filename;
-      }
-    }
-    // If we are renaming around an existing file (rather than a directory),
-    // use its basename for the filename.
-    elseif ($replace == FILE_EXISTS_RENAME && is_file($destination)) {
-      $file->filename = drupal_basename($destination);
-    }
-
-    $file->save();
+function file_copy(File $file, $destination = NULL) {
+  // Copy the file.
+  if ($uri = file_unmanaged_copy($file->uri, $destination, FILE_CHECK_EXISTS_DB_FS)) {
+    // Create a new file entity with the new URI.
+    $copied_file = clone $file;
+    $copied_file->fid = NULL;
+    $copied_file->uri = $uri;
+    $copied_file->save();
 
     // Inform modules that the file has been copied.
-    module_invoke_all('file_copy', $file, $source);
+    module_invoke_all('file_copy', $copied_file, $file);
 
-    return $file;
+    return $copied_file;
   }
   return FALSE;
 }
@@ -856,8 +821,8 @@ function file_valid_uri($uri) {
  * - Checks if $source and $destination are valid and readable/writable.
  * - Checks that $source is not equal to $destination; if they are an error
  *   is reported.
- * - If file already exists in $destination either the call will error out,
- *   replace the file or rename the file based on the $replace parameter.
+ * - Ensures the file is copied to a "free" URI based on the $check_exists
+ *   parameter.
  * - Provides a fallback using realpaths if the move fails using stream
  *   wrappers. This can occur because PHP's copy() function does not properly
  *   support streams if safe_mode or open_basedir are enabled. See
@@ -870,31 +835,29 @@ function file_valid_uri($uri) {
  *   URI may be a bare filepath (without a scheme) and in that case the default
  *   scheme (file://) will be used. If this value is omitted, Drupal's default
  *   files scheme will be used, usually "public://".
- * @param $replace
- *   Replace behavior when the destination file already exists:
- *   - FILE_EXISTS_REPLACE - Replace the existing file.
- *   - FILE_EXISTS_RENAME - Append _{incrementing number} until the filename is
- *       unique.
- *   - FILE_EXISTS_ERROR - Do nothing and return FALSE.
+ * @param $check_exists
+ *   The destination URI will be renamed if it already exists by appending
+ *   _{incrementing number} until it is unique.
+ *   - FILE_CHECK_EXISTS_FALSE - Don't check if it exists.
+ *   - FILE_CHECK_EXISTS_FS - Just check the filesystem.
+ *   - FILE_CHECK_EXISTS_DB_FS - Check the database, then the filesystem.
  *
  * @return
  *   The path to the new file, or FALSE in the event of an error.
  *
  * @see file_copy()
  */
-function file_unmanaged_copy($source, $destination = NULL, $replace = FILE_EXISTS_RENAME) {
-  $original_source = $source;
-  $original_destination = $destination;
+function file_unmanaged_copy($source, $destination = NULL, $check_exists = FILE_CHECK_EXISTS_FS) {
 
   // Assert that the source file actually exists.
   if (!file_exists($source)) {
     // @todo Replace drupal_set_message() calls with exceptions instead.
-    drupal_set_message(t('The specified file %file could not be copied because no file by that name exists. Please check that you supplied the correct filename.', array('%file' => $original_source)), 'error');
-    if (($realpath = drupal_realpath($original_source)) !== FALSE) {
-      watchdog('file', 'File %file (%realpath) could not be copied because it does not exist.', array('%file' => $original_source, '%realpath' => $realpath));
+    drupal_set_message(t('The specified file %file could not be copied because no file by that name exists. Please check that you supplied the correct filename.', array('%file' => $source)), 'error');
+    if (($realpath = drupal_realpath($source)) !== FALSE) {
+      watchdog('file', 'File %file (%realpath) could not be copied because it does not exist.', array('%file' => $source, '%realpath' => $realpath));
     }
     else {
-      watchdog('file', 'File %file could not be copied because it does not exist.', array('%file' => $original_source));
+      watchdog('file', 'File %file could not be copied because it does not exist.', array('%file' => $source));
     }
     return FALSE;
   }
@@ -904,31 +867,30 @@ function file_unmanaged_copy($source, $destination = NULL, $replace = FILE_EXIST
     $destination = file_build_uri(drupal_basename($source));
   }
 
-
-  // Prepare the destination directory.
-  if (file_prepare_directory($destination)) {
-    // The destination is already a directory, so append the source basename.
-    $destination = file_stream_wrapper_uri_normalize($destination . '/' . drupal_basename($source));
+  // Determine the directory name.
+  if (is_dir($destination)) {
+    $dirname = $destination;
+    // A URI may already have a trailing slash or look like "public://".
+    if (substr($destination, -1) != '/') {
+      $destination .= '/';
+    }
+    $destination .= drupal_basename($source);
   }
   else {
-    // Perhaps $destination is a dir/file?
     $dirname = drupal_dirname($destination);
-    if (!file_prepare_directory($dirname)) {
-      // The destination is not valid.
-      watchdog('file', 'File %file could not be copied because the destination directory %destination is not configured correctly.', array('%file' => $original_source, '%destination' => $dirname));
-      drupal_set_message(t('The specified file %file could not be copied because the destination directory is not properly configured. This may be caused by a problem with file or directory permissions. More information is available in the system log.', array('%file' => $original_source)), 'error');
-      return FALSE;
-    }
   }
 
-  // Determine whether we can perform this operation based on overwrite rules.
-  $destination = file_destination($destination, $replace);
-  if ($destination === FALSE) {
-    drupal_set_message(t('The file %file could not be copied because a file by that name already exists in the destination directory.', array('%file' => $original_source)), 'error');
-    watchdog('file', 'File %file could not be copied because a file by that name already exists in the destination directory (%directory)', array('%file' => $original_source, '%destination' => $destination));
+  // Prepare the destination directory.
+  if (!file_prepare_directory($dirname)) {
+    // The destination is not valid.
+    watchdog('file', 'File %file could not be copied because the destination directory %destination is not configured correctly.', array('%file' => $source, '%destination' => $dirname));
+    drupal_set_message(t('The specified file %file could not be copied because the destination directory is not properly configured. This may be caused by a problem with file or directory permissions. More information is available in the system log.', array('%file' => $source)), 'error');
     return FALSE;
   }
 
+  // Ensure the destination URI is suitable for a new file.
+  $destination = file_uri_prepare($destination, $check_exists);
+
   // Assert that the source and destination filenames are not the same.
   $real_source = drupal_realpath($source);
   $real_destination = drupal_realpath($destination);
@@ -964,118 +926,37 @@ function file_build_uri($path) {
 }
 
 /**
- * Determines the destination path for a file.
- *
- * @param $destination
- *   A string specifying the desired final URI or filepath.
- * @param $replace
- *   Replace behavior when the destination file already exists.
- *   - FILE_EXISTS_REPLACE - Replace the existing file.
- *   - FILE_EXISTS_RENAME - Append _{incrementing number} until the filename is
- *       unique.
- *   - FILE_EXISTS_ERROR - Do nothing and return FALSE.
- *
- * @return
- *   The destination filepath, or FALSE if the file already exists
- *   and FILE_EXISTS_ERROR is specified.
- */
-function file_destination($destination, $replace) {
-  if (file_exists($destination)) {
-    switch ($replace) {
-      case FILE_EXISTS_REPLACE:
-        // Do nothing here, we want to overwrite the existing file.
-        break;
-
-      case FILE_EXISTS_RENAME:
-        $basename = drupal_basename($destination);
-        $directory = drupal_dirname($destination);
-        $destination = file_create_filename($basename, $directory);
-        break;
-
-      case FILE_EXISTS_ERROR:
-        // Error reporting handled by calling function.
-        return FALSE;
-    }
-  }
-  return $destination;
-}
-
-/**
  * Moves a file to a new location and update the file's database entry.
  *
  * Moving a file is performed by copying the file to the new location and then
  * deleting the original.
  * - Checks if $source and $destination are valid and readable/writable.
  * - Performs a file move if $source is not equal to $destination.
- * - If file already exists in $destination either the call will error out,
- *   replace the file or rename the file based on the $replace parameter.
- * - Adds the new file to the files database.
  *
  * @param Drupal\Core\File\File $source
  *   A file entity.
  * @param $destination
  *   A string containing the destination that $source should be moved to.
  *   This must be a stream wrapper URI.
- * @param $replace
- *   Replace behavior when the destination file already exists:
- *   - FILE_EXISTS_REPLACE - Replace the existing file. If a managed file with
- *       the destination name exists then its database entry will be updated and
- *       $source->delete() called after invoking hook_file_move().
- *       If no database entry is found then the source files record will be
- *       updated.
- *   - FILE_EXISTS_RENAME - Append _{incrementing number} until the filename is
- *       unique.
- *   - FILE_EXISTS_ERROR - Do nothing and return FALSE.
  *
- * @return Drupal\Core\File\File
- *   Resulting file entity for success, or FALSE in the event of an error.
+ * @return
+ *   Boolean TRUE if the file move was successful, FALSE otherwise.
  *
  * @see file_unmanaged_move()
  * @see hook_file_move()
  */
-function file_move(File $source, $destination = NULL, $replace = FILE_EXISTS_RENAME) {
-  if (!file_valid_uri($destination)) {
-    if (($realpath = drupal_realpath($source->uri)) !== FALSE) {
-      watchdog('file', 'File %file (%realpath) could not be moved because the destination %destination is invalid. This may be caused by improper use of file_move() or a missing stream wrapper.', array('%file' => $source->uri, '%realpath' => $realpath, '%destination' => $destination));
-    }
-    else {
-      watchdog('file', 'File %file could not be moved because the destination %destination is invalid. This may be caused by improper use of file_move() or a missing stream wrapper.', array('%file' => $source->uri, '%destination' => $destination));
-    }
-    drupal_set_message(t('The specified file %file could not be moved because the destination is invalid. More information is available in the system log.', array('%file' => $source->uri)), 'error');
-    return FALSE;
-  }
-
-  if ($uri = file_unmanaged_move($source->uri, $destination, $replace)) {
-    $delete_source = FALSE;
-
-    $file = clone $source;
+function file_move(File $file, $destination = NULL) {
+  // Move the file.
+  if ($uri = file_unmanaged_move($file->uri, $destination, FILE_CHECK_EXISTS_DB_FS)) {
+    // Update the entity with the new URI.
+    $source = clone $file;
     $file->uri = $uri;
-    // If we are replacing an existing file re-use its database record.
-    if ($replace == FILE_EXISTS_REPLACE) {
-      $existing_files = file_load_multiple(array(), array('uri' => $uri));
-      if (count($existing_files)) {
-        $existing = reset($existing_files);
-        $delete_source = TRUE;
-        $file->fid = $existing->fid;
-      }
-    }
-    // If we are renaming around an existing file (rather than a directory),
-    // use its basename for the filename.
-    elseif ($replace == FILE_EXISTS_RENAME && is_file($destination)) {
-      $file->filename = drupal_basename($destination);
-    }
-
     $file->save();
 
     // Inform modules that the file has been moved.
     module_invoke_all('file_move', $file, $source);
 
-    // Delete the original if it's not in use elsewhere.
-    if ($delete_source && !file_usage_list($source)) {
-      $source->delete();
-    }
-
-    return $file;
+    return TRUE;
   }
   return FALSE;
 }
@@ -1083,26 +964,35 @@ function file_move(File $source, $destination = NULL, $replace = FILE_EXISTS_REN
 /**
  * Moves a file to a new location without database changes or hook invocation.
  *
+ * This is a powerful function that in many ways performs like an advanced
+ * version of rename().
+ * - Checks if $source and $destination are valid and readable/writable.
+ * - Checks that $source is not equal to $destination; if they are an error
+ *   is reported.
+ * - Ensures the file is moved to a "free" URI based on the $check_exists
+ *   parameter.
+ *
  * @param $source
  *   A string specifying the filepath or URI of the original file.
  * @param $destination
- *   A string containing the destination that $source should be moved to.
- *   This must be a stream wrapper URI. If this value is omitted, Drupal's
- *   default files scheme will be used, usually "public://".
- * @param $replace
- *   Replace behavior when the destination file already exists:
- *   - FILE_EXISTS_REPLACE - Replace the existing file.
- *   - FILE_EXISTS_RENAME - Append _{incrementing number} until the filename is
- *       unique.
- *   - FILE_EXISTS_ERROR - Do nothing and return FALSE.
+ *   A URI containing the destination that $source should be moved to. The
+ *   URI may be a bare filepath (without a scheme) and in that case the default
+ *   scheme (file://) will be used. If this value is omitted, Drupal's default
+ *   files scheme will be used, usually "public://".
+ * @param $check_exists
+ *   The destination URI will be renamed if it already exists by appending
+ *   _{incrementing number} until it is unique.
+ *   - FILE_CHECK_EXISTS_FALSE - Don't check if it exists.
+ *   - FILE_CHECK_EXISTS_FS - Just check the filesystem.
+ *   - FILE_CHECK_EXISTS_DB_FS - Check the database, then the filesystem.
  *
  * @return
  *   The URI of the moved file, or FALSE in the event of an error.
  *
  * @see file_move()
  */
-function file_unmanaged_move($source, $destination = NULL, $replace = FILE_EXISTS_RENAME) {
-  $filepath = file_unmanaged_copy($source, $destination, $replace);
+function file_unmanaged_move($source, $destination = NULL, $check_exists = FILE_CHECK_EXISTS_FS) {
+  $filepath = file_unmanaged_copy($source, $destination, $check_exists);
   if ($filepath == FALSE || file_unmanaged_delete($source) == FALSE) {
     return FALSE;
   }
@@ -1187,28 +1077,33 @@ function file_unmunge_filename($filename) {
 }
 
 /**
- * Creates a full file path from a directory and filename.
+ * Ensures that a URI is suitable for a new file being created.
  *
- * If a file with the specified name already exists, an alternative will be
- * used.
+ * - Replaces unsuitable characters.
+ * - Ensures the file is copied to a "free" URI based on the $check_exists
+ *   parameter.
  *
- * @param $basename
- *   String filename
- * @param $directory
- *   String containing the directory or parent URI.
+ * @param $uri
+ *   Desired URI for a file.
+ * @param $check_exists
+ *   The URI will be renamed if it already exists by appending
+ *   _{incrementing number} until it is unique.
+ *   - FILE_CHECK_EXISTS_FALSE - Don't check if it exists.
+ *   - FILE_CHECK_EXISTS_FS - Just check the filesystem.
+ *   - FILE_CHECK_EXISTS_DB_FS - Check the database, then the filesystem.
  *
  * @return
- *   File path consisting of $directory and a unique filename based off
- *   of $basename.
+ *   Suitable URI for a new file.
  */
-function file_create_filename($basename, $directory) {
+function file_uri_prepare($uri, $check_exists = FILE_CHECK_EXISTS_FS) {
   // Strip control characters (ASCII value < 32). Though these are allowed in
   // some filesystems, not many applications handle them well.
-  $basename = preg_replace('/[\x00-\x1F]/u', '_', $basename);
+  $basename = preg_replace('/[\x00-\x1F]/u', '_', drupal_basename($uri));
   if (substr(PHP_OS, 0, 3) == 'WIN') {
     // These characters are not allowed in Windows filenames
     $basename = str_replace(array(':', '*', '?', '"', '<', '>', '|'), '_', $basename);
   }
+  $directory = drupal_dirname($uri);
 
   // A URI or path may already have a trailing slash or look like "public://".
   if (substr($directory, -1) == '/') {
@@ -1218,27 +1113,62 @@ function file_create_filename($basename, $directory) {
     $separator = '/';
   }
 
-  $destination = $directory . $separator . $basename;
+  // Compose the URI.
+  $uri = $directory . $separator . $basename;
 
-  if (file_exists($destination)) {
-    // Destination file already exists, generate an alternative.
-    $pos = strrpos($basename, '.');
-    if ($pos !== FALSE) {
-      $name = substr($basename, 0, $pos);
-      $ext = substr($basename, $pos);
-    }
-    else {
-      $name = $basename;
-      $ext = '';
-    }
+  // If required, ensure the URI is unique.
+  if ($check_exists) {
+    if (drupal_file_exists($uri, $check_exists == FILE_CHECK_EXISTS_DB_FS)) {
+      // URI already exists, generate an alternative.
+      $pos = strrpos($basename, '.');
+      if ($pos !== FALSE) {
+        $name = substr($basename, 0, $pos);
+        $ext = substr($basename, $pos);
+      }
+      else {
+        $name = $basename;
+        $ext = '';
+      }
 
-    $counter = 0;
-    do {
-      $destination = $directory . $separator . $name . '_' . $counter++ . $ext;
-    } while (file_exists($destination));
+      $counter = 0;
+      do {
+        $uri = $directory . $separator . $name . '_' . $counter++ . $ext;
+      } while (drupal_file_exists($uri, $check_exists == FILE_CHECK_EXISTS_DB_FS));
+    }
   }
 
-  return $destination;
+  return $uri;
+}
+
+/**
+ * Checks whether a file exists.
+ *
+ * PHP's file_exists() only checks the filesystem, not the database.
+ *
+ * @param $uri
+ *   The URI to check.
+ * @param $check_db
+ *   Boolean TRUE if the database is to be checked.
+ *
+ * @return
+ *   Boolean TRUE if the file exists, FALSE otherwise.
+ *
+ * @see file_exists()
+ * @ingroup php_wrappers
+ */
+function drupal_file_exists($uri, $check_db = FALSE) {
+  if ($check_db) {
+    // Check the database first because it is faster.
+    $query = new EntityFieldQuery();
+    $result = $query->entityCondition('entity_type', 'file')
+      ->propertyCondition('uri', $uri)
+      ->execute();
+    if (isset($result['file'])) {
+      return TRUE;
+    }
+  }
+  // Does the file exist in the filesystem?
+  return file_exists($uri);
 }
 
 /**
@@ -1394,12 +1324,6 @@ function file_space_used($uid = NULL, $status = FILE_STATUS_PERMANENT) {
  *   A string containing the URI $source should be copied to.
  *   This must be a stream wrapper URI. If this value is omitted, Drupal's
  *   temporary files scheme will be used ("temporary://").
- * @param $replace
- *   Replace behavior when the destination file already exists:
- *   - FILE_EXISTS_REPLACE: Replace the existing file.
- *   - FILE_EXISTS_RENAME: Append _{incrementing number} until the filename is
- *     unique.
- *   - FILE_EXISTS_ERROR: Do nothing and return FALSE.
  *
  * @return
  *   An object containing the file information if the upload succeeded, FALSE
@@ -1411,7 +1335,7 @@ function file_space_used($uid = NULL, $status = FILE_STATUS_PERMANENT) {
  *   - source: Path to the file before it is moved.
  *   - destination: Path to the file after it is moved (same as 'uri').
  */
-function file_save_upload($source, $validators = array(), $destination = FALSE, $replace = FILE_EXISTS_RENAME) {
+function file_save_upload($source, $validators = array(), $destination = NULL) {
   global $user;
   static $upload_cache;
 
@@ -1523,13 +1447,8 @@ function file_save_upload($source, $validators = array(), $destination = FALSE,
   if (substr($destination, -1) != '/') {
     $destination .= '/';
   }
-  $file->destination = file_destination($destination . $file->filename, $replace);
-  // If file_destination() returns FALSE then $replace == FILE_EXISTS_ERROR and
-  // there's an existing file so we need to bail.
-  if ($file->destination === FALSE) {
-    drupal_set_message(t('The file %source could not be uploaded because a file by that name already exists in the destination %directory.', array('%source' => $source, '%directory' => $destination)), 'error');
-    return FALSE;
-  }
+  // Ensure the destination is unique in the database and on disk.
+  $file->destination = file_uri_prepare($destination . $file->filename, FILE_CHECK_EXISTS_DB_FS);
 
   // Add in our check of the the file name length.
   $validators['file_validate_name_length'] = array();
@@ -1563,15 +1482,6 @@ function file_save_upload($source, $validators = array(), $destination = FALSE,
   // Set the permissions on the new file.
   drupal_chmod($file->uri);
 
-  // If we are replacing an existing file re-use its database record.
-  if ($replace == FILE_EXISTS_REPLACE) {
-    $existing_files = file_load_multiple(array(), array('uri' => $file->uri));
-    if (count($existing_files)) {
-      $existing = reset($existing_files);
-      $file->fid = $existing->fid;
-    }
-  }
-
   // If we made it this far it's safe to record this file in the database.
   $file->save();
   // Add file to the cache.
@@ -1823,51 +1733,24 @@ function file_validate_image_resolution(File $file, $maximum_dimensions = 0, $mi
  *   A string containing the destination URI. This must be a stream wrapper URI.
  *   If no value is provided, a randomized name will be generated and the file
  *   will be saved using Drupal's default files scheme, usually "public://".
- * @param $replace
- *   Replace behavior when the destination file already exists:
- *   - FILE_EXISTS_REPLACE - Replace the existing file. If a managed file with
- *       the destination name exists then its database entry will be updated. If
- *       no database entry is found then a new one will be created.
- *   - FILE_EXISTS_RENAME - Append _{incrementing number} until the filename is
- *       unique.
- *   - FILE_EXISTS_ERROR - Do nothing and return FALSE.
  *
  * @return Drupal\Core\File\File
  *   A file entity, or FALSE on error.
  *
  * @see file_unmanaged_save_data()
  */
-function file_save_data($data, $destination = NULL, $replace = FILE_EXISTS_RENAME) {
+function file_save_data($data, $destination = NULL) {
   global $user;
 
-  if (empty($destination)) {
-    $destination = file_default_scheme() . '://';
-  }
-  if (!file_valid_uri($destination)) {
-    watchdog('file', 'The data could not be saved because the destination %destination is invalid. This may be caused by improper use of file_save_data() or a missing stream wrapper.', array('%destination' => $destination));
-    drupal_set_message(t('The data could not be saved because the destination is invalid. More information is available in the system log.'), 'error');
-    return FALSE;
-  }
-
-  if ($uri = file_unmanaged_save_data($data, $destination, $replace)) {
+  if ($uri = file_unmanaged_save_data($data, $destination, FILE_CHECK_EXISTS_DB_FS)) {
     // Create a file entity.
     $file = entity_create('file', array(
       'uri' => $uri,
       'uid' => $user->uid,
       'status' => FILE_STATUS_PERMANENT,
     ));
-    // If we are replacing an existing file re-use its database record.
-    if ($replace == FILE_EXISTS_REPLACE) {
-      $existing_files = file_load_multiple(array(), array('uri' => $uri));
-      if (count($existing_files)) {
-        $existing = reset($existing_files);
-        $file->fid = $existing->fid;
-        $file->filename = $existing->filename;
-      }
-    }
-    // If we are renaming around an existing file (rather than a directory),
-    // use its basename for the filename.
-    elseif ($replace == FILE_EXISTS_RENAME && is_file($destination)) {
+    // If $destination is supplied and is not a directory, extract the filename.
+    if ($destination && !is_dir($destination)) {
       $file->filename = drupal_basename($destination);
     }
 
@@ -1891,19 +1774,19 @@ function file_save_data($data, $destination = NULL, $replace = FILE_EXISTS_RENAM
  *   URI. If no value is provided, a randomized name will be generated and the
  *   file will be saved using Drupal's default files scheme, usually
  *   "public://".
- * @param $replace
- *   Replace behavior when the destination file already exists:
- *   - FILE_EXISTS_REPLACE - Replace the existing file.
- *   - FILE_EXISTS_RENAME - Append _{incrementing number} until the filename is
- *                          unique.
- *   - FILE_EXISTS_ERROR - Do nothing and return FALSE.
+ * @param $check_exists
+ *   The destination URI will be renamed if it already exists by appending
+ *   _{incrementing number} until it is unique.
+ *   - FILE_CHECK_EXISTS_FALSE - Don't check if it exists.
+ *   - FILE_CHECK_EXISTS_FS - Just check the filesystem.
+ *   - FILE_CHECK_EXISTS_DB_FS - Check the database, then the filesystem.
  *
  * @return
  *   A string with the path of the resulting file, or FALSE on error.
  *
  * @see file_save_data()
  */
-function file_unmanaged_save_data($data, $destination = NULL, $replace = FILE_EXISTS_RENAME) {
+function file_unmanaged_save_data($data, $destination = NULL, $check_exists = FILE_CHECK_EXISTS_FS) {
   // Write the data to a temporary file.
   $temp_name = drupal_tempnam('temporary://', 'file');
   if (file_put_contents($temp_name, $data) === FALSE) {
@@ -1912,7 +1795,7 @@ function file_unmanaged_save_data($data, $destination = NULL, $replace = FILE_EX
   }
 
   // Move the file to its final destination.
-  return file_unmanaged_move($temp_name, $destination, $replace);
+  return file_unmanaged_move($temp_name, $destination, $check_exists);
 }
 
 /**
diff --git a/core/modules/color/color.module b/core/modules/color/color.module
index b2b67a7..3204a00 100644
--- a/core/modules/color/color.module
+++ b/core/modules/color/color.module
@@ -496,7 +496,7 @@ function _color_rewrite_stylesheet($theme, &$info, &$paths, $palette, $style) {
  * Saves the rewritten stylesheet to disk.
  */
 function _color_save_stylesheet($file, $style, &$paths) {
-  $filepath = file_unmanaged_save_data($style, $file, FILE_EXISTS_REPLACE);
+  $filepath = file_unmanaged_save_data($style, $file, FILE_CHECK_EXISTS_FALSE);
   $paths['files'][] = $filepath;
 
   // Set standard file permissions for webserver-generated files.
diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageDimensionsTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageDimensionsTest.php
index 0d57e11..8ed1e3e 100644
--- a/core/modules/image/lib/Drupal/image/Tests/ImageDimensionsTest.php
+++ b/core/modules/image/lib/Drupal/image/Tests/ImageDimensionsTest.php
@@ -34,7 +34,7 @@ class ImageDimensionsTest extends WebTestBase {
     // Create a working copy of the file.
     $files = $this->drupalGetTestFiles('image');
     $file = reset($files);
-    $original_uri = file_unmanaged_copy($file->uri, 'public://', FILE_EXISTS_RENAME);
+    $original_uri = file_unmanaged_copy($file->uri);
 
     // Create a style.
     $style = image_style_save(array('name' => 'test'));
diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageStylesPathAndUrlTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageStylesPathAndUrlTest.php
index 6bf4eb4..0659373 100644
--- a/core/modules/image/lib/Drupal/image/Tests/ImageStylesPathAndUrlTest.php
+++ b/core/modules/image/lib/Drupal/image/Tests/ImageStylesPathAndUrlTest.php
@@ -94,7 +94,7 @@ class ImageStylesPathAndUrlTest extends WebTestBase {
     $files = $this->drupalGetTestFiles('image');
     $file = reset($files);
     $image_info = image_get_info($file->uri);
-    $original_uri = file_unmanaged_copy($file->uri, $scheme . '://', FILE_EXISTS_RENAME);
+    $original_uri = file_unmanaged_copy($file->uri, $scheme . '://');
     // Let the image_module_test module know about this file, so it can claim
     // ownership in hook_file_download().
     variable_set('image_module_test_file_download', $original_uri);
diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageThemeFunctionTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageThemeFunctionTest.php
index 3c61596..3bbffa1 100644
--- a/core/modules/image/lib/Drupal/image/Tests/ImageThemeFunctionTest.php
+++ b/core/modules/image/lib/Drupal/image/Tests/ImageThemeFunctionTest.php
@@ -33,7 +33,7 @@ class ImageThemeFunctionTest extends WebTestBase {
     // Create an image.
     $files = $this->drupalGetTestFiles('image');
     $file = reset($files);
-    $original_uri = file_unmanaged_copy($file->uri, 'public://', FILE_EXISTS_RENAME);
+    $original_uri = file_unmanaged_copy($file->uri);
 
     // Create a style.
     image_style_save(array('name' => 'test'));
@@ -75,7 +75,7 @@ class ImageThemeFunctionTest extends WebTestBase {
     // Create an image.
     $files = $this->drupalGetTestFiles('image');
     $file = reset($files);
-    $original_uri = file_unmanaged_copy($file->uri, 'public://', FILE_EXISTS_RENAME);
+    $original_uri = file_unmanaged_copy($file->uri);
 
     // Create a style.
     image_style_save(array('name' => 'test'));
diff --git a/core/modules/system/image.gd.inc b/core/modules/system/image.gd.inc
index f6f12ae..edf9e12 100644
--- a/core/modules/system/image.gd.inc
+++ b/core/modules/system/image.gd.inc
@@ -281,7 +281,7 @@ function image_gd_save(stdClass $image, $destination) {
   }
   // Move temporary local file to remote destination.
   if (isset($permanent_destination) && $success) {
-    return (bool) file_unmanaged_move($destination, $permanent_destination, FILE_EXISTS_REPLACE);
+    return (bool) file_unmanaged_move($destination, $permanent_destination, FILE_CHECK_EXISTS_FALSE);
   }
   return $success;
 }
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/CopyTest.php b/core/modules/system/lib/Drupal/system/Tests/File/CopyTest.php
index 70f7493..ac496c7 100644
--- a/core/modules/system/lib/Drupal/system/Tests/File/CopyTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/File/CopyTest.php
@@ -27,9 +27,7 @@ class CopyTest extends FileHookTestBase {
     $source = $this->createFile(NULL, $contents);
     $desired_uri = 'public://' . $this->randomName();
 
-    // Clone the object so we don't have to worry about the function changing
-    // our reference copy.
-    $result = file_copy(clone $source, $desired_uri, FILE_EXISTS_ERROR);
+    $result = file_copy($source, $desired_uri);
 
     // Check the return status and that the contents changed.
     $this->assertTrue($result, t('File copied successfully.'));
@@ -58,9 +56,7 @@ class CopyTest extends FileHookTestBase {
     $target = $this->createFile();
     $this->assertDifferentFile($source, $target);
 
-    // Clone the object so we don't have to worry about the function changing
-    // our reference copy.
-    $result = file_copy(clone $source, $target->uri, FILE_EXISTS_RENAME);
+    $result = file_copy($source, $target->uri);
 
     // Check the return status and that the contents changed.
     $this->assertTrue($result, t('File copied successfully.'));
@@ -88,27 +84,24 @@ class CopyTest extends FileHookTestBase {
     $this->assertDifferentFile($loaded_source, $loaded_result);
   }
 
-  /**
-   * Test replacement when copying over a file that already exists.
-   */
-  function testExistingReplace() {
+  function testDBExistingRename() {
     // Setup a file to overwrite.
     $contents = $this->randomName(10);
     $source = $this->createFile(NULL, $contents);
     $target = $this->createFile();
+    file_unmanaged_delete($target->uri);
+    $this->assertFalse(file_exists($target->uri), t('Target file has been deleted from filesystem.'));
     $this->assertDifferentFile($source, $target);
 
-    // Clone the object so we don't have to worry about the function changing
-    // our reference copy.
-    $result = file_copy(clone $source, $target->uri, FILE_EXISTS_REPLACE);
+    $result = file_copy($source, $target->uri);
 
     // Check the return status and that the contents changed.
     $this->assertTrue($result, t('File copied successfully.'));
-    $this->assertEqual($contents, file_get_contents($result->uri), t('Contents of file were overwritten.'));
-    $this->assertDifferentFile($source, $result);
+    $this->assertEqual($contents, file_get_contents($result->uri), t('Contents of file were copied correctly.'));
+    $this->assertNotEqual($result->uri, $source->uri, t('Returned file path has changed from the original.'));
 
     // Check that the correct hooks were called.
-    $this->assertFileHooksCalled(array('load', 'copy', 'update'));
+    $this->assertFileHooksCalled(array('copy', 'insert'));
 
     // Load all the affected files to check the changes that actually made it
     // to the database.
@@ -122,32 +115,42 @@ class CopyTest extends FileHookTestBase {
     // Verify that what was returned is what's in the database.
     $this->assertFileUnchanged($result, $loaded_result);
 
-    // Target file was reused for the result.
-    $this->assertFileUnchanged($loaded_target, $loaded_result);
+    // Make sure we end up with three distinct files afterwards.
+    $this->assertDifferentFile($loaded_source, $loaded_target);
+    $this->assertDifferentFile($loaded_target, $loaded_result);
+    $this->assertDifferentFile($loaded_source, $loaded_result);
   }
 
-  /**
-   * Test that copying over an existing file fails when FILE_EXISTS_ERROR is
-   * specified.
-   */
-  function testExistingError() {
+  function testFSExistingRename() {
+    // Setup a file to overwrite.
     $contents = $this->randomName(10);
-    $source = $this->createFile();
-    $target = $this->createFile(NULL, $contents);
-    $this->assertDifferentFile($source, $target);
+    $source = $this->createFile(NULL, $contents);
+    $target_uri = file_unmanaged_copy($source->uri, 'public://' . $this->randomName());
+    $this->assertTrue(file_exists($target_uri), t('Target file exists on filesystem.'));
 
-    // Clone the object so we don't have to worry about the function changing
-    // our reference copy.
-    $result = file_copy(clone $source, $target->uri, FILE_EXISTS_ERROR);
+    $result = file_copy($source, $target_uri);
 
-    // Check the return status and that the contents were not changed.
-    $this->assertFalse($result, t('File copy failed.'));
-    $this->assertEqual($contents, file_get_contents($target->uri), t('Contents of file were not altered.'));
+    // Check the return status and that the contents changed.
+    $this->assertTrue($result, t('File copied successfully.'));
+    $this->assertEqual($contents, file_get_contents($result->uri), t('Contents of file were copied correctly.'));
+    $this->assertNotEqual($result->uri, $source->uri, t('Returned file path has changed from the original.'));
+    $this->assertNotEqual($result->uri, $target_uri, t('File on filesystem was not overwritten.'));
 
     // Check that the correct hooks were called.
-    $this->assertFileHooksCalled(array());
+    $this->assertFileHooksCalled(array('copy', 'insert'));
+
+    // Load all the affected files to check the changes that actually made it
+    // to the database.
+    $loaded_source = file_load($source->fid, TRUE);
+    $loaded_result = file_load($result->fid, TRUE);
+
+    // Verify that the source file wasn't changed.
+    $this->assertFileUnchanged($source, $loaded_source);
 
-    $this->assertFileUnchanged($source, file_load($source->fid, TRUE));
-    $this->assertFileUnchanged($target, file_load($target->fid, TRUE));
+    // Verify that what was returned is what's in the database.
+    $this->assertFileUnchanged($result, $loaded_result);
+
+    // Make sure we end up with distinct files afterwards.
+    $this->assertDifferentFile($loaded_source, $loaded_result);
   }
 }
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/DirectoryTest.php b/core/modules/system/lib/Drupal/system/Tests/File/DirectoryTest.php
index 5d57bdf..4f96e87 100644
--- a/core/modules/system/lib/Drupal/system/Tests/File/DirectoryTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/File/DirectoryTest.php
@@ -64,57 +64,29 @@ class DirectoryTest extends FileTestBase {
   }
 
   /**
-   * This will take a directory and path, and find a valid filepath that is not
-   * taken by another file.
-   */
-  function testFileCreateNewFilepath() {
-    // First we test against an imaginary file that does not exist in a
-    // directory.
-    $basename = 'xyz.txt';
-    $directory = 'core/misc';
-    $original = $directory . '/' . $basename;
-    $path = file_create_filename($basename, $directory);
-    $this->assertEqual($path, $original, t('New filepath %new equals %original.', array('%new' => $path, '%original' => $original)), 'File');
-
-    // Then we test against a file that already exists within that directory.
-    $basename = 'druplicon.png';
-    $original = $directory . '/' . $basename;
-    $expected = $directory . '/druplicon_0.png';
-    $path = file_create_filename($basename, $directory);
-    $this->assertEqual($path, $expected, t('Creating a new filepath from %original equals %new (expected %expected).', array('%new' => $path, '%original' => $original, '%expected' => $expected)), 'File');
-
-    // @TODO: Finally we copy a file into a directory several times, to ensure a properly iterating filename suffix.
-  }
-
-  /**
    * This will test the filepath for a destination based on passed flags and
    * whether or not the file exists.
    *
-   * If a file exists, file_destination($destination, $replace) will either
+   * If a file exists, file_uri_prepare($destination, $check_exists) will either
    * return:
-   * - the existing filepath, if $replace is FILE_EXISTS_REPLACE
-   * - a new filepath if FILE_EXISTS_RENAME
-   * - an error (returning FALSE) if FILE_EXISTS_ERROR.
+   * - the existing filepath, if $check_exists is FILE_CHECK_EXISTS_FALSE
+   * - a new filepath if FILE_CHECK_EXISTS_FS (default)
    * If the file doesn't currently exist, then it will simply return the
    * filepath.
    */
-  function testFileDestination() {
+  function testFileURIPrepare() {
     // First test for non-existent file.
     $destination = 'core/misc/xyz.txt';
-    $path = file_destination($destination, FILE_EXISTS_REPLACE);
-    $this->assertEqual($path, $destination, t('Non-existing filepath destination is correct with FILE_EXISTS_REPLACE.'), 'File');
-    $path = file_destination($destination, FILE_EXISTS_RENAME);
-    $this->assertEqual($path, $destination, t('Non-existing filepath destination is correct with FILE_EXISTS_RENAME.'), 'File');
-    $path = file_destination($destination, FILE_EXISTS_ERROR);
-    $this->assertEqual($path, $destination, t('Non-existing filepath destination is correct with FILE_EXISTS_ERROR.'), 'File');
+    $path = file_uri_prepare($destination, FILE_CHECK_EXISTS_FALSE);
+    $this->assertEqual($path, $destination, t('Non-existing filepath destination is correct with FILE_CHECK_EXISTS_FALSE.'), 'File');
+    $path = file_uri_prepare($destination);
+    $this->assertEqual($path, $destination, t('Non-existing filepath destination is correct with FILE_CHECK_EXISTS_FS.'), 'File');
 
     $destination = 'core/misc/druplicon.png';
-    $path = file_destination($destination, FILE_EXISTS_REPLACE);
-    $this->assertEqual($path, $destination, t('Existing filepath destination remains the same with FILE_EXISTS_REPLACE.'), 'File');
-    $path = file_destination($destination, FILE_EXISTS_RENAME);
-    $this->assertNotEqual($path, $destination, t('A new filepath destination is created when filepath destination already exists with FILE_EXISTS_RENAME.'), 'File');
-    $path = file_destination($destination, FILE_EXISTS_ERROR);
-    $this->assertEqual($path, FALSE, t('An error is returned when filepath destination already exists with FILE_EXISTS_ERROR.'), 'File');
+    $path = file_uri_prepare($destination, FILE_CHECK_EXISTS_FALSE);
+    $this->assertEqual($path, $destination, t('Existing filepath destination remains the same with FILE_CHECK_EXISTS_FALSE.'), 'File');
+    $path = file_uri_prepare($destination);
+    $this->assertNotEqual($path, $destination, t('A new filepath destination is created when filepath destination already exists with FILE_CHECK_EXISTS_FS.'), 'File');
   }
 
   /**
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/DownloadTest.php b/core/modules/system/lib/Drupal/system/Tests/File/DownloadTest.php
index acfa062..991b813 100644
--- a/core/modules/system/lib/Drupal/system/Tests/File/DownloadTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/File/DownloadTest.php
@@ -128,7 +128,7 @@ class DownloadTest extends FileTestBase {
     // Convert $filename to a valid filename, i.e. strip characters not
     // supported by the filesystem, and create the file in the specified
     // directory.
-    $filepath = file_create_filename($filename, $directory);
+    $filepath = file_uri_prepare($directory . '/' . $filename);
     $directory_uri = $scheme . '://' . dirname($filepath);
     file_prepare_directory($directory_uri, FILE_CREATE_DIRECTORY);
     $file = $this->createFile($filepath, NULL, $scheme);
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/MoveTest.php b/core/modules/system/lib/Drupal/system/Tests/File/MoveTest.php
index 64f12eb..9e24bd4 100644
--- a/core/modules/system/lib/Drupal/system/Tests/File/MoveTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/File/MoveTest.php
@@ -24,29 +24,28 @@ class MoveTest extends FileHookTestBase {
    */
   function testNormal() {
     $contents = $this->randomName(10);
-    $source = $this->createFile(NULL, $contents);
+    $file = $this->createFile(NULL, $contents);
     $desired_filepath = 'public://' . $this->randomName();
 
-    // Clone the object so we don't have to worry about the function changing
-    // our reference copy.
-    $result = file_move(clone $source, $desired_filepath, FILE_EXISTS_ERROR);
+    $old_file = clone $file;
+    $result = file_move($file, $desired_filepath);
 
     // Check the return status and that the contents changed.
     $this->assertTrue($result, t('File moved successfully.'));
-    $this->assertFalse(file_exists($source->uri));
-    $this->assertEqual($contents, file_get_contents($result->uri), t('Contents of file correctly written.'));
+    $this->assertFalse(file_exists($old_file->uri));
+    $this->assertEqual($contents, file_get_contents($file->uri), t('Contents of file correctly written.'));
 
     // Check that the correct hooks were called.
     $this->assertFileHooksCalled(array('move', 'load', 'update'));
 
     // Make sure we got the same file back.
-    $this->assertEqual($source->fid, $result->fid, t("Source file id's' %fid is unchanged after move.", array('%fid' => $source->fid)));
+    $this->assertEqual($file->fid, $old_file->fid, t("File id's' %fid is unchanged after move.", array('%fid' => $file->fid)));
 
     // Reload the file from the database and check that the changes were
     // actually saved.
-    $loaded_file = file_load($result->fid, TRUE);
+    $loaded_file = file_load($file->fid, TRUE);
     $this->assertTrue($loaded_file, t('File can be loaded from the database.'));
-    $this->assertFileUnchanged($result, $loaded_file);
+    $this->assertFileUnchanged($file, $loaded_file);
   }
 
   /**
@@ -55,114 +54,95 @@ class MoveTest extends FileHookTestBase {
   function testExistingRename() {
     // Setup a file to overwrite.
     $contents = $this->randomName(10);
-    $source = $this->createFile(NULL, $contents);
+    $file = $this->createFile(NULL, $contents);
     $target = $this->createFile();
-    $this->assertDifferentFile($source, $target);
+    $this->assertDifferentFile($file, $target);
 
-    // Clone the object so we don't have to worry about the function changing
-    // our reference copy.
-    $result = file_move(clone $source, $target->uri, FILE_EXISTS_RENAME);
+    $old_file = clone $file;
+    $result = file_move($file, $target->uri);
 
     // Check the return status and that the contents changed.
     $this->assertTrue($result, t('File moved successfully.'));
-    $this->assertFalse(file_exists($source->uri));
-    $this->assertEqual($contents, file_get_contents($result->uri), t('Contents of file correctly written.'));
+    $this->assertFalse(file_exists($old_file->uri));
+    $this->assertEqual($contents, file_get_contents($file->uri), t('Contents of file correctly written.'));
 
     // Check that the correct hooks were called.
     $this->assertFileHooksCalled(array('move', 'load', 'update'));
 
     // Compare the returned value to what made it into the database.
-    $this->assertFileUnchanged($result, file_load($result->fid, TRUE));
-    // The target file should not have been altered.
-    $this->assertFileUnchanged($target, file_load($target->fid, TRUE));
-    // Make sure we end up with two distinct files afterwards.
-    $this->assertDifferentFile($target, $result);
+    $this->assertFileUnchanged($file, file_load($file->fid, TRUE));
 
     // Compare the source and results.
-    $loaded_source = file_load($source->fid, TRUE);
-    $this->assertEqual($loaded_source->fid, $result->fid, t("Returned file's id matches the source."));
-    $this->assertNotEqual($loaded_source->uri, $source->uri, t("Returned file path has changed from the original."));
+    $this->assertEqual($old_file->fid, $file->fid, t("Returned file's id matches the source."));
+    $this->assertNotEqual($old_file->uri, $file->uri, t("Returned file path has changed from the original."));
+
+    // Compare the target URI and result URI.
+    $this->assertNotEqual($target->uri, $file->uri, t("File on filesystem was not overwritten."));
   }
 
   /**
-   * Test replacement when moving onto a file that already exists.
+   * Test renaming when moving onto a file that already exists.
    */
-  function testExistingReplace() {
+  function testDBExistingRename() {
     // Setup a file to overwrite.
     $contents = $this->randomName(10);
-    $source = $this->createFile(NULL, $contents);
+    $file = $this->createFile(NULL, $contents);
     $target = $this->createFile();
-    $this->assertDifferentFile($source, $target);
+    file_unmanaged_delete($target->uri);
+    $this->assertFalse(file_exists($target->uri), t('Target file has been deleted from filesystem.'));
+    $this->assertDifferentFile($file, $target);
 
-    // Clone the object so we don't have to worry about the function changing
-    // our reference copy.
-    $result = file_move(clone $source, $target->uri, FILE_EXISTS_REPLACE);
+    $old_file = clone $file;
+    $result = file_move($file, $target->uri);
 
-    // Look at the results.
-    $this->assertEqual($contents, file_get_contents($result->uri), t('Contents of file were overwritten.'));
-    $this->assertFalse(file_exists($source->uri));
+    // Check the return status and that the contents changed.
     $this->assertTrue($result, t('File moved successfully.'));
+    $this->assertFalse(file_exists($old_file->uri));
+    $this->assertEqual($contents, file_get_contents($file->uri), t('Contents of file correctly written.'));
 
     // Check that the correct hooks were called.
-    $this->assertFileHooksCalled(array('move', 'update', 'delete', 'load'));
+    $this->assertFileHooksCalled(array('move', 'load', 'update'));
 
-    // Reload the file from the database and check that the changes were
-    // actually saved.
-    $loaded_result = file_load($result->fid, TRUE);
-    $this->assertFileUnchanged($result, $loaded_result);
-    // Check that target was re-used.
-    $this->assertSameFile($target, $loaded_result);
-    // Source and result should be totally different.
-    $this->assertDifferentFile($source, $loaded_result);
+    // Compare the returned value to what made it into the database.
+    $this->assertFileUnchanged($file, file_load($file->fid, TRUE));
+
+    // Compare the source and results.
+    $this->assertEqual($old_file->fid, $file->fid, t("Returned file's id matches the source."));
+    $this->assertNotEqual($old_file->uri, $file->uri, t("Returned file path has changed from the original."));
+
+    // Compare the target URI and result URI.
+    $this->assertNotEqual($target->uri, $file->uri, t("File on filesystem was not overwritten."));
   }
 
   /**
-   * Test replacement when moving onto itself.
+   * Test renaming when moving onto a file that already exists.
    */
-  function testExistingReplaceSelf() {
+  function testFSExistingRename() {
     // Setup a file to overwrite.
     $contents = $this->randomName(10);
-    $source = $this->createFile(NULL, $contents);
+    $file = $this->createFile(NULL, $contents);
+    $target_uri = file_unmanaged_copy($file->uri, 'public://' . $this->randomName());
+    $this->assertTrue(file_exists($target_uri), t('Target file exists on filesystem.'));
 
-    // Copy the file over itself. Clone the object so we don't have to worry
-    // about the function changing our reference copy.
-    $result = file_move(clone $source, $source->uri, FILE_EXISTS_REPLACE);
-    $this->assertFalse($result, t('File move failed.'));
-    $this->assertEqual($contents, file_get_contents($source->uri), t('Contents of file were not altered.'));
+    $old_file = clone $file;
+    $result = file_move($file, $target_uri);
 
-    // Check that no hooks were called while failing.
-    $this->assertFileHooksCalled(array());
+    // Check the return status and that the contents changed.
+    $this->assertTrue($result, t('File moved successfully.'));
+    $this->assertFalse(file_exists($old_file->uri));
+    $this->assertEqual($contents, file_get_contents($file->uri), t('Contents of file correctly written.'));
 
-    // Load the file from the database and make sure it is identical to what
-    // was returned.
-    $this->assertFileUnchanged($source, file_load($source->fid, TRUE));
-  }
+    // Check that the correct hooks were called.
+    $this->assertFileHooksCalled(array('move', 'load', 'update'));
 
-  /**
-   * Test that moving onto an existing file fails when FILE_EXISTS_ERROR is
-   * specified.
-   */
-  function testExistingError() {
-    $contents = $this->randomName(10);
-    $source = $this->createFile();
-    $target = $this->createFile(NULL, $contents);
-    $this->assertDifferentFile($source, $target);
-
-    // Clone the object so we don't have to worry about the function changing
-    // our reference copy.
-    $result = file_move(clone $source, $target->uri, FILE_EXISTS_ERROR);
-
-    // Check the return status and that the contents did not change.
-    $this->assertFalse($result, t('File move failed.'));
-    $this->assertTrue(file_exists($source->uri));
-    $this->assertEqual($contents, file_get_contents($target->uri), t('Contents of file were not altered.'));
-
-    // Check that no hooks were called while failing.
-    $this->assertFileHooksCalled(array());
-
-    // Load the file from the database and make sure it is identical to what
-    // was returned.
-    $this->assertFileUnchanged($source, file_load($source->fid, TRUE));
-    $this->assertFileUnchanged($target, file_load($target->fid, TRUE));
+    // Compare the returned value to what made it into the database.
+    $this->assertFileUnchanged($file, file_load($file->fid, TRUE));
+
+    // Compare the source and results.
+    $this->assertEqual($old_file->fid, $file->fid, t("Returned file's id matches the source."));
+    $this->assertNotEqual($old_file->uri, $file->uri, t("Returned file path has changed from the original."));
+
+    // Compare the target URI and result URI.
+    $this->assertNotEqual($target_uri, $file->uri, t("File on filesystem was not overwritten."));
   }
 }
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/SaveDataTest.php b/core/modules/system/lib/Drupal/system/Tests/File/SaveDataTest.php
index a8de40d..595eee2 100644
--- a/core/modules/system/lib/Drupal/system/Tests/File/SaveDataTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/File/SaveDataTest.php
@@ -74,7 +74,7 @@ class SaveDataTest extends FileHookTestBase {
     $existing = $this->createFile();
     $contents = $this->randomName(8);
 
-    $result = file_save_data($contents, $existing->uri, FILE_EXISTS_RENAME);
+    $result = file_save_data($contents, $existing->uri);
     $this->assertTrue($result, t("File saved successfully."));
 
     $this->assertEqual('public', file_uri_scheme($result->uri), t("File was placed in Drupal's files directory."));
@@ -102,7 +102,7 @@ class SaveDataTest extends FileHookTestBase {
     $existing = $this->createFile();
     $contents = $this->randomName(8);
 
-    $result = file_save_data($contents, $existing->uri, FILE_EXISTS_REPLACE);
+    $result = file_save_data($contents, $existing->uri, FILE_CHECK_EXISTS_FALSE);
     $this->assertTrue($result, t('File saved successfully.'));
 
     $this->assertEqual('public', file_uri_scheme($result->uri), t("File was placed in Drupal's files directory."));
@@ -112,31 +112,12 @@ class SaveDataTest extends FileHookTestBase {
     $this->assertEqual($result->status, FILE_STATUS_PERMANENT, t("The file's status was set to permanent."));
 
     // Check that the correct hooks were called.
-    $this->assertFileHooksCalled(array('load', 'update'));
+    $this->assertFileHooksCalled(array('insert'));
 
-    // Verify that the existing file was re-used.
-    $this->assertSameFile($existing, $result);
+    // Verify that the existing file was not re-used.
+    $this->assertNotEqual($existing->fid, $result->fid, t('Files have different ids: %file1 == %file2.', array('%file1' => $existing->fid, '%file2-fid' => $result->fid)));
 
     // Verify that what was returned is what's in the database.
     $this->assertFileUnchanged($result, file_load($result->fid, TRUE));
   }
-
-  /**
-   * Test that file_save_data() fails overwriting an existing file.
-   */
-  function testExistingError() {
-    $contents = $this->randomName(8);
-    $existing = $this->createFile(NULL, $contents);
-
-    // Check the overwrite error.
-    $result = file_save_data('asdf', $existing->uri, FILE_EXISTS_ERROR);
-    $this->assertFalse($result, t('Overwriting a file fails when FILE_EXISTS_ERROR is specified.'));
-    $this->assertEqual($contents, file_get_contents($existing->uri), t('Contents of existing file were unchanged.'));
-
-    // Check that no hooks were called while failing.
-    $this->assertFileHooksCalled(array());
-
-    // Ensure that the existing file wasn't overwritten.
-    $this->assertFileUnchanged($existing, file_load($existing->fid, TRUE));
-  }
 }
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/SaveUploadTest.php b/core/modules/system/lib/Drupal/system/Tests/File/SaveUploadTest.php
index 2cccaec..4c7e63d 100644
--- a/core/modules/system/lib/Drupal/system/Tests/File/SaveUploadTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/File/SaveUploadTest.php
@@ -50,9 +50,7 @@ class SaveUploadTest extends FileHookTestBase {
 
     $this->maxFidBefore = db_query('SELECT MAX(fid) AS fid FROM {file_managed}')->fetchField();
 
-    // Upload with replace to guarantee there's something there.
     $edit = array(
-      'file_test_replace' => FILE_EXISTS_REPLACE,
       'files[file_test_upload]' => drupal_realpath($this->image->uri),
     );
     $this->drupalPost('file-test/upload', $edit, t('Submit'));
@@ -128,7 +126,6 @@ class SaveUploadTest extends FileHookTestBase {
     // file_save_upload() to only allow ".foo".
     $extensions = 'foo';
     $edit = array(
-      'file_test_replace' => FILE_EXISTS_REPLACE,
       'files[file_test_upload]' => drupal_realpath($this->image->uri),
       'extensions' => $extensions,
     );
@@ -148,7 +145,6 @@ class SaveUploadTest extends FileHookTestBase {
     $extensions = 'foo ' . $this->image_extension;
     // Now tell file_save_upload() to allow the extension of our test image.
     $edit = array(
-      'file_test_replace' => FILE_EXISTS_REPLACE,
       'files[file_test_upload]' => drupal_realpath($this->image->uri),
       'extensions' => $extensions,
     );
@@ -159,14 +155,13 @@ class SaveUploadTest extends FileHookTestBase {
     $this->assertRaw(t('You WIN!'), t('Found the success message.'));
 
     // Check that the correct hooks were called.
-    $this->assertFileHooksCalled(array('validate', 'load', 'update'));
+    $this->assertFileHooksCalled(array('validate', 'insert'));
 
     // Reset the hook counters.
     file_test_reset();
 
     // Now tell file_save_upload() to allow any extension.
     $edit = array(
-      'file_test_replace' => FILE_EXISTS_REPLACE,
       'files[file_test_upload]' => drupal_realpath($this->image->uri),
       'allow_all_extensions' => TRUE,
     );
@@ -176,7 +171,7 @@ class SaveUploadTest extends FileHookTestBase {
     $this->assertRaw(t('You WIN!'), t('Found the success message.'));
 
     // Check that the correct hooks were called.
-    $this->assertFileHooksCalled(array('validate', 'load', 'update'));
+    $this->assertFileHooksCalled(array('validate', 'insert'));
   }
 
   /**
@@ -186,7 +181,6 @@ class SaveUploadTest extends FileHookTestBase {
     // Allow the .php extension and make sure it gets renamed to .txt for
     // safety. Also check to make sure its MIME type was changed.
     $edit = array(
-      'file_test_replace' => FILE_EXISTS_REPLACE,
       'files[file_test_upload]' => drupal_realpath($this->phpfile->uri),
       'is_image_file' => FALSE,
       'extensions' => 'php',
@@ -227,7 +221,7 @@ class SaveUploadTest extends FileHookTestBase {
   function testHandleFileMunge() {
     // Ensure insecure uploads are disabled for this test.
     variable_set('allow_insecure_uploads', 0);
-    $this->image = file_move($this->image, $this->image->uri . '.foo.' . $this->image_extension);
+    file_move($this->image, $this->image->uri . '.foo.' . $this->image_extension);
 
     // Reset the hook counters to get rid of the 'move' we just called.
     file_test_reset();
@@ -238,7 +232,7 @@ class SaveUploadTest extends FileHookTestBase {
       'extensions' => $extensions,
     );
 
-    $munged_filename = $this->image->filename;
+    $munged_filename = basename($this->image->uri);
     $munged_filename = substr($munged_filename, 0, strrpos($munged_filename, '.'));
     $munged_filename .= '_.' . $this->image_extension;
 
@@ -275,7 +269,6 @@ class SaveUploadTest extends FileHookTestBase {
    */
   function testExistingRename() {
     $edit = array(
-      'file_test_replace' => FILE_EXISTS_RENAME,
       'files[file_test_upload]' => drupal_realpath($this->image->uri)
     );
     $this->drupalPost('file-test/upload', $edit, t('Submit'));
@@ -287,42 +280,22 @@ class SaveUploadTest extends FileHookTestBase {
   }
 
   /**
-   * Test replacement when uploading over a file that already exists.
-   */
-  function testExistingReplace() {
-    $edit = array(
-      'file_test_replace' => FILE_EXISTS_REPLACE,
-      'files[file_test_upload]' => drupal_realpath($this->image->uri)
-    );
-    $this->drupalPost('file-test/upload', $edit, t('Submit'));
-    $this->assertResponse(200, t('Received a 200 response for posted test file.'));
-    $this->assertRaw(t('You WIN!'), t('Found the success message.'));
-
-    // Check that the correct hooks were called.
-    $this->assertFileHooksCalled(array('validate', 'load', 'update'));
-  }
-
-  /**
-   * Test for failure when uploading over a file that already exists.
-   */
-  function testExistingError() {
-    $edit = array(
-      'file_test_replace' => FILE_EXISTS_ERROR,
-      'files[file_test_upload]' => drupal_realpath($this->image->uri)
-    );
-    $this->drupalPost('file-test/upload', $edit, t('Submit'));
-    $this->assertResponse(200, t('Received a 200 response for posted test file.'));
-    $this->assertRaw(t('Epic upload FAIL!'), t('Found the failure message.'));
-
-    // Check that the no hooks were called while failing.
-    $this->assertFileHooksCalled(array());
-  }
-
-  /**
    * Test for no failures when not uploading a file.
    */
   function testNoUpload() {
     $this->drupalPost('file-test/upload', array(), t('Submit'));
     $this->assertNoRaw(t('Epic upload FAIL!'), t('Failure message not found.'));
   }
+
+  /**
+   * Test renaming when uploading over a file that exists in {file_managed} but
+   * not on disk.
+   */
+  function testZombieRename() {
+    $uri = 'temporary://' . drupal_basename($this->image->uri);
+    $this->assertTrue(file_exists($uri));
+    file_unmanaged_delete($uri);
+    $this->assertFalse(file_exists($uri));
+    $this->testExistingRename();
+  }
 }
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/UnmanagedCopyTest.php b/core/modules/system/lib/Drupal/system/Tests/File/UnmanagedCopyTest.php
index 5d5aa21..c6a1f01 100644
--- a/core/modules/system/lib/Drupal/system/Tests/File/UnmanagedCopyTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/File/UnmanagedCopyTest.php
@@ -28,7 +28,7 @@ class UnmanagedCopyTest extends FileTestBase {
 
     // Copying to a new name.
     $desired_filepath = 'public://' . $this->randomName();
-    $new_filepath = file_unmanaged_copy($file->uri, $desired_filepath, FILE_EXISTS_ERROR);
+    $new_filepath = file_unmanaged_copy($file->uri, $desired_filepath);
     $this->assertTrue($new_filepath, t('Copy was successful.'));
     $this->assertEqual($new_filepath, $desired_filepath, t('Returned expected filepath.'));
     $this->assertTrue(file_exists($file->uri), t('Original file remains.'));
@@ -38,13 +38,22 @@ class UnmanagedCopyTest extends FileTestBase {
     // Copying with rename.
     $desired_filepath = 'public://' . $this->randomName();
     $this->assertTrue(file_put_contents($desired_filepath, ' '), t('Created a file so a rename will have to happen.'));
-    $newer_filepath = file_unmanaged_copy($file->uri, $desired_filepath, FILE_EXISTS_RENAME);
+    $newer_filepath = file_unmanaged_copy($file->uri, $desired_filepath);
     $this->assertTrue($newer_filepath, t('Copy was successful.'));
     $this->assertNotEqual($newer_filepath, $desired_filepath, t('Returned expected filepath.'));
     $this->assertTrue(file_exists($file->uri), t('Original file remains.'));
     $this->assertTrue(file_exists($newer_filepath), t('New file exists.'));
     $this->assertFilePermissions($newer_filepath, variable_get('file_chmod_file', 0664));
 
+    // Copying with overwrite.
+    $desired_filepath = 'public://' . $this->randomName();
+    $this->assertTrue(file_put_contents($desired_filepath, ' '), t('Created a file that will be overwritten.'));
+    $newer_filepath = file_unmanaged_copy($file->uri, $desired_filepath, FILE_CHECK_EXISTS_FALSE);
+    $this->assertTrue($newer_filepath, t('Copy was successful.'));
+    $this->assertEqual($newer_filepath, $desired_filepath, t('Returned expected filepath.'));
+    $this->assertTrue(file_exists($file->uri), t('Original file remains.'));
+    $this->assertFilePermissions($newer_filepath, variable_get('file_chmod_file', 0664));
+
     // TODO: test copying to a directory (rather than full directory/file path)
     // TODO: test copying normal files using normal paths (rather than only streams)
   }
@@ -68,29 +77,27 @@ class UnmanagedCopyTest extends FileTestBase {
     $file = $this->createFile();
 
     // Copy the file onto itself with renaming works.
-    $new_filepath = file_unmanaged_copy($file->uri, $file->uri, FILE_EXISTS_RENAME);
+    $new_filepath = file_unmanaged_copy($file->uri, $file->uri);
     $this->assertTrue($new_filepath, t('Copying onto itself with renaming works.'));
     $this->assertNotEqual($new_filepath, $file->uri, t('Copied file has a new name.'));
     $this->assertTrue(file_exists($file->uri), t('Original file exists after copying onto itself.'));
     $this->assertTrue(file_exists($new_filepath), t('Copied file exists after copying onto itself.'));
     $this->assertFilePermissions($new_filepath, variable_get('file_chmod_file', 0664));
 
-    // Copy the file onto itself without renaming fails.
-    $new_filepath = file_unmanaged_copy($file->uri, $file->uri, FILE_EXISTS_ERROR);
-    $this->assertFalse($new_filepath, t('Copying onto itself without renaming fails.'));
-    $this->assertTrue(file_exists($file->uri), t('File exists after copying onto itself.'));
-
-    // Copy the file into same directory without renaming fails.
-    $new_filepath = file_unmanaged_copy($file->uri, drupal_dirname($file->uri), FILE_EXISTS_ERROR);
-    $this->assertFalse($new_filepath, t('Copying onto itself fails.'));
-    $this->assertTrue(file_exists($file->uri), t('File exists after copying onto itself.'));
-
     // Copy the file into same directory with renaming works.
-    $new_filepath = file_unmanaged_copy($file->uri, drupal_dirname($file->uri), FILE_EXISTS_RENAME);
+    $new_filepath = file_unmanaged_copy($file->uri, drupal_dirname($file->uri));
     $this->assertTrue($new_filepath, t('Copying into same directory works.'));
     $this->assertNotEqual($new_filepath, $file->uri, t('Copied file has a new name.'));
     $this->assertTrue(file_exists($file->uri), t('Original file exists after copying onto itself.'));
     $this->assertTrue(file_exists($new_filepath), t('Copied file exists after copying onto itself.'));
     $this->assertFilePermissions($new_filepath, variable_get('file_chmod_file', 0664));
+
+    // Copy the file onto itself without renaming doesn't work.
+    $new_filepath = file_unmanaged_copy($file->uri, $file->uri, FILE_CHECK_EXISTS_FALSE);
+    $this->assertFalse($new_filepath, t('Copying the file onto itself without renaming doesn\'t work.'));
+
+    // Copy the file into same directory without renaming doesn't work.
+    $new_filepath = file_unmanaged_copy($file->uri, drupal_dirname($file->uri), FILE_CHECK_EXISTS_FALSE);
+    $this->assertFalse($new_filepath, t('Copy the file into same directory without renaming doesn\'t work.'));
   }
 }
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/UnmanagedMoveTest.php b/core/modules/system/lib/Drupal/system/Tests/File/UnmanagedMoveTest.php
index 4e5c8c4..c7be4c3 100644
--- a/core/modules/system/lib/Drupal/system/Tests/File/UnmanagedMoveTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/File/UnmanagedMoveTest.php
@@ -28,7 +28,7 @@ class UnmanagedMoveTest extends FileTestBase {
 
     // Moving to a new name.
     $desired_filepath = 'public://' . $this->randomName();
-    $new_filepath = file_unmanaged_move($file->uri, $desired_filepath, FILE_EXISTS_ERROR);
+    $new_filepath = file_unmanaged_move($file->uri, $desired_filepath);
     $this->assertTrue($new_filepath, t('Move was successful.'));
     $this->assertEqual($new_filepath, $desired_filepath, t('Returned expected filepath.'));
     $this->assertTrue(file_exists($new_filepath), t('File exists at the new location.'));
@@ -39,13 +39,25 @@ class UnmanagedMoveTest extends FileTestBase {
     $desired_filepath = 'public://' . $this->randomName();
     $this->assertTrue(file_exists($new_filepath), t('File exists before moving.'));
     $this->assertTrue(file_put_contents($desired_filepath, ' '), t('Created a file so a rename will have to happen.'));
-    $newer_filepath = file_unmanaged_move($new_filepath, $desired_filepath, FILE_EXISTS_RENAME);
+    $newer_filepath = file_unmanaged_move($new_filepath, $desired_filepath);
     $this->assertTrue($newer_filepath, t('Move was successful.'));
     $this->assertNotEqual($newer_filepath, $desired_filepath, t('Returned expected filepath.'));
     $this->assertTrue(file_exists($newer_filepath), t('File exists at the new location.'));
     $this->assertFalse(file_exists($new_filepath), t('No file remains at the old location.'));
     $this->assertFilePermissions($newer_filepath, variable_get('file_chmod_file', 0664));
 
+    // Moving with overwrite.
+    $new_filepath = $newer_filepath;
+    $desired_filepath = 'public://' . $this->randomName();
+    $this->assertTrue(file_exists($new_filepath), t('File exists before moving.'));
+    $this->assertTrue(file_put_contents($desired_filepath, ' '), t('Created a file that will be overwritten.'));
+    $newer_filepath = file_unmanaged_move($new_filepath, $desired_filepath, FILE_CHECK_EXISTS_FALSE);
+    $this->assertTrue($newer_filepath, t('Move was successful.'));
+    $this->assertEqual($newer_filepath, $desired_filepath, t('Returned expected filepath.'));
+    $this->assertTrue(file_exists($newer_filepath), t('File exists at the new location.'));
+    $this->assertFalse(file_exists($new_filepath), t('No file remains at the old location.'));
+    $this->assertFilePermissions($newer_filepath, variable_get('file_chmod_file', 0664));
+
     // TODO: test moving to a directory (rather than full directory/file path)
     // TODO: test creating and moving normal files (rather than streams)
   }
@@ -55,8 +67,8 @@ class UnmanagedMoveTest extends FileTestBase {
    */
   function testMissing() {
     // Move non-existent file.
-    $new_filepath = file_unmanaged_move($this->randomName(), $this->randomName());
-    $this->assertFalse($new_filepath, t('Moving a missing file fails.'));
+    $result = file_unmanaged_move($this->randomName(), $this->randomName());
+    $this->assertFalse($result, t('Moving a missing file fails.'));
   }
 
   /**
@@ -67,14 +79,22 @@ class UnmanagedMoveTest extends FileTestBase {
     $file = $this->createFile();
 
     // Move the file onto itself without renaming shouldn't make changes.
-    $new_filepath = file_unmanaged_move($file->uri, $file->uri, FILE_EXISTS_REPLACE);
+    $new_filepath = file_unmanaged_move($file->uri, $file->uri, FILE_CHECK_EXISTS_FALSE);
     $this->assertFalse($new_filepath, t('Moving onto itself without renaming fails.'));
     $this->assertTrue(file_exists($file->uri), t('File exists after moving onto itself.'));
 
     // Move the file onto itself with renaming will result in a new filename.
-    $new_filepath = file_unmanaged_move($file->uri, $file->uri, FILE_EXISTS_RENAME);
+    $new_filepath = file_unmanaged_move($file->uri, $file->uri);
     $this->assertTrue($new_filepath, t('Moving onto itself with renaming works.'));
     $this->assertFalse(file_exists($file->uri), t('Original file has been removed.'));
     $this->assertTrue(file_exists($new_filepath), t('File exists after moving onto itself.'));
+
+    // Move the file onto itself without renaming doesn't work.
+    $new_filepath = file_unmanaged_move($file->uri, $file->uri, FILE_CHECK_EXISTS_FALSE);
+    $this->assertFalse($new_filepath, t('Copying the file onto itself without renaming doesn\'t work.'));
+
+    // Copy the file into same directory without renaming doesn't work.
+    $new_filepath = file_unmanaged_move($file->uri, drupal_dirname($file->uri), FILE_CHECK_EXISTS_FALSE);
+    $this->assertFalse($new_filepath, t('Copy the file into same directory without renaming doesn\'t work.'));
   }
 }
diff --git a/core/modules/system/lib/Drupal/system/Tests/File/UnmanagedSaveDataTest.php b/core/modules/system/lib/Drupal/system/Tests/File/UnmanagedSaveDataTest.php
index 6494b86..0e08d45 100644
--- a/core/modules/system/lib/Drupal/system/Tests/File/UnmanagedSaveDataTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/File/UnmanagedSaveDataTest.php
@@ -32,7 +32,7 @@ class UnmanagedSaveDataTest extends FileTestBase {
     $this->assertEqual($contents, file_get_contents($filepath), t('Contents of the file are correct.'));
 
     // Provide a filename.
-    $filepath = file_unmanaged_save_data($contents, 'public://asdf.txt', FILE_EXISTS_REPLACE);
+    $filepath = file_unmanaged_save_data($contents, 'public://asdf.txt', FILE_CHECK_EXISTS_FALSE);
     $this->assertTrue($filepath, t('Unnamed file saved correctly.'));
     $this->assertEqual('asdf.txt', drupal_basename($filepath), t('File was named correctly.'));
     $this->assertEqual($contents, file_get_contents($filepath), t('Contents of the file are correct.'));
diff --git a/core/modules/system/lib/Drupal/system/Tests/Image/FileMoveTest.php b/core/modules/system/lib/Drupal/system/Tests/Image/FileMoveTest.php
index ebd2a5d..a6c3cc3 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Image/FileMoveTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Image/FileMoveTest.php
@@ -38,13 +38,10 @@ class FileMoveTest extends ToolkitTestBase {
     // Check if derivative image exists.
     $this->assertTrue(file_exists($derivative_uri), 'Make sure derivative image is generated successfully.');
 
-    // Clone the object so we don't have to worry about the function changing
-    // our reference copy.
-    $desired_filepath = 'public://' . $this->randomName();
-    $result = file_move(clone $file, $desired_filepath, FILE_EXISTS_ERROR);
+    file_move($file, 'public://' . $this->randomName());
 
     // Check if image has been moved.
-    $this->assertTrue(file_exists($result->uri), 'Make sure image is moved successfully.');
+    $this->assertTrue(file_exists($file->uri), 'Make sure image is moved successfully.');
 
     // Check if derivative image has been flushed.
     $this->assertFalse(file_exists($derivative_uri), 'Make sure derivative image has been flushed.');
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index a530c30..72c8429 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -3750,22 +3750,17 @@ function system_image_toolkits() {
  *   be used instead.
  *   If this value is omitted, the site's default files scheme will be used,
  *   usually "public://".
- *
- * @param $managed boolean
- *   If this is set to TRUE, the file API hooks will be invoked and the file is
- *   registered in the database.
- *
- * @param $replace boolean
- *   Replace behavior when the destination file already exists:
- *   - FILE_EXISTS_REPLACE: Replace the existing file.
- *   - FILE_EXISTS_RENAME: Append _{incrementing number} until the filename is
- *     unique.
- *   - FILE_EXISTS_ERROR: Do nothing and return FALSE.
+ * @param $check_exists
+ *   The destination URI will be renamed if it already exists by appending
+ *   _{incrementing number} until it is unique.
+ *   - FILE_CHECK_EXISTS_FALSE - Don't check if it exists.
+ *   - FILE_CHECK_EXISTS_FS - Just check the filesystem.
+ *   - FILE_CHECK_EXISTS_DB_FS - Check the database, then the filesystem.
  *
  * @return
  *   On success the location the file was saved to, FALSE on failure.
  */
-function system_retrieve_file($url, $destination = NULL, $managed = FALSE, $replace = FILE_EXISTS_RENAME) {
+function system_retrieve_file($url, $destination = NULL, $check_exists = FILE_CHECK_EXISTS_FS) {
   $parsed_url = parse_url($url);
   if (!isset($destination)) {
     $path = file_build_uri(drupal_basename($parsed_url['path']));
@@ -3784,7 +3779,7 @@ function system_retrieve_file($url, $destination = NULL, $managed = FALSE, $repl
     drupal_set_message(t('HTTP error @errorcode occurred when trying to fetch @remote.', array('@errorcode' => $result->code, '@remote' => $url)), 'error');
     return FALSE;
   }
-  $local = $managed ? file_save_data($result->data, $path, $replace) : file_unmanaged_save_data($result->data, $path, $replace);
+  $local = file_unmanaged_save_data($result->data, $path, $check_exists);
   if (!$local) {
     drupal_set_message(t('@remote could not be saved to @path.', array('@remote' => $url, '@path' => $path)), 'error');
   }
diff --git a/core/modules/system/tests/modules/file_test/file_test.module b/core/modules/system/tests/modules/file_test/file_test.module
index 20e45cb..1155489 100644
--- a/core/modules/system/tests/modules/file_test/file_test.module
+++ b/core/modules/system/tests/modules/file_test/file_test.module
@@ -53,16 +53,6 @@ function _file_test_form($form, &$form_state) {
     '#type' => 'file',
     '#title' => t('Upload a file'),
   );
-  $form['file_test_replace'] = array(
-    '#type' => 'select',
-    '#title' => t('Replace existing image'),
-    '#options' => array(
-      FILE_EXISTS_RENAME => t('Appends number until name is unique'),
-      FILE_EXISTS_REPLACE => t('Replace the existing file'),
-      FILE_EXISTS_ERROR => t('Fail with an error'),
-    ),
-    '#default_value' => FILE_EXISTS_RENAME,
-  );
   $form['file_subdir'] = array(
     '#type' => 'textfield',
     '#title' => t('Subdirectory for test file'),
@@ -121,7 +111,7 @@ function _file_test_form_submit(&$form, &$form_state) {
     $validators['file_validate_extensions'] = array($form_state['values']['extensions']);
   }
 
-  $file = file_save_upload('file_test_upload', $validators, $destination, $form_state['values']['file_test_replace']);
+  $file = file_save_upload('file_test_upload', $validators, $destination);
   if ($file) {
     $form_state['values']['file_test_upload'] = $file;
     drupal_set_message(t('File @filepath was uploaded.', array('@filepath' => $file->uri)));
diff --git a/core/modules/update/update.manager.inc b/core/modules/update/update.manager.inc
index 5720af7..4e591b9 100644
--- a/core/modules/update/update.manager.inc
+++ b/core/modules/update/update.manager.inc
@@ -645,7 +645,7 @@ function update_manager_install_form_submit($form, &$form_state) {
   elseif ($_FILES['files']['name']['project_upload']) {
     $validators = array('file_validate_extensions' => array(archiver_get_extensions()));
     $field = 'project_upload';
-    if (!($finfo = file_save_upload($field, $validators, NULL, FILE_EXISTS_REPLACE))) {
+    if (!($finfo = file_save_upload($field, $validators))) {
       // Failed to upload the file. file_save_upload() calls form_set_error() on
       // failure.
       return;
@@ -836,7 +836,7 @@ function update_manager_file_get($url) {
   $local = $cache_directory . '/' . drupal_basename($parsed_url['path']);
 
   if (!file_exists($local) || update_delete_file_if_stale($local)) {
-    return system_retrieve_file($url, $local, FALSE, FILE_EXISTS_REPLACE);
+    return system_retrieve_file($url, $local, FILE_CHECK_EXISTS_FALSE);
   }
   else {
     return $local;
diff --git a/core/modules/user/lib/Drupal/user/UserStorageController.php b/core/modules/user/lib/Drupal/user/UserStorageController.php
index bde430c..2d4f0e2 100644
--- a/core/modules/user/lib/Drupal/user/UserStorageController.php
+++ b/core/modules/user/lib/Drupal/user/UserStorageController.php
@@ -124,7 +124,7 @@ class UserStorageController extends DatabaseStorageController {
           $destination = file_stream_wrapper_uri_normalize($picture_directory . '/picture-' . $entity->uid . '-' . REQUEST_TIME . '.' . $info['extension']);
 
           // Move the temporary file into the final location.
-          if ($picture = file_move($picture, $destination, FILE_EXISTS_RENAME)) {
+          if (file_move($picture, $destination)) {
             $entity->picture = $picture;
             file_usage_add($picture, 'user', 'user', $entity->uid);
           }
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index e373062..dd17075 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -600,22 +600,6 @@ function user_file_download($uri) {
 }
 
 /**
- * Implements hook_file_move().
- */
-function user_file_move(File $file, File $source) {
-  // If a user's picture is replaced with a new one, update the record in
-  // the users table.
-  if (isset($file->fid) && isset($source->fid) && $file->fid != $source->fid) {
-    db_update('users')
-      ->fields(array(
-        'picture' => $file->fid,
-      ))
-      ->condition('picture', $source->fid)
-      ->execute();
-  }
-}
-
-/**
  * Implements hook_file_predelete().
  */
 function user_file_predelete(File $file) {
