diff --git a/core/includes/file.entity.inc b/core/includes/file.entity.inc
new file mode 100644
index 0000000..549a43d
--- /dev/null
+++ b/core/includes/file.entity.inc
@@ -0,0 +1,134 @@
+<?php
+
+/**
+ * @file
+ * Entity controller and class for files.
+ */
+
+/**
+ * Defines the comment entity class.
+ */
+class File extends Entity {
+
+  /**
+   * The file ID.
+   *
+   * @var integer
+   */
+  public $fid;
+
+  /**
+   * The uid of the user who is associated with the file.
+   *
+   * @var integer
+   */
+  public $uid;
+
+  /**
+   * Name of the file with no path components.
+   *
+   * This may differ from the basename of the URI if the file is renamed to
+   * avoid overwriting an existing file.
+   *
+   * @var string
+   */
+  public $filename;
+
+  /**
+   * The URI to access the file (either local or remote).
+   *
+   * @var string
+   */
+  public $uri;
+
+  /**
+   * The file's MIME type.
+   *
+   * @var string
+   */
+  public $filemime;
+
+  /**
+   * The size of the file in bytes.
+   *
+   * @var string
+   */
+  public $filesize;
+
+  /**
+   * A field indicating the status of the file.
+   *
+   * Two status are defined in core: temporary (0) and permanent (1).
+   * Temporary files older than DRUPAL_MAXIMUM_TEMP_FILE_AGE will be removed
+   * during a cron run.
+   *
+   * @var integer
+   */
+  public $status;
+
+  /**
+   * UNIX timestamp for when the file was added.
+   *
+   * @var integer
+   */
+  public $timestamp;
+
+}
+
+/**
+ * File storage controller for files.
+ */
+class FileStorageController extends EntityDatabaseStorageController {
+
+  /**
+   * Overrides EntityDatabaseStorageController::presave().
+   */
+  protected function preSave(EntityInterface $entity) {
+    $entity->timestamp = REQUEST_TIME;
+    $entity->filesize = filesize($entity->uri);
+  }
+
+  /**
+   * Overrides EntityDatabaseStorageController::delete().
+   *
+   * file_usage_list() is called to determine if the file is being used by any
+   * modules. If the file is being used the delete will be canceled.
+   */
+  public function delete($ids) {
+    foreach (file_load_multiple($ids) as $file) {
+      if (!file_valid_uri($file->uri)) {
+        if (($realpath = drupal_realpath($file->uri)) !== FALSE) {
+          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' => $realpath));
+        }
+        else {
+          watchdog('file', 'File %file 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));
+        }
+        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');
+        continue;
+      }
+
+      // 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.
+      if ($references = file_usage_list($file)) {
+        continue;
+      }
+
+      // Let other modules clean up any references to the file prior to deletion.
+      module_invoke_all('file_predelete', $file);
+      module_invoke_all('entity_predelete', $file, 'file');
+
+      // Make sure the file is deleted before removing its row from the
+      // database, so UIs can still find the file in the database.
+      if (file_unmanaged_delete($file->uri)) {
+        db_delete('file_managed')->condition('fid', $file->fid)->execute();
+        db_delete('file_usage')->condition('fid', $file->fid)->execute();
+
+        // Let other modules respond to file deletion.
+        module_invoke_all('file_delete', $file);
+        module_invoke_all('entity_delete', $file, 'file');
+      }
+    }
+  }
+
+}
diff --git a/core/includes/file.inc b/core/includes/file.inc
index babf465..dab25c7 100644
--- a/core/includes/file.inc
+++ b/core/includes/file.inc
@@ -557,44 +557,12 @@ function file_load($fid) {
 /**
  * Save a file object to the database.
  *
- * If the $file->fid is not set a new record will be added.
- *
  * @param $file
  *   A file object returned by file_load().
  *
- * @return
- *   The updated file object.
- *
- * @see hook_file_insert()
- * @see hook_file_update()
  */
-function file_save(stdClass $file) {
-  $file->timestamp = REQUEST_TIME;
-  $file->filesize = filesize($file->uri);
-
-  // Load the stored entity, if any.
-  if (!empty($file->fid) && !isset($file->original)) {
-    $file->original = entity_load_unchanged('file', $file->fid);
-  }
-
-  module_invoke_all('file_presave', $file);
-  module_invoke_all('entity_presave', $file, 'file');
-
-  if (empty($file->fid)) {
-    drupal_write_record('file_managed', $file);
-    // Inform modules about the newly added file.
-    module_invoke_all('file_insert', $file);
-    module_invoke_all('entity_insert', $file, 'file');
-  }
-  else {
-    drupal_write_record('file_managed', $file, 'fid');
-    // Inform modules that the file has been updated.
-    module_invoke_all('file_update', $file);
-    module_invoke_all('entity_update', $file, 'file');
-  }
-
-  unset($file->original);
-  return $file;
+function file_save(File $file) {
+  $file->save();
 }
 
 /**
@@ -611,7 +579,7 @@ function file_save(stdClass $file) {
  * @see file_usage_add()
  * @see file_usage_delete()
  */
-function file_usage_list(stdClass $file) {
+function file_usage_list(File $file) {
   $result = db_select('file_usage', 'f')
     ->fields('f', array('module', 'type', 'id', 'count'))
     ->condition('fid', $file->fid)
@@ -651,7 +619,7 @@ function file_usage_list(stdClass $file) {
  * @see file_usage_list()
  * @see file_usage_delete()
  */
-function file_usage_add(stdClass $file, $module, $type, $id, $count = 1) {
+function file_usage_add(File $file, $module, $type, $id, $count = 1) {
   db_merge('file_usage')
     ->key(array(
       'fid' => $file->fid,
@@ -689,7 +657,7 @@ function file_usage_add(stdClass $file, $module, $type, $id, $count = 1) {
  * @see file_usage_list()
  * @see file_delete()
  */
-function file_usage_delete(stdClass $file, $module, $type = NULL, $id = NULL, $count = 1) {
+function file_usage_delete(File $file, $module, $type = NULL, $id = NULL, $count = 1) {
   // Delete rows that have a exact or less value to prevent empty rows.
   $query = db_delete('file_usage')
     ->condition('module', $module)
@@ -754,7 +722,7 @@ function file_usage_delete(stdClass $file, $module, $type = NULL, $id = NULL, $c
  * @see file_unmanaged_copy()
  * @see hook_file_copy()
  */
-function file_copy(stdClass $source, $destination = NULL, $replace = FILE_EXISTS_RENAME) {
+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));
@@ -786,7 +754,7 @@ function file_copy(stdClass $source, $destination = NULL, $replace = FILE_EXISTS
       $file->filename = basename($destination);
     }
 
-    $file = file_save($file);
+    file_save($file);
 
     // Inform modules that the file has been copied.
     module_invoke_all('file_copy', $file, $source);
@@ -1004,7 +972,7 @@ function file_destination($destination, $replace) {
  * @see file_unmanaged_move()
  * @see hook_file_move()
  */
-function file_move(stdClass $source, $destination = NULL, $replace = FILE_EXISTS_RENAME) {
+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));
@@ -1036,14 +1004,14 @@ function file_move(stdClass $source, $destination = NULL, $replace = FILE_EXISTS
       $file->filename = basename($destination);
     }
 
-    $file = file_save($file);
+    file_save($file);
 
     // Inform modules that the file has been moved.
     module_invoke_all('file_move', $file, $source);
 
     if ($delete_source) {
       // Try a soft delete to remove original if it's not in use elsewhere.
-      file_delete($source);
+      file_delete($source->fid);
     }
 
     return $file;
@@ -1216,62 +1184,35 @@ function file_create_filename($basename, $directory) {
 /**
  * Delete a file and its database record.
  *
- * If the $force parameter is not TRUE, file_usage_list() will be called to
+ * file_usage_list() will be called to
  * determine if the file is being used by any modules. If the file is being
  * used the delete will be canceled.
  *
- * @param $file
- *   A file object.
- * @param $force
- *   Boolean indicating that the file should be deleted even if the file is
- *   reported as in use by the file_usage table.
- *
- * @return mixed
- *   TRUE for success, FALSE in the event of an error, or an array if the file
- *   is being used by any modules.
+ * @param $fid
+ *   The file id.
  *
  * @see file_unmanaged_delete()
  * @see file_usage_list()
- * @see file_usage_delete()
- * @see hook_file_predelete()
- * @see hook_file_delete()
  */
-function file_delete(stdClass $file, $force = FALSE) {
-  if (!file_valid_uri($file->uri)) {
-    if (($realpath = drupal_realpath($file->uri)) !== FALSE) {
-      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' => $realpath));
-    }
-    else {
-      watchdog('file', 'File %file 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));
-    }
-    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.
-  if (!$force && ($references = file_usage_list($file))) {
-    return $references;
-  }
-
-  // Let other modules clean up any references to the file prior to deletion.
-  module_invoke_all('file_predelete', $file);
-  module_invoke_all('entity_predelete', $file, 'file');
-
-  // Make sure the file is deleted before removing its row from the
-  // database, so UIs can still find the file in the database.
-  if (file_unmanaged_delete($file->uri)) {
-    db_delete('file_managed')->condition('fid', $file->fid)->execute();
-    db_delete('file_usage')->condition('fid', $file->fid)->execute();
-
-    // Let other modules respond to file deletion.
-    module_invoke_all('file_delete', $file);
-    module_invoke_all('entity_delete', $file, 'file');
+function file_delete($fid) {
+  return file_delete_multiple(array($fid));
+}
 
-    return TRUE;
-  }
-  return FALSE;
+/**
+ * Delete files.
+ *
+ * file_usage_list() will be called to
+ * determine if the file is being used by any modules. If the file is being
+ * used the delete will be canceled.
+ *
+ * @param $fid
+ *   The file id.
+ *
+ * @see file_unmanaged_delete()
+ * @see file_usage_list()
+ */
+function file_delete_multiple(array $fids) {
+  entity_delete_multiple('file', $fids);
 }
 
 /**
@@ -1454,7 +1395,7 @@ function file_save_upload($source, $validators = array(), $destination = FALSE,
   }
 
   // Begin building file object.
-  $file = new stdClass();
+  $file = entity_create('file', array());
   $file->uid      = $user->uid;
   $file->status   = 0;
   $file->filename = trim(basename($_FILES['files']['name'][$source]), '.');
@@ -1572,7 +1513,7 @@ function file_save_upload($source, $validators = array(), $destination = FALSE,
   }
 
   // If we made it this far it's safe to record this file in the database.
-  if ($file = file_save($file)) {
+  if (file_save($file)) {
     // Add file to the cache.
     $upload_cache[$source] = $file;
     return $file;
@@ -1638,7 +1579,7 @@ function drupal_move_uploaded_file($filename, $uri) {
  *
  * @see hook_file_validate()
  */
-function file_validate(stdClass &$file, $validators = array()) {
+function file_validate(File &$file, $validators = array()) {
   // Call the validation functions specified by this function's caller.
   $errors = array();
   foreach ($validators as $function => $args) {
@@ -1660,7 +1601,7 @@ function file_validate(stdClass &$file, $validators = array()) {
  * @return
  *   An array. If the file name is too long, it will contain an error message.
  */
-function file_validate_name_length(stdClass $file) {
+function file_validate_name_length(File $file) {
   $errors = array();
 
   if (empty($file->filename)) {
@@ -1686,7 +1627,7 @@ function file_validate_name_length(stdClass $file) {
  *
  * @see hook_file_validate()
  */
-function file_validate_extensions(stdClass $file, $extensions) {
+function file_validate_extensions(File $file, $extensions) {
   $errors = array();
 
   $regex = '/\.(' . preg_replace('/ +/', '|', preg_quote($extensions)) . ')$/i';
@@ -1716,7 +1657,7 @@ function file_validate_extensions(stdClass $file, $extensions) {
  *
  * @see hook_file_validate()
  */
-function file_validate_size(stdClass $file, $file_limit = 0, $user_limit = 0) {
+function file_validate_size(File $file, $file_limit = 0, $user_limit = 0) {
   global $user;
 
   $errors = array();
@@ -1746,7 +1687,7 @@ function file_validate_size(stdClass $file, $file_limit = 0, $user_limit = 0) {
  *
  * @see hook_file_validate()
  */
-function file_validate_is_image(stdClass $file) {
+function file_validate_is_image(File $file) {
   $errors = array();
 
   $info = image_get_info($file->uri);
@@ -1781,7 +1722,7 @@ function file_validate_is_image(stdClass $file) {
  *
  * @see hook_file_validate()
  */
-function file_validate_image_resolution(stdClass $file, $maximum_dimensions = 0, $minimum_dimensions = 0) {
+function file_validate_image_resolution(File $file, $maximum_dimensions = 0, $minimum_dimensions = 0) {
   $errors = array();
 
   // Check first that the file is an image.
@@ -1852,7 +1793,7 @@ function file_save_data($data, $destination = NULL, $replace = FILE_EXISTS_RENAM
 
   if ($uri = file_unmanaged_save_data($data, $destination, $replace)) {
     // Create a file object.
-    $file = new stdClass();
+    $file = entity_create('file', array());
     $file->fid = NULL;
     $file->uri = $uri;
     $file->filename = basename($uri);
@@ -1874,7 +1815,8 @@ function file_save_data($data, $destination = NULL, $replace = FILE_EXISTS_RENAM
       $file->filename = basename($destination);
     }
 
-    return file_save($file);
+    file_save($file);
+    return $file;
   }
   return FALSE;
 }
diff --git a/core/modules/entity/entity.class.inc b/core/modules/entity/entity.class.inc
index 1dec8ee..8cdda64 100644
--- a/core/modules/entity/entity.class.inc
+++ b/core/modules/entity/entity.class.inc
@@ -163,6 +163,9 @@ class Entity implements EntityInterface {
    * Sets up the object instance on construction or unserialization.
    */
   protected function setUp() {
+    if (!function_exists('entity_get_info')) {
+      debug_print_backtrace();
+    }
     $this->entityInfo = entity_get_info($this->entityType);
     $this->idKey = $this->entityInfo['entity keys']['id'];
     $this->bundleKey = isset($this->entityInfo['entity keys']['bundle']) ? $this->entityInfo['entity keys']['bundle'] : NULL;
diff --git a/core/modules/entity/tests/entity_crud_hook_test.test b/core/modules/entity/tests/entity_crud_hook_test.test
index 2bb459f..9a43b9a 100644
--- a/core/modules/entity/tests/entity_crud_hook_test.test
+++ b/core/modules/entity/tests/entity_crud_hook_test.test
@@ -129,7 +129,7 @@ class EntityCrudHookTestCase extends DrupalWebTestCase {
   public function testFileHooks() {
     $url = 'public://entity_crud_hook_test.file';
     file_put_contents($url, 'Test test test');
-    $file = (object) array(
+    $file = entity_create('file', array(
       'fid' => NULL,
       'uid' => 1,
       'filename' => 'entity_crud_hook_test.file',
@@ -138,7 +138,7 @@ class EntityCrudHookTestCase extends DrupalWebTestCase {
       'filesize' => filesize($url),
       'status' => 1,
       'timestamp' => REQUEST_TIME,
-    );
+    ));
     $_SESSION['entity_crud_hook_test'] = array();
     file_save($file);
 
@@ -169,7 +169,7 @@ class EntityCrudHookTestCase extends DrupalWebTestCase {
     ));
 
     $_SESSION['entity_crud_hook_test'] = array();
-    file_delete($file);
+    file_delete($file->fid);
 
     $this->assertHookMessageOrder(array(
       'entity_crud_hook_test_file_predelete called',
diff --git a/core/modules/file/file.field.inc b/core/modules/file/file.field.inc
index a46ed1a..ec1de42 100644
--- a/core/modules/file/file.field.inc
+++ b/core/modules/file/file.field.inc
@@ -353,7 +353,7 @@ function file_field_delete_file($item, $field, $entity_type, $id, $count = 1) {
   $file_usage = file_usage_list($file);
   if ($file->status == 0 || !empty($file_usage['file'])) {
     file_usage_delete($file, 'file', $entity_type, $id, $count);
-    return file_delete($file);
+    return file_delete($file->fid);
   }
 
   // Even if the file is not deleted, return TRUE to indicate the file field
diff --git a/core/modules/file/file.module b/core/modules/file/file.module
index 68204aa..d3a8ce6 100644
--- a/core/modules/file/file.module
+++ b/core/modules/file/file.module
@@ -602,7 +602,7 @@ function file_managed_file_submit($form, &$form_state) {
     // If it's a temporary file we can safely remove it immediately, otherwise
     // it's up to the implementing module to clean up files that are in use.
     if ($element['#file'] && $element['#file']->status == 0) {
-      file_delete($element['#file']);
+      file_delete($element['#file']->fid);
     }
     // Update both $form_state['values'] and $form_state['input'] to reflect
     // that the file has been removed, so that the form is rebuilt correctly.
diff --git a/core/modules/simpletest/tests/file.test b/core/modules/simpletest/tests/file.test
index 7496902..0d7064b 100644
--- a/core/modules/simpletest/tests/file.test
+++ b/core/modules/simpletest/tests/file.test
@@ -224,7 +224,7 @@ class FileTestCase extends DrupalWebTestCase {
     // invoke the hooks.
     $this->assertNotIdentical(drupal_write_record('file_managed', $file), FALSE, t('The file was added to the database.'), 'Create test file');
 
-    return $file;
+    return entity_create('file', (array)$file);
   }
 }
 
@@ -370,11 +370,11 @@ class FileValidatorTest extends DrupalWebTestCase {
   function setUp() {
     parent::setUp();
 
-    $this->image = new stdClass();
+    $this->image = entity_create('file', array());
     $this->image->uri = 'core/misc/druplicon.png';
     $this->image->filename = basename($this->image->uri);
 
-    $this->non_image = new stdClass();
+    $this->image = entity_create('file', array());
     $this->non_image->uri = 'core/misc/jquery.js';
     $this->non_image->filename = basename($this->non_image->uri);
   }
@@ -594,7 +594,7 @@ class FileSaveUploadTest extends FileHookTestCase {
     $this->drupalLogin($account);
 
     $image_files = $this->drupalGetTestFiles('image');
-    $this->image = current($image_files);
+    $this->image = entity_create('file', (array)current($image_files));
 
     list(, $this->image_extension) = explode('.', $this->image->filename);
     $this->assertTrue(is_file($this->image->uri), t("The image file we're going to upload exists."));
@@ -1546,8 +1546,9 @@ class FileDeleteTest extends FileHookTestCase {
 
     // Check that deletion removes the file and database record.
     $this->assertTrue(is_file($file->uri), t('File exists.'));
-    $this->assertIdentical(file_delete($file), TRUE, t('Delete worked.'));
-    $this->assertFileHooksCalled(array('delete'));
+    file_delete($file->fid);
+    // Load is called inside the delete() implementation.
+    $this->assertFileHooksCalled(array('delete', 'load'));
     $this->assertFalse(file_exists($file->uri), t('Test file has actually been deleted.'));
     $this->assertFalse(file_load($file->fid), t('File was removed from the database.'));
   }
@@ -1561,7 +1562,7 @@ class FileDeleteTest extends FileHookTestCase {
     file_usage_add($file, 'testing', 'test', 1);
 
     file_usage_delete($file, 'testing', 'test', 1);
-    file_delete($file);
+    file_delete($file->fid);
     $usage = file_usage_list($file);
     $this->assertEqual($usage['testing']['test'], array(1 => 1), t('Test file is still in use.'));
     $this->assertTrue(file_exists($file->uri), t('File still exists on the disk.'));
@@ -1571,9 +1572,9 @@ class FileDeleteTest extends FileHookTestCase {
     file_test_reset();
 
     file_usage_delete($file, 'testing', 'test', 1);
-    file_delete($file);
+    file_delete($file->fid);
     $usage = file_usage_list($file);
-    $this->assertFileHooksCalled(array('delete'));
+    $this->assertFileHooksCalled(array('delete', 'load'));
     $this->assertTrue(empty($usage), t('File usage data was removed.'));
     $this->assertFalse(file_exists($file->uri), t('File has been deleted after its last usage was removed.'));
     $this->assertFalse(file_load($file->fid), t('File was removed from the database.'));
@@ -1985,45 +1986,45 @@ class FileSaveTest extends FileHookTestCase {
 
   function testFileSave() {
     // Create a new file object.
-    $file = array(
+    $file = entity_create('file', array(
       'uid' => 1,
       'filename' => 'druplicon.txt',
       'uri' => 'public://druplicon.txt',
       'filemime' => 'text/plain',
       'timestamp' => 1,
       'status' => FILE_STATUS_PERMANENT,
-    );
-    $file = (object) $file;
+    ));
     file_put_contents($file->uri, 'hello world');
+    debug($file);
 
     // Save it, inserting a new record.
-    $saved_file = file_save($file);
+    file_save($file);
 
     // Check that the correct hooks were called.
     $this->assertFileHooksCalled(array('insert'));
 
-    $this->assertNotNull($saved_file, t("Saving the file should give us back a file object."), 'File');
-    $this->assertTrue($saved_file->fid > 0, t("A new file ID is set when saving a new file to the database."), 'File');
-    $loaded_file = db_query('SELECT * FROM {file_managed} f WHERE f.fid = :fid', array(':fid' => $saved_file->fid))->fetch(PDO::FETCH_OBJ);
+    $this->assertNotNull($file, t("Saving the file should give us back a file object."), 'File');
+    $this->assertTrue($file->fid > 0, t("A new file ID is set when saving a new file to the database."), 'File');
+    $loaded_file = db_query('SELECT * FROM {file_managed} f WHERE f.fid = :fid', array(':fid' => $file->fid))->fetch(PDO::FETCH_OBJ);
     $this->assertNotNull($loaded_file, t("Record exists in the database."));
     $this->assertEqual($loaded_file->status, $file->status, t("Status was saved correctly."));
-    $this->assertEqual($saved_file->filesize, filesize($file->uri), t("File size was set correctly."), 'File');
-    $this->assertTrue($saved_file->timestamp > 1, t("File size was set correctly."), 'File');
+    $this->assertEqual($file->filesize, filesize($file->uri), t("File size was set correctly."), 'File');
+    $this->assertTrue($file->timestamp > 1, t("File size was set correctly."), 'File');
 
 
     // Resave the file, updating the existing record.
     file_test_reset();
-    $saved_file->status = 7;
-    $resaved_file = file_save($saved_file);
+    $file->status = 7;
+    file_save($file);
 
     // Check that the correct hooks were called.
     $this->assertFileHooksCalled(array('load', 'update'));
 
-    $this->assertEqual($resaved_file->fid, $saved_file->fid, t("The file ID of an existing file is not changed when updating the database."), 'File');
-    $this->assertTrue($resaved_file->timestamp >= $saved_file->timestamp, t("Timestamp didn't go backwards."), 'File');
-    $loaded_file = db_query('SELECT * FROM {file_managed} f WHERE f.fid = :fid', array(':fid' => $saved_file->fid))->fetch(PDO::FETCH_OBJ);
+    $this->assertEqual($file->fid, $file->fid, t("The file ID of an existing file is not changed when updating the database."), 'File');
+    $this->assertTrue($file->timestamp >= $file->timestamp, t("Timestamp didn't go backwards."), 'File');
+    $loaded_file = db_query('SELECT * FROM {file_managed} f WHERE f.fid = :fid', array(':fid' => $file->fid))->fetch(PDO::FETCH_OBJ);
     $this->assertNotNull($loaded_file, t("Record still exists in the database."), 'File');
-    $this->assertEqual($loaded_file->status, $saved_file->status, t("Status was saved correctly."));
+    $this->assertEqual($loaded_file->status, $file->status, t("Status was saved correctly."));
   }
 }
 
@@ -2441,7 +2442,7 @@ class FileDownloadTest extends FileTestCase {
       $this->assertRaw(file_get_contents($file->uri), t('Contents of the file are correct.'));
     }
 
-    file_delete($file);
+    file_delete($file->fid);
   }
 }
 
diff --git a/core/modules/simpletest/tests/file_test.module b/core/modules/simpletest/tests/file_test.module
index 21c7419..82adf17 100644
--- a/core/modules/simpletest/tests/file_test.module
+++ b/core/modules/simpletest/tests/file_test.module
@@ -138,7 +138,7 @@ function _file_test_form_submit(&$form, &$form_state) {
 /**
  * Reset/initialize the history of calls to the file_* hooks.
  *
- * @see file_test_get_calls() 
+ * @see file_test_get_calls()
  * @see file_test_reset()
  */
 function file_test_reset() {
@@ -251,7 +251,7 @@ function file_test_set_return($op, $value) {
  */
 function file_test_file_load($files) {
   foreach ($files as $file) {
-    _file_test_log_call('load', array($file));
+    _file_test_log_call('load', array($file->fid));
     // Assign a value on the object so that we can test that the $file is passed
     // by reference.
     $file->file_test['loaded'] = TRUE;
@@ -262,7 +262,7 @@ function file_test_file_load($files) {
  * Implements hook_file_validate().
  */
 function file_test_file_validate($file) {
-  _file_test_log_call('validate', array($file));
+  _file_test_log_call('validate', array($file->fid));
   return _file_test_get_return('validate');
 }
 
@@ -278,35 +278,35 @@ function file_test_file_download($uri) {
  * Implements hook_file_insert().
  */
 function file_test_file_insert($file) {
-  _file_test_log_call('insert', array($file));
+  _file_test_log_call('insert', array($file->fid));
 }
 
 /**
  * Implements hook_file_update().
  */
 function file_test_file_update($file) {
-  _file_test_log_call('update', array($file));
+  _file_test_log_call('update', array($file->fid));
 }
 
 /**
  * Implements hook_file_copy().
  */
 function file_test_file_copy($file, $source) {
-  _file_test_log_call('copy', array($file, $source));
+  _file_test_log_call('copy', array($file->fid, $source));
 }
 
 /**
  * Implements hook_file_move().
  */
 function file_test_file_move($file, $source) {
-  _file_test_log_call('move', array($file, $source));
+  _file_test_log_call('move', array($file->fid, $source));
 }
 
 /**
  * Implements hook_file_predelete().
  */
 function file_test_file_predelete($file) {
-  _file_test_log_call('delete', array($file));
+  _file_test_log_call('delete', array($file->fid));
 }
 
 /**
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 725cad7..33172da 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -277,6 +277,8 @@ function system_entity_info() {
     'file' => array(
       'label' => t('File'),
       'base table' => 'file_managed',
+      'controller class' => 'FileStorageController',
+      'entity class' => 'File',
       'entity keys' => array(
         'id' => 'fid',
         'label' => 'filename',
@@ -3021,7 +3023,7 @@ function system_cron() {
     if ($file = file_load($row->fid)) {
       $references = file_usage_list($file);
       if (empty($references)) {
-        if (!file_delete($file)) {
+        if (!file_delete($file->fid)) {
           watchdog('file system', 'Could not delete temporary file "%path" during garbage collection', array('%path' => $file->uri), WATCHDOG_ERROR);
         }
       }
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index 009a716..459d5de 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -443,14 +443,15 @@ function user_save($account, $edit = array()) {
           // Move the temporary file into the final location.
           if ($picture = file_move($picture, $destination, FILE_EXISTS_RENAME)) {
             $picture->status = FILE_STATUS_PERMANENT;
-            $account->picture = file_save($picture);
+            file_save($picture);
+            $account->picture = $picture;
             file_usage_add($picture, 'user', 'user', $account->uid);
           }
         }
         // Delete the previous picture if it was deleted or replaced.
         if (!empty($account->original->picture->fid)) {
           file_usage_delete($account->original->picture, 'user', 'user', $account->uid);
-          file_delete($account->original->picture);
+          file_delete($account->original->picture->fid);
         }
       }
       $account->picture = empty($account->picture->fid) ? 0 : $account->picture->fid;
