Merge "Remove execonce."
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 0a960ff..4b9eeeb 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -772,7 +772,7 @@
}
static int qual_match(const char *to_test,
- const char *prefix, const char *qual, int sanitize_qual)
+ const char *prefix, const char *qual, bool sanitize_qual)
{
if (!to_test || !*to_test)
/* Return true if both the qual and to_test are null strings. */
@@ -790,7 +790,7 @@
while (*qual) {
char ch = *qual++;
- if (sanitize_qual && isalnum(ch))
+ if (sanitize_qual && !isalnum(ch))
ch = '_';
if (ch != *to_test++)
return 0;
@@ -823,9 +823,9 @@
if (serial) {
if ((t->serial && !strcmp(serial, t->serial)) ||
(t->devpath && !strcmp(serial, t->devpath)) ||
- qual_match(serial, "product:", t->product, 0) ||
- qual_match(serial, "model:", t->model, 1) ||
- qual_match(serial, "device:", t->device, 0)) {
+ qual_match(serial, "product:", t->product, false) ||
+ qual_match(serial, "model:", t->model, true) ||
+ qual_match(serial, "device:", t->device, false)) {
if (result) {
if (error_out)
*error_out = "more than one device";
@@ -918,20 +918,17 @@
}
static void add_qual(char **buf, size_t *buf_size,
- const char *prefix, const char *qual, int sanitize_qual)
+ const char *prefix, const char *qual, bool sanitize_qual)
{
- size_t len;
- int prefix_len;
-
if (!buf || !*buf || !buf_size || !*buf_size || !qual || !*qual)
return;
- len = snprintf(*buf, *buf_size, "%s%n%s", prefix, &prefix_len, qual);
+ int prefix_len;
+ size_t len = snprintf(*buf, *buf_size, "%s%n%s", prefix, &prefix_len, qual);
if (sanitize_qual) {
- char *cp;
- for (cp = *buf + prefix_len; cp < *buf + len; cp++) {
- if (isalnum(*cp))
+ for (char* cp = *buf + prefix_len; cp < *buf + len; cp++) {
+ if (!isalnum(*cp))
*cp = '_';
}
}
@@ -956,10 +953,10 @@
remaining -= len;
buf += len;
- add_qual(&buf, &remaining, " ", t->devpath, 0);
- add_qual(&buf, &remaining, " product:", t->product, 0);
- add_qual(&buf, &remaining, " model:", t->model, 1);
- add_qual(&buf, &remaining, " device:", t->device, 0);
+ add_qual(&buf, &remaining, " ", t->devpath, false);
+ add_qual(&buf, &remaining, " product:", t->product, false);
+ add_qual(&buf, &remaining, " model:", t->model, true);
+ add_qual(&buf, &remaining, " device:", t->device, false);
len = snprintf(buf, remaining, "\n");
remaining -= len;
diff --git a/base/CPPLINT.cfg b/base/CPPLINT.cfg
index a61c08d..d94a89c 100644
--- a/base/CPPLINT.cfg
+++ b/base/CPPLINT.cfg
@@ -1,2 +1,2 @@
set noparent
-filter=-build/header_guard,-build/include,-build/c++11
+filter=-build/header_guard,-build/include,-build/c++11,-whitespace/operators
diff --git a/base/include/base/logging.h b/base/include/base/logging.h
index 5e115fe..19c1b64 100644
--- a/base/include/base/logging.h
+++ b/base/include/base/logging.h
@@ -17,6 +17,7 @@
#ifndef BASE_LOGGING_H
#define BASE_LOGGING_H
+#include <functional>
#include <memory>
#include <ostream>
@@ -34,6 +35,33 @@
FATAL,
};
+enum LogId {
+ DEFAULT,
+ MAIN,
+ SYSTEM,
+};
+
+typedef std::function<void(LogId, LogSeverity, const char*, const char*,
+ unsigned int, const char*)> LogFunction;
+
+extern void StderrLogger(LogId, LogSeverity, const char*, const char*,
+ unsigned int, const char*);
+
+#ifdef __ANDROID__
+// We expose this even though it is the default because a user that wants to
+// override the default log buffer will have to construct this themselves.
+class LogdLogger {
+ public:
+ explicit LogdLogger(LogId default_log_id = android::base::MAIN);
+
+ void operator()(LogId, LogSeverity, const char* tag, const char* file,
+ unsigned int line, const char* message);
+
+ private:
+ LogId default_log_id_;
+};
+#endif
+
// Configure logging based on ANDROID_LOG_TAGS environment variable.
// We need to parse a string that looks like
//
@@ -42,8 +70,15 @@
// The tag (or '*' for the global level) comes first, followed by a colon and a
// letter indicating the minimum priority level we're expected to log. This can
// be used to reveal or conceal logs with specific tags.
+extern void InitLogging(char* argv[], LogFunction&& logger);
+
+// Configures logging using the default logger (logd for the device, stderr for
+// the host).
extern void InitLogging(char* argv[]);
+// Replace the current logger.
+extern void SetLogger(LogFunction&& logger);
+
// Returns the command line used to invoke the current tool or nullptr if
// InitLogging hasn't been performed.
extern const char* GetCmdLine();
@@ -60,15 +95,26 @@
// FATAL it also causes an abort. For example:
//
// LOG(FATAL) << "We didn't expect to reach here";
-#define LOG(severity) \
- ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::severity, \
- -1).stream()
+#define LOG(severity) \
+ ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::DEFAULT, \
+ ::android::base::severity, -1).stream()
+
+// Logs a message to logcat with the specified log ID on Android otherwise to
+// stderr. If the severity is FATAL it also causes an abort.
+#define LOG_TO(dest, severity) \
+ ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::dest, \
+ ::android::base::severity, -1).stream()
// A variant of LOG that also logs the current errno value. To be used when
// library calls fail.
-#define PLOG(severity) \
- ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::severity, \
- errno).stream()
+#define PLOG(severity) \
+ ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::DEFAULT, \
+ ::android::base::severity, errno).stream()
+
+// Behaves like PLOG, but logs to the specified log ID.
+#define PLOG_TO(dest, severity) \
+ ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::dest, \
+ ::android::base::severity, errno).stream()
// Marker that code is yet to be implemented.
#define UNIMPLEMENTED(level) \
@@ -82,18 +128,18 @@
// "Check failed: false == true".
#define CHECK(x) \
if (UNLIKELY(!(x))) \
- ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::FATAL, \
- -1).stream() \
- << "Check failed: " #x << " "
+ ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::DEFAULT, \
+ ::android::base::FATAL, -1).stream() \
+ << "Check failed: " #x << " "
// Helper for CHECK_xx(x,y) macros.
-#define CHECK_OP(LHS, RHS, OP) \
- for (auto _values = ::android::base::MakeEagerEvaluator(LHS, RHS); \
- UNLIKELY(!(_values.lhs OP _values.rhs)); \
- /* empty */) \
- ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::FATAL, -1) \
- .stream() \
- << "Check failed: " << #LHS << " " << #OP << " " << #RHS \
+#define CHECK_OP(LHS, RHS, OP) \
+ for (auto _values = ::android::base::MakeEagerEvaluator(LHS, RHS); \
+ UNLIKELY(!(_values.lhs OP _values.rhs)); \
+ /* empty */) \
+ ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::DEFAULT, \
+ ::android::base::FATAL, -1).stream() \
+ << "Check failed: " << #LHS << " " << #OP << " " << #RHS \
<< " (" #LHS "=" << _values.lhs << ", " #RHS "=" << _values.rhs << ") "
// Check whether a condition holds between x and y, LOG(FATAL) if not. The value
@@ -228,8 +274,8 @@
// of a CHECK. The destructor will abort if the severity is FATAL.
class LogMessage {
public:
- LogMessage(const char* file, unsigned int line, LogSeverity severity,
- int error);
+ LogMessage(const char* file, unsigned int line, LogId id,
+ LogSeverity severity, int error);
~LogMessage();
@@ -238,12 +284,8 @@
std::ostream& stream();
// The routine that performs the actual logging.
- static void LogLine(const char* file, unsigned int line, LogSeverity severity,
- const char* msg);
-
- // A variant of the above for use with little stack.
- static void LogLineLowStack(const char* file, unsigned int line,
- LogSeverity severity, const char* msg);
+ static void LogLine(const char* file, unsigned int line, LogId id,
+ LogSeverity severity, const char* msg);
private:
const std::unique_ptr<LogMessageData> data_;
diff --git a/base/logging.cpp b/base/logging.cpp
index 38ee2af..a36ac5f 100644
--- a/base/logging.cpp
+++ b/base/logging.cpp
@@ -21,6 +21,7 @@
#include <mutex>
#include <sstream>
#include <string>
+#include <utility>
#include <vector>
#include "base/strings.h"
@@ -40,6 +41,12 @@
static std::mutex logging_lock;
+#ifdef __ANDROID__
+static LogFunction gLogger = LogdLogger();
+#else
+static LogFunction gLogger = StderrLogger;
+#endif
+
static LogSeverity gMinimumLogSeverity = INFO;
static std::unique_ptr<std::string> gCmdLine;
static std::unique_ptr<std::string> gProgramInvocationName;
@@ -61,6 +68,58 @@
: "unknown";
}
+void StderrLogger(LogId, LogSeverity severity, const char*, const char* file,
+ unsigned int line, const char* message) {
+ static const char* log_characters = "VDIWEF";
+ CHECK_EQ(strlen(log_characters), FATAL + 1U);
+ char severity_char = log_characters[severity];
+ fprintf(stderr, "%s %c %5d %5d %s:%u] %s\n", ProgramInvocationShortName(),
+ severity_char, getpid(), gettid(), file, line, message);
+}
+
+
+#ifdef __ANDROID__
+LogdLogger::LogdLogger(LogId default_log_id) : default_log_id_(default_log_id) {
+}
+
+static const android_LogPriority kLogSeverityToAndroidLogPriority[] = {
+ ANDROID_LOG_VERBOSE, ANDROID_LOG_DEBUG, ANDROID_LOG_INFO,
+ ANDROID_LOG_WARN, ANDROID_LOG_ERROR, ANDROID_LOG_FATAL,
+};
+static_assert(arraysize(kLogSeverityToAndroidLogPriority) == FATAL + 1,
+ "Mismatch in size of kLogSeverityToAndroidLogPriority and values "
+ "in LogSeverity");
+
+static const log_id kLogIdToAndroidLogId[] = {
+ LOG_ID_MAX, LOG_ID_MAIN, LOG_ID_SYSTEM,
+};
+static_assert(arraysize(kLogIdToAndroidLogId) == SYSTEM + 1,
+ "Mismatch in size of kLogIdToAndroidLogId and values in LogId");
+
+void LogdLogger::operator()(LogId id, LogSeverity severity, const char* tag,
+ const char* file, unsigned int line,
+ const char* message) {
+ int priority = kLogSeverityToAndroidLogPriority[severity];
+ if (id == DEFAULT) {
+ id = default_log_id_;
+ }
+
+ log_id lg_id = kLogIdToAndroidLogId[id];
+
+ if (priority == ANDROID_LOG_FATAL) {
+ __android_log_buf_print(lg_id, priority, tag, "%s:%u] %s", file, line,
+ message);
+ } else {
+ __android_log_buf_print(lg_id, priority, tag, "%s", message);
+ }
+}
+#endif
+
+void InitLogging(char* argv[], LogFunction&& logger) {
+ SetLogger(std::forward<LogFunction>(logger));
+ InitLogging(argv);
+}
+
void InitLogging(char* argv[]) {
if (gCmdLine.get() != nullptr) {
return;
@@ -124,13 +183,22 @@
}
}
+void SetLogger(LogFunction&& logger) {
+ std::lock_guard<std::mutex> lock(logging_lock);
+ gLogger = std::move(logger);
+}
+
// This indirection greatly reduces the stack impact of having lots of
// checks/logging in a function.
class LogMessageData {
public:
- LogMessageData(const char* file, unsigned int line, LogSeverity severity,
- int error)
- : file_(file), line_number_(line), severity_(severity), error_(error) {
+ LogMessageData(const char* file, unsigned int line, LogId id,
+ LogSeverity severity, int error)
+ : file_(file),
+ line_number_(line),
+ id_(id),
+ severity_(severity),
+ error_(error) {
const char* last_slash = strrchr(file, '/');
file = (last_slash == nullptr) ? file : last_slash + 1;
}
@@ -147,6 +215,10 @@
return severity_;
}
+ LogId GetId() const {
+ return id_;
+ }
+
int GetError() const {
return error_;
}
@@ -163,15 +235,16 @@
std::ostringstream buffer_;
const char* const file_;
const unsigned int line_number_;
+ const LogId id_;
const LogSeverity severity_;
const int error_;
DISALLOW_COPY_AND_ASSIGN(LogMessageData);
};
-LogMessage::LogMessage(const char* file, unsigned int line,
+LogMessage::LogMessage(const char* file, unsigned int line, LogId id,
LogSeverity severity, int error)
- : data_(new LogMessageData(file, line, severity, error)) {
+ : data_(new LogMessageData(file, line, id, severity, error)) {
}
LogMessage::~LogMessage() {
@@ -185,22 +258,18 @@
}
std::string msg(data_->ToString());
- // Do the actual logging with the lock held.
- {
- std::lock_guard<std::mutex> lock(logging_lock);
- if (msg.find('\n') == std::string::npos) {
- LogLine(data_->GetFile(), data_->GetLineNumber(), data_->GetSeverity(),
- msg.c_str());
- } else {
- msg += '\n';
- size_t i = 0;
- while (i < msg.size()) {
- size_t nl = msg.find('\n', i);
- msg[nl] = '\0';
- LogLine(data_->GetFile(), data_->GetLineNumber(), data_->GetSeverity(),
- &msg[i]);
- i = nl + 1;
- }
+ if (msg.find('\n') == std::string::npos) {
+ LogLine(data_->GetFile(), data_->GetLineNumber(), data_->GetId(),
+ data_->GetSeverity(), msg.c_str());
+ } else {
+ msg += '\n';
+ size_t i = 0;
+ while (i < msg.size()) {
+ size_t nl = msg.find('\n', i);
+ msg[nl] = '\0';
+ LogLine(data_->GetFile(), data_->GetLineNumber(), data_->GetId(),
+ data_->GetSeverity(), &msg[i]);
+ i = nl + 1;
}
}
@@ -217,76 +286,11 @@
return data_->GetBuffer();
}
-#ifdef __ANDROID__
-static const android_LogPriority kLogSeverityToAndroidLogPriority[] = {
- ANDROID_LOG_VERBOSE, ANDROID_LOG_DEBUG, ANDROID_LOG_INFO,
- ANDROID_LOG_WARN, ANDROID_LOG_ERROR, ANDROID_LOG_FATAL};
-static_assert(arraysize(kLogSeverityToAndroidLogPriority) == FATAL + 1,
- "Mismatch in size of kLogSeverityToAndroidLogPriority and values "
- "in LogSeverity");
-#endif
-
-void LogMessage::LogLine(const char* file, unsigned int line,
- LogSeverity log_severity, const char* message) {
-#ifdef __ANDROID__
+void LogMessage::LogLine(const char* file, unsigned int line, LogId id,
+ LogSeverity severity, const char* message) {
const char* tag = ProgramInvocationShortName();
- int priority = kLogSeverityToAndroidLogPriority[log_severity];
- if (priority == ANDROID_LOG_FATAL) {
- LOG_PRI(priority, tag, "%s:%u] %s", file, line, message);
- } else {
- LOG_PRI(priority, tag, "%s", message);
- }
-#else
- static const char* log_characters = "VDIWEF";
- CHECK_EQ(strlen(log_characters), FATAL + 1U);
- char severity = log_characters[log_severity];
- fprintf(stderr, "%s %c %5d %5d %s:%u] %s\n", ProgramInvocationShortName(),
- severity, getpid(), gettid(), file, line, message);
-#endif
-}
-
-void LogMessage::LogLineLowStack(const char* file, unsigned int line,
- LogSeverity log_severity, const char* message) {
-#ifdef __ANDROID__
- // Use android_writeLog() to avoid stack-based buffers used by
- // android_printLog().
- const char* tag = ProgramInvocationShortName();
- int priority = kLogSeverityToAndroidLogPriority[log_severity];
- char* buf = nullptr;
- size_t buf_size = 0u;
- if (priority == ANDROID_LOG_FATAL) {
- // Allocate buffer for snprintf(buf, buf_size, "%s:%u] %s", file, line,
- // message) below. If allocation fails, fall back to printing only the
- // message.
- buf_size = strlen(file) + 1 /* ':' */ +
- std::numeric_limits<typeof(line)>::max_digits10 + 2 /* "] " */ +
- strlen(message) + 1 /* terminating 0 */;
- buf = reinterpret_cast<char*>(malloc(buf_size));
- }
- if (buf != nullptr) {
- snprintf(buf, buf_size, "%s:%u] %s", file, line, message);
- android_writeLog(priority, tag, buf);
- free(buf);
- } else {
- android_writeLog(priority, tag, message);
- }
-#else
- static const char* log_characters = "VDIWEF";
- CHECK_EQ(strlen(log_characters), FATAL + 1U);
-
- const char* program_name = ProgramInvocationShortName();
- write(STDERR_FILENO, program_name, strlen(program_name));
- write(STDERR_FILENO, " ", 1);
- write(STDERR_FILENO, &log_characters[log_severity], 1);
- write(STDERR_FILENO, " ", 1);
- // TODO: pid and tid.
- write(STDERR_FILENO, file, strlen(file));
- // TODO: line.
- UNUSED(line);
- write(STDERR_FILENO, "] ", 2);
- write(STDERR_FILENO, message, strlen(message));
- write(STDERR_FILENO, "\n", 1);
-#endif
+ std::lock_guard<std::mutex> lock(logging_lock);
+ gLogger(id, severity, tag, file, line, message);
}
ScopedLogSeverity::ScopedLogSeverity(LogSeverity level) {
diff --git a/base/logging_test.cpp b/base/logging_test.cpp
index 0a03e38..d947c1d 100644
--- a/base/logging_test.cpp
+++ b/base/logging_test.cpp
@@ -61,7 +61,7 @@
int old_stderr_;
};
-HOST_TEST(logging, CHECK) {
+TEST(logging, CHECK) {
ASSERT_DEATH(CHECK(false), "Check failed: false ");
CHECK(true);
@@ -82,7 +82,7 @@
log_char, message);
}
-HOST_TEST(logging, LOG) {
+TEST(logging, LOG) {
ASSERT_DEATH(LOG(FATAL) << "foobar", "foobar");
{
@@ -136,7 +136,7 @@
}
}
-HOST_TEST(logging, PLOG) {
+TEST(logging, PLOG) {
{
CapturedStderr cap;
errno = ENOENT;
@@ -152,7 +152,7 @@
}
}
-HOST_TEST(logging, UNIMPLEMENTED) {
+TEST(logging, UNIMPLEMENTED) {
{
CapturedStderr cap;
errno = ENOENT;
diff --git a/base/test_main.cpp b/base/test_main.cpp
index c49ca4b..546923d 100644
--- a/base/test_main.cpp
+++ b/base/test_main.cpp
@@ -20,6 +20,6 @@
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
- android::base::InitLogging(argv);
+ android::base::InitLogging(argv, android::base::StderrLogger);
return RUN_ALL_TESTS();
}
diff --git a/include/utils/Compat.h b/include/utils/Compat.h
index ca4a8e0..7d96310 100644
--- a/include/utils/Compat.h
+++ b/include/utils/Compat.h
@@ -41,12 +41,12 @@
#define DEFFILEMODE 0666
#endif /* _WIN32 */
-#if HAVE_PRINTF_ZD
-# define ZD "%zd"
-# define ZD_TYPE ssize_t
+#if defined(_WIN32)
+#define ZD "%ld"
+#define ZD_TYPE long
#else
-# define ZD "%ld"
-# define ZD_TYPE long
+#define ZD "%zd"
+#define ZD_TYPE ssize_t
#endif
/*
diff --git a/liblog/logd_write.c b/liblog/logd_write.c
index dfe34d1..c62a246 100644
--- a/liblog/logd_write.c
+++ b/liblog/logd_write.c
@@ -356,43 +356,7 @@
int __android_log_write(int prio, const char *tag, const char *msg)
{
- struct iovec vec[3];
- log_id_t log_id = LOG_ID_MAIN;
- char tmp_tag[32];
-
- if (!tag)
- tag = "";
-
- /* XXX: This needs to go! */
- if (!strcmp(tag, "HTC_RIL") ||
- !strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */
- !strncmp(tag, "IMS", 3) || /* Any log tag with "IMS" as the prefix */
- !strcmp(tag, "AT") ||
- !strcmp(tag, "GSM") ||
- !strcmp(tag, "STK") ||
- !strcmp(tag, "CDMA") ||
- !strcmp(tag, "PHONE") ||
- !strcmp(tag, "SMS")) {
- log_id = LOG_ID_RADIO;
- /* Inform third party apps/ril/radio.. to use Rlog or RLOG */
- snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag);
- tag = tmp_tag;
- }
-
-#if __BIONIC__
- if (prio == ANDROID_LOG_FATAL) {
- android_set_abort_message(msg);
- }
-#endif
-
- vec[0].iov_base = (unsigned char *) &prio;
- vec[0].iov_len = 1;
- vec[1].iov_base = (void *) tag;
- vec[1].iov_len = strlen(tag) + 1;
- vec[2].iov_base = (void *) msg;
- vec[2].iov_len = strlen(msg) + 1;
-
- return write_to_log(log_id, vec, 3);
+ return __android_log_buf_write(LOG_ID_MAIN, prio, tag, msg);
}
int __android_log_buf_write(int bufID, int prio, const char *tag, const char *msg)
@@ -420,6 +384,12 @@
tag = tmp_tag;
}
+#if __BIONIC__
+ if (prio == ANDROID_LOG_FATAL) {
+ android_set_abort_message(msg);
+ }
+#endif
+
vec[0].iov_base = (unsigned char *) &prio;
vec[0].iov_len = 1;
vec[1].iov_base = (void *) tag;
diff --git a/liblog/logd_write_kern.c b/liblog/logd_write_kern.c
index ca63067..8742b34 100644
--- a/liblog/logd_write_kern.c
+++ b/liblog/logd_write_kern.c
@@ -139,41 +139,7 @@
int __android_log_write(int prio, const char *tag, const char *msg)
{
- struct iovec vec[3];
- log_id_t log_id = LOG_ID_MAIN;
- char tmp_tag[32];
-
- if (!tag)
- tag = "";
-
- /* XXX: This needs to go! */
- if (!strcmp(tag, "HTC_RIL") ||
- !strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */
- !strncmp(tag, "IMS", 3) || /* Any log tag with "IMS" as the prefix */
- !strcmp(tag, "AT") ||
- !strcmp(tag, "GSM") ||
- !strcmp(tag, "STK") ||
- !strcmp(tag, "CDMA") ||
- !strcmp(tag, "PHONE") ||
- !strcmp(tag, "SMS")) {
- log_id = LOG_ID_RADIO;
- /* Inform third party apps/ril/radio.. to use Rlog or RLOG */
- snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag);
- tag = tmp_tag;
- }
-
- if (prio == ANDROID_LOG_FATAL) {
- android_set_abort_message(msg);
- }
-
- vec[0].iov_base = (unsigned char *) &prio;
- vec[0].iov_len = 1;
- vec[1].iov_base = (void *) tag;
- vec[1].iov_len = strlen(tag) + 1;
- vec[2].iov_base = (void *) msg;
- vec[2].iov_len = strlen(msg) + 1;
-
- return write_to_log(log_id, vec, 3);
+ return __android_log_buf_write(LOG_ID_MAIN, prio, tag, msg);
}
int __android_log_buf_write(int bufID, int prio, const char *tag, const char *msg)
@@ -201,6 +167,10 @@
tag = tmp_tag;
}
+ if (prio == ANDROID_LOG_FATAL) {
+ android_set_abort_message(msg);
+ }
+
vec[0].iov_base = (unsigned char *) &prio;
vec[0].iov_len = 1;
vec[1].iov_base = (void *) tag;
diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c
index 39ce0eb..041c37a 100644
--- a/sdcard/sdcard.c
+++ b/sdcard/sdcard.c
@@ -199,6 +199,8 @@
* position. Used to support things like OBB. */
char* graft_path;
size_t graft_pathlen;
+
+ bool deleted;
};
static int str_hash(void *key) {
@@ -631,6 +633,8 @@
node->ino = fuse->inode_ctr++;
node->gen = fuse->next_generation++;
+ node->deleted = false;
+
derive_permissions_locked(fuse, parent, node);
acquire_node_locked(node);
add_node_to_parent_locked(node, parent);
@@ -704,7 +708,7 @@
* must be considered distinct even if they refer to the same
* underlying file as otherwise operations such as "mv x x"
* will not work because the source and target nodes are the same. */
- if (!strcmp(name, node->name)) {
+ if (!strcmp(name, node->name) && !node->deleted) {
return node;
}
}
@@ -1070,6 +1074,7 @@
{
bool has_rw;
struct node* parent_node;
+ struct node* child_node;
char parent_path[PATH_MAX];
char child_path[PATH_MAX];
@@ -1091,6 +1096,12 @@
if (unlink(child_path) < 0) {
return -errno;
}
+ pthread_mutex_lock(&fuse->lock);
+ child_node = lookup_child_by_name_locked(parent_node, name);
+ if (child_node) {
+ child_node->deleted = true;
+ }
+ pthread_mutex_unlock(&fuse->lock);
return 0;
}
@@ -1098,6 +1109,7 @@
const struct fuse_in_header* hdr, const char* name)
{
bool has_rw;
+ struct node* child_node;
struct node* parent_node;
char parent_path[PATH_MAX];
char child_path[PATH_MAX];
@@ -1120,6 +1132,12 @@
if (rmdir(child_path) < 0) {
return -errno;
}
+ pthread_mutex_lock(&fuse->lock);
+ child_node = lookup_child_by_name_locked(parent_node, name);
+ if (child_node) {
+ child_node->deleted = true;
+ }
+ pthread_mutex_unlock(&fuse->lock);
return 0;
}