am 16052ec5: Merge "ext4_utils: Fix long symbolic links"
* commit '16052ec56a0836db7de51d6ea4173c6b53f0a9b9':
ext4_utils: Fix long symbolic links
diff --git a/atrace/Android.mk b/atrace/Android.mk
new file mode 100644
index 0000000..df79e82
--- /dev/null
+++ b/atrace/Android.mk
@@ -0,0 +1,16 @@
+# Copyright 2012 The Android Open Source Project
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= atrace.c
+
+LOCAL_C_INCLUDES += external/zlib
+
+LOCAL_MODULE:= atrace
+
+LOCAL_MODULE_TAGS:= debug
+
+LOCAL_STATIC_LIBRARIES := libz
+
+include $(BUILD_EXECUTABLE)
diff --git a/atrace/MODULE_LICENSE_APACHE2 b/atrace/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/atrace/MODULE_LICENSE_APACHE2
diff --git a/atrace/NOTICE b/atrace/NOTICE
new file mode 100644
index 0000000..c77f135
--- /dev/null
+++ b/atrace/NOTICE
@@ -0,0 +1,190 @@
+
+ Copyright (c) 2012, 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.
+
+ 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.
+
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
diff --git a/atrace/atrace.c b/atrace/atrace.c
new file mode 100644
index 0000000..7b4f55e
--- /dev/null
+++ b/atrace/atrace.c
@@ -0,0 +1,462 @@
+/*
+ * Copyright (C) 2012 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 <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/sendfile.h>
+#include <time.h>
+#include <zlib.h>
+
+/* Command line options */
+static int g_traceDurationSeconds = 5;
+static bool g_traceSchedSwitch = false;
+static bool g_traceCpuFrequency = false;
+static bool g_traceGovernorLoad = false;
+static bool g_traceWorkqueue = false;
+static bool g_traceOverwrite = false;
+static int g_traceBufferSizeKB = 2048;
+static bool g_compress = false;
+
+/* Global state */
+static bool g_traceAborted = false;
+
+/* Sys file paths */
+static const char* k_traceClockPath =
+ "/sys/kernel/debug/tracing/trace_clock";
+
+static const char* k_traceBufferSizePath =
+ "/sys/kernel/debug/tracing/buffer_size_kb";
+
+static const char* k_tracingOverwriteEnablePath =
+ "/sys/kernel/debug/tracing/options/overwrite";
+
+static const char* k_schedSwitchEnablePath =
+ "/sys/kernel/debug/tracing/events/sched/sched_switch/enable";
+
+static const char* k_cpuFreqEnablePath =
+ "/sys/kernel/debug/tracing/events/power/cpu_frequency/enable";
+
+static const char* k_governorLoadEnablePath =
+ "/sys/kernel/debug/tracing/events/cpufreq_interactive/enable";
+
+static const char* k_workqueueEnablePath =
+ "/sys/kernel/debug/tracing/events/workqueue/enable";
+
+static const char* k_tracingOnPath =
+ "/sys/kernel/debug/tracing/tracing_on";
+
+static const char* k_tracePath =
+ "/sys/kernel/debug/tracing/trace";
+
+static const char* k_traceMarkerPath =
+ "/sys/kernel/debug/tracing/trace_marker";
+
+// Write a string to a file, returning true if the write was successful.
+bool writeStr(const char* filename, const char* str)
+{
+ int fd = open(filename, O_WRONLY);
+ if (fd == -1) {
+ fprintf(stderr, "error opening %s: %s (%d)\n", filename,
+ strerror(errno), errno);
+ return false;
+ }
+
+ bool ok = true;
+ ssize_t len = strlen(str);
+ if (write(fd, str, len) != len) {
+ fprintf(stderr, "error writing to %s: %s (%d)\n", filename,
+ strerror(errno), errno);
+ ok = false;
+ }
+
+ close(fd);
+
+ return ok;
+}
+
+// Enable or disable a kernel option by writing a "1" or a "0" into a /sys file.
+static bool setKernelOptionEnable(const char* filename, bool enable)
+{
+ return writeStr(filename, enable ? "1" : "0");
+}
+
+// Enable or disable overwriting of the kernel trace buffers. Disabling this
+// will cause tracing to stop once the trace buffers have filled up.
+static bool setTraceOverwriteEnable(bool enable)
+{
+ return setKernelOptionEnable(k_tracingOverwriteEnablePath, enable);
+}
+
+// Enable or disable tracing of the kernel scheduler switching.
+static bool setSchedSwitchTracingEnable(bool enable)
+{
+ return setKernelOptionEnable(k_schedSwitchEnablePath, enable);
+}
+
+// Enable or disable tracing of the CPU clock frequency.
+static bool setCpuFrequencyTracingEnable(bool enable)
+{
+ return setKernelOptionEnable(k_cpuFreqEnablePath, enable);
+}
+
+// Enable or disable tracing of the interactive CPU frequency governor's idea of
+// the CPU load.
+static bool setGovernorLoadTracingEnable(bool enable)
+{
+ return setKernelOptionEnable(k_governorLoadEnablePath, enable);
+}
+
+// Enable or disable tracing of the kernel workqueues.
+static bool setWorkqueueTracingEnabled(bool enable)
+{
+ return setKernelOptionEnable(k_workqueueEnablePath, enable);
+}
+
+// Enable or disable kernel tracing.
+static bool setTracingEnabled(bool enable)
+{
+ return setKernelOptionEnable(k_tracingOnPath, enable);
+}
+
+// Clear the contents of the kernel trace.
+static bool clearTrace()
+{
+ int traceFD = creat(k_tracePath, 0);
+ if (traceFD == -1) {
+ fprintf(stderr, "error truncating %s: %s (%d)\n", k_tracePath,
+ strerror(errno), errno);
+ return false;
+ }
+
+ close(traceFD);
+
+ return true;
+}
+
+// Set the size of the kernel's trace buffer in kilobytes.
+static bool setTraceBufferSizeKB(int size)
+{
+ char str[32] = "1";
+ int len;
+ if (size < 1) {
+ size = 1;
+ }
+ snprintf(str, 32, "%d", size);
+ return writeStr(k_traceBufferSizePath, str);
+}
+
+// Enable or disable the kernel's use of the global clock. Disabling the global
+// clock will result in the kernel using a per-CPU local clock.
+static bool setGlobalClockEnable(bool enable)
+{
+ return writeStr(k_traceClockPath, enable ? "global" : "local");
+}
+
+// Check whether a file exists.
+static bool fileExists(const char* filename) {
+ return access(filename, F_OK) != -1;
+}
+
+// Enable tracing in the kernel.
+static bool startTrace()
+{
+ bool ok = true;
+
+ // Set up the tracing options.
+ ok &= setTraceOverwriteEnable(g_traceOverwrite);
+ ok &= setSchedSwitchTracingEnable(g_traceSchedSwitch);
+ ok &= setCpuFrequencyTracingEnable(g_traceCpuFrequency);
+ if (fileExists(k_governorLoadEnablePath) || g_traceGovernorLoad) {
+ ok &= setGovernorLoadTracingEnable(g_traceGovernorLoad);
+ }
+ ok &= setWorkqueueTracingEnabled(g_traceWorkqueue);
+ ok &= setTraceBufferSizeKB(g_traceBufferSizeKB);
+ ok &= setGlobalClockEnable(true);
+
+ // Enable tracing.
+ ok &= setTracingEnabled(true);
+
+ if (!ok) {
+ fprintf(stderr, "error: unable to start trace\n");
+ }
+
+ return ok;
+}
+
+// Disable tracing in the kernel.
+static void stopTrace()
+{
+ // Disable tracing.
+ setTracingEnabled(false);
+
+ // Set the options back to their defaults.
+ setTraceOverwriteEnable(true);
+ setSchedSwitchTracingEnable(false);
+ setCpuFrequencyTracingEnable(false);
+ if (fileExists(k_governorLoadEnablePath)) {
+ setGovernorLoadTracingEnable(false);
+ }
+ setWorkqueueTracingEnabled(false);
+ setGlobalClockEnable(false);
+
+ // Note that we can't reset the trace buffer size here because that would
+ // clear the trace before we've read it.
+}
+
+// Read the current kernel trace and write it to stdout.
+static void dumpTrace()
+{
+ int traceFD = open(k_tracePath, O_RDWR);
+ if (traceFD == -1) {
+ fprintf(stderr, "error opening %s: %s (%d)\n", k_tracePath,
+ strerror(errno), errno);
+ return;
+ }
+
+ if (g_compress) {
+ z_stream zs;
+ uint8_t *in, *out;
+ int result, flush;
+
+ bzero(&zs, sizeof(zs));
+ result = deflateInit(&zs, Z_DEFAULT_COMPRESSION);
+ if (result != Z_OK) {
+ fprintf(stderr, "error initializing zlib: %d\n", result);
+ close(traceFD);
+ return;
+ }
+
+ const size_t bufSize = 64*1024;
+ in = (uint8_t*)malloc(bufSize);
+ out = (uint8_t*)malloc(bufSize);
+ flush = Z_NO_FLUSH;
+
+ zs.next_out = out;
+ zs.avail_out = bufSize;
+
+ do {
+
+ if (zs.avail_in == 0) {
+ // More input is needed.
+ result = read(traceFD, in, bufSize);
+ if (result < 0) {
+ fprintf(stderr, "error reading trace: %s (%d)\n",
+ strerror(errno), errno);
+ result = Z_STREAM_END;
+ break;
+ } else if (result == 0) {
+ flush = Z_FINISH;
+ } else {
+ zs.next_in = in;
+ zs.avail_in = result;
+ }
+ }
+
+ if (zs.avail_out == 0) {
+ // Need to write the output.
+ result = write(STDOUT_FILENO, out, bufSize);
+ if ((size_t)result < bufSize) {
+ fprintf(stderr, "error writing deflated trace: %s (%d)\n",
+ strerror(errno), errno);
+ result = Z_STREAM_END; // skip deflate error message
+ zs.avail_out = bufSize; // skip the final write
+ break;
+ }
+ zs.next_out = out;
+ zs.avail_out = bufSize;
+ }
+
+ } while ((result = deflate(&zs, flush)) == Z_OK);
+
+ if (result != Z_STREAM_END) {
+ fprintf(stderr, "error deflating trace: %s\n", zs.msg);
+ }
+
+ if (zs.avail_out < bufSize) {
+ size_t bytes = bufSize - zs.avail_out;
+ result = write(STDOUT_FILENO, out, bytes);
+ if ((size_t)result < bytes) {
+ fprintf(stderr, "error writing deflated trace: %s (%d)\n",
+ strerror(errno), errno);
+ }
+ }
+
+ result = deflateEnd(&zs);
+ if (result != Z_OK) {
+ fprintf(stderr, "error cleaning up zlib: %d\n", result);
+ }
+
+ free(in);
+ free(out);
+ } else {
+ ssize_t sent = 0;
+ while ((sent = sendfile(STDOUT_FILENO, traceFD, NULL, 64*1024*1024)) > 0);
+ if (sent == -1) {
+ fprintf(stderr, "error dumping trace: %s (%d)\n", strerror(errno),
+ errno);
+ }
+ }
+
+ close(traceFD);
+}
+
+// Print the command usage help to stderr.
+static void showHelp(const char *cmd)
+{
+ fprintf(stderr, "usage: %s [options]\n", cmd);
+ fprintf(stderr, "options include:\n"
+ " -b N use a trace buffer size of N KB\n"
+ " -c trace into a circular buffer\n"
+ " -f trace CPU frequency changes\n"
+ " -l trace CPU frequency governor load\n"
+ " -s trace the kernel scheduler switches\n"
+ " -t N trace for N seconds [defualt 5]\n"
+ " -w trace the kernel workqueue\n"
+ " -z compress the trace dump\n");
+}
+
+static void handleSignal(int signo) {
+ g_traceAborted = true;
+}
+
+static void registerSigHandler() {
+ struct sigaction sa;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+ sa.sa_handler = handleSignal;
+ sigaction(SIGHUP, &sa, NULL);
+ sigaction(SIGINT, &sa, NULL);
+ sigaction(SIGQUIT, &sa, NULL);
+ sigaction(SIGTERM, &sa, NULL);
+}
+
+int main(int argc, char **argv)
+{
+ if (argc == 2 && 0 == strcmp(argv[1], "--help")) {
+ showHelp(argv[0]);
+ exit(0);
+ }
+
+ if (getuid() != 0) {
+ fprintf(stderr, "error: %s must be run as root.", argv[0]);
+ exit(1);
+ }
+
+ for (;;) {
+ int ret;
+
+ ret = getopt(argc, argv, "b:cflst:wz");
+
+ if (ret < 0) {
+ break;
+ }
+
+ switch(ret) {
+ case 'b':
+ g_traceBufferSizeKB = atoi(optarg);
+ break;
+
+ case 'c':
+ g_traceOverwrite = true;
+ break;
+
+ case 'l':
+ g_traceGovernorLoad = true;
+ break;
+
+ case 'f':
+ g_traceCpuFrequency = true;
+ break;
+
+ case 's':
+ g_traceSchedSwitch = true;
+ break;
+
+ case 't':
+ g_traceDurationSeconds = atoi(optarg);
+ break;
+
+ case 'w':
+ g_traceWorkqueue = true;
+ break;
+
+ case 'z':
+ g_compress = true;
+ break;
+
+ default:
+ fprintf(stderr, "\n");
+ showHelp(argv[0]);
+ exit(-1);
+ break;
+ }
+ }
+
+ registerSigHandler();
+
+ bool ok = startTrace();
+
+ if (ok) {
+ printf("capturing trace...");
+ fflush(stdout);
+
+ // We clear the trace after starting it because tracing gets enabled for
+ // each CPU individually in the kernel. Having the beginning of the trace
+ // contain entries from only one CPU can cause "begin" entries without a
+ // matching "end" entry to show up if a task gets migrated from one CPU to
+ // another.
+ ok = clearTrace();
+
+ if (ok) {
+ // Sleep to allow the trace to be captured.
+ struct timespec timeLeft;
+ timeLeft.tv_sec = g_traceDurationSeconds;
+ timeLeft.tv_nsec = 0;
+ do {
+ if (g_traceAborted) {
+ break;
+ }
+ } while (nanosleep(&timeLeft, &timeLeft) == -1 && errno == EINTR);
+ }
+ }
+
+ // Stop the trace and restore the default settings.
+ stopTrace();
+
+ if (ok) {
+ if (!g_traceAborted) {
+ printf(" done\nTRACE:\n");
+ fflush(stdout);
+ dumpTrace();
+ } else {
+ printf("\ntrace aborted.\n");
+ fflush(stdout);
+ }
+ clearTrace();
+ } else {
+ fprintf(stderr, "unable to start tracing\n");
+ }
+
+ // Reset the trace buffer size to 1.
+ setTraceBufferSizeKB(1);
+
+ return g_traceAborted ? 1 : 0;
+}
diff --git a/bugmailer/Android.mk b/bugmailer/Android.mk
index 9ae4fd8..1bb3099 100644
--- a/bugmailer/Android.mk
+++ b/bugmailer/Android.mk
@@ -1,9 +1,12 @@
# Copyright 2011 The Android Open Source Project
#
LOCAL_PATH:= $(call my-dir)
+
+ifneq ($(TARGET_BUILD_PDK), true)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_MODULE := send_bug
LOCAL_MODULE_TAGS := optional
include $(BUILD_JAVA_LIBRARY)
+endif
diff --git a/bugmailer/src/com/android/commands/sendbug/SendBug.java b/bugmailer/src/com/android/commands/sendbug/SendBug.java
index 41a550a..da8788e 100644
--- a/bugmailer/src/com/android/commands/sendbug/SendBug.java
+++ b/bugmailer/src/com/android/commands/sendbug/SendBug.java
@@ -71,8 +71,8 @@
}
final IActivityManager mAm = ActivityManagerNative.getDefault();
try {
- mAm.startActivity(null, intent, intent.getType(), null, 0, null, null, 0, false,
- false, null, null, false);
+ mAm.startActivity(null, intent, intent.getType(), null, null, 0, 0,
+ null, null, null);
} catch (RemoteException e) {
// ignore
}
@@ -87,7 +87,7 @@
if (mPm != null) {
final List<ResolveInfo> results;
try {
- results = mPm.queryIntentActivities(intent, null, 0);
+ results = mPm.queryIntentActivities(intent, null, 0, 0);
} catch (RemoteException e) {
return null;
}
diff --git a/cpustats/Android.mk b/cpustats/Android.mk
new file mode 100644
index 0000000..2789989
--- /dev/null
+++ b/cpustats/Android.mk
@@ -0,0 +1,10 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := cpustats.c
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
+LOCAL_MODULE_TAGS := debug
+LOCAL_MODULE := cpustats
+
+include $(BUILD_EXECUTABLE)
diff --git a/cpustats/cpustats.c b/cpustats/cpustats.c
new file mode 100644
index 0000000..d720f5e
--- /dev/null
+++ b/cpustats/cpustats.c
@@ -0,0 +1,429 @@
+/*
+ * Copyright (c) 2012, The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google, Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define MAX_BUF_SIZE 64
+
+struct freq_info {
+ unsigned freq;
+ long unsigned time;
+};
+
+struct cpu_info {
+ long unsigned utime, ntime, stime, itime, iowtime, irqtime, sirqtime;
+ struct freq_info *freqs;
+ int freq_count;
+};
+
+#define die(...) { fprintf(stderr, __VA_ARGS__); exit(EXIT_FAILURE); }
+
+static struct cpu_info old_total_cpu, new_total_cpu, *old_cpus, *new_cpus;
+static int cpu_count, delay, iterations;
+static char minimal, aggregate_freq_stats;
+
+static int get_cpu_count();
+static int get_cpu_count_from_file(char *filename);
+static long unsigned get_cpu_total_time(struct cpu_info *cpu);
+static int get_freq_scales_count(int cpu);
+static void print_stats();
+static void print_cpu_stats(char *label, struct cpu_info *new_cpu, struct cpu_info *old_cpu,
+ char print_freq);
+static void print_freq_stats(struct cpu_info *new_cpu, struct cpu_info *old_cpu);
+static void read_stats();
+static void read_freq_stats(int cpu);
+static char should_aggregate_freq_stats();
+static char should_print_freq_stats();
+static void usage(char *cmd);
+
+int main(int argc, char *argv[]) {
+ struct cpu_info *tmp_cpus, tmp_total_cpu;
+ int i, freq_count;
+
+ delay = 3;
+ iterations = -1;
+ minimal = 0;
+ aggregate_freq_stats = 0;
+
+ for (i = 0; i < argc; i++) {
+ if (!strcmp(argv[i], "-n")) {
+ if (i + 1 >= argc) {
+ fprintf(stderr, "Option -n expects an argument.\n");
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ iterations = atoi(argv[++i]);
+ continue;
+ }
+ if (!strcmp(argv[i], "-d")) {
+ if (i + 1 >= argc) {
+ fprintf(stderr, "Option -d expects an argument.\n");
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ delay = atoi(argv[++i]);
+ continue;
+ }
+ if (!strcmp(argv[i], "-m")) {
+ minimal = 1;
+ }
+ if (!strcmp(argv[i], "-h")) {
+ usage(argv[0]);
+ exit(EXIT_SUCCESS);
+ }
+ }
+
+ cpu_count = get_cpu_count();
+
+ old_cpus = malloc(sizeof(struct cpu_info) * cpu_count);
+ if (!old_cpus) die("Could not allocate struct cpu_info\n");
+ new_cpus = malloc(sizeof(struct cpu_info) * cpu_count);
+ if (!new_cpus) die("Could not allocate struct cpu_info\n");
+
+ for (i = 0; i < cpu_count; i++) {
+ old_cpus[i].freq_count = new_cpus[i].freq_count = get_freq_scales_count(i);
+ new_cpus[i].freqs = malloc(sizeof(struct freq_info) * new_cpus[i].freq_count);
+ if (!new_cpus[i].freqs) die("Could not allocate struct freq_info\n");
+ old_cpus[i].freqs = malloc(sizeof(struct freq_info) * old_cpus[i].freq_count);
+ if (!old_cpus[i].freqs) die("Could not allocate struct freq_info\n");
+ }
+
+ // Read stats without aggregating freq stats in the total cpu
+ read_stats();
+
+ aggregate_freq_stats = should_aggregate_freq_stats();
+ if (aggregate_freq_stats) {
+ old_total_cpu.freq_count = new_total_cpu.freq_count = new_cpus[0].freq_count;
+ new_total_cpu.freqs = malloc(sizeof(struct freq_info) * new_total_cpu.freq_count);
+ if (!new_total_cpu.freqs) die("Could not allocate struct freq_info\n");
+ old_total_cpu.freqs = malloc(sizeof(struct freq_info) * old_total_cpu.freq_count);
+ if (!old_total_cpu.freqs) die("Could not allocate struct freq_info\n");
+
+ // Read stats again with aggregating freq stats in the total cpu
+ read_stats();
+ }
+
+ while ((iterations == -1) || (iterations-- > 0)) {
+ // Swap new and old cpu buffers;
+ tmp_total_cpu = old_total_cpu;
+ old_total_cpu = new_total_cpu;
+ new_total_cpu = tmp_total_cpu;
+
+ tmp_cpus = old_cpus;
+ old_cpus = new_cpus;
+ new_cpus = tmp_cpus;
+
+ sleep(delay);
+ read_stats();
+ print_stats();
+ }
+
+ // Clean up
+ if (aggregate_freq_stats) {
+ free(new_total_cpu.freqs);
+ free(old_total_cpu.freqs);
+ }
+ for (i = 0; i < cpu_count; i++) {
+ free(new_cpus[i].freqs);
+ free(old_cpus[i].freqs);
+ }
+ free(new_cpus);
+ free(old_cpus);
+
+ return 0;
+}
+
+/*
+ * Get the number of CPUs of the system.
+ *
+ * Uses the two files /sys/devices/system/cpu/present and
+ * /sys/devices/system/cpu/online to determine the number of CPUs. Expects the
+ * format of both files to be either 0 or 0-N where N+1 is the number of CPUs.
+ *
+ * Exits if the present CPUs is not equal to the online CPUs
+ */
+static int get_cpu_count() {
+ int cpu_count = get_cpu_count_from_file("/sys/devices/system/cpu/present");
+ if (cpu_count != get_cpu_count_from_file("/sys/devices/system/cpu/online")) {
+ die("present cpus != online cpus\n");
+ }
+ return cpu_count;
+}
+
+/*
+ * Get the number of CPUs from a given filename.
+ */
+static int get_cpu_count_from_file(char *filename) {
+ FILE *file;
+ char line[MAX_BUF_SIZE];
+ int cpu_count;
+
+ file = fopen(filename, "r");
+ if (!file) die("Could not open %s\n", filename);
+ if (!fgets(line, MAX_BUF_SIZE, file)) die("Could not get %s contents\n", filename);
+ fclose(file);
+
+ if (strcmp(line, "0\n") == 0) {
+ return 1;
+ }
+
+ if (1 == sscanf(line, "0-%d\n", &cpu_count)) {
+ return cpu_count + 1;
+ }
+
+ die("Unexpected input in file %s (%s).\n", filename, line);
+ return -1;
+}
+
+/*
+ * Get the number of frequency states a given CPU can be scaled to.
+ */
+static int get_freq_scales_count(int cpu) {
+ FILE *file;
+ char filename[MAX_BUF_SIZE];
+ long unsigned freq;
+ int count = 0;
+
+ sprintf(filename, "/sys/devices/system/cpu/cpu%d/cpufreq/stats/time_in_state", cpu);
+ file = fopen(filename, "r");
+ if (!file) die("Could not open %s\n", filename);
+ do {
+ freq = 0;
+ fscanf(file, "%lu %*d\n", &freq);
+ if (freq) count++;
+ } while(freq);
+ fclose(file);
+
+ return count;
+}
+
+/*
+ * Read the CPU and frequency stats for all cpus.
+ */
+static void read_stats() {
+ FILE *file;
+ char scanline[MAX_BUF_SIZE];
+ int i;
+
+ file = fopen("/proc/stat", "r");
+ if (!file) die("Could not open /proc/stat.\n");
+ fscanf(file, "cpu %lu %lu %lu %lu %lu %lu %lu %*d %*d %*d\n",
+ &new_total_cpu.utime, &new_total_cpu.ntime, &new_total_cpu.stime, &new_total_cpu.itime,
+ &new_total_cpu.iowtime, &new_total_cpu.irqtime, &new_total_cpu.sirqtime);
+ if (aggregate_freq_stats) {
+ for (i = 0; i < new_total_cpu.freq_count; i++) {
+ new_total_cpu.freqs[i].time = 0;
+ }
+ }
+
+ for (i = 0; i < cpu_count; i++) {
+ sprintf(scanline, "cpu%d %%lu %%lu %%lu %%lu %%lu %%lu %%lu %%*d %%*d %%*d\n", i);
+ fscanf(file, scanline, &new_cpus[i].utime, &new_cpus[i].ntime, &new_cpus[i].stime,
+ &new_cpus[i].itime, &new_cpus[i].iowtime, &new_cpus[i].irqtime,
+ &new_cpus[i].sirqtime);
+ read_freq_stats(i);
+ }
+ fclose(file);
+}
+
+/*
+ * Read the frequency stats for a given cpu.
+ */
+static void read_freq_stats(int cpu) {
+ FILE *file;
+ char filename[MAX_BUF_SIZE];
+ int i;
+
+ sprintf(filename, "/sys/devices/system/cpu/cpu%d/cpufreq/stats/time_in_state", cpu);
+ file = fopen(filename, "r");
+ if (!file) die("Could not open %s\n", filename);
+ for (i = 0; i < new_cpus[cpu].freq_count; i++) {
+ fscanf(file, "%u %lu\n", &new_cpus[cpu].freqs[i].freq,
+ &new_cpus[cpu].freqs[i].time);
+ if (aggregate_freq_stats) {
+ new_total_cpu.freqs[i].freq = new_cpus[cpu].freqs[i].freq;
+ new_total_cpu.freqs[i].time += new_cpus[cpu].freqs[i].time;
+ }
+ }
+ fclose(file);
+}
+
+/*
+ * Get the sum of the cpu time from all categories.
+ */
+static long unsigned get_cpu_total_time(struct cpu_info *cpu) {
+ return (cpu->utime + cpu->ntime + cpu->stime + cpu->itime + cpu->iowtime + cpu->irqtime +
+ cpu->sirqtime);
+}
+
+/*
+ * Print the stats for all CPUs.
+ */
+static void print_stats() {
+ char label[8];
+ int i, j;
+ char print_freq;
+
+ print_freq = should_print_freq_stats();
+
+ print_cpu_stats("Total", &new_total_cpu, &old_total_cpu, 1);
+ for (i = 0; i < cpu_count; i++) {
+ sprintf(label, "cpu%d", i);
+ print_cpu_stats(label, &new_cpus[i], &old_cpus[i], print_freq);
+ }
+ printf("\n");
+}
+
+/*
+ * Print the stats for a single CPU.
+ */
+static void print_cpu_stats(char *label, struct cpu_info *new_cpu, struct cpu_info *old_cpu,
+ char print_freq) {
+ long int total_delta_time;
+
+ if (!minimal) {
+ total_delta_time = get_cpu_total_time(new_cpu) - get_cpu_total_time(old_cpu);
+ printf("%s: User %ld + Nice %ld + Sys %ld + Idle %ld + IOW %ld + IRQ %ld + SIRQ %ld = "
+ "%ld\n", label,
+ new_cpu->utime - old_cpu->utime,
+ new_cpu->ntime - old_cpu->ntime,
+ new_cpu->stime - old_cpu->stime,
+ new_cpu->itime - old_cpu->itime,
+ new_cpu->iowtime - old_cpu->iowtime,
+ new_cpu->irqtime - old_cpu->irqtime,
+ new_cpu->sirqtime - old_cpu->sirqtime,
+ total_delta_time);
+ if (print_freq) {
+ print_freq_stats(new_cpu, old_cpu);
+ }
+ } else {
+ printf("%s,%ld,%ld,%ld,%ld,%ld,%ld,%ld", label,
+ new_cpu->utime - old_cpu->utime,
+ new_cpu->ntime - old_cpu->ntime,
+ new_cpu->stime - old_cpu->stime,
+ new_cpu->itime - old_cpu->itime,
+ new_cpu->iowtime - old_cpu->iowtime,
+ new_cpu->irqtime - old_cpu->irqtime,
+ new_cpu->sirqtime - old_cpu->sirqtime);
+ print_freq_stats(new_cpu, old_cpu);
+ printf("\n");
+ }
+}
+
+/*
+ * Print the CPU stats for a single CPU.
+ */
+static void print_freq_stats(struct cpu_info *new_cpu, struct cpu_info *old_cpu) {
+ long int delta_time, total_delta_time;
+ int i;
+
+ if (new_cpu->freq_count > 0) {
+ if (!minimal) {
+ total_delta_time = 0;
+ printf(" ");
+ for (i = 0; i < new_cpu->freq_count; i++) {
+ delta_time = new_cpu->freqs[i].time - old_cpu->freqs[i].time;
+ total_delta_time += delta_time;
+ printf("%ukHz %ld", new_cpu->freqs[i].freq, delta_time);
+ if (i + 1 != new_cpu->freq_count) {
+ printf(" + \n ");
+ } else {
+ printf(" = ");
+ }
+ }
+ printf("%ld\n", total_delta_time);
+ } else {
+ for (i = 0; i < new_cpu->freq_count; i++) {
+ printf(",%u,%ld", new_cpu->freqs[i].freq,
+ new_cpu->freqs[i].time - old_cpu->freqs[i].time);
+ }
+ }
+ }
+}
+
+/*
+ * Determine if frequency stats should be printed.
+ *
+ * If the frequency stats are different between CPUs, the stats should be
+ * printed for each CPU, else only the aggregate frequency stats should be
+ * printed.
+ */
+static char should_print_freq_stats() {
+ int i, j;
+
+ for (i = 1; i < cpu_count; i++) {
+ for (j = 0; j < new_cpus[i].freq_count; j++) {
+ if (new_cpus[i].freqs[j].time - old_cpus[i].freqs[j].time !=
+ new_cpus[0].freqs[j].time - old_cpus[0].freqs[j].time) {
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+ * Determine if the frequency stats should be aggregated.
+ *
+ * Only aggregate the frequency stats in the total cpu stats if the frequencies
+ * reported by all CPUs are identical. Must be called after read_stats() has
+ * been called once.
+ */
+static char should_aggregate_freq_stats() {
+ int i, j;
+
+ for (i = 1; i < cpu_count; i++) {
+ if (new_cpus[i].freq_count != new_cpus[0].freq_count) {
+ return 0;
+ }
+ for (j = 0; j < new_cpus[i].freq_count; j++) {
+ if (new_cpus[i].freqs[j].freq != new_cpus[0].freqs[j].freq) {
+ return 0;
+ }
+ }
+ }
+
+ return 1;
+}
+
+/*
+ * Print the usage message.
+ */
+static void usage(char *cmd) {
+ fprintf(stderr, "Usage %s [ -n iterations ] [ -d delay ] [ -c cpu ] [ -m ] [ -h ]\n"
+ " -n num Updates to show before exiting.\n"
+ " -d num Seconds to wait between updates.\n"
+ " -m Display minimal output.\n"
+ " -h Display this help screen.\n",
+ cmd);
+}
diff --git a/ext4_utils/Android.mk b/ext4_utils/Android.mk
index 10b6285..5dae31f 100644
--- a/ext4_utils/Android.mk
+++ b/ext4_utils/Android.mk
@@ -4,7 +4,7 @@
include $(CLEAR_VARS)
libext4_utils_src_files := \
- make_ext4fs.c \
+ make_ext4fs.c \
ext4fixup.c \
ext4_utils.c \
allocate.c \
@@ -15,8 +15,44 @@
indirect.c \
uuid.c \
sha1.c \
- sparse_crc32.c \
- wipe.c
+ sparse_crc32.c \
+ wipe.c
+
+# -- All host/targets including windows
+
+LOCAL_SRC_FILES := $(libext4_utils_src_files)
+LOCAL_MODULE := libext4_utils
+LOCAL_MODULE_TAGS := optional
+LOCAL_C_INCLUDES += external/zlib
+
+ifeq ($(HAVE_SELINUX), true)
+LOCAL_C_INCLUDES += external/libselinux/include
+LOCAL_STATIC_LIBRARIES += libselinux
+LOCAL_CFLAGS += -DHAVE_SELINUX
+endif # HAVE_SELINUX
+
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := make_ext4fs_main.c
+LOCAL_MODULE := make_ext4fs
+LOCAL_STATIC_LIBRARIES += libext4_utils libz
+ifeq ($(HOST_OS),windows)
+LOCAL_LDLIBS += -lws2_32
+else
+ifeq ($(HAVE_SELINUX), true)
+LOCAL_STATIC_LIBRARIES += libselinux
+endif # HAVE_SELINUX
+endif
+
+include $(BUILD_HOST_EXECUTABLE)
+
+include $(CLEAR_VARS)
+
+# -- All host/targets excluding windows
+
+ifneq ($(HOST_OS),windows)
LOCAL_SRC_FILES := $(libext4_utils_src_files)
LOCAL_MODULE := libext4_utils
@@ -38,7 +74,6 @@
LOCAL_MODULE := libext4_utils
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES += external/zlib
-LOCAL_STATIC_LIBRARIES := libz
ifeq ($(HAVE_SELINUX), true)
LOCAL_C_INCLUDES += external/libselinux/include
@@ -50,21 +85,6 @@
include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(libext4_utils_src_files)
-LOCAL_MODULE := libext4_utils
-LOCAL_MODULE_TAGS := optional
-LOCAL_SHARED_LIBRARIES := libz
-
-ifeq ($(HAVE_SELINUX), true)
-LOCAL_C_INCLUDES += external/libselinux/include
-LOCAL_SHARED_LIBRARIES += libselinux
-LOCAL_CFLAGS += -DHAVE_SELINUX
-endif # HAVE_SELINUX
-
-include $(BUILD_HOST_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-
LOCAL_SRC_FILES := make_ext4fs_main.c
LOCAL_MODULE := make_ext4fs
LOCAL_MODULE_TAGS := optional
@@ -80,20 +100,6 @@
include $(CLEAR_VARS)
-LOCAL_SRC_FILES := make_ext4fs_main.c
-LOCAL_MODULE := make_ext4fs
-LOCAL_STATIC_LIBRARIES += libext4_utils libz
-
-ifeq ($(HAVE_SELINUX), true)
-LOCAL_C_INCLUDES += external/libselinux/include
-LOCAL_STATIC_LIBRARIES += libselinux
-LOCAL_CFLAGS += -DHAVE_SELINUX
-endif # HAVE_SELINUX
-
-include $(BUILD_HOST_EXECUTABLE)
-
-include $(CLEAR_VARS)
-
LOCAL_SRC_FILES := ext2simg.c
LOCAL_MODULE := ext2simg
LOCAL_MODULE_TAGS := optional
@@ -127,6 +133,7 @@
LOCAL_SRC_FILES := simg2img.c \
sparse_crc32.c
LOCAL_MODULE := simg2img
+LOCAL_MODULE_TAGS := debug
include $(BUILD_HOST_EXECUTABLE)
@@ -135,6 +142,23 @@
LOCAL_SRC_FILES := simg2img.c \
sparse_crc32.c
LOCAL_MODULE := simg2img
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := img2simg.c
+LOCAL_MODULE := img2simg
+LOCAL_MODULE_TAGS := debug
+
+include $(BUILD_HOST_EXECUTABLE)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := img2simg.c
+LOCAL_MODULE := img2simg
+LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)
@@ -174,3 +198,15 @@
LOCAL_IS_HOST_MODULE := true
include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := simg_dump.py
+LOCAL_MODULE_TAGS := debug
+LOCAL_SRC_FILES := simg_dump.py
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_IS_HOST_MODULE := true
+
+include $(BUILD_PREBUILT)
+
+endif
diff --git a/ext4_utils/backed_block.c b/ext4_utils/backed_block.c
index f8399ef..c0070f1 100644
--- a/ext4_utils/backed_block.c
+++ b/ext4_utils/backed_block.c
@@ -150,7 +150,7 @@
/* Frees the memory used by the linked list of data blocks */
void free_data_blocks()
{
- if (!data_blocks) return;
+ if (!data_blocks) return;
struct data_block *db = data_blocks;
while (db) {
struct data_block *next = db->next;
@@ -167,6 +167,6 @@
free(db);
db = next;
}
- data_blocks = NULL;
- last_used = NULL;
+ data_blocks = NULL;
+ last_used = NULL;
}
diff --git a/ext4_utils/contents.c b/ext4_utils/contents.c
index 71143bc..de38bb0 100644
--- a/ext4_utils/contents.c
+++ b/ext4_utils/contents.c
@@ -27,6 +27,10 @@
#include "indirect.h"
#include "xattr.h"
+#ifdef USE_MINGW
+#define S_IFLNK 0 /* used by make_link, not needed under mingw */
+#endif
+
static u32 dentry_size(u32 entries, struct dentry *dentries)
{
u32 len = 24;
diff --git a/ext4_utils/ext2simg.c b/ext4_utils/ext2simg.c
index 9332bad..1fe085a 100644
--- a/ext4_utils/ext2simg.c
+++ b/ext4_utils/ext2simg.c
@@ -28,6 +28,10 @@
#include <libgen.h>
#include <unistd.h>
+#ifndef USE_MINGW /* O_BINARY is windows-specific flag */
+#define O_BINARY 0
+#endif
+
extern struct fs_info info;
static int verbose = 0;
@@ -169,7 +173,7 @@
const char *out = NULL;
int gzip = 0;
int sparse = 1;
- int fd;
+ int infd, outfd;
int crc = 0;
while ((opt = getopt(argc, argv, "cvzS")) != -1) {
@@ -211,18 +215,29 @@
exit(EXIT_FAILURE);
}
- fd = open(in, O_RDONLY);
+ infd = open(in, O_RDONLY);
- if (fd < 0)
+ if (infd < 0)
critical_error_errno("failed to open input image");
- read_ext(fd);
+ read_ext(infd);
- build_sparse_ext(fd, in);
+ build_sparse_ext(infd, in);
- close(fd);
+ close(infd);
- write_ext4_image(out, gzip, sparse, crc, 0);
+ if (strcmp(out, "-")) {
+ outfd = open(out, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
+ if (outfd < 0) {
+ error_errno("open");
+ return EXIT_FAILURE;
+ }
+ } else {
+ outfd = STDOUT_FILENO;
+ }
+
+ write_ext4_image(outfd, gzip, sparse, crc, 0);
+ close(outfd);
return 0;
}
diff --git a/ext4_utils/ext4_utils.c b/ext4_utils/ext4_utils.c
index 3d5895e..7f226c8 100644
--- a/ext4_utils/ext4_utils.c
+++ b/ext4_utils/ext4_utils.c
@@ -23,12 +23,17 @@
#include "extent.h"
#include <fcntl.h>
-#include <arpa/inet.h>
-#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
+#ifdef USE_MINGW
+#include <winsock2.h>
+#else
+#include <arpa/inet.h>
+#include <sys/ioctl.h>
+#endif
+
#if defined(__linux__)
#include <linux/fs.h>
#elif defined(__APPLE__) && defined(__MACH__)
@@ -137,11 +142,11 @@
}
/* Write the filesystem image to a file */
-void write_ext4_image(const char *filename, int gz, int sparse, int crc,
- int wipe)
+void write_ext4_image(int fd, int gz, int sparse, int crc, int wipe)
{
int ret = 0;
- struct output_file *out = open_output_file(filename, gz, sparse,
+
+ struct output_file *out = open_output_fd(fd, gz, sparse,
count_sparse_chunks(), crc, wipe);
if (!out)
@@ -446,15 +451,11 @@
}
}
-static u64 get_block_device_size(const char *filename)
+static u64 get_block_device_size(int fd)
{
- int fd = open(filename, O_RDONLY);
u64 size = 0;
int ret;
- if (fd < 0)
- return 0;
-
#if defined(__linux__)
ret = ioctl(fd, BLKGETSIZE64, &size);
#elif defined(__APPLE__) && defined(__MACH__)
@@ -464,22 +465,20 @@
return 0;
#endif
- close(fd);
-
if (ret)
return 0;
return size;
}
-u64 get_file_size(const char *filename)
+u64 get_file_size(int fd)
{
struct stat buf;
int ret;
u64 reserve_len = 0;
s64 computed_size;
- ret = stat(filename, &buf);
+ ret = fstat(fd, &buf);
if (ret)
return 0;
@@ -489,7 +488,7 @@
if (S_ISREG(buf.st_mode))
computed_size = buf.st_size - reserve_len;
else if (S_ISBLK(buf.st_mode))
- computed_size = get_block_device_size(filename) - reserve_len;
+ computed_size = get_block_device_size(fd) - reserve_len;
else
computed_size = 0;
@@ -514,4 +513,3 @@
return num;
}
-
diff --git a/ext4_utils/ext4_utils.h b/ext4_utils/ext4_utils.h
index 94f4bc9..1d701d0 100644
--- a/ext4_utils/ext4_utils.h
+++ b/ext4_utils/ext4_utils.h
@@ -17,7 +17,13 @@
#ifndef _EXT4_UTILS_H_
#define _EXT4_UTILS_H_
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _GNU_SOURCE
#define _GNU_SOURCE
+#endif
#define _FILE_OFFSET_BITS 64
#define _LARGEFILE64_SOURCE
#include <sys/types.h>
@@ -58,7 +64,9 @@
#define EXT4_SUPER_MAGIC 0xEF53
#define EXT4_JNL_BACKUP_BLOCKS 1
+#ifndef min /* already defined by windows.h */
#define min(a, b) ((a) < (b) ? (a) : (b))
+#endif
#define DIV_ROUND_UP(x, y) (((x) + (y) - 1)/(y))
#define ALIGN(x, y) ((y) * DIV_ROUND_UP((x), (y)))
@@ -145,7 +153,7 @@
}
int ext4_bg_has_super_block(int bg);
-void write_ext4_image(const char *filename, int gz, int sparse, int crc,
+void write_ext4_image(int fd, int gz, int sparse, int crc,
int wipe);
void ext4_create_fs_aux_info(void);
void ext4_free_fs_aux_info(void);
@@ -154,8 +162,12 @@
void ext4_create_journal_inode(void);
void ext4_update_free(void);
void ext4_queue_sb(void);
-u64 get_file_size(const char *filename);
+u64 get_file_size(int fd);
u64 parse_num(const char *arg);
void ext4_parse_sb(struct ext4_super_block *sb);
+#ifdef __cplusplus
+}
+#endif
+
#endif
diff --git a/ext4_utils/ext4fixup.c b/ext4_utils/ext4fixup.c
index 5e04602..c664ac3 100644
--- a/ext4_utils/ext4fixup.c
+++ b/ext4_utils/ext4fixup.c
@@ -24,10 +24,13 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
-#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
+#ifndef USE_MINGW
+#include <sys/mman.h>
+#endif
+
#if defined(__APPLE__) && defined(__MACH__)
#define lseek64 lseek
#define off64_t off_t
diff --git a/ext4_utils/img2simg.c b/ext4_utils/img2simg.c
new file mode 100644
index 0000000..3b46613
--- /dev/null
+++ b/ext4_utils/img2simg.c
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2010-2012 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.
+ */
+
+#define DEFAULT_BLOCK_SIZE "4K"
+#define DEFAULT_CHUNK_SIZE "64M"
+#define DEFAULT_SUFFIX "%03d"
+
+#include "ext4_utils.h"
+#include "sparse_format.h"
+#if 0 /* endian.h is not on all platforms */
+# include <endian.h>
+#else
+ /* For now, just assume we're going to run on little-endian. */
+# define my_htole32(h) (h)
+# define my_htole16(h) (h)
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#define COPY_BUF_SIZE (1024*1024)
+static char *copy_buf;
+
+static const char *progname(const char *argv0)
+{
+ const char *prog_name;
+ if ((prog_name = strrchr(argv0, '/')))
+ return(prog_name + 1); /* Advance beyond '/'. */
+ return(argv0); /* No '/' in argv0, use it as is. */
+}
+
+static void error_exit(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ fputc('\n', stderr);
+ va_end(ap);
+
+ exit(EXIT_FAILURE);
+}
+
+static void usage(const char *argv0, const char *error_fmt, ...)
+{
+ fprintf(stderr,
+ "Usage: %s [OPTIONS] <raw_image_file>\n",
+ progname(argv0));
+ fprintf(stderr, "The <raw_image_file> will be split into as many sparse\n");
+ fprintf(stderr, "files as needed. Each sparse file will contain a single\n");
+ fprintf(stderr, "DONT CARE chunk to offset to the correct block and then\n");
+ fprintf(stderr, "a single RAW chunk containing a portion of the data from\n");
+ fprintf(stderr, "the raw image file. The sparse files will be named by\n");
+ fprintf(stderr, "appending a number to the name of the raw image file.\n");
+ fprintf(stderr, "\n");
+ fprintf(stderr, "OPTIONS (Defaults are enclosed by square brackets):\n");
+ fprintf(stderr, " -s SUFFIX Format appended number with SUFFIX [%s]\n",
+ DEFAULT_SUFFIX);
+ fprintf(stderr, " -B SIZE Use a block size of SIZE [%s]\n",
+ DEFAULT_BLOCK_SIZE);
+ fprintf(stderr, " -C SIZE Use a chunk size of SIZE [%s]\n",
+ DEFAULT_CHUNK_SIZE);
+ fprintf(stderr, "SIZE is a decimal integer that may optionally be\n");
+ fprintf(stderr, "followed by a suffix that specifies a multiplier for\n");
+ fprintf(stderr, "the integer:\n");
+ fprintf(stderr, " c 1 byte (the default when omitted)\n");
+ fprintf(stderr, " w 2 bytes\n");
+ fprintf(stderr, " b 512 bytes\n");
+ fprintf(stderr, " kB 1000 bytes\n");
+ fprintf(stderr, " K 1024 bytes\n");
+ fprintf(stderr, " MB 1000*1000 bytes\n");
+ fprintf(stderr, " M 1024*1024 bytes\n");
+ fprintf(stderr, " GB 1000*1000*1000 bytes\n");
+ fprintf(stderr, " G 1024*1024*1024 bytes\n");
+
+ if (error_fmt && *error_fmt)
+ {
+ fprintf(stderr, "\n");
+ va_list ap;
+ va_start(ap, error_fmt);
+ vfprintf(stderr, error_fmt, ap);
+ va_end(ap);
+ fprintf(stderr, "\n");
+ }
+
+ exit(EXIT_FAILURE);
+}
+
+static void cpy_file(int out_fd, char *out_path, int in_fd, char *in_path,
+ size_t len)
+{
+ ssize_t s, cpy_len = COPY_BUF_SIZE;
+
+ while (len) {
+ if (len < COPY_BUF_SIZE)
+ cpy_len = len;
+
+ s = read(in_fd, copy_buf, cpy_len);
+ if (s < 0)
+ error_exit("\"%s\": %s", in_path, strerror(errno));
+ if (!s)
+ error_exit("\"%s\": Unexpected EOF", in_path);
+
+ cpy_len = s;
+
+ s = write(out_fd, copy_buf, cpy_len);
+ if (s < 0)
+ error_exit("\"%s\": %s", out_path, strerror(errno));
+ if (s != cpy_len)
+ error_exit("\"%s\": Short data write (%lu)", out_path,
+ (unsigned long)s);
+
+ len -= cpy_len;
+ }
+}
+
+static int parse_size(const char *size_str, size_t *size)
+{
+ static const size_t MAX_SIZE_T = ~(size_t)0;
+ size_t mult;
+ unsigned long long int value;
+ const char *end;
+ errno = 0;
+ value = strtoull(size_str, (char **)&end, 10);
+ if (errno != 0 || end == size_str || value > MAX_SIZE_T)
+ return -1;
+ if (*end == '\0') {
+ *size = value;
+ return 0;
+ }
+ if (!strcmp(end, "c"))
+ mult = 1;
+ else if (!strcmp(end, "w"))
+ mult = 2;
+ else if (!strcmp(end, "b"))
+ mult = 512;
+ else if (!strcmp(end, "kB"))
+ mult = 1000;
+ else if (!strcmp(end, "K"))
+ mult = 1024;
+ else if (!strcmp(end, "MB"))
+ mult = (size_t)1000*1000;
+ else if (!strcmp(end, "M"))
+ mult = (size_t)1024*1024;
+ else if (!strcmp(end, "GB"))
+ mult = (size_t)1000*1000*1000;
+ else if (!strcmp(end, "G"))
+ mult = (size_t)1024*1024*1024;
+ else
+ return -1;
+
+ if (value > MAX_SIZE_T / mult)
+ return -1;
+ *size = value * mult;
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ char *suffix = DEFAULT_SUFFIX;
+ char *block_size_str = DEFAULT_BLOCK_SIZE;
+ char *chunk_size_str = DEFAULT_CHUNK_SIZE;
+ size_t block_size, chunk_size, blocks_per_chunk, to_write;
+ char *in_path, *out_path, *out_fmt;
+ int in_fd, out_fd;
+ struct stat in_st;
+ off_t left_to_write;
+ struct {
+ sparse_header_t sparse_hdr;
+ chunk_header_t dont_care_hdr;
+ chunk_header_t raw_hdr;
+ } file_hdr;
+ unsigned int file_count;
+ ssize_t s;
+ int i;
+
+ /* Parse the command line. */
+ while ((i = getopt(argc, argv, "s:B:C:")) != -1)
+ {
+ switch (i) {
+ case 's':
+ suffix = optarg;
+ break;
+ case 'B':
+ block_size_str = optarg;
+ break;
+ case 'C':
+ chunk_size_str = optarg;
+ break;
+ default:
+ usage(argv[0], NULL);
+ break;
+ }
+ }
+
+ if (parse_size(block_size_str, &block_size))
+ usage(argv[0], "Can not parse \"%s\" as a block size.",
+ block_size_str);
+ if (block_size % 4096)
+ usage(argv[0], "Block size is not a multiple of 4096.");
+
+ if (parse_size(chunk_size_str, &chunk_size))
+ usage(argv[0], "Can not parse \"%s\" as a chunk size.",
+ chunk_size_str);
+ if (chunk_size % block_size)
+ usage(argv[0], "Chunk size is not a multiple of the block size.");
+ blocks_per_chunk = chunk_size / block_size;
+
+ if ((argc - optind) != 1)
+ usage(argv[0], "Missing or extra arguments.");
+ in_path = argv[optind];
+
+ /* Open the input file and validate it. */
+ if ((in_fd = open(in_path, O_RDONLY)) < 0)
+ error_exit("open \"%s\": %s", in_path, strerror(errno));
+ if (fstat(in_fd, &in_st))
+ error_exit("fstat \"%s\": %s", in_path, strerror(errno));
+ left_to_write = in_st.st_size;
+ if (left_to_write % block_size)
+ error_exit(
+ "\"%s\" size (%llu) is not a multiple of the block size (%llu).\n",
+ in_path,
+ (unsigned long long)left_to_write, (unsigned long long)block_size);
+
+ /* Get a buffer for copying the chunks. */
+ if ((copy_buf = malloc(COPY_BUF_SIZE)) == 0)
+ error_exit("malloc copy buffer: %s", strerror(errno));
+
+ /* Get a buffer for a sprintf format to form output paths. */
+ if ((out_fmt = malloc(sizeof("%s") + strlen(suffix))) == 0)
+ error_exit("malloc format buffer: %s", strerror(errno));
+ out_fmt[0] = '%';
+ out_fmt[1] = 's';
+ strcpy(out_fmt + 2, suffix);
+
+ /* Get a buffer for an output path. */
+ i = snprintf(copy_buf, COPY_BUF_SIZE, out_fmt, in_path, UINT_MAX);
+ if (i >= COPY_BUF_SIZE)
+ error_exit("Ridulously long suffix: %s", suffix);
+ if ((out_path = malloc(i + 1)) == 0)
+ error_exit("malloc output path buffer: %s", strerror(errno));
+
+ /*
+ * Each file gets a sparse_header, a Don't Care chunk to offset to
+ * where the data belongs and then a Raw chunk with the actual data.
+ */
+ memset((void *)&file_hdr.sparse_hdr, 0, sizeof(file_hdr.sparse_hdr));
+ file_hdr.sparse_hdr.magic = my_htole32(SPARSE_HEADER_MAGIC);
+ file_hdr.sparse_hdr.major_version = my_htole16(1);
+ file_hdr.sparse_hdr.minor_version = my_htole16(0);
+ file_hdr.sparse_hdr.file_hdr_sz = my_htole16(sizeof(sparse_header_t));
+ file_hdr.sparse_hdr.chunk_hdr_sz = my_htole16(sizeof(chunk_header_t));
+ file_hdr.sparse_hdr.blk_sz = my_htole32(block_size);
+ /* The total_blks will be set in the file loop below. */
+ file_hdr.sparse_hdr.total_chunks = my_htole32(2);
+ file_hdr.sparse_hdr.image_checksum = my_htole32(0); /* Typically unused. */
+
+ memset((void *)&file_hdr.dont_care_hdr, 0, sizeof(file_hdr.dont_care_hdr));
+ file_hdr.dont_care_hdr.chunk_type = my_htole16(CHUNK_TYPE_DONT_CARE);
+ /* The Don't Care's chunk_sz will be set in the file loop below. */
+ file_hdr.dont_care_hdr.total_sz = my_htole32(sizeof(chunk_header_t));
+
+ memset((void *)&file_hdr.raw_hdr, 0, sizeof(file_hdr.raw_hdr));
+ file_hdr.raw_hdr.chunk_type = my_htole16(CHUNK_TYPE_RAW);
+ file_hdr.raw_hdr.chunk_sz = my_htole32(blocks_per_chunk);
+ file_hdr.raw_hdr.total_sz = my_htole32(chunk_size + sizeof(chunk_header_t));
+
+ /* Loop through writing chunk_size to each of the output files. */
+ to_write = chunk_size;
+ for (file_count = 1; left_to_write ; file_count++) {
+ /* Fix up the headers on the last block. */
+ if (left_to_write < (off_t)chunk_size) {
+ to_write = left_to_write;
+ file_hdr.raw_hdr.chunk_sz = my_htole32(left_to_write / block_size);
+ file_hdr.raw_hdr.total_sz = my_htole32(left_to_write
+ + sizeof(chunk_header_t));
+ }
+
+ /* Form the pathname for this output file and open it. */
+ sprintf(out_path, out_fmt, in_path, file_count);
+ if ((out_fd = creat(out_path, 0666)) < 0)
+ error_exit("\"%s\": %s", out_path, strerror(errno));
+
+ /* Update and write the headers to this output file. */
+ s = (file_count-1) * blocks_per_chunk;
+ file_hdr.dont_care_hdr.chunk_sz = my_htole32(s);
+ file_hdr.sparse_hdr.total_blks = my_htole32(s
+ + (to_write / block_size));
+ s = write(out_fd, (void *)&file_hdr, sizeof(file_hdr));
+ if (s < 0)
+ error_exit("\"%s\": %s", out_path, strerror(errno));
+ if (s != sizeof(file_hdr))
+ error_exit("\"%s\": Short write (%lu)", out_path, (unsigned long)s);
+
+ /* Copy this chunk from the input file to the output file. */
+ cpy_file(out_fd, out_path, in_fd, in_path, to_write);
+
+ /* Close this output file and update the amount left to write. */
+ if (close(out_fd))
+ error_exit("close \"%s\": %s", out_path, strerror(errno));
+ left_to_write -= to_write;
+ }
+
+ if (close(in_fd))
+ error_exit("close \"%s\": %s", in_path, strerror(errno));
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/ext4_utils/make_ext4fs.c b/ext4_utils/make_ext4fs.c
index af05eb3..6cd5ade 100644
--- a/ext4_utils/make_ext4fs.c
+++ b/ext4_utils/make_ext4fs.c
@@ -22,7 +22,9 @@
#include "uuid.h"
#include "backed_block.h"
+#include <assert.h>
#include <dirent.h>
+#include <fcntl.h>
#include <libgen.h>
#include <stdio.h>
#include <stdlib.h>
@@ -31,8 +33,33 @@
#include <sys/stat.h>
#include <sys/types.h>
-#ifdef ANDROID
-#include <private/android_filesystem_config.h>
+#ifdef USE_MINGW
+
+#include <winsock2.h>
+
+/* These match the Linux definitions of these flags.
+ L_xx is defined to avoid conflicting with the win32 versions.
+*/
+#define L_S_IRUSR 00400
+#define L_S_IWUSR 00200
+#define L_S_IXUSR 00100
+#define S_IRWXU (L_S_IRUSR | L_S_IWUSR | L_S_IXUSR)
+#define S_IRGRP 00040
+#define S_IWGRP 00020
+#define S_IXGRP 00010
+#define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP)
+#define S_IROTH 00004
+#define S_IWOTH 00002
+#define S_IXOTH 00001
+#define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH)
+#define S_ISUID 0004000
+#define S_ISGID 0002000
+#define S_ISVTX 0001000
+
+#else
+
+#define O_BINARY 0
+
#endif
/* TODO: Not implemented:
@@ -67,10 +94,12 @@
return root_inode;
}
+#ifndef USE_MINGW
/* Read a local directory and create the same tree in the generated filesystem.
Calls itself recursively with each directory in the given directory */
static u32 build_directory_structure(const char *full_path, const char *dir_path,
- u32 dir_inode, int android, struct selabel_handle *sehnd)
+ u32 dir_inode, fs_config_func_t fs_config_func,
+ struct selabel_handle *sehnd)
{
int entries = 0;
struct dentry *dentries;
@@ -113,13 +142,13 @@
dentries[i].size = stat.st_size;
dentries[i].mode = stat.st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO);
dentries[i].mtime = stat.st_mtime;
- if (android) {
+ if (fs_config_func != NULL) {
#ifdef ANDROID
unsigned int mode = 0;
unsigned int uid = 0;
unsigned int gid = 0;
int dir = S_ISDIR(stat.st_mode);
- fs_config(dentries[i].path, dir, &uid, &gid, &mode);
+ fs_config_func(dentries[i].path, dir, &uid, &gid, &mode);
dentries[i].mode = mode;
dentries[i].uid = uid;
dentries[i].gid = gid;
@@ -172,7 +201,7 @@
entry_inode = make_file(dentries[i].full_path, dentries[i].size);
} else if (dentries[i].file_type == EXT4_FT_DIR) {
entry_inode = build_directory_structure(dentries[i].full_path,
- dentries[i].path, inode, android, sehnd);
+ dentries[i].path, inode, fs_config_func, sehnd);
} else if (dentries[i].file_type == EXT4_FT_SYMLINK) {
entry_inode = make_link(dentries[i].full_path, dentries[i].link);
} else {
@@ -200,6 +229,7 @@
free(dentries);
return inode;
}
+#endif
static u32 compute_block_size()
{
@@ -269,29 +299,40 @@
int make_ext4fs(const char *filename, s64 len,
const char *mountpoint, struct selabel_handle *sehnd)
{
- reset_ext4fs_info();
- info.len = len;
- return make_ext4fs_internal(filename, NULL, mountpoint, 0, 0, 0, 0, 1, 0, sehnd);
+ int fd;
+ int status;
+
+ reset_ext4fs_info();
+ info.len = len;
+
+ fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
+ if (fd < 0) {
+ error_errno("open");
+ return EXIT_FAILURE;
+ }
+
+ status = make_ext4fs_internal(fd, NULL, mountpoint, NULL, 0, 0, 0, 1, 0, sehnd);
+ close(fd);
+
+ return status;
}
-int make_ext4fs_internal(const char *filename, const char *directory,
- const char *mountpoint,
- int android, int gzip, int sparse,
- int crc, int wipe, int init_itabs,
- struct selabel_handle *sehnd)
+int make_ext4fs_internal(int fd, const char *directory,
+ char *mountpoint, fs_config_func_t fs_config_func, int gzip, int sparse,
+ int crc, int wipe, int init_itabs, struct selabel_handle *sehnd)
{
- u32 root_inode_num;
- u16 root_mode;
+ u32 root_inode_num;
+ u16 root_mode;
if (setjmp(setjmp_env))
return EXIT_FAILURE; /* Handle a call to longjmp() */
if (info.len <= 0)
- info.len = get_file_size(filename);
+ info.len = get_file_size(fd);
if (info.len <= 0) {
fprintf(stderr, "Need size of filesystem\n");
- return EXIT_FAILURE;
+ return EXIT_FAILURE;
}
if (info.block_size <= 0)
@@ -364,10 +405,17 @@
if (info.feat_compat & EXT4_FEATURE_COMPAT_RESIZE_INODE)
ext4_create_resize_inode();
+#ifdef USE_MINGW
+ // Windows needs only 'create an empty fs image' functionality
+ assert(!directory);
+ root_inode_num = build_default_directory_structure();
+#else
if (directory)
- root_inode_num = build_directory_structure(directory, mountpoint, 0, android, sehnd);
+ root_inode_num = build_directory_structure(directory, mountpoint, 0,
+ fs_config_func, sehnd);
else
root_inode_num = build_default_directory_structure();
+#endif
root_mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
inode_set_permissions(root_inode_num, root_mode, 0, 0, 0);
@@ -408,7 +456,7 @@
aux_info.sb->s_blocks_count_lo - aux_info.sb->s_free_blocks_count_lo,
aux_info.sb->s_blocks_count_lo);
- write_ext4_image(filename, gzip, sparse, crc, wipe);
+ write_ext4_image(fd, gzip, sparse, crc, wipe);
return 0;
}
diff --git a/ext4_utils/make_ext4fs.h b/ext4_utils/make_ext4fs.h
index 53ff840..c217c3d 100644
--- a/ext4_utils/make_ext4fs.h
+++ b/ext4_utils/make_ext4fs.h
@@ -20,6 +20,10 @@
#include "ext4_utils.h"
#include "ext4.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#ifdef HAVE_SELINUX
#include <selinux/selinux.h>
#include <selinux/label.h>
@@ -27,13 +31,18 @@
struct selabel_handle;
#endif
+typedef void (*fs_config_func_t)(const char *path, int dir, unsigned *uid, unsigned *gid,
+ unsigned *mode);
+
void reset_ext4fs_info();
int make_ext4fs(const char *filename, s64 len,
const char *mountpoint, struct selabel_handle *sehnd);
-int make_ext4fs_internal(const char *filename, const char *directory,
- const char *mountpoint,
- int android, int gzip, int sparse,
- int crc, int wipe, int init_itabs,
- struct selabel_handle *sehnd);
+int make_ext4fs_internal(int fd, const char *directory,
+ char *mountpoint, fs_config_func_t fs_config_func, int gzip, int sparse,
+ int crc, int wipe, int init_itabs, struct selabel_handle *sehnd);
+
+#ifdef __cplusplus
+}
+#endif
#endif
diff --git a/ext4_utils/make_ext4fs_main.c b/ext4_utils/make_ext4fs_main.c
index 6a885d2..d545423 100644
--- a/ext4_utils/make_ext4fs_main.c
+++ b/ext4_utils/make_ext4fs_main.c
@@ -14,8 +14,9 @@
* limitations under the License.
*/
-#include <unistd.h>
+#include <fcntl.h>
#include <libgen.h>
+#include <unistd.h>
#if defined(__linux__)
#include <linux/fs.h>
@@ -23,137 +24,166 @@
#include <sys/disk.h>
#endif
+#ifdef ANDROID
+#include <private/android_filesystem_config.h>
+#endif
+
#include "make_ext4fs.h"
+#ifndef USE_MINGW /* O_BINARY is windows-specific flag */
+#define O_BINARY 0
+#endif
+
extern struct fs_info info;
static void usage(char *path)
{
- fprintf(stderr, "%s [ -l <len> ] [ -j <journal size> ] [ -b <block_size> ]\n", basename(path));
- fprintf(stderr, " [ -g <blocks per group> ] [ -i <inodes> ] [ -I <inode size> ]\n");
- fprintf(stderr, " [ -L <label> ] [ -f ] [ -a <android mountpoint> ]\n");
- fprintf(stderr, " [ -S file_contexts ]\n");
- fprintf(stderr, " [ -z | -s ] [ -t ] [ -w ] [ -c ] [ -J ]\n");
- fprintf(stderr, " <filename> [<directory>]\n");
+ fprintf(stderr, "%s [ -l <len> ] [ -j <journal size> ] [ -b <block_size> ]\n", basename(path));
+ fprintf(stderr, " [ -g <blocks per group> ] [ -i <inodes> ] [ -I <inode size> ]\n");
+ fprintf(stderr, " [ -L <label> ] [ -f ] [ -a <android mountpoint> ]\n");
+ fprintf(stderr, " [ -S file_contexts ]\n");
+ fprintf(stderr, " [ -z | -s ] [ -t ] [ -w ] [ -c ] [ -J ]\n");
+ fprintf(stderr, " <filename> [<directory>]\n");
}
int main(int argc, char **argv)
{
- int opt;
- const char *filename = NULL;
- const char *directory = NULL;
- char *mountpoint = "";
- int android = 0;
- int gzip = 0;
- int sparse = 0;
- int crc = 0;
- int wipe = 0;
- int init_itabs = 0;
- struct selabel_handle *sehnd = NULL;
+ int opt;
+ const char *filename = NULL;
+ const char *directory = NULL;
+ char *mountpoint = "";
+ fs_config_func_t fs_config_func = NULL;
+ int gzip = 0;
+ int sparse = 0;
+ int crc = 0;
+ int wipe = 0;
+ int init_itabs = 0;
+ int fd;
+ int exitcode;
+ struct selabel_handle *sehnd = NULL;
#ifdef HAVE_SELINUX
- struct selinux_opt seopts[] = { { SELABEL_OPT_PATH, "" } };
+ struct selinux_opt seopts[] = { { SELABEL_OPT_PATH, "" } };
#endif
- while ((opt = getopt(argc, argv, "l:j:b:g:i:I:L:a:fwzJsctS:")) != -1) {
- switch (opt) {
- case 'l':
- info.len = parse_num(optarg);
- break;
- case 'j':
- info.journal_blocks = parse_num(optarg);
- break;
- case 'b':
- info.block_size = parse_num(optarg);
- break;
- case 'g':
- info.blocks_per_group = parse_num(optarg);
- break;
- case 'i':
- info.inodes = parse_num(optarg);
- break;
- case 'I':
- info.inode_size = parse_num(optarg);
- break;
- case 'L':
- info.label = optarg;
- break;
- case 'f':
- force = 1;
- break;
- case 'a':
- android = 1;
- mountpoint = optarg;
- break;
- case 'w':
- wipe = 1;
- break;
- case 'z':
- gzip = 1;
- break;
+ while ((opt = getopt(argc, argv, "l:j:b:g:i:I:L:a:fwzJsctS:")) != -1) {
+ switch (opt) {
+ case 'l':
+ info.len = parse_num(optarg);
+ break;
+ case 'j':
+ info.journal_blocks = parse_num(optarg);
+ break;
+ case 'b':
+ info.block_size = parse_num(optarg);
+ break;
+ case 'g':
+ info.blocks_per_group = parse_num(optarg);
+ break;
+ case 'i':
+ info.inodes = parse_num(optarg);
+ break;
+ case 'I':
+ info.inode_size = parse_num(optarg);
+ break;
+ case 'L':
+ info.label = optarg;
+ break;
+ case 'f':
+ force = 1;
+ break;
+ case 'a':
+#ifdef ANDROID
+ fs_config_func = fs_config;
+ mountpoint = optarg;
+#else
+ fprintf(stderr, "can't set android permissions - built without android support\n");
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+#endif
+ break;
+ case 'w':
+ wipe = 1;
+ break;
+ case 'z':
+ gzip = 1;
+ break;
case 'J':
info.no_journal = 1;
break;
case 'c':
crc = 1;
break;
- case 's':
- sparse = 1;
- break;
- case 't':
- init_itabs = 1;
- break;
- case 'S':
+ case 's':
+ sparse = 1;
+ break;
+ case 't':
+ init_itabs = 1;
+ break;
+ case 'S':
#ifdef HAVE_SELINUX
- seopts[0].value = optarg;
- sehnd = selabel_open(SELABEL_CTX_FILE, seopts, 1);
- if (!sehnd) {
- perror(optarg);
- exit(EXIT_FAILURE);
- }
+ seopts[0].value = optarg;
+ sehnd = selabel_open(SELABEL_CTX_FILE, seopts, 1);
+ if (!sehnd) {
+ perror(optarg);
+ exit(EXIT_FAILURE);
+ }
#endif
- break;
- default: /* '?' */
- usage(argv[0]);
- exit(EXIT_FAILURE);
- }
- }
-
- if (gzip && sparse) {
- fprintf(stderr, "Cannot specify both gzip and sparse\n");
- usage(argv[0]);
- exit(EXIT_FAILURE);
+ break;
+ default: /* '?' */
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
}
- if (wipe && sparse) {
- fprintf(stderr, "Cannot specifiy both wipe and sparse\n");
- usage(argv[0]);
- exit(EXIT_FAILURE);
- }
+ if (gzip && sparse) {
+ fprintf(stderr, "Cannot specify both gzip and sparse\n");
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
- if (wipe && gzip) {
- fprintf(stderr, "Cannot specifiy both wipe and gzip\n");
- usage(argv[0]);
- exit(EXIT_FAILURE);
- }
+ if (wipe && sparse) {
+ fprintf(stderr, "Cannot specifiy both wipe and sparse\n");
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
- if (optind >= argc) {
- fprintf(stderr, "Expected filename after options\n");
- usage(argv[0]);
- exit(EXIT_FAILURE);
- }
+ if (wipe && gzip) {
+ fprintf(stderr, "Cannot specifiy both wipe and gzip\n");
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
- filename = argv[optind++];
+ if (optind >= argc) {
+ fprintf(stderr, "Expected filename after options\n");
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
- if (optind < argc)
- directory = argv[optind++];
+ filename = argv[optind++];
- if (optind < argc) {
- fprintf(stderr, "Unexpected argument: %s\n", argv[optind]);
- usage(argv[0]);
- exit(EXIT_FAILURE);
- }
+ if (optind < argc)
+ directory = argv[optind++];
- return make_ext4fs_internal(filename, directory, mountpoint, android, gzip,
- sparse, crc, wipe, init_itabs, sehnd);
+ if (optind < argc) {
+ fprintf(stderr, "Unexpected argument: %s\n", argv[optind]);
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ if (strcmp(filename, "-")) {
+ fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
+ if (fd < 0) {
+ error_errno("open");
+ return EXIT_FAILURE;
+ }
+ } else {
+ fd = STDOUT_FILENO;
+ }
+
+ exitcode = make_ext4fs_internal(fd, directory, mountpoint, fs_config_func, gzip,
+ sparse, crc, wipe, init_itabs, sehnd);
+ close(fd);
+
+ return exitcode;
}
diff --git a/ext4_utils/output_file.c b/ext4_utils/output_file.c
index d7cf91b..40655a9 100644
--- a/ext4_utils/output_file.c
+++ b/ext4_utils/output_file.c
@@ -20,15 +20,20 @@
#include "sparse_crc32.h"
#include "wipe.h"
+#include <fcntl.h>
+#include <stdbool.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
-#include <sys/mman.h>
#include <unistd.h>
-#include <fcntl.h>
-
#include <zlib.h>
+#ifndef USE_MINGW
+#include <sys/mman.h>
+#define O_BINARY 0
+#endif
+
+
#if defined(__APPLE__) && defined(__MACH__)
#define lseek64 lseek
#define off64_t off_t
@@ -48,6 +53,7 @@
struct output_file {
int fd;
gzFile gz_fd;
+ bool close_fd;
int sparse;
u64 cur_out_ptr;
u32 chunk_cnt;
@@ -85,7 +91,9 @@
static void file_close(struct output_file *out)
{
- close(out->fd);
+ if (out->close_fd) {
+ close(out->fd);
+ }
}
@@ -343,7 +351,7 @@
out->ops->close(out);
}
-struct output_file *open_output_file(const char *filename, int gz, int sparse,
+struct output_file *open_output_fd(int fd, int gz, int sparse,
int chunks, int crc, int wipe)
{
int ret;
@@ -362,25 +370,17 @@
if (gz) {
out->ops = &gz_file_ops;
- out->gz_fd = gzopen(filename, "wb9");
+ out->gz_fd = gzdopen(fd, "wb9");
if (!out->gz_fd) {
error_errno("gzopen");
free(out);
return NULL;
}
} else {
- if (strcmp(filename, "-")) {
- out->fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
- if (out->fd < 0) {
- error_errno("open");
- free(out);
- return NULL;
- }
- } else {
- out->fd = STDOUT_FILENO;
- }
+ out->fd = fd;
out->ops = &file_ops;
}
+ out->close_fd = false;
out->sparse = sparse;
out->cur_out_ptr = 0ll;
out->chunk_cnt = 0;
@@ -407,6 +407,33 @@
return out;
}
+struct output_file *open_output_file(const char *filename, int gz, int sparse,
+ int chunks, int crc, int wipe) {
+
+ int fd;
+ struct output_file *file;
+
+ if (strcmp(filename, "-")) {
+ fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
+ if (fd < 0) {
+ error_errno("open");
+ return NULL;
+ }
+ } else {
+ fd = STDOUT_FILENO;
+ }
+
+ file = open_output_fd(fd, gz, sparse, chunks, crc, wipe);
+ if (!file) {
+ close(fd);
+ return NULL;
+ }
+
+ file->close_fd = true; // we opened descriptor thus we responsible for closing it
+
+ return file;
+}
+
void pad_output_file(struct output_file *out, u64 len)
{
int ret;
@@ -447,7 +474,7 @@
void write_data_block(struct output_file *out, u64 off, u8 *data, int len)
{
int ret;
-
+
if (off + len > (u64) info.len) {
error("attempted to write block %llu past end of filesystem",
off + len - info.len);
@@ -512,6 +539,7 @@
int ret;
off64_t aligned_offset;
int aligned_diff;
+ int buffer_size;
if (off + len >= (u64) info.len) {
error("attempted to write block %llu past end of filesystem",
@@ -519,7 +547,7 @@
return;
}
- int file_fd = open(file, O_RDONLY);
+ int file_fd = open(file, O_RDONLY | O_BINARY);
if (file_fd < 0) {
error_errno("open");
return;
@@ -527,14 +555,25 @@
aligned_offset = offset & ~(4096 - 1);
aligned_diff = offset - aligned_offset;
+ buffer_size = len + aligned_diff;
- u8 *data = mmap64(NULL, len + aligned_diff, PROT_READ, MAP_SHARED, file_fd,
+#ifndef USE_MINGW
+ u8 *data = mmap64(NULL, buffer_size, PROT_READ, MAP_SHARED, file_fd,
aligned_offset);
if (data == MAP_FAILED) {
error_errno("mmap64");
close(file_fd);
return;
}
+#else
+ u8 *data = malloc(buffer_size);
+ if (!data) {
+ error_errno("malloc");
+ close(file_fd);
+ return;
+ }
+ memset(data, 0, buffer_size);
+#endif
if (out->sparse) {
write_chunk_raw(out, off, data + aligned_diff, len);
@@ -549,6 +588,11 @@
}
err:
- munmap(data, len);
+#ifndef USE_MINGW
+ munmap(data, buffer_size);
+#else
+ write(file_fd, data, buffer_size);
+ free(data);
+#endif
close(file_fd);
}
diff --git a/ext4_utils/output_file.h b/ext4_utils/output_file.h
index b448706..a578c80 100644
--- a/ext4_utils/output_file.h
+++ b/ext4_utils/output_file.h
@@ -21,6 +21,8 @@
struct output_file *open_output_file(const char *filename, int gz, int sparse,
int chunks, int crc, int wipe);
+struct output_file *open_output_fd(int fd, int gz, int sparse,
+ int chunks, int crc, int wipe);
void write_data_block(struct output_file *out, u64 off, u8 *data, int len);
void write_fill_block(struct output_file *out, u64 off, u32 fill_val, int len);
void write_data_file(struct output_file *out, u64 off, const char *file,
diff --git a/ext4_utils/sha1.c b/ext4_utils/sha1.c
index 1db9134..463ec38 100644
--- a/ext4_utils/sha1.c
+++ b/ext4_utils/sha1.c
@@ -17,7 +17,9 @@
#define SHA1HANDSOFF /* Copies data before messing with it. */
+#ifndef USE_MINGW
#include <sys/cdefs.h>
+#endif
#include <sys/types.h>
#include <assert.h>
#include <string.h>
diff --git a/ext4_utils/sha1.h b/ext4_utils/sha1.h
index 71334c8..9a8f7e3 100644
--- a/ext4_utils/sha1.h
+++ b/ext4_utils/sha1.h
@@ -9,10 +9,21 @@
#ifndef _SYS_SHA1_H_
#define _SYS_SHA1_H_
-#include <sys/cdefs.h>
#include <sys/types.h>
#include <stdint.h>
+#ifdef USE_MINGW
+typedef unsigned char u_char;
+typedef unsigned int uint32_t;
+typedef unsigned int u_int32_t;
+typedef unsigned int u_int;
+
+#define __BEGIN_DECLS
+#define __END_DECLS
+#else
+#include <sys/cdefs.h>
+#endif
+
#define SHA1_DIGEST_LENGTH 20
#define SHA1_DIGEST_STRING_LENGTH 41
diff --git a/ext4_utils/simg2img.c b/ext4_utils/simg2img.c
index 228d289..12b92eb 100644
--- a/ext4_utils/simg2img.c
+++ b/ext4_utils/simg2img.c
@@ -247,7 +247,7 @@
fprintf(stderr, "Error reading chunk header\n");
exit(-1);
}
-
+
if (sparse_header.chunk_hdr_sz > CHUNK_HEADER_LEN) {
/* Skip the remaining bytes in a header that is longer than
* we expected.
diff --git a/ext4_utils/simg_dump.py b/ext4_utils/simg_dump.py
new file mode 100755
index 0000000..6ece31d
--- /dev/null
+++ b/ext4_utils/simg_dump.py
@@ -0,0 +1,169 @@
+#! /usr/bin/env python
+
+# Copyright (C) 2012 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.
+
+from __future__ import print_function
+import getopt, posixpath, signal, struct, sys
+
+def usage(argv0):
+ print("""
+Usage: %s [-v] sparse_image_file ...
+ -v verbose output
+""" % ( argv0 ))
+ sys.exit(2)
+
+def main():
+
+ signal.signal(signal.SIGPIPE, signal.SIG_DFL)
+
+ me = posixpath.basename(sys.argv[0])
+
+ # Parse the command line
+ verbose = 0 # -v
+ try:
+ opts, args = getopt.getopt(sys.argv[1:],
+ "v",
+ ["verbose"])
+ except getopt.GetoptError, e:
+ print(e)
+ usage(me)
+ for o, a in opts:
+ if o in ("-v", "--verbose"):
+ verbose += 1
+ else:
+ print("Unrecognized option \"%s\"" % (o))
+ usage(me)
+
+ if len(args) == 0:
+ print("No sparse_image_file specified")
+ usage(me)
+
+ for path in args:
+ FH = open(path, 'rb')
+ header_bin = FH.read(28)
+ header = struct.unpack("<I4H4I", header_bin)
+
+ magic = header[0]
+ major_version = header[1]
+ minor_version = header[2]
+ file_hdr_sz = header[3]
+ chunk_hdr_sz = header[4]
+ blk_sz = header[5]
+ total_blks = header[6]
+ total_chunks = header[7]
+ image_checksum = header[8]
+
+ if magic != 0xED26FF3A:
+ print("%s: %s: Magic should be 0xED26FF3A but is 0x%08X"
+ % (me, path, magic))
+ continue
+ if major_version != 1 or minor_version != 0:
+ print("%s: %s: I only know about version 1.0, but this is version %u.%u"
+ % (me, path, major_version, minor_version))
+ continue
+ if file_hdr_sz != 28:
+ print("%s: %s: The file header size was expected to be 28, but is %u."
+ % (me, path, file_hdr_sz))
+ continue
+ if chunk_hdr_sz != 12:
+ print("%s: %s: The chunk header size was expected to be 12, but is %u."
+ % (me, path, chunk_hdr_sz))
+ continue
+
+ print("%s: Total of %u %u-byte output blocks in %u input chunks."
+ % (path, total_blks, blk_sz, total_chunks))
+
+ if image_checksum != 0:
+ print("checksum=0x%08X" % (image_checksum))
+
+ if not verbose:
+ continue
+ print(" input_bytes output_blocks")
+ print("chunk offset number offset number")
+ offset = 0
+ for i in xrange(1,total_chunks+1):
+ header_bin = FH.read(12)
+ header = struct.unpack("<2H2I", header_bin)
+ chunk_type = header[0]
+ reserved1 = header[1]
+ chunk_sz = header[2]
+ total_sz = header[3]
+ data_sz = total_sz - 12
+
+ print("%4u %10u %10u %7u %7u" % (i, FH.tell(), data_sz, offset, chunk_sz),
+ end=" ")
+
+ if chunk_type == 0xCAC1:
+ if data_sz != (chunk_sz * blk_sz):
+ print("Raw chunk input size (%u) does not match output size (%u)"
+ % (data_sz, chunk_sz * blk_sz))
+ break;
+ else:
+ print("Raw data", end="")
+ FH.read(data_sz)
+ elif chunk_type == 0xCAC2:
+ if data_sz != 4:
+ print("Fill chunk should have 4 bytes of fill, but this has %u"
+ % (data_sz), end="")
+ break;
+ else:
+ fill_bin = FH.read(4)
+ fill = struct.unpack("<I", fill_bin)
+ print("Fill with 0x%08X" % (fill))
+ elif chunk_type == 0xCAC3:
+ if data_sz != 0:
+ print("Don't care chunk input size is non-zero (%u)" % (data_sz))
+ break;
+ else:
+ print("Don't care", end="")
+ elif chunk_type == 0xCAC4:
+ if data_sz != 4:
+ print("CRC32 chunk should have 4 bytes of CRC, but this has %u"
+ % (data_sz), end="")
+ break;
+ else:
+ crc_bin = FH.read(4)
+ crc = struct.unpack("<I", crc)
+ print("Unverified CRC32 0x%08X" % (crc))
+ else:
+ print("Unknown chunk type 0x%04X" % (chunk_type), end="")
+ break;
+
+ if verbose > 1:
+ header = struct.unpack("<12B", header_bin)
+ print(" (%02X%02X %02X%02X %02X%02X%02X%02X %02X%02X%02X%02X)"
+ % (header[0], header[1], header[2], header[3],
+ header[4], header[5], header[6], header[7],
+ header[8], header[9], header[10], header[11]))
+ else:
+ print()
+
+ offset += chunk_sz
+
+ print(" %10u %7u End" % (FH.tell(), offset))
+
+ if total_blks != offset:
+ print("The header said we should have %u output blocks, but we saw %u"
+ % (total_blks, offset))
+
+ junk_len = len(FH.read())
+ if junk_len:
+ print("There were %u bytes of extra data at the end of the file."
+ % (junk_len))
+
+ sys.exit(0)
+
+if __name__ == "__main__":
+ main()
diff --git a/ext4_utils/uuid.c b/ext4_utils/uuid.c
index d518476..33d2494 100644
--- a/ext4_utils/uuid.c
+++ b/ext4_utils/uuid.c
@@ -15,7 +15,12 @@
*/
#include <string.h>
+
+#ifdef USE_MINGW
+#include <winsock2.h>
+#else
#include <arpa/inet.h>
+#endif
#include "ext4_utils.h"
#include "sha1.h"
diff --git a/libpagemap/include/pagemap/pagemap.h b/libpagemap/include/pagemap/pagemap.h
index 09ff29d..25c6161 100644
--- a/libpagemap/include/pagemap/pagemap.h
+++ b/libpagemap/include/pagemap/pagemap.h
@@ -129,10 +129,10 @@
unsigned long low, unsigned long hi,
uint64_t **range_out, size_t *len);
-#define _BITS(x, offset, bits) (((x) >> offset) & ((1LL << ((bits) + 1)) - 1))
+#define _BITS(x, offset, bits) (((x) >> offset) & ((1LL << (bits)) - 1))
#define PM_PAGEMAP_PRESENT(x) (_BITS(x, 63, 1))
-#define PM_PAGEMAP_SWAPPED(x) (!_BITS(x, 62, 1))
+#define PM_PAGEMAP_SWAPPED(x) (_BITS(x, 62, 1))
#define PM_PAGEMAP_SHIFT(x) (_BITS(x, 55, 6))
#define PM_PAGEMAP_PFN(x) (_BITS(x, 0, 55))
#define PM_PAGEMAP_SWAP_OFFSET(x) (_BITS(x, 5, 50))
diff --git a/libpagemap/pm_map.c b/libpagemap/pm_map.c
index f683ba6..2d5c2f9 100644
--- a/libpagemap/pm_map.c
+++ b/libpagemap/pm_map.c
@@ -83,10 +83,6 @@
pm_memusage_zero(&ws);
for (i = 0; i < len; i++) {
- if (!PM_PAGEMAP_PRESENT(pagemap[i]) ||
- PM_PAGEMAP_SWAPPED(pagemap[i]))
- continue;
-
error = pm_kernel_flags(map->proc->ker, PM_PAGEMAP_PFN(pagemap[i]),
&flags);
if (error) goto out;
@@ -99,6 +95,7 @@
if (error) goto out;
ws.vss += map->proc->ker->pagesize;
+ if( PM_PAGEMAP_SWAPPED(pagemap[i]) ) continue;
ws.rss += (count >= 1) ? (map->proc->ker->pagesize) : (0);
ws.pss += (count >= 1) ? (map->proc->ker->pagesize / count) : (0);
ws.uss += (count == 1) ? (map->proc->ker->pagesize) : (0);
diff --git a/libpagemap/pm_process.c b/libpagemap/pm_process.c
index b3c077e..dddff01 100644
--- a/libpagemap/pm_process.c
+++ b/libpagemap/pm_process.c
@@ -122,7 +122,7 @@
free(range);
*range_out = NULL;
return 0;
- } else if (error < 0 || (error > 0 && error < numpages * sizeof(uint64_t))) {
+ } else if (error < 0 || (error > 0 && error < (int)(numpages * sizeof(uint64_t)))) {
error = (error < 0) ? errno : -1;
free(range);
return error;
@@ -210,7 +210,7 @@
}
#define INITIAL_MAPS 10
-#define MAX_LINE 256
+#define MAX_LINE 1024
#define MAX_PERMS 5
/*
diff --git a/showmap/showmap.c b/showmap/showmap.c
index 5c4a26f..bb359f6 100644
--- a/showmap/showmap.c
+++ b/showmap/showmap.c
@@ -56,9 +56,7 @@
if (line[name_pos]) {
strlcpy(name, line + name_pos, sizeof(name));
} else {
- if ((start >= 0x10000000) && (start < 0x40000000)) {
- strlcpy(name, "[stack]", sizeof(name));
- } else if (prev && start == prev->end && is_library(prev->name)) {
+ if (prev && start == prev->end && is_library(prev->name)) {
// anonymous mappings immediately adjacent to shared libraries
// usually correspond to the library BSS segment, so we use the
// library's own name
diff --git a/su/su.c b/su/su.c
index b87cece..f87f073 100644
--- a/su/su.c
+++ b/su/su.c
@@ -44,6 +44,13 @@
struct passwd *pw;
int uid, gid, myuid;
+ /* Until we have something better, only root and the shell can use su. */
+ myuid = getuid();
+ if (myuid != AID_ROOT && myuid != AID_SHELL) {
+ fprintf(stderr,"su: uid %d not allowed to su\n", myuid);
+ return 1;
+ }
+
if(argc < 2) {
uid = gid = 0;
} else {
@@ -57,13 +64,6 @@
}
}
- /* Until we have something better, only root and the shell can use su. */
- myuid = getuid();
- if (myuid != AID_ROOT && myuid != AID_SHELL) {
- fprintf(stderr,"su: uid %d not allowed to su\n", myuid);
- return 1;
- }
-
if(setgid(gid) || setuid(uid)) {
fprintf(stderr,"su: permission denied\n");
return 1;
diff --git a/tests/bionic/libc/Android.mk b/tests/bionic/libc/Android.mk
index 5dcf130..52ef01e 100644
--- a/tests/bionic/libc/Android.mk
+++ b/tests/bionic/libc/Android.mk
@@ -61,6 +61,7 @@
# First, the tests in 'common'
sources := \
+ common/bench_stdio.c \
common/test_clock.c \
common/test_cpu_set.c \
common/test_drand48.c \
@@ -252,4 +253,31 @@
EXTRA_CFLAGS := -mandroid
#$(call device-test, $(sources))
+# NOTE: We build both a shared and static version of bench_pthread.
+# the shared version will use the target device's C library, while
+# the static one will use the current build product implementation.
+# This is ideal to quantify pthread optimizations.
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := common/bench_pthread.c
+LOCAL_MODULE := bench_pthread_shared
+LOCAL_MODULE_TAGS := tests
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := common/bench_pthread.c
+LOCAL_MODULE := bench_pthread_static
+LOCAL_MODULE_TAGS := tests
+LOCAL_FORCE_STATIC_EXECUTABLE := true
+LOCAL_STATIC_LIBRARIES := libc
+include $(BUILD_EXECUTABLE)
+
+ifeq ($(HOST_OS),linux)
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := common/bench_pthread.c
+LOCAL_MODULE := bench_pthread
+LOCAL_LDLIBS += -lpthread -lrt
+LOCAL_MODULE_TAGS := tests
+include $(BUILD_HOST_EXECUTABLE)
+endif
+
endif # BIONIC_TESTS
diff --git a/tests/bionic/libc/common/bench_pthread.c b/tests/bionic/libc/common/bench_pthread.c
new file mode 100644
index 0000000..4e46f61
--- /dev/null
+++ b/tests/bionic/libc/common/bench_pthread.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* This program is used to benchmark various pthread operations
+ * Note that we want to be able to build it with GLibc, both on
+ * a Linux host and an Android device. For example, on ARM, one
+ * can build it manually with:
+ *
+ * arm-linux-none-gnueabi-gcc -static -o bench_pthread_gnueabi \
+ * bench_pthread.c -O2 -lpthread -lrt
+ */
+#define _GNU_SOURCE 1
+#include <time.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <limits.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define S(x) S_(x)
+#define S_(x) #x
+
+#define C(x,y) C_(x,y)
+#define C_(x,y) x ## y
+
+#ifndef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER
+#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
+#endif
+
+#ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER
+#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
+#endif
+
+static int64_t now_ns(void)
+{
+ struct timespec ts;
+ /* NOTE: get thread-specific CPU-time clock to ensure
+ * we don't measure stuff like kernel thread preemptions
+ * that might happen during the benchmark
+ */
+ clock_gettime(CLOCK_THREAD_CPUTIME_ID,&ts);
+ return ts.tv_sec*1000000000LL + ts.tv_nsec;
+}
+
+#define SUBCOUNT 10000
+#define MAX_STATS 1000000
+
+/* Maximum time we'll wait for a single bench run */
+#define MAX_WAIT_MS 1000
+
+static int64_t stats[MAX_STATS];
+
+static int
+compare_stats(const void* a, const void* b)
+{
+ uint64_t sa = *(const uint64_t*)a;
+ uint64_t sb = *(const uint64_t*)b;
+ if (sa < sb)
+ return -1;
+ if (sa > sb)
+ return +1;
+ else
+ return 0;
+}
+
+static void
+filter_stats(int count, const char* statement)
+{
+ int64_t min, max, avg, median;
+
+ /* sort the array in increasing order */
+ qsort(stats, count, sizeof(stats[0]), compare_stats);
+
+ /* trim 10% to remove outliers */
+ int min_index = count*0.05;
+ int max_index = count - min_index;
+ if (max_index >= count)
+ max_index = count-1;
+
+ count = (max_index - min_index)+1;
+
+ /* the median is the center item */
+ median = stats[(min_index+max_index)/2];
+
+ /* the minimum is the first, the max the last */
+ min = stats[min_index];
+ max = stats[max_index];
+
+ /* compute the average */
+ int nn;
+ int64_t total = 0;
+ for (nn = min_index; nn <= max_index; nn++) {
+ total += stats[nn];
+ }
+
+ printf("BENCH: %5.1f %5.1f %5.1f, %s\n",
+ min*1./SUBCOUNT,
+ max*1./SUBCOUNT,
+ median*1./SUBCOUNT,
+ statement);
+ if (0) {
+ for (nn = min_index; nn <= max_index; nn++) {
+ printf(" %lld", (long long)stats[nn]);
+ }
+ printf("\n");
+ }
+}
+
+#define BENCH_COUNT(stmnt,total) do { \
+ int64_t count = total; \
+ int num_stats = 0; \
+ int64_t bench_start = now_ns(); \
+ while (num_stats < MAX_STATS && count >= SUBCOUNT) { \
+ int tries = SUBCOUNT; \
+ int64_t sub_start = now_ns(); \
+ count -= tries; \
+ for ( ; tries > 0; tries-- ) {\
+ stmnt;\
+ }\
+ int64_t sub_end = now_ns(); \
+ stats[num_stats++] = sub_end - sub_start; \
+ if (sub_end - bench_start >= MAX_WAIT_MS*1e6) \
+ break; \
+ } \
+ filter_stats(num_stats, #stmnt); \
+ } while (0)
+
+#define DEFAULT_COUNT 10000000
+
+#define BENCH(stmnt) BENCH_COUNT(stmnt,DEFAULT_COUNT)
+
+/* Will be called by pthread_once() for benchmarking */
+static void _dummy_init(void)
+{
+ /* nothing */
+}
+
+/* Used when creating the key */
+static void key_destroy(void* param)
+{
+ /* nothing */
+}
+
+int main(void)
+{
+ pthread_once_t once = PTHREAD_ONCE_INIT;
+ pthread_once(&once, _dummy_init);
+
+ pthread_key_t key;
+ pthread_key_create(&key, key_destroy);
+ pthread_setspecific(key, (void*)(int)100);
+
+ BENCH(getpid());
+ BENCH(pthread_self());
+ BENCH(pthread_getspecific(key));
+ BENCH(pthread_once(&once, _dummy_init));
+
+ pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+ BENCH(pthread_mutex_lock(&mutex); pthread_mutex_unlock(&mutex));
+
+ pthread_mutex_t errorcheck_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER;
+ BENCH(pthread_mutex_lock(&errorcheck_mutex); pthread_mutex_unlock(&errorcheck_mutex));
+
+ pthread_mutex_t recursive_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
+ BENCH(pthread_mutex_lock(&recursive_mutex); pthread_mutex_unlock(&recursive_mutex));
+
+ /* TODO: Benchmark pshared mutexes */
+
+ sem_t semaphore;
+ int dummy;
+ sem_init(&semaphore, 1, 1);
+ BENCH(sem_getvalue(&semaphore,&dummy));
+ BENCH(sem_wait(&semaphore); sem_post(&semaphore));
+ return 0;
+}
diff --git a/tests/bionic/libc/common/bench_stdio.c b/tests/bionic/libc/common/bench_stdio.c
new file mode 100644
index 0000000..4c19bf1
--- /dev/null
+++ b/tests/bionic/libc/common/bench_stdio.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* This program tries to benchmark stdio operations like fread() and
+ * fwrite() with various chunk sizes. We always read/write from /dev/zero
+ * to ensure that disk speed and caching don't change our results.
+ *
+ * We really do this to measure improvements in the low-level stdio
+ * features.
+ */
+
+#include <stdio.h>
+#include <time.h>
+#include <string.h>
+#include <errno.h>
+
+static char buffer[1024*1024];
+
+/* Return current time in milli-seconds, as a double */
+static double
+now_ms(void)
+{
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ return ts.tv_sec*1000. + ts.tv_nsec*1e-6;
+}
+
+void read_file(FILE* fp, int chunkSize)
+{
+ int totalSize = sizeof(buffer);
+ for ( ; totalSize > 0; totalSize -= chunkSize) {
+ fread(buffer, 1, chunkSize, fp);
+ }
+}
+
+void write_file(FILE* fp, int chunkSize)
+{
+ int totalSize = sizeof(buffer);
+ for ( ; totalSize > 0; totalSize -= chunkSize) {
+ fwrite(buffer, 1, chunkSize, fp);
+ }
+}
+
+#define BENCH(op,...) \
+ do { \
+ double time_ms = now_ms(); \
+ op ; \
+ time_ms = now_ms() - time_ms; \
+ double bandwidth = sizeof(buffer)*1000./1024./time_ms; \
+ printf("bench %-30s %8.2f ms (%.1f KB/s) \n", #op, time_ms, bandwidth ); \
+ } while (0)
+
+int main(void)
+{
+ FILE* fp = fopen("/dev/zero", "rw");
+
+ if (fp == NULL) {
+ fprintf(stderr,"Could not open /dev/zero: %s\n", strerror(errno));
+ return 1;
+ }
+
+ BENCH(read_file(fp,1));
+ BENCH(read_file(fp,2));
+ BENCH(read_file(fp,3));
+ BENCH(read_file(fp,4));
+ BENCH(read_file(fp,8));
+ BENCH(read_file(fp,16));
+ BENCH(read_file(fp,32));
+ BENCH(read_file(fp,64));
+ BENCH(read_file(fp,256));
+ BENCH(read_file(fp,1024));
+ BENCH(read_file(fp,4096));
+ BENCH(read_file(fp,16384));
+ BENCH(read_file(fp,65536));
+
+ BENCH(write_file(fp,1));
+ BENCH(write_file(fp,2));
+ BENCH(write_file(fp,3));
+ BENCH(write_file(fp,4));
+ BENCH(write_file(fp,8));
+ BENCH(write_file(fp,16));
+ BENCH(write_file(fp,32));
+ BENCH(write_file(fp,64));
+ BENCH(write_file(fp,256));
+ BENCH(write_file(fp,1024));
+ BENCH(write_file(fp,4096));
+ BENCH(write_file(fp,16384));
+ BENCH(write_file(fp,65536));
+
+ fclose(fp);
+ return 0;
+}
diff --git a/tests/framebuffer/refresh.c b/tests/framebuffer/refresh.c
index 43dc7cf..38e7871 100644
--- a/tests/framebuffer/refresh.c
+++ b/tests/framebuffer/refresh.c
@@ -67,12 +67,10 @@
if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
return -errno;
- int refreshRate = 1000000000000000LLU /
- (
- (uint64_t)( info.upper_margin + info.lower_margin + info.yres )
- * ( info.left_margin + info.right_margin + info.xres )
- * info.pixclock
- );
+ uint64_t denominator = (uint64_t)( info.upper_margin + info.lower_margin + info.yres )
+ * ( info.left_margin + info.right_margin + info.xres )
+ * info.pixclock;
+ int refreshRate = denominator ? (1000000000000000LLU / denominator) : 0;
float xdpi = (info.xres * 25.4f) / info.width;
float ydpi = (info.yres * 25.4f) / info.height;
diff --git a/tests/fstest/perm_checker.conf b/tests/fstest/perm_checker.conf
index 25f1b5f..580eb85 100644
--- a/tests/fstest/perm_checker.conf
+++ b/tests/fstest/perm_checker.conf
@@ -16,8 +16,8 @@
/data/dalvik-cache/... 400 744 root 19999 root 19999
/data/data 701 771 system system system system
/data/data/... 000 775 system 19999 system 19999
-/data/local/ 771 771 shell shell shell shell
-/data/local/tmp/ 771 1771 shell shell shell shell
+/data/local/ 751 751 root root root root
+/data/local/tmp/ 771 771 shell shell shell shell
/data/lost+found/ 700 770 root root root root
/data/misc/ 1711 1771 root system root misc
/data/misc/akmd_set.txt 600 640 root compass compass compass
diff --git a/tests/iptables/qtaguid/Android.mk b/tests/iptables/qtaguid/Android.mk
index 5eba34f..cf0a2ba 100644
--- a/tests/iptables/qtaguid/Android.mk
+++ b/tests/iptables/qtaguid/Android.mk
@@ -19,7 +19,6 @@
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := tests
LOCAL_MODULE := socketTag
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativestresstest
LOCAL_SRC_FILES := socketTag.cpp
LOCAL_SHARED_LIBRARIES += libcutils libutils
LOCAL_STATIC_LIBRARIES += libtestUtil
diff --git a/tests/iptables/qtaguid/socketTag.cpp b/tests/iptables/qtaguid/socketTag.cpp
index 68d9257..fb7ecdc 100644
--- a/tests/iptables/qtaguid/socketTag.cpp
+++ b/tests/iptables/qtaguid/socketTag.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*
*/
+
/*
* This socket tagging test is to ensure that the
* netfilter/xt_qtaguid kernel module somewhat behaves as expected
@@ -24,6 +25,7 @@
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
+#include <gtest/gtest.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string>
@@ -32,15 +34,15 @@
#include <utils/Log.h>
#include <testUtil.h>
+namespace android {
class SockInfo {
public:
- SockInfo()
- : fd(-1), addr(NULL) {};
- int setup(uint64_t tag);
- bool checkTag(uint64_t tag, uid_t uid);
- int fd;
- void *addr;
+ SockInfo() : fd(-1), addr(NULL) {};
+ int setup(uint64_t tag);
+ bool checkTag(uint64_t tag, uid_t uid);
+ int fd;
+ void *addr;
};
@@ -90,6 +92,7 @@
close(param_fd);
return res;
}
+
/*----------------------------------------------------------------*/
int SockInfo::setup(uint64_t tag) {
fd = socket(AF_INET, SOCK_STREAM, 0);
@@ -180,528 +183,217 @@
return pos != NULL;
}
-/*----------------------------------------------------------------*/
-int testSocketTagging(void) {
- SockInfo sock0;
- SockInfo sock1;
- int res;
- int total_errors = 0;
- int ctrl_fd = -1;
- int dev_fd = -1;
- const uint64_t invalid_tag1 = 0x0000000100000001llu;
- uint64_t valid_tag1;
- uint64_t valid_tag2;
- uint64_t max_uint_tag = 0xffffffff00000000llu;
- uid_t fake_uid;
- uid_t fake_uid2;
- const char *test_name;
- uid_t my_uid = getuid();
- pid_t my_pid = getpid();
- srand48(my_pid * my_uid);
- /* Adjust fake UIDs and tags so that multiple instances can run in parallel. */
- fake_uid = testRand();
- fake_uid2 = testRand();
- valid_tag1 = ((uint64_t)my_pid << 48) | ((uint64_t)testRand() << 32);
- valid_tag2 = ((uint64_t)my_pid << 48) | ((uint64_t)testRand() << 32);
- max_uint_tag = 1llu << 63 | (((uint64_t)my_pid << 48) ^ max_uint_tag);
- testSetLogCatTag(LOG_TAG);
+class SocketTaggingTest : public ::testing::Test {
+protected:
+ virtual void SetUp() {
+ ctrl_fd = -1;
+ dev_fd = -1;
+ my_uid = getuid();
+ my_pid = getpid();
+ srand48(my_pid * my_uid);
+ // Adjust fake UIDs and tags so that multiple instances can run in parallel.
+ fake_uid = testRand();
+ fake_uid2 = testRand();
+ valid_tag1 = ((uint64_t)my_pid << 48) | ((uint64_t)testRand() << 32);
+ valid_tag2 = ((uint64_t)my_pid << 48) | ((uint64_t)testRand() << 32);
+ valid_tag2 &= 0xffffff00ffffffffllu; // Leave some room to make counts visible.
+ testPrintI("* start: pid=%lu uid=%lu uid1=0x%lx/%lu uid2=0x%lx/%lu"
+ " tag1=0x%llx/%llu tag2=0x%llx/%llu",
+ my_pid, my_uid, fake_uid, fake_uid, fake_uid2, fake_uid2,
+ valid_tag1, valid_tag1, valid_tag2, valid_tag2);
+ max_uint_tag = 0xffffffff00000000llu;
+ max_uint_tag = 1llu << 63 | (((uint64_t)my_pid << 48) ^ max_uint_tag);
- testPrintI("** %s ** ============================", __FUNCTION__);
- testPrintI("* start: pid=%lu uid=%lu uid1=0x%lx/%lu uid2=0x%lx/%lu"
- " tag1=0x%llx/%llu tag2=0x%llx/%llu",
- my_pid, my_uid, fake_uid, fake_uid, fake_uid2, fake_uid2,
- valid_tag1, valid_tag1, valid_tag2, valid_tag2);
-
- // ---------------
- test_name = "kernel has qtaguid";
- testPrintI("* test: %s ", test_name);
- ctrl_fd = openCtrl();
- if (ctrl_fd < 0) {
- testPrintE("qtaguid ctrl open failed: %s", strerror(errno));
- total_errors++;
- goto done;
- }
- close(ctrl_fd);
- dev_fd = open("/dev/xt_qtaguid", O_RDONLY);
- if (dev_fd < 0) {
- testPrintE("qtaguid dev open failed: %s", strerror(errno));
- total_errors++;
- }
- // ---------------
- test_name = "delete command doesn't fail";
- testPrintI("* test: %s", test_name);
- res = doCtrlCommand("d 0 %u", fake_uid);
- if (res < 0) {
- testPrintE("! %s: Unexpected results", test_name);
- total_errors++;
- }
-
- res = doCtrlCommand("d 0 %u", fake_uid2);
- if (res < 0) {
- testPrintE("! %s: Unexpected results", test_name);
- total_errors++;
- }
-
- res = doCtrlCommand("d 0 %u", my_uid);
- if (res < 0) {
- testPrintE("! %s: Unexpected results", test_name);
- total_errors++;
- }
- // ---------------
- test_name = "setup sock0 and addr via tag";
- testPrintI("* test: %s", test_name);
- if (sock0.setup(valid_tag1) < 0) {
- testPrintE("socket setup failed: %s", strerror(errno));
- total_errors++;
- goto done;
-
- }
- // ---------------
- test_name = "setup sock1 and addr via tag";
- testPrintI("* test: %s", test_name);
- if (sock1.setup(valid_tag1) < 0) {
- testPrintE("socket setup failed: %s", strerror(errno));
- total_errors++;
- goto done;
- }
- // ---------------
- test_name = "insufficient args. Expected failure";
- testPrintI("* test: %s", test_name);
- res = doCtrlCommand("t");
- if (res > 0) {
- testPrintE("! %s: Unexpected results", test_name);
- total_errors++;
- }
-
- // ---------------
- test_name = "bad command. Expected failure";
- testPrintI("* test: %s", test_name);
- res = doCtrlCommand("?");
- if (res > 0) {
- testPrintE("! %s: Unexpected results", test_name);
- total_errors++;
- }
-
- // ---------------
- test_name = "no tag, no uid";
- testPrintI("* test: %s", test_name);
- res = doCtrlCommand("t %d", sock0.fd);
- if (res < 0) {
- testPrintE("! %s: Unexpected results", test_name);
- total_errors++;
- }
- if (!sock0.checkTag(0, my_uid)) {
- testPrintE("! %s: Unexpected results: tag not found", test_name);
- total_errors++;
- }
-
- // ---------------
- test_name = "invalid tag. Expected failure";
- testPrintI("* test: %s", test_name);
- res = doCtrlCommand("t %d %llu", sock0.fd, invalid_tag1);
- if (res > 0) {
- testPrintE("! %s: Unexpected results", test_name);
- total_errors++;
- }
- if (sock0.checkTag(invalid_tag1, my_uid)) {
- testPrintE("! %s: Unexpected results: tag should not be there", test_name);
- total_errors++;
- }
-
- // ---------------
- test_name = "valid tag with no uid";
- testPrintI("* test: %s", test_name);
- res = doCtrlCommand("t %d %llu", sock0.fd, valid_tag1);
- if (res < 0) {
- testPrintE("! %s: Unexpected results", test_name);
- total_errors++;
- }
- if (!sock0.checkTag(valid_tag1, my_uid)) {
- testPrintE("! %s: Unexpected results: tag not found", test_name);
- total_errors++;
- }
- // ---------------
- test_name = "valid untag";
- testPrintI("* test: %s", test_name);
- res = doCtrlCommand("u %d", sock0.fd);
- if (res < 0) {
- testPrintE("! %s: Unexpected results", test_name);
- total_errors++;
- }
- if (sock0.checkTag(valid_tag1, my_uid)) {
- testPrintE("! %s: Unexpected results: tag not removed", test_name);
- total_errors++;
- }
-
- // ---------------
- test_name = "valid 1st tag";
- testPrintI("* test: %s", test_name);
- res = doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag2, fake_uid);
- if (res < 0) {
- testPrintE("! %s: Unexpected results", test_name);
- total_errors++;
- }
- if (!sock0.checkTag(valid_tag2, fake_uid)) {
- testPrintE("! %s: Unexpected results: tag not found", test_name);
- total_errors++;
- }
-
- // ---------------
- test_name = "valid re-tag";
- testPrintI("* test: %s", test_name);
- res = doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag2, fake_uid);
- if (res < 0) {
- testPrintE("! %s: Unexpected results", test_name);
- total_errors++;
- }
- if (!sock0.checkTag(valid_tag2, fake_uid)) {
- testPrintE("! %s: Unexpected results: tag not found", test_name);
- total_errors++;
- }
-
- // ---------------
- test_name = "valid re-tag with acct_tag change";
- testPrintI("* test: %s", test_name);
- res = doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag1, fake_uid);
- if (res < 0) {
- testPrintE("! %s: Unexpected results", test_name);
- total_errors++;
- }
- if (!sock0.checkTag(valid_tag1, fake_uid)) {
- testPrintE("! %s: Unexpected results: tag not found", test_name);
- total_errors++;
- }
-
- // ---------------
- test_name = "re-tag with uid change";
- testPrintI("* test: %s", test_name);
- res = doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag2, fake_uid2);
- if (res < 0) {
- testPrintE("! %s: Unexpected results", test_name);
- total_errors++;
- }
- if (!sock0.checkTag(valid_tag2, fake_uid2)) {
- testPrintE("! %s: Unexpected results: tag not found", test_name);
- total_errors++;
- }
-
- // ---------------
- test_name = "valid 64bit acct tag";
- testPrintI("* test: %s", test_name);
- res = doCtrlCommand("t %d %llu", sock0.fd, max_uint_tag);
- if (res < 0) {
- testPrintE("! %s: Unexpected results", test_name);
- total_errors++;
- }
- if (!sock0.checkTag(max_uint_tag, my_uid)) {
- testPrintE("! %s: Unexpected results: tag not found", test_name);
- total_errors++;
- }
-
- // ---------------
- test_name = "tag another socket";
- testPrintI("* test: %s", test_name);
- res = doCtrlCommand("t %d %llu %u", sock1.fd, valid_tag1, fake_uid2);
- if (res < 0) {
- testPrintE("! %s: Unexpected results", test_name);
- total_errors++;
- }
- if (!sock1.checkTag(valid_tag1, fake_uid2)) {
- testPrintE("! %s: Unexpected results: tag not found", test_name);
- total_errors++;
- }
-
- // ---------------
- test_name = "valid untag";
- testPrintI("* test: %s", test_name);
- res = doCtrlCommand("u %d", sock0.fd);
- if (res < 0) {
- testPrintE("! %s: Unexpected results", test_name);
- total_errors++;
- }
- if (sock0.checkTag(max_uint_tag, fake_uid)) {
- testPrintE("! %s: Unexpected results: tag should not be there", test_name);
- total_errors++;
- }
- if (!sock1.checkTag(valid_tag1, fake_uid2)) {
- testPrintE("! %s: Unexpected results: tag not found", test_name);
- total_errors++;
- }
- res = doCtrlCommand("u %d", sock1.fd);
- if (res < 0) {
- testPrintE("! %s: Unexpected results", test_name);
- total_errors++;
- }
- if (sock1.checkTag(valid_tag1, fake_uid2)) {
- testPrintE("! %s: Unexpected results: tag should not be there", test_name);
- total_errors++;
- }
-
- // ---------------
- test_name = "invalid sock0.fd. Expected failure";
- testPrintI("* test: %s", test_name);
- close(sock0.fd);
- res = doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag1, my_uid);
- if (res > 0) {
- testPrintE("! %s: Unexpected results", test_name);
- total_errors++;
- }
- if (sock0.checkTag(valid_tag1, my_uid)) {
- testPrintE("! %s: Unexpected results: tag should not be there", test_name);
- total_errors++;
- }
-
- // ---------------
- test_name = "invalid untag. Expected failure";
- testPrintI("* test: %s", test_name);
- close(sock1.fd);
- res = doCtrlCommand("u %d", sock1.fd);
- if (res > 0) {
- testPrintE("! %s: Unexpected results", test_name);
- total_errors++;
- }
-
- if (total_errors) {
- testPrintE("! Errors found");
- } else {
- testPrintI("No Errors found");
- }
-
-done:
- if (dev_fd >= 0) {
- close(dev_fd);
- }
- if (ctrl_fd >= 0) {
+ testPrintI("kernel has qtaguid");
+ ctrl_fd = openCtrl();
+ ASSERT_GE(ctrl_fd, 0) << "qtaguid ctrl open failed";
close(ctrl_fd);
- }
- return total_errors;
-}
+ dev_fd = open("/dev/xt_qtaguid", O_RDONLY);
+ EXPECT_GE(dev_fd, 0) << "qtaguid dev open failed";
-int testTagData(void) {
- SockInfo sock0;
- SockInfo sock1;
- int res;
- int total_errors = 0;
- int ctrl_fd = -1;
- int dev_fd = -1;
- const uint64_t invalid_tag1 = 0x0000000100000001llu;
- uint64_t valid_tag1;
- uint64_t valid_tag2;
- uint64_t max_uint_tag = 0xffffffff00000000llu;
- uid_t fake_uid;
- uid_t fake_uid2;
- const char *test_name;
- uid_t my_uid = getuid();
- pid_t my_pid = getpid();
- const int max_tags = 5;
+ // We want to clean up any previous faulty test runs.
+ testPrintI("delete command does not fail");
+ EXPECT_GE(doCtrlCommand("d 0 %u", fake_uid), 0) << "Failed to delete fake_uid";
+ EXPECT_GE(doCtrlCommand("d 0 %u", fake_uid2), 0) << "Failed to delete fake_uid2";
+ EXPECT_GE(doCtrlCommand("d 0 %u", my_uid), 0) << "Failed to delete my_uid";
- srand48(my_pid * my_uid);
- /* Adjust fake UIDs and tags so that multiple instances can run in parallel. */
- fake_uid = testRand();
- fake_uid2 = testRand();
- valid_tag1 = ((uint64_t)my_pid << 48) | ((uint64_t)testRand() << 32);
- valid_tag2 = ((uint64_t)my_pid << 48) | ((uint64_t)testRand() << 32);
- valid_tag2 &= 0xffffff00ffffffffllu; // Leave some room to make counts visible.
- testSetLogCatTag(LOG_TAG);
-
- testPrintI("** %s ** ============================", __FUNCTION__);
- testPrintI("* start: pid=%lu uid=%lu uid1=0x%lx/%lu uid2=0x%lx/%lu"
- " tag1=0x%llx/%llu tag2=0x%llx/%llu",
- my_pid, my_uid, fake_uid, fake_uid, fake_uid2, fake_uid2,
- valid_tag1, valid_tag1, valid_tag2, valid_tag2);
-
- // ---------------
- test_name = "kernel has qtaguid";
- testPrintI("* test: %s ", test_name);
- ctrl_fd = openCtrl();
- if (ctrl_fd < 0) {
- testPrintE("qtaguid ctrl open failed: %s", strerror(errno));
- return 1;
- }
- close(ctrl_fd);
- dev_fd = open("/dev/xt_qtaguid", O_RDONLY);
- if (dev_fd < 0) {
- testPrintE("! %s: qtaguid dev open failed: %s", test_name, strerror(errno));
- total_errors++;
- }
- // ---------------
- test_name = "delete command doesn't fail";
- testPrintI("* test: %s", test_name);
- res = doCtrlCommand("d 0 %u", fake_uid);
- if (res < 0) {
- testPrintE("! %s: Unexpected results", test_name);
- total_errors++;
+ testPrintI("setup sock0 and addr via tag");
+ ASSERT_FALSE(sock0.setup(valid_tag1)) << "socket0 setup failed";
+ testPrintI("setup sock1 and addr via tag");
+ ASSERT_FALSE(sock1.setup(valid_tag1)) << "socket1 setup failed";
}
- res = doCtrlCommand("d 0 %u", fake_uid2);
- if (res < 0) {
- testPrintE("! %s: Unexpected results", test_name);
- total_errors++;
- }
+ virtual void TearDown() {
+ if (dev_fd >= 0) {
+ close(dev_fd);
+ }
+ if (ctrl_fd >= 0) {
+ close(ctrl_fd);
+ }
+ }
- res = doCtrlCommand("d 0 %u", my_uid);
- if (res < 0) {
- testPrintE("! %s: Unexpected results", test_name);
- total_errors++;
- }
+ SockInfo sock0;
+ SockInfo sock1;
+ int ctrl_fd;
+ int dev_fd;
+ uid_t fake_uid;
+ uid_t fake_uid2;
+ uid_t my_uid;
+ pid_t my_pid;
+ uint64_t valid_tag1;
+ uint64_t valid_tag2;
+ uint64_t max_uint_tag;
+ static const uint64_t invalid_tag1 = 0x0000000100000001llu;
+ static const int max_tags = 5;
+};
- // ---------------
- test_name = "setup sock0 and addr via tag";
- testPrintI("* test: %s", test_name);
- if (sock0.setup(valid_tag1)) {
- testPrintE("socket setup failed: %s", strerror(errno));
- return 1;
- }
- // ---------------
- test_name = "setup sock1 and addr via tag";
- testPrintI("* test: %s", test_name);
- if (sock1.setup(valid_tag1)) {
- testPrintE("socket setup failed: %s", strerror(errno));
- return 1;
- }
- // ---------------
- test_name = "setup tag limit";
- testPrintI("* test: %s ", test_name);
+TEST_F(SocketTaggingTest, TagData) {
+ max_uint_tag = 0xffffffff00000000llu;
char *max_tags_str;
+
+ testPrintI("setup tag limit");
asprintf(&max_tags_str, "%d", max_tags);
- res = writeModuleParam("max_sock_tags", max_tags_str);
- if (res < 0) {
- testPrintE("! %s: Unexpected results", test_name);
- free(max_tags_str);
- return 1;
- }
+ ASSERT_GE(writeModuleParam("max_sock_tags", max_tags_str), 0) << "Failed to setup tag limit";
- // ---------------
- test_name = "tag quota reach limit";
- testPrintI("* test: %s", test_name);
+ testPrintI("tag quota reach limit");
for (int cnt = 0; cnt < max_tags; cnt++ ) {
- uint64_t new_tag = valid_tag2 + ((uint64_t)cnt << 32);
- res = doCtrlCommand("t %d %llu %u", sock0.fd, new_tag , fake_uid2);
- if (res < 0) {
- testPrintE("! %s: Unexpected results", test_name);
- total_errors++;
- }
- if (!sock0.checkTag(new_tag, fake_uid2)) {
- testPrintE("! %s: Unexpected results: tag not found", test_name);
- total_errors++;
- }
- }
- test_name = "tag quota go over limit";
- testPrintI("* test: %s", test_name);
- {
- uint64_t new_tag = valid_tag2 + ((uint64_t)max_tags << 32);
- res = doCtrlCommand("t %d %llu %u", sock0.fd, new_tag , fake_uid2);
- if (res > 0) {
- testPrintE("! %s: Unexpected results", test_name);
- total_errors++;
- }
- if (!sock0.checkTag(valid_tag2 + (((uint64_t)max_tags - 1) << 32), fake_uid2)) {
- testPrintE("! %s: Unexpected results: tag not found", test_name);
- total_errors++;
- }
+ uint64_t tag = valid_tag2 + ((uint64_t)cnt << 32);
+ EXPECT_GE(doCtrlCommand("t %d %llu %u", sock0.fd, tag , fake_uid2), 0)
+ << "Tagging within limit failed";
+ EXPECT_TRUE(sock0.checkTag(tag, fake_uid2))<< "Unexpected results: tag not found";
}
- // ---------------
- test_name = "valid untag";
- testPrintI("* test: %s", test_name);
- res = doCtrlCommand("u %d", sock0.fd);
- if (res < 0) {
- testPrintE("! %s: Unexpected results", test_name);
- total_errors++;
- }
- if (sock0.checkTag(valid_tag2 + (((uint64_t)max_tags - 1) << 32), fake_uid2)) {
- testPrintE("! %s: Unexpected results: tag should not be there", test_name);
- total_errors++;
- }
+ testPrintI("tag quota go over limit");
+ uint64_t new_tag = valid_tag2 + ((uint64_t)max_tags << 32);
+ EXPECT_LT(doCtrlCommand("t %d %llu %u", sock0.fd, new_tag , fake_uid2), 0);
+ EXPECT_TRUE(sock0.checkTag(valid_tag2 + (((uint64_t)max_tags - 1) << 32),
+ fake_uid2)) << "Unexpected results: tag not found";
- // ---------------
- test_name = "tag after untag shouldn't free up max tags";
- testPrintI("* test: %s", test_name);
- {
- uint64_t new_tag = valid_tag2 + ((uint64_t)max_tags << 32);
- res = doCtrlCommand("t %d %llu %u", sock0.fd, new_tag , fake_uid2);
- if (res > 0) {
- testPrintE("! %s: Unexpected results", test_name);
- total_errors++;
- }
- if (sock0.checkTag(valid_tag2 + ((uint64_t)max_tags << 32), fake_uid2)) {
- testPrintE("! %s: Unexpected results: tag should not be there", test_name);
- total_errors++;
- }
- }
+ testPrintI("valid untag");
+ EXPECT_GE(doCtrlCommand("u %d", sock0.fd), 0);
+ EXPECT_FALSE(sock0.checkTag(valid_tag2 + (((uint64_t)max_tags - 1) << 32), fake_uid2))
+ << "Untagged tag should not be there";
- // ---------------
- test_name = "delete one tag";
- testPrintI("* test: %s", test_name);
- {
- uint64_t new_tag = valid_tag2 + (((uint64_t)max_tags / 2) << 32);
- res = doCtrlCommand("d %llu %u", new_tag, fake_uid2);
- if (res < 0) {
- testPrintE("! %s: Unexpected results", test_name);
- total_errors++;
- }
- }
+ testPrintI("tag after untag should not free up max tags");
+ uint64_t new_tag2 = valid_tag2 + ((uint64_t)max_tags << 32);
+ EXPECT_LT(doCtrlCommand("t %d %llu %u", sock0.fd, new_tag2 , fake_uid2), 0);
+ EXPECT_FALSE(sock0.checkTag(valid_tag2 + ((uint64_t)max_tags << 32), fake_uid2))
+ << "Tag should not be there";
- // ---------------
- test_name = "2 tags after 1 delete pass/fail";
- testPrintI("* test: %s", test_name);
- {
- uint64_t new_tag;
- new_tag = valid_tag2 + (((uint64_t)max_tags + 1 ) << 32);
- res = doCtrlCommand("t %d %llu %u", sock0.fd, new_tag , fake_uid2);
- if (res < 0) {
- testPrintE("! %s: Unexpected results", test_name);
- total_errors++;
- }
- if (!sock0.checkTag(valid_tag2 + (((uint64_t)max_tags + 1) << 32), fake_uid2)) {
- testPrintE("! %s: Unexpected results: tag not found", test_name);
- total_errors++;
- }
+ testPrintI("delete one tag");
+ uint64_t new_tag3 = valid_tag2 + (((uint64_t)max_tags / 2) << 32);
+ EXPECT_GE(doCtrlCommand("d %llu %u", new_tag3, fake_uid2), 0);
- new_tag = valid_tag2 + (((uint64_t)max_tags + 2 ) << 32);
- res = doCtrlCommand("t %d %llu %u", sock0.fd, new_tag , fake_uid2);
- if (res > 0) {
- testPrintE("! %s: Unexpected results", test_name);
- total_errors++;
- }
- if (sock0.checkTag(valid_tag2 + (((uint64_t)max_tags + 2) << 32), fake_uid2)) {
- testPrintE("! %s: Unexpected results: tag should not be there", test_name);
- total_errors++;
- }
- }
+ testPrintI("2 tags after 1 delete pass/fail");
+ uint64_t new_tag4;
+ new_tag4 = valid_tag2 + (((uint64_t)max_tags + 1 ) << 32);
+ EXPECT_GE(doCtrlCommand("t %d %llu %u", sock0.fd, new_tag4 , fake_uid2), 0);
+ EXPECT_TRUE(sock0.checkTag(valid_tag2 + (((uint64_t)max_tags + 1) << 32), fake_uid2))
+ << "Tag not found";
+ new_tag4 = valid_tag2 + (((uint64_t)max_tags + 2 ) << 32);
+ EXPECT_LT(doCtrlCommand("t %d %llu %u", sock0.fd, new_tag4 , fake_uid2), 0);
+ EXPECT_FALSE(sock0.checkTag(valid_tag2 + (((uint64_t)max_tags + 2) << 32), fake_uid2))
+ << "Tag should not be there";
/* TODO(jpa): test tagging two different sockets with same tags and
* check refcounts the tag_node should be +2
*/
-
- // ---------------
- if (total_errors) {
- testPrintE("! Errors found");
- } else {
- testPrintI("No Errors found");
- }
-
-done:
- if (dev_fd >= 0) {
- close(dev_fd);
- }
- if (ctrl_fd >= 0) {
- close(ctrl_fd);
- }
- return total_errors;
}
-/*----------------------------------------------------------------*/
-
-int main(int argc, char *argv[]) {
- int res = 0;
- res += testTagData();
- res += testSocketTagging();
- if (res) {
- testPrintE("!! %d Errors found", res);
- } else {
- testPrintE("No Errors found");
- }
- return res;
+TEST_F(SocketTaggingTest, InsufficientArgsFails) {
+ // Insufficient args. Expected failure
+ EXPECT_LE(doCtrlCommand("t"), 0) << "Insufficient args, should fail.";
}
+
+TEST_F(SocketTaggingTest, BadCommandFails) {
+ // Bad command. Expected failure";
+ EXPECT_LE(doCtrlCommand("?"), 0) << "Bad command, should fail";
+}
+
+TEST_F(SocketTaggingTest, NoTagNoUid) {
+ // no tag, no uid
+ EXPECT_GE(doCtrlCommand("t %d", sock0.fd), 0);
+ ASSERT_TRUE(sock0.checkTag(0, my_uid)) << "Tag not found";
+}
+
+TEST_F(SocketTaggingTest, InvalidTagFail) {
+ // Invalid tag. Expected failure
+ EXPECT_LE(doCtrlCommand("t %d %llu", sock0.fd, invalid_tag1), 0);
+ ASSERT_FALSE(sock0.checkTag(invalid_tag1, my_uid)) << "Tag should not be there";
+}
+
+TEST_F(SocketTaggingTest, ValidTagWithNoUid) {
+ // Valid tag with no uid
+ EXPECT_GE(doCtrlCommand("t %d %llu", sock0.fd, valid_tag1), 0);
+ EXPECT_TRUE(sock0.checkTag(valid_tag1, my_uid)) << "Tag not found";
+}
+
+TEST_F(SocketTaggingTest, ValidUntag) {
+ // Valid untag
+ EXPECT_GE(doCtrlCommand("t %d %llu", sock0.fd, valid_tag1), 0);
+ EXPECT_TRUE(sock0.checkTag(valid_tag1, my_uid)) << "Tag not found";
+ EXPECT_GE(doCtrlCommand("u %d", sock0.fd), 0);
+ EXPECT_FALSE(sock0.checkTag(valid_tag1, my_uid)) << "Tag should be removed";
+}
+
+TEST_F(SocketTaggingTest, ValidFirsttag) {
+ // Valid 1st tag
+ EXPECT_GE(doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag2, fake_uid), 0);
+ EXPECT_TRUE(sock0.checkTag(valid_tag2, fake_uid)) << "Tag not found.";
+}
+
+TEST_F(SocketTaggingTest, ValidReTag) {
+ // Valid re-tag
+ EXPECT_GE(doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag2, fake_uid), 0);
+ EXPECT_GE(doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag2, fake_uid), 0);
+ EXPECT_TRUE(sock0.checkTag(valid_tag2, fake_uid)) << "Tag not found.";
+}
+
+TEST_F(SocketTaggingTest, ValidReTagWithAcctTagChange) {
+ // Valid re-tag with acct_tag change
+ EXPECT_GE(doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag2, fake_uid), 0);
+ EXPECT_GE(doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag1, fake_uid), 0);
+ EXPECT_TRUE(sock0.checkTag(valid_tag1, fake_uid)) << "Tag not found.";
+}
+
+TEST_F(SocketTaggingTest, ReTagWithUidChange) {
+ // Re-tag with uid change
+ EXPECT_GE(doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag1, fake_uid), 0);
+ EXPECT_GE(doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag2, fake_uid2), 0);
+}
+
+TEST_F(SocketTaggingTest, Valid64BitAcctTag) {
+ // Valid 64bit acct tag
+ EXPECT_GE(doCtrlCommand("t %d %llu", sock0.fd, max_uint_tag), 0);
+ EXPECT_TRUE(sock0.checkTag(max_uint_tag, my_uid)) << "Tag not found.";
+}
+
+TEST_F(SocketTaggingTest, TagAnotherSocket) {
+ testPrintI("Tag two sockets");
+ EXPECT_GE(doCtrlCommand("t %d %llu", sock0.fd, max_uint_tag), 0);
+ EXPECT_GE(doCtrlCommand("t %d %llu %u", sock1.fd, valid_tag1, fake_uid2), 0);
+ EXPECT_TRUE(sock1.checkTag(valid_tag1, fake_uid2)) << "Tag not found.";
+ testPrintI("Untag socket0 of them only.");
+ EXPECT_GE(doCtrlCommand("u %d", sock0.fd), 0);
+ EXPECT_FALSE(sock0.checkTag(max_uint_tag, fake_uid)) << "Tag should not be there";
+ EXPECT_TRUE(sock1.checkTag(valid_tag1, fake_uid2)) << "Tag not found";
+ testPrintI("Now untag socket1 as well.");
+ EXPECT_GE(doCtrlCommand("u %d", sock1.fd), 0);
+ EXPECT_FALSE(sock1.checkTag(valid_tag1, fake_uid2)) << "Tag should not be there";
+}
+
+TEST_F(SocketTaggingTest, TagInvalidSocketFail) {
+ // Invalid tag. Expected failure
+ close(sock0.fd);
+ EXPECT_LE(doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag1, my_uid), 0);
+ EXPECT_FALSE(sock0.checkTag(valid_tag1, my_uid)) << "Tag should not be there";
+}
+
+TEST_F(SocketTaggingTest, UntagInvalidSocketFail) {
+ // Invalid untag. Expected failure";
+ close(sock1.fd);
+ EXPECT_LE(doCtrlCommand("u %d", sock1.fd), 0);
+}
+
+} // namespace android
diff --git a/tests/lib/testUtil/testUtil.c b/tests/lib/testUtil/testUtil.c
index d63fbba..b4edbd6 100644
--- a/tests/lib/testUtil/testUtil.c
+++ b/tests/lib/testUtil/testUtil.c
@@ -150,9 +150,9 @@
va_start(args, fmt);
vsnprintf(line, sizeof(line), fmt, args);
if (stream == stderr) {
- LOG(LOG_ERROR, logCatTag, "%s", line);
+ ALOG(LOG_ERROR, logCatTag, "%s", line);
} else {
- LOG(LOG_INFO, logCatTag, "%s", line);
+ ALOG(LOG_INFO, logCatTag, "%s", line);
}
vfprintf(stream, fmt, args);
fputc('\n', stream);
diff --git a/tests/wifi/stress/wifiLoadScanAssoc.c b/tests/wifi/stress/wifiLoadScanAssoc.c
index 62b179c..17536e4 100644
--- a/tests/wifi/stress/wifiLoadScanAssoc.c
+++ b/tests/wifi/stress/wifiLoadScanAssoc.c
@@ -285,7 +285,7 @@
// Start Supplicant
randBind(&availCPU, &cpu);
- if ((rv = wifi_start_supplicant()) != 0) {
+ if ((rv = wifi_start_supplicant(false)) != 0) {
testPrintE("CPU: %i wifi_start_supplicant() failed, rv: %i\n",
cpu, rv);
exit(21);
@@ -341,7 +341,7 @@
}
// Start supplicant
- if ((rv = wifi_start_supplicant()) != 0) {
+ if ((rv = wifi_start_supplicant(false)) != 0) {
testPrintE("main start supplicant failed, rv: %i", rv);
exit(26);
}