Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 43cba5fe authored by Zimuzo Ezeozue's avatar Zimuzo Ezeozue Committed by Automerger Merge Worker
Browse files

Merge "Fix FileUtils#copy to fallback on userspace copy if sendfile fails"...

Merge "Fix FileUtils#copy to fallback on userspace copy if sendfile fails" into sc-dev am: 3f2a7540

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/14141620

Change-Id: Ib834da966d06c6602b04cde95a7eef006b6f8588
parents 8195b125 3f2a7540
Loading
Loading
Loading
Loading
+15 −1
Original line number Original line Diff line number Diff line
@@ -22,6 +22,8 @@ import static android.os.ParcelFileDescriptor.MODE_READ_ONLY;
import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
import static android.os.ParcelFileDescriptor.MODE_TRUNCATE;
import static android.os.ParcelFileDescriptor.MODE_TRUNCATE;
import static android.os.ParcelFileDescriptor.MODE_WRITE_ONLY;
import static android.os.ParcelFileDescriptor.MODE_WRITE_ONLY;
import static android.system.OsConstants.EINVAL;
import static android.system.OsConstants.ENOSYS;
import static android.system.OsConstants.F_OK;
import static android.system.OsConstants.F_OK;
import static android.system.OsConstants.O_ACCMODE;
import static android.system.OsConstants.O_ACCMODE;
import static android.system.OsConstants.O_APPEND;
import static android.system.OsConstants.O_APPEND;
@@ -441,7 +443,19 @@ public final class FileUtils {
                final StructStat st_in = Os.fstat(in);
                final StructStat st_in = Os.fstat(in);
                final StructStat st_out = Os.fstat(out);
                final StructStat st_out = Os.fstat(out);
                if (S_ISREG(st_in.st_mode) && S_ISREG(st_out.st_mode)) {
                if (S_ISREG(st_in.st_mode) && S_ISREG(st_out.st_mode)) {
                    try {
                        return copyInternalSendfile(in, out, count, signal, executor, listener);
                        return copyInternalSendfile(in, out, count, signal, executor, listener);
                    } catch (ErrnoException e) {
                        if (e.errno == EINVAL || e.errno == ENOSYS) {
                            // sendfile(2) will fail in at least any of the following conditions:
                            // 1. |in| doesn't support mmap(2)
                            // 2. |out| was opened with O_APPEND
                            // We fallback to userspace copy if that fails
                            return copyInternalUserspace(in, out, count, signal, executor,
                                    listener);
                        }
                        throw e;
                    }
                } else if (S_ISFIFO(st_in.st_mode) || S_ISFIFO(st_out.st_mode)) {
                } else if (S_ISFIFO(st_in.st_mode) || S_ISFIFO(st_out.st_mode)) {
                    return copyInternalSplice(in, out, count, signal, executor, listener);
                    return copyInternalSplice(in, out, count, signal, executor, listener);
                }
                }
+21 −6
Original line number Original line Diff line number Diff line
@@ -227,6 +227,27 @@ public class FileUtilsTest {
        }
        }
    }
    }


    @Test
    public void testCopyFileWithAppend() throws Exception {
        final File src = new File(mTarget, "src");
        final File dest = new File(mTarget, "dest");

        byte[] expected = new byte[10];
        byte[] actual = new byte[10];
        new Random().nextBytes(expected);
        writeFile(src, expected);

        try (FileInputStream in = new FileInputStream(src);
                FileOutputStream out = new FileOutputStream(dest, true /* append */)) {
            // sendfile(2) fails if output fd is opened with O_APPEND, but FileUtils#copy should
            // fallback to userspace copy
            FileUtils.copy(in, out);
        }

        actual = readFile(dest);
        assertArrayEquals(expected, actual);
    }

    @Test
    @Test
    public void testIsFilenameSafe() throws Exception {
    public void testIsFilenameSafe() throws Exception {
        assertTrue(FileUtils.isFilenameSafe(new File("foobar")));
        assertTrue(FileUtils.isFilenameSafe(new File("foobar")));
@@ -577,7 +598,6 @@ public class FileUtilsTest {


        final File validVideoCameraDir = new File(cameraDir, "validVideo-" + nonce + ".mp4");
        final File validVideoCameraDir = new File(cameraDir, "validVideo-" + nonce + ".mp4");
        final File validImageCameraDir = new File(cameraDir, "validImage-" + nonce + ".jpg");
        final File validImageCameraDir = new File(cameraDir, "validImage-" + nonce + ".jpg");
        final File invalidVideoCameraDir = new File(cameraDir, ".invalidVideo-" + nonce + ".mp4");


        final File validVideoNonCameraDir = new File(nonCameraDir, "validVideo-" + nonce + ".mp4");
        final File validVideoNonCameraDir = new File(nonCameraDir, "validVideo-" + nonce + ".mp4");
        final File validImageNonCameraDir = new File(nonCameraDir, "validImage-" + nonce + ".jpg");
        final File validImageNonCameraDir = new File(nonCameraDir, "validImage-" + nonce + ".jpg");
@@ -589,9 +609,6 @@ public class FileUtilsTest {
            FileDescriptor pfdValidImageCameraDir =
            FileDescriptor pfdValidImageCameraDir =
                    ParcelFileDescriptor.open(validImageCameraDir,
                    ParcelFileDescriptor.open(validImageCameraDir,
                            MODE_CREATE | MODE_READ_WRITE).getFileDescriptor();
                            MODE_CREATE | MODE_READ_WRITE).getFileDescriptor();
            FileDescriptor pfdInvalidVideoCameraDir =
                    ParcelFileDescriptor.open(invalidVideoCameraDir,
                            MODE_CREATE | MODE_READ_WRITE).getFileDescriptor();


            FileDescriptor pfdValidVideoNonCameraDir =
            FileDescriptor pfdValidVideoNonCameraDir =
                    ParcelFileDescriptor.open(validVideoNonCameraDir,
                    ParcelFileDescriptor.open(validVideoNonCameraDir,
@@ -603,13 +620,11 @@ public class FileUtilsTest {
            assertNotNull(convertToModernFd(pfdValidVideoCameraDir));
            assertNotNull(convertToModernFd(pfdValidVideoCameraDir));


            assertNull(convertToModernFd(pfdValidImageCameraDir));
            assertNull(convertToModernFd(pfdValidImageCameraDir));
            assertNull(convertToModernFd(pfdInvalidVideoCameraDir));
            assertNull(convertToModernFd(pfdValidVideoNonCameraDir));
            assertNull(convertToModernFd(pfdValidVideoNonCameraDir));
            assertNull(convertToModernFd(pfdValidImageNonCameraDir));
            assertNull(convertToModernFd(pfdValidImageNonCameraDir));
        } finally {
        } finally {
            validVideoCameraDir.delete();
            validVideoCameraDir.delete();
            validImageCameraDir.delete();
            validImageCameraDir.delete();
            invalidVideoCameraDir.delete();
            validVideoNonCameraDir.delete();
            validVideoNonCameraDir.delete();
            validImageNonCameraDir.delete();
            validImageNonCameraDir.delete();
        }
        }