blob: 63b2e2aaee126a6e1da05fee1dcde0b04cb21e2e [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"
Christopher Tate11ae7682015-03-24 18:48:10 -070018#include <sys/stat.h>
19
Christopher Tate4a627c72011-04-01 14:43:32 -070020#include <utils/Log.h>
21#include <utils/String8.h>
22
23#include "JNIHelp.h"
24#include <android_runtime/AndroidRuntime.h>
25
Mathias Agopianb13b9bd2012-02-17 18:27:36 -080026#include <androidfw/BackupHelpers.h>
Christopher Tate4a627c72011-04-01 14:43:32 -070027
Andreas Gampe987f79f2014-11-18 17:29:46 -080028#include "core_jni_helpers.h"
29
Christopher Tate4a627c72011-04-01 14:43:32 -070030#include <string.h>
31
32namespace android
33{
34
Christopher Tate11ae7682015-03-24 18:48:10 -070035// android.app.backup.FullBackupDataOutput
36static struct {
37 jfieldID mData; // type android.app.backup.BackupDataOutput
38 jmethodID addSize;
39} sFullBackupDataOutput;
40
Christopher Tate4a627c72011-04-01 14:43:32 -070041// android.app.backup.BackupDataOutput
42static struct {
43 // This is actually a native pointer to the underlying BackupDataWriter instance
44 jfieldID mBackupWriter;
45} sBackupDataOutput;
46
47/*
48 * Write files to the given output. This implementation does *not* create
49 * a standalone archive suitable for restore on its own. In particular, the identification of
50 * the application's name etc is not in-band here; it's assumed that the calling code has
51 * taken care of supplying that information previously in the output stream.
52 *
53 * The file format is 'tar's, with special semantics applied by use of a "fake" directory
54 * hierarchy within the tar stream:
55 *
56 * apps/packagename/a/Filename.apk - this is an actual application binary, which will be
57 * installed on the target device at restore time. These need to appear first in the tar
58 * stream.
59 * apps/packagename/obb/[relpath] - OBB containers belonging the app
60 * apps/packagename/r/[relpath] - these are files at the root of the app's data tree
61 * apps/packagename/f/[relpath] - this is a file within the app's getFilesDir() tree, stored
62 * at [relpath] relative to the top of that tree.
63 * apps/packagename/db/[relpath] - as with "files" but for the getDatabasePath() tree
64 * apps/packagename/sp/[relpath] - as with "files" but for the getSharedPrefsFile() tree
65 * apps/packagename/c/[relpath] - as with "files" but for the getCacheDir() tree
66 *
67 * and for the shared storage hierarchy:
68 *
69 * shared/[relpaths] - files belonging in the device's shared storage location. This will
70 * *not* include .obb files; those are saved with their owning apps.
71 *
72 * This method writes one file data block. 'domain' is the name of the appropriate pseudo-
73 * directory to be applied for this file; 'linkdomain' is the pseudo-dir for a relative
74 * symlink's antecedent.
75 *
76 * packagename: the package name to use as the top level directory tag
77 * domain: which semantic name the file is to be stored under (a, r, f, db, etc)
78 * linkdomain: where a symlink points for purposes of rewriting; current unused
79 * rootpath: prefix to be snipped from full path when encoding in tar
80 * path: absolute path to the file to be saved
Christopher Tate11ae7682015-03-24 18:48:10 -070081 * dataOutput: the FullBackupDataOutput object that we're saving into
Christopher Tate4a627c72011-04-01 14:43:32 -070082 */
Ashok Bhat58b8b242014-01-02 16:52:41 +000083static jint backupToTar(JNIEnv* env, jobject clazz, jstring packageNameObj,
Christopher Tate4a627c72011-04-01 14:43:32 -070084 jstring domainObj, jstring linkdomain,
85 jstring rootpathObj, jstring pathObj, jobject dataOutputObj) {
Christopher Tate4a627c72011-04-01 14:43:32 -070086 // Extract the various strings, allowing for null object pointers
Christopher Tateca1605e2011-09-23 13:12:49 -070087 const char* packagenamechars = (packageNameObj) ? env->GetStringUTFChars(packageNameObj, NULL) : NULL;
88 const char* rootchars = (rootpathObj) ? env->GetStringUTFChars(rootpathObj, NULL) : NULL;
89 const char* pathchars = (pathObj) ? env->GetStringUTFChars(pathObj, NULL) : NULL;
90 const char* domainchars = (domainObj) ? env->GetStringUTFChars(domainObj, NULL) : NULL;
Christopher Tate4a627c72011-04-01 14:43:32 -070091
92 String8 packageName(packagenamechars ? packagenamechars : "");
93 String8 rootpath(rootchars ? rootchars : "");
94 String8 path(pathchars ? pathchars : "");
95 String8 domain(domainchars ? domainchars : "");
96
97 if (domainchars) env->ReleaseStringUTFChars(domainObj, domainchars);
98 if (pathchars) env->ReleaseStringUTFChars(pathObj, pathchars);
99 if (rootchars) env->ReleaseStringUTFChars(rootpathObj, rootchars);
100 if (packagenamechars) env->ReleaseStringUTFChars(packageNameObj, packagenamechars);
101
Christopher Tate11ae7682015-03-24 18:48:10 -0700102 // Extract the data output fd. 'writer' ends up NULL in the measure-only case.
103 jobject bdo = env->GetObjectField(dataOutputObj, sFullBackupDataOutput.mData);
104 BackupDataWriter* writer = (bdo != NULL)
105 ? (BackupDataWriter*) env->GetLongField(bdo, sBackupDataOutput.mBackupWriter)
106 : NULL;
Christopher Tate4a627c72011-04-01 14:43:32 -0700107
108 if (path.length() < rootpath.length()) {
Steve Block3762c312012-01-06 19:20:56 +0000109 ALOGE("file path [%s] shorter than root path [%s]",
Christopher Tate4a627c72011-04-01 14:43:32 -0700110 path.string(), rootpath.string());
Ashok Bhat58b8b242014-01-02 16:52:41 +0000111 return (jint) -1;
Christopher Tate4a627c72011-04-01 14:43:32 -0700112 }
113
Christopher Tate11ae7682015-03-24 18:48:10 -0700114 off_t tarSize = 0;
115 jint err = write_tarfile(packageName, domain, rootpath, path, &tarSize, writer);
116 if (!err) {
117 //ALOGI("measured [%s] at %lld", path.string(), (long long) tarSize);
118 env->CallVoidMethod(dataOutputObj, sFullBackupDataOutput.addSize, (jlong) tarSize);
119 }
120
121 return err;
Christopher Tate4a627c72011-04-01 14:43:32 -0700122}
123
124static const JNINativeMethod g_methods[] = {
125 { "backupToTar",
Christopher Tate11ae7682015-03-24 18:48:10 -0700126 "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/app/backup/FullBackupDataOutput;)I",
Christopher Tate4a627c72011-04-01 14:43:32 -0700127 (void*)backupToTar },
128};
129
130int register_android_app_backup_FullBackup(JNIEnv* env)
131{
Christopher Tate11ae7682015-03-24 18:48:10 -0700132 jclass fbdoClazz = FindClassOrDie(env, "android/app/backup/FullBackupDataOutput");
133 sFullBackupDataOutput.mData = GetFieldIDOrDie(env, fbdoClazz, "mData", "Landroid/app/backup/BackupDataOutput;");
134 sFullBackupDataOutput.addSize = GetMethodIDOrDie(env, fbdoClazz, "addSize", "(J)V");
Christopher Tate4a627c72011-04-01 14:43:32 -0700135
Christopher Tate11ae7682015-03-24 18:48:10 -0700136 jclass bdoClazz = FindClassOrDie(env, "android/app/backup/BackupDataOutput");
137 sBackupDataOutput.mBackupWriter = GetFieldIDOrDie(env, bdoClazz, "mBackupWriter", "J");
Christopher Tate4a627c72011-04-01 14:43:32 -0700138
Andreas Gampe987f79f2014-11-18 17:29:46 -0800139 return RegisterMethodsOrDie(env, "android/app/backup/FullBackup", g_methods, NELEM(g_methods));
Christopher Tate4a627c72011-04-01 14:43:32 -0700140}
141
142}