Index: wp-admin/includes/update.php
===================================================================
--- wp-admin/includes/update.php	(revision 25414)
+++ wp-admin/includes/update.php	(working copy)
@@ -87,6 +87,71 @@
 	return $auto_update;
 }
 
+/**
+ * Gets and caches the checksums for the given versions of WordPress
+ *
+ * @since 3.7.0
+ *
+ * @param $version string|array A single version, or an array of versions to fetch
+ *
+ * @return bool|array False on failure, otherwise the array of checksums, keyed by version
+ */
+
+
+function get_core_checksums( $version ) {
+	if ( ! is_array( $version ) )
+		$version = array( $version );
+
+	$return = array();
+
+	// Check to see if we have cached copies available, if we do, no need to request them
+	foreach ( $version as $i => $v ) {
+		if ( $checksums = get_site_transient( "core_checksums_$v" ) ) {
+			unset( $version[ $i ] );
+			$return[ $v ] = $checksums;
+		}
+	}
+
+	// We had cached copies for all of the versions!
+	if ( empty( $version ) )
+		return $return;
+
+	$url = 'http://api.wordpress.org/core/checksum/1.0/?' . http_build_query( array( 'version' => $version ), null, '&' );
+
+	if ( wp_http_supports( array( 'ssl' ) ) )
+		$url = set_url_scheme( $url, 'https' );
+
+	$options = array(
+		'timeout' => ( ( defined('DOING_CRON') && DOING_CRON ) ? 30 : 3 ),
+		'user-agent' => 'WordPress/' . $version . '; ' . home_url( '/' )
+	);
+
+	$response = wp_remote_get( $url, $options );
+
+	if ( is_wp_error( $response ) || 200 != wp_remote_retrieve_response_code( $response ) )
+		return false;
+
+	$body = trim( wp_remote_retrieve_body( $response ) );
+	$body = json_decode( $body, true );
+
+	if ( ! is_array( $body ) || ! isset( $body['checksums'] ) || ! is_array( $body['checksums'] ) )
+		return false;
+
+	// Cache the checksums for later
+	foreach ( $version as $v ) {
+		set_site_transient( "core_checksums_$v", $body['checksums'][ $v ], HOUR_IN_SECONDS );
+		$return[ $v ] = $body['checksums'][ $v ];
+	}
+
+	// If the API didn't return anything for a version, explicitly set it's return value to false
+	foreach ( $return as $v => $r ) {
+		if ( empty( $r ) )
+			$return[ $v ] = false;
+	}
+
+	return $return;
+}
+
 function dismiss_core_update( $update ) {
 	$dismissed = get_site_option( 'dismissed_update_core' );
 	$dismissed[ $update->current . '|' . $update->locale ] = true;
Index: wp-admin/includes/class-wp-upgrader.php
===================================================================
--- wp-admin/includes/class-wp-upgrader.php	(revision 25414)
+++ wp-admin/includes/class-wp-upgrader.php	(working copy)
@@ -1111,11 +1111,18 @@
 
 		$wp_dir = trailingslashit($wp_filesystem->abspath());
 
+		// Pre-cache the checksums for the versions we care about
+		get_core_checksums( array( $wp_version, $current->version ) );
+
+		$no_partial = false;
+		if ( ! $this->check_files() )
+			$no_partial = true;
+
 		// If partial update is returned from the API, use that, unless we're doing a reinstall.
 		// If we cross the new_bundled version number, then use the new_bundled zip.
 		// Don't though if the constant is set to skip bundled items.
 		// If the API returns a no_content zip, go with it. Finally, default to the full zip.
-		if ( $current->packages->partial && 'reinstall' != $current->response && $wp_version == $current->partial_version )
+		if ( $current->packages->partial && 'reinstall' != $current->response && $wp_version == $current->partial_version && ! $no_partial )
 			$to_download = 'partial';
 		elseif ( $current->packages->new_bundled && version_compare( $wp_version, $current->new_bundled, '<' )
 			&& ( ! defined( 'CORE_UPGRADE_SKIP_NEW_BUNDLED' ) || ! CORE_UPGRADE_SKIP_NEW_BUNDLED ) )
@@ -1205,6 +1212,21 @@
 		return false;
 	}
 
+	function check_files() {
+		global $wp_version;
+
+		$checksums = get_core_checksums( $wp_version );
+
+		if ( empty( $checksums[ $wp_version ] ) || ! is_array( $checksums[ $wp_version ] ) )
+			return false;
+
+		foreach ( $checksums[ $wp_version ] as $file => $checksum ) {
+			if ( md5_file( ABSPATH . $file ) !== $checksum )
+				return false;
+		}
+
+		return true;
+	}
 }
 
 /**
Index: wp-admin/includes/update-core.php
===================================================================
--- wp-admin/includes/update-core.php	(revision 25414)
+++ wp-admin/includes/update-core.php	(working copy)
@@ -690,6 +690,16 @@
 
 	apply_filters('update_feedback', __('Installing the latest version&#8230;'));
 
+	// Check to see which files don't really need updating
+	$skip = array( 'wp-content' );
+	$checksums = get_core_checksums( $wp_version );
+	if ( ! empty( $checksums[ $wp_version ] && is_array( $checksums[ $wp_version ] ) ) {
+		foreach( $checksums[ $wp_version ] as $file => $checksum ) {
+			if ( md5_file( $to . $file ) === $checksum )
+				$skip[] = $file;
+		}
+	}
+
 	// Create maintenance file to signal that we are upgrading
 	$maintenance_string = '<?php $upgrading = ' . time() . '; ?>';
 	$maintenance_file = $to . '.maintenance';
@@ -697,7 +707,32 @@
 	$wp_filesystem->put_contents($maintenance_file, $maintenance_string, FS_CHMOD_FILE);
 
 	// Copy new versions of WP files into place.
-	$result = _copy_dir($from . $distro, $to, array('wp-content') );
+	$result = _copy_dir($from . $distro, $to, $skip );
+
+	// Check to make sure everything copied correctly
+	$skip = array( 'wp-content' );
+	$failed = array();
+	if ( ! empty( $checksums[ $wp_version ] && is_array( $checksums[ $wp_version ] ) ) {
+		foreach( $checksums[ $wp_version ] as $file => $checksum ) {
+			if ( md5_file( $to . $file ) === $checksum )
+				$skip[] = $file;
+			else
+				$failed[] = $file;
+		}
+	}
+
+	// Some files didn't copy properly
+	if ( ! empty( $failed ) ) {
+		$total_size = 0;
+		foreach ( $failed as $file => $checksum )
+			$total_size += filesize( $from . $file );
+
+		// If we don't have enough free space, it isn't worth trying again
+		if ( $total_size >= disk_free_space( $to ) )
+			$result = new WP_Error( 'disk_full', __( "There isn't enough free disk space to complete the upgrade." ), $to );
+		else
+			$result = _copy_dir( $from . $distro, $to, $skip );
+	}
 
 	// Custom Content Directory needs updating now.
 	// Copy Languages
