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

Commit 7bc4827e authored by Christopher Tate's avatar Christopher Tate Committed by Android (Google) Code Review
Browse files

Merge "Fix partial-read handling during restore"

parents 9cc07c39 6853fcf5
Loading
Loading
Loading
Loading
+50 −28
Original line number Diff line number Diff line
@@ -2105,10 +2105,13 @@ class BackupManagerService extends IBackupManager.Stub {
                    backupOnePackage(pkg, out);
                }

                // Finally, shared storage if requested
                // Shared storage if requested
                if (mIncludeShared) {
                    backupSharedStorage();
                }

                // Done!
                finalizeBackup(out);
            } catch (RemoteException e) {
                Slog.e(TAG, "App died during full backup");
            } finally {
@@ -2326,6 +2329,16 @@ class BackupManagerService extends IBackupManager.Stub {
            }
        }

        private void finalizeBackup(OutputStream out) {
            try {
                // A standard 'tar' EOF sequence: two 512-byte blocks of all zeroes.
                byte[] eof = new byte[512 * 2]; // newly allocated == zero filled
                out.write(eof);
            } catch (IOException e) {
                Slog.w(TAG, "Error attempting to finalize backup stream");
            }
        }

        private void writeAppManifest(PackageInfo pkg, File manifestFile, boolean withApk)
                throws IOException {
            // Manifest format. All data are strings ending in LF:
@@ -3186,9 +3199,11 @@ class BackupManagerService extends IBackupManager.Stub {
        void skipTarPadding(long size, InputStream instream) throws IOException {
            long partial = (size + 512) % 512;
            if (partial > 0) {
                byte[] buffer = new byte[512];
                int nRead = instream.read(buffer, 0, 512 - (int)partial);
                if (nRead >= 0) mBytes += nRead;
                final int needed = 512 - (int)partial;
                byte[] buffer = new byte[needed];
                if (readExactly(instream, buffer, 0, needed) == needed) {
                    mBytes += needed;
                } else throw new IOException("Unexpected EOF in padding");
            }
        }

@@ -3199,12 +3214,11 @@ class BackupManagerService extends IBackupManager.Stub {
            if (info.size > 64 * 1024) {
                throw new IOException("Restore manifest too big; corrupt? size=" + info.size);
            }

            byte[] buffer = new byte[(int) info.size];
            int nRead = 0;
            while (nRead < info.size) {
                nRead += instream.read(buffer, nRead, (int)info.size - nRead);
            }
            if (nRead >= 0) mBytes += nRead;
            if (readExactly(instream, buffer, 0, (int)info.size) == info.size) {
                mBytes += info.size;
            } else throw new IOException("Unexpected EOF in manifest");

            RestorePolicy policy = RestorePolicy.IGNORE;
            String[] str = new String[1];
@@ -3453,7 +3467,7 @@ class BackupManagerService extends IBackupManager.Stub {
                    }
                } catch (IOException e) {
                    if (DEBUG) {
                        Slog.e(TAG, "Parse error in header.  Hexdump:");
                        Slog.e(TAG, "Parse error in header: " + e.getMessage());
                        HEXLOG(block);
                    }
                    throw e;
@@ -3479,22 +3493,31 @@ class BackupManagerService extends IBackupManager.Stub {
            }
        }

        boolean readTarHeader(InputStream instream, byte[] block) throws IOException {
            int totalRead = 0;
            while (totalRead < 512) {
                int nRead = instream.read(block, totalRead, 512 - totalRead);
                if (nRead >= 0) {
                    mBytes += nRead;
                    totalRead += nRead;
                } else {
                    if (totalRead == 0) {
                        // EOF instead of a new header; we're done
        // Read exactly the given number of bytes into a buffer at the stated offset.
        // Returns false if EOF is encountered before the requested number of bytes
        // could be read.
        int readExactly(InputStream in, byte[] buffer, int offset, int size)
                throws IOException {
            if (size <= 0) throw new IllegalArgumentException("size must be > 0");

            int soFar = 0;
            while (soFar < size) {
                int nRead = in.read(buffer, offset + soFar, size - soFar);
                if (nRead <= 0) {
                    if (MORE_DEBUG) Slog.w(TAG, "- wanted exactly " + size + " but got only " + soFar);
                    break;
                }
                    throw new IOException("Unable to read full block header, t=" + totalRead);
                soFar += nRead;
            }
            return soFar;
        }
            return (totalRead == 512);

        boolean readTarHeader(InputStream instream, byte[] block) throws IOException {
            final int got = readExactly(instream, block, 0, 512);
            if (got == 0) return false;     // Clean EOF
            if (got < 512) throw new IOException("Unable to read full block header");
            mBytes += 512;
            return true;
        }

        // overwrites 'info' fields based on the pax extended header
@@ -3510,11 +3533,10 @@ class BackupManagerService extends IBackupManager.Stub {
            // read whole blocks, not just the content size
            int numBlocks = (int)((info.size + 511) >> 9);
            byte[] data = new byte[numBlocks * 512];
            int nRead = instream.read(data);
            if (nRead >= 0) mBytes += nRead;
            if (nRead != data.length) {
                return false;
            if (readExactly(instream, data, 0, data.length) < data.length) {
                throw new IOException("Unable to read full pax header");
            }
            mBytes += data.length;

            final int contentSize = (int) info.size;
            int offset = 0;