Loading liblog/event_tag_map.cpp +111 −51 Original line number Diff line number Diff line Loading @@ -53,21 +53,27 @@ template <> struct std::hash<TagFmt> // Map struct EventTagMap { # define NUM_MAPS 2 // memory-mapped source file; we get strings from here void* mapAddr; size_t mapLen; void* mapAddr[NUM_MAPS]; size_t mapLen[NUM_MAPS]; private: std::unordered_map<uint32_t, TagFmt> Idx2TagFmt; public: EventTagMap() : mapAddr(NULL), mapLen(0) { } EventTagMap() { memset(mapAddr, 0, sizeof(mapAddr)); memset(mapLen, 0, sizeof(mapLen)); } ~EventTagMap() { Idx2TagFmt.clear(); if (mapAddr) { munmap(mapAddr, mapLen); mapAddr = 0; for (size_t which = 0; which < NUM_MAPS; ++which) { if (mapAddr[which]) { munmap(mapAddr[which], mapLen[which]); mapAddr[which] = 0; } } } Loading Loading @@ -157,6 +163,19 @@ static int scanTagLine(EventTagMap* map, char** pData, int lineNum) { 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 != '\n')) ++cp; if (*cp == '#') { do { ++cp; } while (isspace(*cp) && (*cp != '\n')); verbose = !!fastcmp<strncmp>(cp, "uid=", strlen("uid=")); } while (*cp != '\n') ++cp; #ifdef DEBUG fprintf(stderr, "%d: %p: %.*s\n", lineNum, tag, (int)(cp - *pData), *pData); Loading @@ -164,24 +183,33 @@ static int scanTagLine(EventTagMap* map, char** pData, int lineNum) { *pData = cp; if (map->emplaceUnique(tagIndex, TagFmt(std::make_pair( MapString(tag, tagLen), MapString(fmt, fmtLen))), true)) { MapString(tag, tagLen), MapString(fmt, fmtLen))), verbose)) { return 0; } errno = EMLINK; return -1; } static const char* eventTagFiles[NUM_MAPS] = { EVENT_TAG_MAP_FILE, "/dev/event-log-tags", }; // Parse the tags out of the file. static int parseMapLines(EventTagMap* map) { char* cp = static_cast<char*>(map->mapAddr); size_t len = map->mapLen; static int parseMapLines(EventTagMap* map, size_t which) { char* cp = static_cast<char*>(map->mapAddr[which]); size_t len = map->mapLen[which]; char* endp = cp + len; // insist on EOL at EOF; simplifies parsing and null-termination if (!len || (*(endp - 1) != '\n')) { #ifdef DEBUG fprintf(stderr, OUT_TAG ": map file missing EOL on last line\n"); fprintf(stderr, OUT_TAG ": map file %zu[%zu] missing EOL on last line\n", which, len); #endif if (which) { // do not propagate errors for other files return 0; } errno = EINVAL; return -1; } Loading @@ -199,8 +227,10 @@ static int parseMapLines(EventTagMap* map) { } else if (isdigit(*cp)) { // looks like a tag; scan it out if (scanTagLine(map, &cp, lineNum) != 0) { if (!which || (errno != EMLINK)) { return -1; } } lineNum++; // we eat the '\n' // leave lineStart==true } else if (isspace(*cp)) { Loading @@ -226,57 +256,87 @@ static int parseMapLines(EventTagMap* map) { // We create a private mapping because we want to terminate the log tag // strings with '\0'. LIBLOG_ABI_PUBLIC EventTagMap* android_openEventTagMap(const char* fileName) { int save_errno; EventTagMap* newTagMap; off_t end[NUM_MAPS]; int save_errno, fd[NUM_MAPS]; size_t which; memset(fd, -1, sizeof(fd)); memset(end, 0, sizeof(end)); for (which = 0; which < NUM_MAPS; ++which) { const char* tagfile = fileName ? fileName : eventTagFiles[which]; const char* tagfile = fileName ? fileName : EVENT_TAG_MAP_FILE; int fd = open(tagfile, O_RDONLY | O_CLOEXEC); if (fd < 0) { fd[which] = open(tagfile, O_RDONLY | O_CLOEXEC); if (fd[which] < 0) { if (!which) { save_errno = errno; fprintf(stderr, OUT_TAG ": unable to open map '%s': %s\n", tagfile, strerror(save_errno)); errno = save_errno; return NULL; goto fail_errno; } off_t end = lseek(fd, 0L, SEEK_END); continue; } end[which] = lseek(fd[which], 0L, SEEK_END); save_errno = errno; (void)lseek(fd, 0L, SEEK_SET); if (end < 0) { (void)lseek(fd[which], 0L, SEEK_SET); if (!which && (end[0] < 0)) { fprintf(stderr, OUT_TAG ": unable to seek map '%s' %s\n", tagfile, strerror(save_errno)); close(fd); errno = save_errno; return NULL; goto fail_close; } if (fileName) break; // Only allow one as specified } EventTagMap* newTagMap = new EventTagMap; newTagMap = new EventTagMap; if (newTagMap == NULL) { save_errno = errno; close(fd); errno = save_errno; return NULL; goto fail_close; } newTagMap->mapAddr = mmap(NULL, end, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); for (which = 0; which < NUM_MAPS; ++which) { if (fd[which] >= 0) { newTagMap->mapAddr[which] = mmap(NULL, end[which], which ? PROT_READ : PROT_READ | PROT_WRITE, which ? MAP_SHARED : MAP_PRIVATE, fd[which], 0); save_errno = errno; close(fd); fd = -1; if ((newTagMap->mapAddr == MAP_FAILED) || (newTagMap->mapAddr == NULL)) { close(fd[which]); fd[which] = -1; if ((newTagMap->mapAddr[which] != MAP_FAILED) && (newTagMap->mapAddr[which] != NULL)) { newTagMap->mapLen[which] = end[which]; } else if (!which) { const char* tagfile = fileName ? fileName : eventTagFiles[which]; fprintf(stderr, OUT_TAG ": mmap(%s) failed: %s\n", tagfile, strerror(save_errno)); delete newTagMap; errno = save_errno; return NULL; goto fail_unmap; } } } newTagMap->mapLen = end; if (parseMapLines(newTagMap) != 0) { for (which = 0; which < NUM_MAPS; ++which) { if (parseMapLines(newTagMap, which) != 0) { delete newTagMap; return NULL; } } return newTagMap; fail_unmap: save_errno = EINVAL; delete newTagMap; fail_close: for (which = 0; which < NUM_MAPS; ++which) close(fd[which]); fail_errno: errno = save_errno; return NULL; } // Close the map. Loading Loading
liblog/event_tag_map.cpp +111 −51 Original line number Diff line number Diff line Loading @@ -53,21 +53,27 @@ template <> struct std::hash<TagFmt> // Map struct EventTagMap { # define NUM_MAPS 2 // memory-mapped source file; we get strings from here void* mapAddr; size_t mapLen; void* mapAddr[NUM_MAPS]; size_t mapLen[NUM_MAPS]; private: std::unordered_map<uint32_t, TagFmt> Idx2TagFmt; public: EventTagMap() : mapAddr(NULL), mapLen(0) { } EventTagMap() { memset(mapAddr, 0, sizeof(mapAddr)); memset(mapLen, 0, sizeof(mapLen)); } ~EventTagMap() { Idx2TagFmt.clear(); if (mapAddr) { munmap(mapAddr, mapLen); mapAddr = 0; for (size_t which = 0; which < NUM_MAPS; ++which) { if (mapAddr[which]) { munmap(mapAddr[which], mapLen[which]); mapAddr[which] = 0; } } } Loading Loading @@ -157,6 +163,19 @@ static int scanTagLine(EventTagMap* map, char** pData, int lineNum) { 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 != '\n')) ++cp; if (*cp == '#') { do { ++cp; } while (isspace(*cp) && (*cp != '\n')); verbose = !!fastcmp<strncmp>(cp, "uid=", strlen("uid=")); } while (*cp != '\n') ++cp; #ifdef DEBUG fprintf(stderr, "%d: %p: %.*s\n", lineNum, tag, (int)(cp - *pData), *pData); Loading @@ -164,24 +183,33 @@ static int scanTagLine(EventTagMap* map, char** pData, int lineNum) { *pData = cp; if (map->emplaceUnique(tagIndex, TagFmt(std::make_pair( MapString(tag, tagLen), MapString(fmt, fmtLen))), true)) { MapString(tag, tagLen), MapString(fmt, fmtLen))), verbose)) { return 0; } errno = EMLINK; return -1; } static const char* eventTagFiles[NUM_MAPS] = { EVENT_TAG_MAP_FILE, "/dev/event-log-tags", }; // Parse the tags out of the file. static int parseMapLines(EventTagMap* map) { char* cp = static_cast<char*>(map->mapAddr); size_t len = map->mapLen; static int parseMapLines(EventTagMap* map, size_t which) { char* cp = static_cast<char*>(map->mapAddr[which]); size_t len = map->mapLen[which]; char* endp = cp + len; // insist on EOL at EOF; simplifies parsing and null-termination if (!len || (*(endp - 1) != '\n')) { #ifdef DEBUG fprintf(stderr, OUT_TAG ": map file missing EOL on last line\n"); fprintf(stderr, OUT_TAG ": map file %zu[%zu] missing EOL on last line\n", which, len); #endif if (which) { // do not propagate errors for other files return 0; } errno = EINVAL; return -1; } Loading @@ -199,8 +227,10 @@ static int parseMapLines(EventTagMap* map) { } else if (isdigit(*cp)) { // looks like a tag; scan it out if (scanTagLine(map, &cp, lineNum) != 0) { if (!which || (errno != EMLINK)) { return -1; } } lineNum++; // we eat the '\n' // leave lineStart==true } else if (isspace(*cp)) { Loading @@ -226,57 +256,87 @@ static int parseMapLines(EventTagMap* map) { // We create a private mapping because we want to terminate the log tag // strings with '\0'. LIBLOG_ABI_PUBLIC EventTagMap* android_openEventTagMap(const char* fileName) { int save_errno; EventTagMap* newTagMap; off_t end[NUM_MAPS]; int save_errno, fd[NUM_MAPS]; size_t which; memset(fd, -1, sizeof(fd)); memset(end, 0, sizeof(end)); for (which = 0; which < NUM_MAPS; ++which) { const char* tagfile = fileName ? fileName : eventTagFiles[which]; const char* tagfile = fileName ? fileName : EVENT_TAG_MAP_FILE; int fd = open(tagfile, O_RDONLY | O_CLOEXEC); if (fd < 0) { fd[which] = open(tagfile, O_RDONLY | O_CLOEXEC); if (fd[which] < 0) { if (!which) { save_errno = errno; fprintf(stderr, OUT_TAG ": unable to open map '%s': %s\n", tagfile, strerror(save_errno)); errno = save_errno; return NULL; goto fail_errno; } off_t end = lseek(fd, 0L, SEEK_END); continue; } end[which] = lseek(fd[which], 0L, SEEK_END); save_errno = errno; (void)lseek(fd, 0L, SEEK_SET); if (end < 0) { (void)lseek(fd[which], 0L, SEEK_SET); if (!which && (end[0] < 0)) { fprintf(stderr, OUT_TAG ": unable to seek map '%s' %s\n", tagfile, strerror(save_errno)); close(fd); errno = save_errno; return NULL; goto fail_close; } if (fileName) break; // Only allow one as specified } EventTagMap* newTagMap = new EventTagMap; newTagMap = new EventTagMap; if (newTagMap == NULL) { save_errno = errno; close(fd); errno = save_errno; return NULL; goto fail_close; } newTagMap->mapAddr = mmap(NULL, end, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); for (which = 0; which < NUM_MAPS; ++which) { if (fd[which] >= 0) { newTagMap->mapAddr[which] = mmap(NULL, end[which], which ? PROT_READ : PROT_READ | PROT_WRITE, which ? MAP_SHARED : MAP_PRIVATE, fd[which], 0); save_errno = errno; close(fd); fd = -1; if ((newTagMap->mapAddr == MAP_FAILED) || (newTagMap->mapAddr == NULL)) { close(fd[which]); fd[which] = -1; if ((newTagMap->mapAddr[which] != MAP_FAILED) && (newTagMap->mapAddr[which] != NULL)) { newTagMap->mapLen[which] = end[which]; } else if (!which) { const char* tagfile = fileName ? fileName : eventTagFiles[which]; fprintf(stderr, OUT_TAG ": mmap(%s) failed: %s\n", tagfile, strerror(save_errno)); delete newTagMap; errno = save_errno; return NULL; goto fail_unmap; } } } newTagMap->mapLen = end; if (parseMapLines(newTagMap) != 0) { for (which = 0; which < NUM_MAPS; ++which) { if (parseMapLines(newTagMap, which) != 0) { delete newTagMap; return NULL; } } return newTagMap; fail_unmap: save_errno = EINVAL; delete newTagMap; fail_close: for (which = 0; which < NUM_MAPS; ++which) close(fd[which]); fail_errno: errno = save_errno; return NULL; } // Close the map. Loading