diff --git includes/file.inc includes/file.inc
index ec52f62..114b626 100644
--- includes/file.inc
+++ includes/file.inc
@@ -202,6 +202,7 @@ function file_stream_wrapper_valid_scheme($scheme) {
   }
 }
 
+
 /**
  * Returns the part of an URI after the schema.
  *
@@ -594,9 +595,9 @@ function file_usage_list(stdClass $file) {
  * @param $module
  *   The name of the module using the file.
  * @param $type
- *   The type of the object that contains the referenced file. 
+ *   The type of the object that contains the referenced file.
  * @param $id
- *   The unique, numeric ID of the object containing the referenced file. 
+ *   The unique, numeric ID of the object containing the referenced file.
  * @param $count
  *   (optional) The number of references to add to the object. Defaults to 1.
  *
@@ -710,6 +711,12 @@ function file_usage_delete(stdClass $file, $module, $type = NULL, $id = NULL, $c
  * @see hook_file_copy()
  */
 function file_copy(stdClass $source, $destination = NULL, $replace = FILE_EXISTS_RENAME) {
+  if (!file_valid_uri($destination)) {
+    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' => drupal_realpath($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;
@@ -741,6 +748,28 @@ function file_copy(stdClass $source, $destination = NULL, $replace = FILE_EXISTS
 }
 
 /**
+ * Determine whether the URI has a valid scheme for file API operations.
+ *
+ * There must be a scheme and it must be a Drupal-provided scheme like
+ * 'public', 'private', 'temporary', or an extension provided with
+ * hook_stream_wrappers().
+ *
+ * @param $uti
+ *   The URI to be tested.
+ *
+ * @return
+ *   TRUE if the URI is allowed.
+ */
+function file_valid_uri($uti) {
+  // Assert that the URI has an allowed scheme. Barepaths are not allowed.
+  $uri_scheme = file_uri_scheme($uri);
+  if (empty($uri_scheme) || !file_stream_wrapper_valid_scheme($uri_scheme)) {
+    return FALSE;
+  }
+  return TRUE;
+}
+
+/**
  * Copies a file to a new location without invoking the file API.
  *
  * This is a powerful function that in many ways performs like an advanced
@@ -752,11 +781,12 @@ function file_copy(stdClass $source, $destination = NULL, $replace = FILE_EXISTS
  *   replace the file or rename the file based on the $replace parameter.
  *
  * @param $source
- *   A string specifying the filepath or URI of the original file.
+ *   A string specifying the filepath or URI of the source file.
  * @param $destination
- *   A URI containing the destination that $source should be copied to.
- *   This must be a stream wrapper URI. If this value is omitted, Drupal's
- *   default files scheme will be used, usually "public://".
+ *   A URI containing the destination that $source should be copied 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 $replace
  *   Replace behavior when the destination file already exists:
  *   - FILE_EXISTS_REPLACE - Replace the existing file.
@@ -778,6 +808,7 @@ function file_unmanaged_copy($source, $destination = NULL, $replace = FILE_EXIST
   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');
+    watchdog('file', 'File %file (%realpath) could not be copied because it does not exist.', array('%file' => $original_source, '%realpath' => drupal_realpath($original_source)));
     return FALSE;
   }
 
@@ -786,11 +817,6 @@ function file_unmanaged_copy($source, $destination = NULL, $replace = FILE_EXIST
     $destination = file_build_uri(basename($source));
   }
 
-  // Assert that the destination contains a valid stream.
-  $destination_scheme = file_uri_scheme($destination);
-  if (!$destination_scheme || !file_stream_wrapper_valid_scheme($destination_scheme)) {
-    drupal_set_message(t('The specified file %file could not be copied, because the destination %destination is invalid. This is often caused by improper use of file_unmanaged_copy() or a missing stream wrapper.', array('%file' => $original_source, '%destination' => $destination)), 'error');
-  }
 
   // Prepare the destination directory.
   if (file_prepare_directory($destination)) {
@@ -802,7 +828,8 @@ function file_unmanaged_copy($source, $destination = NULL, $replace = FILE_EXIST
     $dirname = drupal_dirname($destination);
     if (!file_prepare_directory($dirname)) {
       // The destination is not valid.
-      drupal_set_message(t('The specified file %file could not be copied, because the destination %directory is not properly configured. This is often caused by a problem with file or directory permissions.', array('%file' => $original_source, '%directory' => $destination)), 'error');
+      watchdog('file', 'File %file could not be copied, because the destination directory %directory is not configured correctly.', array('%file' => $original_source, '%destination' => drupal_realpath($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;
     }
   }
@@ -810,20 +837,23 @@ function file_unmanaged_copy($source, $destination = NULL, $replace = FILE_EXIST
   // 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 (%directory)', array('%file' => $source, '%directory' => $destination)), 'error');
+    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' => drupal_realpath($destination)));
     return FALSE;
   }
 
   // Assert that the source and destination filenames are not the same.
   if (drupal_realpath($source) == drupal_realpath($destination)) {
     drupal_set_message(t('The specified file %file was not copied because it would overwrite itself.', array('%file' => $source)), 'error');
+    watchdog('file', 'File %file could not be copied because it would overwrite itself.', array('%file' => $source));
     return FALSE;
   }
   // Make sure the .htaccess files are present.
   file_ensure_htaccess();
   // Perform the copy operation.
   if (!@copy($source, $destination)) {
-    watchdog('file', 'The specified file %file could not be copied to %destination.', array('%file' => $source, '%destination' => $destination), WATCHDOG_ERROR);
+    drupal_set_message(t('The specified file %file could not be copied.', array('%file' => $source)), 'error');
+    watchdog('file', 'The specified file %file could not be copied to %destination.', array('%file' => $source, '%destination' => drupal_realpath($destination)), WATCHDOG_ERROR);
     return FALSE;
   }
 
@@ -914,6 +944,12 @@ function file_destination($destination, $replace) {
  * @see hook_file_move()
  */
 function file_move(stdClass $source, $destination = NULL, $replace = FILE_EXISTS_RENAME) {
+  if (!file_valid_uri($destination)) {
+    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' => drupal_realpath($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;
 
@@ -1134,6 +1170,12 @@ function file_create_filename($basename, $directory) {
  * @see hook_file_delete()
  */
 function file_delete(stdClass $file, $force = FALSE) {
+  if (!file_valid_uri($file->uri)) {
+    watchdog('file', 'File %file (%realpath) could not be deleted because it is not a valid URI. This may be caused by improper use of file_delete() or a missing stream wrapper.', array('%file' => $file->uri, '%realpath' => drupal_realpath($file->uri)));
+    drupal_set_message(t('The specified file %file could not be deleted, because it is not a valid URI. More information is available in the system log.', array('%file' => $file->uri)), 'error');
+    return FALSE;
+  }
+
   // If any module still has a usage entry in the file_usage table, the file
   // will not be deleted, but file_delete() will return a populated array
   // that tests as TRUE.
@@ -1689,6 +1731,12 @@ function file_validate_image_resolution(stdClass $file, $maximum_dimensions = 0,
 function file_save_data($data, $destination = NULL, $replace = FILE_EXISTS_RENAME) {
   global $user;
 
+  if (!file_valid_uri($destination)) {
+    watchdog('file', 'File %file (%realpath) 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('%file' => $source->uri, '%realpath' => drupal_realpath($source->uri), '%destination' => $destination));
+    drupal_set_message(t('The specified file %file could not be saved, because the destination is invalid. More information is available in the system log.', array('%file' => $source->uri)), 'error');
+    return FALSE;
+  }
+
   if ($uri = file_unmanaged_save_data($data, $destination, $replace)) {
     // Create a file object.
     $file = new stdClass();
diff --git modules/file/tests/file.test modules/file/tests/file.test
index 7c9d643..ae7fef7 100644
--- modules/file/tests/file.test
+++ modules/file/tests/file.test
@@ -116,11 +116,11 @@ class FileFieldTestCase extends DrupalWebTestCase {
     if (is_numeric($nid_or_type)) {
       $node = node_load($nid_or_type);
       $delta = isset($node->$field_name) ? count($node->$field_name) : 0;
-      $edit['files[' . $field_name . '_' . LANGUAGE_NONE . '_' . $delta . ']'] = realpath($file->uri);
+      $edit['files[' . $field_name . '_' . LANGUAGE_NONE . '_' . $delta . ']'] = drupal_realpath($file->uri);
       $this->drupalPost('node/' . $nid_or_type . '/edit', $edit, t('Save'));
     }
     else {
-      $edit['files[' . $field_name . '_' . LANGUAGE_NONE . '_0]'] = realpath($file->uri);
+      $edit['files[' . $field_name . '_' . LANGUAGE_NONE . '_0]'] = drupal_realpath($file->uri);
       $type_name = str_replace('_', '-', $nid_or_type);
       $this->drupalPost('node/add/' . $type_name, $edit, t('Save'));
     }
@@ -149,7 +149,7 @@ class FileFieldTestCase extends DrupalWebTestCase {
    */
   function replaceNodeFile($file, $field_name, $nid, $new_revision = TRUE) {
     $edit = array(
-      'files[' . $field_name . '_' . LANGUAGE_NONE . '_0]' => realpath($file->uri),
+      'files[' . $field_name . '_' . LANGUAGE_NONE . '_0]' => drupal_realpath($file->uri),
       'revision' => (string) (int) $new_revision,
     );
 
@@ -566,6 +566,8 @@ class FileFieldValidateTestCase extends FileFieldTestCase {
 
     // Create a new node with the uploaded file.
     $nid = $this->uploadNodeFile($test_file, $field_name, $type_name);
+    $this->assertTrue($nid !== FALSE, t('uploadNodeFile(@test_file, @field_name, @type_name) succeeded', array('@test_file' => $test_file->uri, '@field_name' => $field_name, '@type_name' => $type_name)));
+
     $node = node_load($nid, NULL, TRUE);
 
     $node_file = (object) $node->{$field_name}[LANGUAGE_NONE][0];
diff --git modules/image/image.test modules/image/image.test
index 5da9b37..93243e8 100644
--- modules/image/image.test
+++ modules/image/image.test
@@ -94,7 +94,7 @@ class ImageFieldTestCase extends DrupalWebTestCase {
     $edit = array(
       'title' => $this->randomName(),
     );
-    $edit['files[' . $field_name . '_' . LANGUAGE_NONE . '_0]'] = realpath($image->uri);
+    $edit['files[' . $field_name . '_' . LANGUAGE_NONE . '_0]'] = drupal_realpath($image->uri);
     $this->drupalPost('node/add/' . $type, $edit, t('Save'));
 
     // Retrieve ID of the newly created node from the current URL.
@@ -747,7 +747,7 @@ class ImageFieldDisplayTestCase extends ImageFieldTestCase {
     // Add a default image to the imagefield instance.
     $images = $this->drupalGetTestFiles('image');
     $edit = array(
-      'files[field_settings_default_image]' => realpath($images[0]->uri),
+      'files[field_settings_default_image]' => drupal_realpath($images[0]->uri),
     );
     $this->drupalPost('admin/structure/types/manage/article/fields/' . $field_name, $edit, t('Save settings'));
     // Clear field info cache so the new default image is detected.
diff --git modules/system/system.test modules/system/system.test
index 805d59a..acee974 100644
--- modules/system/system.test
+++ modules/system/system.test
@@ -1299,13 +1299,14 @@ class SystemThemeFunctionalTest extends DrupalWebTestCase {
   function testThemeSettings() {
     // Specify a filesystem path to be used for the logo.
     $file = current($this->drupalGetTestFiles('image'));
+    $fullpath = drupal_realpath($file->uri);
     $edit = array(
       'default_logo' => FALSE,
-      'logo_path' => $file->uri,
+      'logo_path' => $fullpath,
     );
     $this->drupalPost('admin/appearance/settings', $edit, t('Save configuration'));
     $this->drupalGet('node');
-    $this->assertRaw($file->uri, t('Logo path successfully changed.'));
+    $this->assertRaw($fullpath, t('Logo path successfully changed.'));
 
     // Upload a file to use for the logo.
     $file = current($this->drupalGetTestFiles('image'));
