When moving temporary files, try to copy if rename fails, and throw if that fails too (#1686)

Fixes #1243
This commit is contained in:
Vincent Breitmoser 2016-10-12 16:47:23 +02:00 committed by cketti
parent 6eca92ea97
commit aaa904e075
2 changed files with 55 additions and 25 deletions

View file

@ -4,11 +4,13 @@ package com.fsck.k9.helper;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Locale;
import android.util.Log;
import com.fsck.k9.K9;
import org.apache.commons.io.IOUtils;
public class FileHelper {
@ -83,6 +85,50 @@ public class FileHelper {
}
}
private static void copyFile(File from, File to) throws IOException {
FileInputStream in = new FileInputStream(from);
FileOutputStream out = new FileOutputStream(to);
try {
byte[] buffer = new byte[1024];
int count;
while ((count = in.read(buffer)) > 0) {
out.write(buffer, 0, count);
}
out.close();
} finally {
IOUtils.closeQuietly(in);
IOUtils.closeQuietly(out);
}
}
public static void renameOrMoveByCopying(File from, File to) throws IOException {
deleteFileIfExists(to);
boolean renameFailed = !from.renameTo(to);
if (renameFailed) {
copyFile(from, to);
boolean deleteFromFailed = !from.delete();
if (deleteFromFailed) {
Log.e(K9.LOG_TAG, "Unable to delete source file after copying to destination!");
}
}
}
private static void deleteFileIfExists(File to) throws IOException {
boolean fileDoesNotExist = !to.exists();
if (fileDoesNotExist) {
return;
}
boolean deleteOk = to.delete();
if (deleteOk) {
return;
}
throw new IOException("Unable to delete file: " + to.getAbsolutePath());
}
public static boolean move(final File from, final File to) {
if (to.exists()) {
if (!to.delete()) {
@ -95,31 +141,17 @@ public class FileHelper {
}
try {
FileInputStream in = new FileInputStream(from);
try {
FileOutputStream out = new FileOutputStream(to);
try {
byte[] buffer = new byte[1024];
int count = -1;
while ((count = in.read(buffer)) > 0) {
out.write(buffer, 0, count);
}
} finally {
out.close();
}
} finally {
try { in.close(); } catch (Throwable ignore) {}
}
copyFile(from, to);
if (!from.delete()) {
Log.d(K9.LOG_TAG, "Unable to delete file: " + from.getAbsolutePath());
boolean deleteFromFailed = !from.delete();
if (deleteFromFailed) {
Log.e(K9.LOG_TAG, "Unable to delete source file after copying to destination!");
}
return true;
} catch (Exception e) {
Log.w(K9.LOG_TAG, "cannot move " + from.getAbsolutePath() + " to " + to.getAbsolutePath(), e);
return false;
}
}
public static void moveRecursive(final File fromDir, final File toDir) {

View file

@ -32,6 +32,7 @@ import com.fsck.k9.Account;
import com.fsck.k9.K9;
import com.fsck.k9.activity.MessageReference;
import com.fsck.k9.activity.Search;
import com.fsck.k9.helper.FileHelper;
import com.fsck.k9.helper.Utility;
import com.fsck.k9.mail.Address;
import com.fsck.k9.mail.Body;
@ -1360,12 +1361,9 @@ public class LocalFolder extends Folder<LocalMessage> implements Serializable {
return updateOrInsertMessagePart(db, cv, part, INVALID_MESSAGE_PART_ID);
}
private void renameTemporaryFile(File file, String messagePartId) {
File destination = localStore.getAttachmentFile(messagePartId);
if (!file.renameTo(destination)) {
Log.w(K9.LOG_TAG, "Couldn't rename temporary file " + file.getAbsolutePath() +
" to " + destination.getAbsolutePath());
}
private void moveTemporaryFile(File tempFile, String messagePartId) throws IOException {
File destinationFile = localStore.getAttachmentFile(messagePartId);
FileHelper.renameOrMoveByCopying(tempFile, destinationFile);
}
private long updateOrInsertMessagePart(SQLiteDatabase db, ContentValues cv, Part part, long existingMessagePartId)
@ -1397,7 +1395,7 @@ public class LocalFolder extends Folder<LocalMessage> implements Serializable {
}
if (file != null) {
renameTemporaryFile(file, Long.toString(messagePartId));
moveTemporaryFile(file, Long.toString(messagePartId));
}
return messagePartId;