aboutsummaryrefslogtreecommitdiff
path: root/android/ext4_resize.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'android/ext4_resize.cpp')
-rw-r--r--android/ext4_resize.cpp164
1 files changed, 164 insertions, 0 deletions
diff --git a/android/ext4_resize.cpp b/android/ext4_resize.cpp
new file mode 100644
index 0000000000..cbeb206be9
--- /dev/null
+++ b/android/ext4_resize.cpp
@@ -0,0 +1,164 @@
+// Copyright (C) 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#ifdef _WIN32
+#include "android/base/system/Win32Utils.h"
+#include "android/utils/win32_cmdline_quote.h"
+#include <windows.h>
+
+using android::base::Win32Utils;
+#else
+#include <sys/wait.h>
+#endif
+
+#include "android/base/String.h"
+#include "android/ext4_resize.h"
+#include "android/utils/path.h"
+#include "base/system/System.h"
+#include "main-common.h"
+
+using android::base::String;
+using android::base::System;
+
+// Convenience function for formatting and printing system call/library
+// function errors that show up regardless of host platform. Equivalent
+// to printing the stringified error code from errno or GetLastError()
+// (for windows).
+void explainSystemErrors (const char * msg) {
+#ifdef _WIN32
+ char *pstr = NULL;
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_ALLOCATE_BUFFER,
+ NULL,
+ GetLastError(),
+ 0,
+ (LPTSTR) &pstr,
+ 2,
+ NULL);
+ fprintf(stderr, "ERROR: %s - %s\n", msg, pstr);
+ LocalFree(pstr);
+#else
+ fprintf(stderr, "ERROR: %s - %s\n", msg, strerror(errno));
+#endif
+}
+
+int resizeExt4Partition (const char * partitionPath, int64_t newByteSize) {
+ // sanity checks
+ if (partitionPath == NULL || !checkExt4PartitionSize(newByteSize)) {
+ return -1;
+ }
+
+ // format common arguments once
+ String executable = System::get()->findBundledExecutable("resize2fs");
+ if(executable.empty()) {
+ fprintf(stderr, "ERROR: couldn't get path to resize2fs binary\n");
+ return -1;
+ }
+
+ char size_in_MB[50];
+ int copied = snprintf(size_in_MB, sizeof(size_in_MB),
+ "%uM", convertBytesToMB(newByteSize));
+ size_in_MB[sizeof(size_in_MB) - 1] = '\0';
+ if (copied < 0 || copied >= sizeof(size_in_MB)) {
+ fprintf(stderr, "ERROR: failed to format size in resize2fs command\n");
+ return -1;
+ }
+
+
+#ifdef _WIN32
+ STARTUPINFO startup;
+ PROCESS_INFORMATION pinfo;
+ DWORD exitCode;
+
+ ZeroMemory(&startup, sizeof(startup));
+ ZeroMemory(&pinfo, sizeof(pinfo));
+ startup.cb = sizeof(startup);
+
+ char args[PATH_MAX * 2 + 1];
+ copied = snprintf(args, sizeof(args), "resize2fs.exe -f %s %s",
+ Win32Utils::quoteCommandLine(partitionPath).c_str(),
+ size_in_MB);
+ args[sizeof(args) - 1] = '\0';
+ if (copied < 0 || copied >= sizeof(args)) {
+ fprintf(stderr, "ERROR: failed to format resize2fs command\n");
+ return -1;
+ }
+
+ BOOL success = CreateProcess(
+ Win32Utils::quoteCommandLine(executable.c_str()).c_str(), /* program path */
+ args, /* command line args */
+ NULL, /* process handle is not inheritable */
+ NULL, /* thread handle is not inheritable */
+ FALSE, /* no, don't inherit any handles */
+ CREATE_NO_WINDOW, /* the new process doesn't have a console */
+ NULL, /* use parent's environment block */
+ NULL, /* use parent's starting directory */
+ &startup, /* startup info, i.e. std handles */
+ &pinfo);
+ if (!success) {
+ explainSystemErrors("failed to create process while resizing partition");
+ return -2;
+ }
+
+ WaitForSingleObject(pinfo.hProcess, INFINITE);
+ if (!GetExitCodeProcess(pinfo.hProcess, &exitCode)) {
+ explainSystemErrors("couldn't get exit code from resizing partition process");
+ CloseHandle(pinfo.hProcess);
+ CloseHandle(pinfo.hThread);
+ return -2;
+ }
+ CloseHandle(pinfo.hProcess);
+ CloseHandle(pinfo.hThread);
+
+#else
+ int32_t exitCode = 0;
+ pid_t pid;
+ pid_t child = fork();
+
+ if (child < 0) {
+ explainSystemErrors("couldn't create a child process to resize the partition");
+ return -2;
+ }else if (child == 0) {
+ execlp(executable.c_str(), executable.c_str(), "-f", partitionPath,
+ size_in_MB, NULL);
+ exit(-1);
+ }
+
+ while ((pid = waitpid(-1, &exitCode, 0)) != child) {
+ if (pid == -1) {
+ explainSystemErrors("resizing partition waitpid failed");
+ return -2;
+ }
+ }
+#endif
+ if(exitCode != 0) {
+ fprintf(stderr, "ERROR: resizing partition failed with exit code %d\n",
+ exitCode);
+ return exitCode;
+ }
+ return 0;
+}
+
+bool checkExt4PartitionSize (int64_t byteSize) {
+ uint64_t maxSizeMB = 16 * 1024 * 1024; // (16 TiB) * (1024 GiB / TiB) * (1024 MiB / GiB)
+ uint64_t minSizeMB = 128;
+ uint64_t sizeMB = convertBytesToMB(byteSize);
+
+ //compiler converts signed to unsigned
+ return (sizeMB >= minSizeMB) && (sizeMB <= maxSizeMB);
+}