1/* 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 24#include <androidfw/BackupHelpers.h> 25 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 jint backupToTar(JNIEnv* env, jobject clazz, jstring packageNameObj, 74 jstring domainObj, jstring linkdomain, 75 jstring rootpathObj, jstring pathObj, jobject dataOutputObj) { 76 int ret; 77 78 // Extract the various strings, allowing for null object pointers 79 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; 83 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->GetLongField(dataOutputObj, 96 sBackupDataOutput.mBackupWriter); 97 98 // Validate 99 if (!writer) { 100 ALOGE("No output stream provided [%s]", path.string()); 101 return (jint) -1; 102 } 103 104 if (path.length() < rootpath.length()) { 105 ALOGE("file path [%s] shorter than root path [%s]", 106 path.string(), rootpath.string()); 107 return (jint) -1; 108 } 109 110 return (jint) 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", "J"); 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} 133