static void TestMapping (const char* str) { #ifdef TEST_UNICODE_MAPPINGS csPrintf (" Upper: %s\n Lower: %s\n Fold: %s\n", MapString (str, &csUnicodeTransform::MapToUpper).GetData(), MapString (str, &csUnicodeTransform::MapToLower).GetData(), MapString (str, &csUnicodeTransform::MapToFold).GetData()); #else (void) str; // unused except for the above block so silence the warning #endif // TEST_UNICODE_MAPPINGS }
// Look up tagname, generate one if necessary, and return a tag LIBLOG_ABI_PUBLIC int android_lookupEventTagNum(EventTagMap* map, const char* tagname, const char* format, int prio) { const char* ep = endOfTag(tagname); size_t len = ep - tagname; if (!len || *ep) { errno = EINVAL; return -1; } if ((prio != ANDROID_LOG_UNKNOWN) && (prio < ANDROID_LOG_SILENT) && !__android_log_is_loggable_len(prio, tagname, len, __android_log_is_debuggable() ? ANDROID_LOG_VERBOSE : ANDROID_LOG_DEBUG)) { errno = EPERM; return -1; } if (!format) format = ""; ssize_t fmtLen = strlen(format); int ret = map->find(TagFmt( std::make_pair(MapString(tagname, len), MapString(format, fmtLen)))); if (ret != -1) return ret; // call event tag service to arrange for a new tag char* buf = NULL; // Can not use android::base::StringPrintf, asprintf + free instead. static const char command_template[] = "getEventTag name=%s format=\"%s\""; ret = asprintf(&buf, command_template, tagname, format); if (ret > 0) { // Add some buffer margin for an estimate of the full return content. char* cp; size_t size = ret - strlen(command_template) + strlen("65535\n4294967295\t?\t\t\t?\t# uid=32767\n\n\f?success?"); if (size > (size_t)ret) { cp = static_cast<char*>(realloc(buf, size)); if (cp) { buf = cp; } else { size = ret; } } else { size = ret; } // Ask event log tag service for an allocation if (__send_log_msg(buf, size) >= 0) { buf[size - 1] = '\0'; unsigned long val = strtoul(buf, &cp, 10); // return size if ((buf != cp) && (val > 0) && (*cp == '\n')) { // truncation OK val = strtoul(cp + 1, &cp, 10); // allocated tag number if ((val > 0) && (val < UINT32_MAX) && (*cp == '\t')) { free(buf); ret = val; // cache map->emplaceUnique(ret, TagFmt(std::make_pair( MapString(std::string(tagname, len)), MapString(std::string(format, fmtLen))))); return ret; } } } free(buf); } // Hail Mary ret = map->find(MapString(tagname, len)); if (ret == -1) errno = ESRCH; return ret; }
// Scan one tag line. // // "pData" should be pointing to the first digit in the tag number. On // successful return, it will be pointing to the last character in the // tag line (i.e. the character before the start of the next line). // // lineNum = 0 removes verbose comments and requires us to cache the // content rather than make direct raw references since the content // will disappear after the call. A non-zero lineNum means we own the // data and it will outlive the call. // // Returns 0 on success, nonzero on failure. static int scanTagLine(EventTagMap* map, const char*& pData, int lineNum) { char* ep; unsigned long val = strtoul(pData, &ep, 10); const char* cp = ep; if (cp == pData) { if (lineNum) { fprintf(stderr, OUT_TAG ": malformed tag number on line %d\n", lineNum); } errno = EINVAL; return -1; } uint32_t tagIndex = val; if (tagIndex != val) { if (lineNum) { fprintf(stderr, OUT_TAG ": tag number too large on line %d\n", lineNum); } errno = ERANGE; return -1; } while ((*++cp != '\n') && isspace(*cp)) { } if (*cp == '\n') { if (lineNum) { fprintf(stderr, OUT_TAG ": missing tag string on line %d\n", lineNum); } errno = EINVAL; return -1; } const char* tag = cp; cp = endOfTag(cp); size_t tagLen = cp - tag; if (!isspace(*cp)) { if (lineNum) { fprintf(stderr, OUT_TAG ": invalid tag char %c on line %d\n", *cp, lineNum); } errno = EINVAL; return -1; } while (isspace(*cp) && (*cp != '\n')) ++cp; const char* fmt = NULL; size_t fmtLen = 0; if (*cp && (*cp != '#')) { fmt = cp; while (*cp && (*cp != '\n') && (*cp != '#')) ++cp; while ((cp > fmt) && isspace(*(cp - 1))) --cp; fmtLen = cp - fmt; } // KISS Only report identicals if they are global // Ideally we want to check if there are identicals // recorded for the same uid, but recording that // unused detail in our database is too burdensome. bool verbose = true; while (*cp && (*cp != '#') && (*cp != '\n')) ++cp; if (*cp == '#') { do { ++cp; } while (isspace(*cp) && (*cp != '\n')); verbose = !!fastcmp<strncmp>(cp, "uid=", strlen("uid=")); } while (*cp && (*cp != '\n')) ++cp; #ifdef DEBUG fprintf(stderr, "%d: %p: %.*s\n", lineNum, tag, (int)(cp - pData), pData); #endif pData = cp; if (lineNum) { if (map->emplaceUnique(tagIndex, TagFmt(std::make_pair(MapString(tag, tagLen), MapString(fmt, fmtLen))), verbose)) { return 0; } } else { // cache if (map->emplaceUnique( tagIndex, TagFmt(std::make_pair(MapString(std::string(tag, tagLen)), MapString(std::string(fmt, fmtLen)))))) { return 0; } } errno = EMLINK; return -1; }