168d4acd205e8c2da524e62734ca42847306cc029Andres Morales/*
268d4acd205e8c2da524e62734ca42847306cc029Andres Morales * Copyright (C) 2010 The Android Open Source Project
368d4acd205e8c2da524e62734ca42847306cc029Andres Morales *
468d4acd205e8c2da524e62734ca42847306cc029Andres Morales * Licensed under the Apache License, Version 2.0 (the "License");
568d4acd205e8c2da524e62734ca42847306cc029Andres Morales * you may not use this file except in compliance with the License.
668d4acd205e8c2da524e62734ca42847306cc029Andres Morales * You may obtain a copy of the License at
768d4acd205e8c2da524e62734ca42847306cc029Andres Morales *
868d4acd205e8c2da524e62734ca42847306cc029Andres Morales *      http://www.apache.org/licenses/LICENSE-2.0
968d4acd205e8c2da524e62734ca42847306cc029Andres Morales *
1068d4acd205e8c2da524e62734ca42847306cc029Andres Morales * Unless required by applicable law or agreed to in writing, software
1168d4acd205e8c2da524e62734ca42847306cc029Andres Morales * distributed under the License is distributed on an "AS IS" BASIS,
1268d4acd205e8c2da524e62734ca42847306cc029Andres Morales * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1368d4acd205e8c2da524e62734ca42847306cc029Andres Morales * See the License for the specific language governing permissions and
1468d4acd205e8c2da524e62734ca42847306cc029Andres Morales * limitations under the License.
1568d4acd205e8c2da524e62734ca42847306cc029Andres Morales */
1668d4acd205e8c2da524e62734ca42847306cc029Andres Morales
1768d4acd205e8c2da524e62734ca42847306cc029Andres Morales#include <android_runtime/AndroidRuntime.h>
1868d4acd205e8c2da524e62734ca42847306cc029Andres Morales#include <JNIHelp.h>
1968d4acd205e8c2da524e62734ca42847306cc029Andres Morales#include <jni.h>
2068d4acd205e8c2da524e62734ca42847306cc029Andres Morales
2168d4acd205e8c2da524e62734ca42847306cc029Andres Morales#include <utils/misc.h>
2268d4acd205e8c2da524e62734ca42847306cc029Andres Morales#include <sys/ioctl.h>
2368d4acd205e8c2da524e62734ca42847306cc029Andres Morales#include <sys/mount.h>
24963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales#include <utils/Log.h>
25963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales
2668d4acd205e8c2da524e62734ca42847306cc029Andres Morales
2768d4acd205e8c2da524e62734ca42847306cc029Andres Morales#include <inttypes.h>
2868d4acd205e8c2da524e62734ca42847306cc029Andres Morales#include <fcntl.h>
29963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales#include <errno.h>
30963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales#include <string.h>
3168d4acd205e8c2da524e62734ca42847306cc029Andres Morales
3268d4acd205e8c2da524e62734ca42847306cc029Andres Moralesnamespace android {
3368d4acd205e8c2da524e62734ca42847306cc029Andres Morales
3468d4acd205e8c2da524e62734ca42847306cc029Andres Morales    uint64_t get_block_device_size(int fd)
3568d4acd205e8c2da524e62734ca42847306cc029Andres Morales    {
3668d4acd205e8c2da524e62734ca42847306cc029Andres Morales        uint64_t size = 0;
3768d4acd205e8c2da524e62734ca42847306cc029Andres Morales        int ret;
3868d4acd205e8c2da524e62734ca42847306cc029Andres Morales
3968d4acd205e8c2da524e62734ca42847306cc029Andres Morales        ret = ioctl(fd, BLKGETSIZE64, &size);
4068d4acd205e8c2da524e62734ca42847306cc029Andres Morales
4168d4acd205e8c2da524e62734ca42847306cc029Andres Morales        if (ret)
4268d4acd205e8c2da524e62734ca42847306cc029Andres Morales            return 0;
4368d4acd205e8c2da524e62734ca42847306cc029Andres Morales
4468d4acd205e8c2da524e62734ca42847306cc029Andres Morales        return size;
4568d4acd205e8c2da524e62734ca42847306cc029Andres Morales    }
4668d4acd205e8c2da524e62734ca42847306cc029Andres Morales
47963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales    int wipe_block_device(int fd)
48963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales    {
49963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales        uint64_t range[2];
50963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales        int ret;
51963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales        uint64_t len = get_block_device_size(fd);
52963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales
53963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales        range[0] = 0;
54963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales        range[1] = len;
55963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales
56963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales        if (range[1] == 0)
57963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales            return 0;
58963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales
59963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales        ret = ioctl(fd, BLKSECDISCARD, &range);
60963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales        if (ret < 0) {
61963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales            ALOGE("Something went wrong secure discarding block: %s\n", strerror(errno));
62963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales            range[0] = 0;
63963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales            range[1] = len;
64963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales            ret = ioctl(fd, BLKDISCARD, &range);
65963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales            if (ret < 0) {
66963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales                ALOGE("Discard failed: %s\n", strerror(errno));
67963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales                return -1;
68963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales            } else {
69963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales                ALOGE("Wipe via secure discard failed, used non-secure discard instead\n");
70963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales                return 0;
71963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales            }
72963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales
73963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales        }
74963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales
75963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales        return ret;
76963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales    }
77963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales
78963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales    static jlong com_android_server_PersistentDataBlockService_getBlockDeviceSize(JNIEnv *env, jclass, jstring jpath)
79963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales    {
8068d4acd205e8c2da524e62734ca42847306cc029Andres Morales        const char *path = env->GetStringUTFChars(jpath, 0);
8168d4acd205e8c2da524e62734ca42847306cc029Andres Morales        int fd = open(path, O_RDONLY);
8268d4acd205e8c2da524e62734ca42847306cc029Andres Morales
8368d4acd205e8c2da524e62734ca42847306cc029Andres Morales        if (fd < 0)
8468d4acd205e8c2da524e62734ca42847306cc029Andres Morales            return 0;
8568d4acd205e8c2da524e62734ca42847306cc029Andres Morales
8668d4acd205e8c2da524e62734ca42847306cc029Andres Morales        return get_block_device_size(fd);
8768d4acd205e8c2da524e62734ca42847306cc029Andres Morales    }
8868d4acd205e8c2da524e62734ca42847306cc029Andres Morales
89963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales    static int com_android_server_PersistentDataBlockService_wipe(JNIEnv *env, jclass, jstring jpath) {
90963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales        const char *path = env->GetStringUTFChars(jpath, 0);
91963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales        int fd = open(path, O_WRONLY);
92963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales
93963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales        if (fd < 0)
94963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales            return 0;
95963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales
96963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales        return wipe_block_device(fd);
97963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales    }
98963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales
9968d4acd205e8c2da524e62734ca42847306cc029Andres Morales    static JNINativeMethod sMethods[] = {
10068d4acd205e8c2da524e62734ca42847306cc029Andres Morales         /* name, signature, funcPtr */
101963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales        {"nativeGetBlockDeviceSize", "(Ljava/lang/String;)J", (void*)com_android_server_PersistentDataBlockService_getBlockDeviceSize},
102963295ea105314e28e4ca9563aa09cb7440de4c3Andres Morales        {"nativeWipe", "(Ljava/lang/String;)I", (void*)com_android_server_PersistentDataBlockService_wipe},
10368d4acd205e8c2da524e62734ca42847306cc029Andres Morales    };
10468d4acd205e8c2da524e62734ca42847306cc029Andres Morales
10568d4acd205e8c2da524e62734ca42847306cc029Andres Morales    int register_android_server_PersistentDataBlockService(JNIEnv* env)
10668d4acd205e8c2da524e62734ca42847306cc029Andres Morales    {
10768d4acd205e8c2da524e62734ca42847306cc029Andres Morales        return jniRegisterNativeMethods(env, "com/android/server/PersistentDataBlockService",
10868d4acd205e8c2da524e62734ca42847306cc029Andres Morales                                        sMethods, NELEM(sMethods));
10968d4acd205e8c2da524e62734ca42847306cc029Andres Morales    }
11068d4acd205e8c2da524e62734ca42847306cc029Andres Morales
11168d4acd205e8c2da524e62734ca42847306cc029Andres Morales} /* namespace android */