blob: 2ca645a6ee0393a9f90b50a50e6d51f1531bec9d [file] [log] [blame]
Christopher Tate4a627c72011-04-01 14:43:32 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17#define LOG_TAG "FullBackup_native"
18#include <utils/Log.h>
19#include <utils/String8.h>
20
21#include "JNIHelp.h"
22#include <android_runtime/AndroidRuntime.h>
23
Mathias Agopianb13b9bd2012-02-17 18:27:36 -080024#include <androidfw/BackupHelpers.h>
Christopher Tate4a627c72011-04-01 14:43:32 -070025
26#include <string.h>
27
28namespace android
29{
30
31// android.app.backup.BackupDataOutput
32static struct {
33 // This is actually a native pointer to the underlying BackupDataWriter instance
34 jfieldID mBackupWriter;
35} sBackupDataOutput;
36
37/*
38 * Write files to the given output. This implementation does *not* create
39 * a standalone archive suitable for restore on its own. In particular, the identification of
40 * the application's name etc is not in-band here; it's assumed that the calling code has
41 * taken care of supplying that information previously in the output stream.
42 *
43 * The file format is 'tar's, with special semantics applied by use of a "fake" directory
44 * hierarchy within the tar stream:
45 *
46 * apps/packagename/a/Filename.apk - this is an actual application binary, which will be
47 * installed on the target device at restore time. These need to appear first in the tar
48 * stream.
49 * apps/packagename/obb/[relpath] - OBB containers belonging the app
50 * apps/packagename/r/[relpath] - these are files at the root of the app's data tree
51 * apps/packagename/f/[relpath] - this is a file within the app's getFilesDir() tree, stored
52 * at [relpath] relative to the top of that tree.
53 * apps/packagename/db/[relpath] - as with "files" but for the getDatabasePath() tree
54 * apps/packagename/sp/[relpath] - as with "files" but for the getSharedPrefsFile() tree
55 * apps/packagename/c/[relpath] - as with "files" but for the getCacheDir() tree
56 *
57 * and for the shared storage hierarchy:
58 *
59 * shared/[relpaths] - files belonging in the device's shared storage location. This will
60 * *not* include .obb files; those are saved with their owning apps.
61 *
62 * This method writes one file data block. 'domain' is the name of the appropriate pseudo-
63 * directory to be applied for this file; 'linkdomain' is the pseudo-dir for a relative
64 * symlink's antecedent.
65 *
66 * packagename: the package name to use as the top level directory tag
67 * domain: which semantic name the file is to be stored under (a, r, f, db, etc)
68 * linkdomain: where a symlink points for purposes of rewriting; current unused
69 * rootpath: prefix to be snipped from full path when encoding in tar
70 * path: absolute path to the file to be saved
71 * dataOutput: the BackupDataOutput object that we're saving into
72 */
73static int backupToTar(JNIEnv* env, jobject clazz, jstring packageNameObj,
74 jstring domainObj, jstring linkdomain,
75 jstring rootpathObj, jstring pathObj, jobject dataOutputObj) {
Christopher Tateb0628bf2011-06-02 15:08:13 -070076 int ret;
77
Christopher Tate4a627c72011-04-01 14:43:32 -070078 // Extract the various strings, allowing for null object pointers
Christopher Tateca1605e2011-09-23 13:12:49 -070079 const char* packagenamechars = (packageNameObj) ? env->GetStringUTFChars(packageNameObj, NULL) : NULL;
80 const char* rootchars = (rootpathObj) ? env->GetStringUTFChars(rootpathObj, NULL) : NULL;
81 const char* pathchars = (pathObj) ? env->GetStringUTFChars(pathObj, NULL) : NULL;
82 const char* domainchars = (domainObj) ? env->GetStringUTFChars(domainObj, NULL) : NULL;
Christopher Tate4a627c72011-04-01 14:43:32 -070083
84 String8 packageName(packagenamechars ? packagenamechars : "");
85 String8 rootpath(rootchars ? rootchars : "");
86 String8 path(pathchars ? pathchars : "");
87 String8 domain(domainchars ? domainchars : "");
88
89 if (domainchars) env->ReleaseStringUTFChars(domainObj, domainchars);
90 if (pathchars) env->ReleaseStringUTFChars(pathObj, pathchars);
91 if (rootchars) env->ReleaseStringUTFChars(rootpathObj, rootchars);
92 if (packagenamechars) env->ReleaseStringUTFChars(packageNameObj, packagenamechars);
93
94 // Extract the data output fd
95 BackupDataWriter* writer = (BackupDataWriter*) env->GetIntField(dataOutputObj,
96 sBackupDataOutput.mBackupWriter);
97
98 // Validate
99 if (!writer) {
Steve Block3762c312012-01-06 19:20:56 +0000100 ALOGE("No output stream provided [%s]", path.string());
Christopher Tate4a627c72011-04-01 14:43:32 -0700101 return -1;
102 }
103
104 if (path.length() < rootpath.length()) {
Steve Block3762c312012-01-06 19:20:56 +0000105 ALOGE("file path [%s] shorter than root path [%s]",
Christopher Tate4a627c72011-04-01 14:43:32 -0700106 path.string(), rootpath.string());
107 return -1;
108 }
109
110 return write_tarfile(packageName, domain, rootpath, path, writer);
111}
112
113static const JNINativeMethod g_methods[] = {
114 { "backupToTar",
115 "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/app/backup/BackupDataOutput;)I",
116 (void*)backupToTar },
117};
118
119int register_android_app_backup_FullBackup(JNIEnv* env)
120{
121 jclass clazz = env->FindClass("android/app/backup/BackupDataOutput");
122 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.app.backup.BackupDataOutput");
123
124 sBackupDataOutput.mBackupWriter = env->GetFieldID(clazz, "mBackupWriter", "I");
125 LOG_FATAL_IF(sBackupDataOutput.mBackupwriter == NULL,
126 "Unable to find mBackupWriter field in android.app.backup.BackupDataOutput");
127
128 return AndroidRuntime::registerNativeMethods(env, "android/app/backup/FullBackup",
129 g_methods, NELEM(g_methods));
130}
131
132}