2 * Copyright (C) 2011 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package android.app.backup;
19 import android.content.Context;
20 import android.content.pm.ApplicationInfo;
21 import android.content.pm.PackageManager;
22 import android.os.ParcelFileDescriptor;
23 import android.system.ErrnoException;
24 import android.system.Os;
25 import android.util.Log;
28 import java.io.FileInputStream;
29 import java.io.FileOutputStream;
30 import java.io.IOException;
33 * Global constant definitions et cetera related to the full-backup-to-fd
34 * binary format. Nothing in this namespace is part of any API; it's all
35 * hidden details of the current implementation gathered into one location.
39 public class FullBackup {
40 static final String TAG = "FullBackup";
42 public static final String APK_TREE_TOKEN = "a";
43 public static final String OBB_TREE_TOKEN = "obb";
44 public static final String ROOT_TREE_TOKEN = "r";
45 public static final String DATA_TREE_TOKEN = "f";
46 public static final String DATABASE_TREE_TOKEN = "db";
47 public static final String SHAREDPREFS_TREE_TOKEN = "sp";
48 public static final String MANAGED_EXTERNAL_TREE_TOKEN = "ef";
49 public static final String CACHE_TREE_TOKEN = "c";
50 public static final String SHARED_STORAGE_TOKEN = "shared";
52 public static final String APPS_PREFIX = "apps/";
53 public static final String SHARED_PREFIX = SHARED_STORAGE_TOKEN + "/";
55 public static final String FULL_BACKUP_INTENT_ACTION = "fullback";
56 public static final String FULL_RESTORE_INTENT_ACTION = "fullrest";
57 public static final String CONF_TOKEN_INTENT_EXTRA = "conftoken";
62 static public native int backupToTar(String packageName, String domain,
63 String linkdomain, String rootpath, String path, BackupDataOutput output);
66 * Copy data from a socket to the given File location on permanent storage. The
67 * modification time and access mode of the resulting file will be set if desired,
68 * although group/all rwx modes will be stripped: the restored file will not be
69 * accessible from outside the target application even if the original file was.
70 * If the {@code type} parameter indicates that the result should be a directory,
71 * the socket parameter may be {@code null}; even if it is valid, no data will be
72 * read from it in this case.
74 * If the {@code mode} argument is negative, then the resulting output file will not
75 * have its access mode or last modification time reset as part of this operation.
77 * @param data Socket supplying the data to be copied to the output file. If the
78 * output is a directory, this may be {@code null}.
79 * @param size Number of bytes of data to copy from the socket to the file. At least
80 * this much data must be available through the {@code data} parameter.
81 * @param type Must be either {@link BackupAgent#TYPE_FILE} for ordinary file data
82 * or {@link BackupAgent#TYPE_DIRECTORY} for a directory.
83 * @param mode Unix-style file mode (as used by the chmod(2) syscall) to be set on
84 * the output file or directory. group/all rwx modes are stripped even if set
85 * in this parameter. If this parameter is negative then neither
86 * the mode nor the mtime values will be applied to the restored file.
87 * @param mtime A timestamp in the standard Unix epoch that will be imposed as the
88 * last modification time of the output file. if the {@code mode} parameter is
89 * negative then this parameter will be ignored.
90 * @param outFile Location within the filesystem to place the data. This must point
91 * to a location that is writeable by the caller, preferably using an absolute path.
94 static public void restoreFile(ParcelFileDescriptor data,
95 long size, int type, long mode, long mtime, File outFile) throws IOException {
96 if (type == BackupAgent.TYPE_DIRECTORY) {
97 // Canonically a directory has no associated content, so we don't need to read
98 // anything from the pipe in this case. Just create the directory here and
99 // drop down to the final metadata adjustment.
100 if (outFile != null) outFile.mkdirs();
102 FileOutputStream out = null;
104 // Pull the data from the pipe, copying it to the output file, until we're done
106 if (outFile != null) {
107 File parent = outFile.getParentFile();
108 if (!parent.exists()) {
109 // in practice this will only be for the default semantic directories,
110 // and using the default mode for those is appropriate.
113 out = new FileOutputStream(outFile);
115 } catch (IOException e) {
116 Log.e(TAG, "Unable to create/open file " + outFile.getPath(), e);
119 byte[] buffer = new byte[32 * 1024];
120 final long origSize = size;
121 FileInputStream in = new FileInputStream(data.getFileDescriptor());
123 int toRead = (size > buffer.length) ? buffer.length : (int)size;
124 int got = in.read(buffer, 0, toRead);
126 Log.w(TAG, "Incomplete read: expected " + size + " but got "
127 + (origSize - size));
132 out.write(buffer, 0, got);
133 } catch (IOException e) {
134 // Problem writing to the file. Quit copying data and delete
135 // the file, but of course keep consuming the input stream.
136 Log.e(TAG, "Unable to write to file " + outFile.getPath(), e);
144 if (out != null) out.close();
147 // Now twiddle the state to match the backup, assuming all went well
148 if (mode >= 0 && outFile != null) {
150 // explicitly prevent emplacement of files accessible by outside apps
152 Os.chmod(outFile.getPath(), (int)mode);
153 } catch (ErrnoException e) {
154 e.rethrowAsIOException();
156 outFile.setLastModified(mtime);