Merge "liblog: fix errno issues with event tag map"
This commit is contained in:
commit
dfd30c4a16
2 changed files with 100 additions and 129 deletions
|
|
@ -41,7 +41,7 @@ void android_closeEventTagMap(EventTagMap* map);
|
||||||
/*
|
/*
|
||||||
* Look up a tag by index. Returns the tag string, or NULL if not found.
|
* Look up a tag by index. Returns the tag string, or NULL if not found.
|
||||||
*/
|
*/
|
||||||
const char* android_lookupEventTag(const EventTagMap* map, int tag);
|
const char* android_lookupEventTag(const EventTagMap* map, unsigned int tag);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <inttypes.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
@ -32,8 +34,8 @@
|
||||||
* Single entry.
|
* Single entry.
|
||||||
*/
|
*/
|
||||||
typedef struct EventTag {
|
typedef struct EventTag {
|
||||||
unsigned int tagIndex;
|
uint32_t tagIndex;
|
||||||
const char* tagStr;
|
const char* tagStr;
|
||||||
} EventTag;
|
} EventTag;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -56,7 +58,6 @@ static int parseMapLines(EventTagMap* map);
|
||||||
static int scanTagLine(char** pData, EventTag* tag, int lineNum);
|
static int scanTagLine(char** pData, EventTag* tag, int lineNum);
|
||||||
static int sortTags(EventTagMap* map);
|
static int sortTags(EventTagMap* map);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Open the map file and allocate a structure to manage it.
|
* Open the map file and allocate a structure to manage it.
|
||||||
*
|
*
|
||||||
|
|
@ -67,47 +68,57 @@ LIBLOG_ABI_PUBLIC EventTagMap* android_openEventTagMap(const char* fileName)
|
||||||
{
|
{
|
||||||
EventTagMap* newTagMap;
|
EventTagMap* newTagMap;
|
||||||
off_t end;
|
off_t end;
|
||||||
int fd = -1;
|
int save_errno;
|
||||||
|
|
||||||
newTagMap = calloc(1, sizeof(EventTagMap));
|
int fd = open(fileName, O_RDONLY | O_CLOEXEC);
|
||||||
if (newTagMap == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
fd = open(fileName, O_RDONLY | O_CLOEXEC);
|
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
|
save_errno = errno;
|
||||||
fprintf(stderr, "%s: unable to open map '%s': %s\n",
|
fprintf(stderr, "%s: unable to open map '%s': %s\n",
|
||||||
OUT_TAG, fileName, strerror(errno));
|
OUT_TAG, fileName, strerror(save_errno));
|
||||||
goto fail;
|
goto fail_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
end = lseek(fd, 0L, SEEK_END);
|
end = lseek(fd, 0L, SEEK_END);
|
||||||
|
save_errno = errno;
|
||||||
(void) lseek(fd, 0L, SEEK_SET);
|
(void) lseek(fd, 0L, SEEK_SET);
|
||||||
if (end < 0) {
|
if (end < 0) {
|
||||||
fprintf(stderr, "%s: unable to seek map '%s'\n", OUT_TAG, fileName);
|
fprintf(stderr, "%s: unable to seek map '%s' %s\n",
|
||||||
goto fail;
|
OUT_TAG, fileName, strerror(save_errno));
|
||||||
|
goto fail_close;
|
||||||
}
|
}
|
||||||
|
|
||||||
newTagMap->mapAddr = mmap(NULL, end, PROT_READ | PROT_WRITE, MAP_PRIVATE,
|
newTagMap = (EventTagMap*)calloc(1, sizeof(EventTagMap));
|
||||||
fd, 0);
|
if (newTagMap == NULL) {
|
||||||
if (newTagMap->mapAddr == MAP_FAILED) {
|
save_errno = errno;
|
||||||
fprintf(stderr, "%s: mmap(%s) failed: %s\n",
|
goto fail_close;
|
||||||
OUT_TAG, fileName, strerror(errno));
|
|
||||||
goto fail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
newTagMap->mapAddr = mmap(NULL, end, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
|
||||||
|
save_errno = errno;
|
||||||
|
close(fd);
|
||||||
|
fd = -1;
|
||||||
|
if ((newTagMap->mapAddr == MAP_FAILED) || (newTagMap->mapAddr == NULL)) {
|
||||||
|
fprintf(stderr, "%s: mmap(%s) failed: %s\n",
|
||||||
|
OUT_TAG, fileName, strerror(save_errno));
|
||||||
|
goto fail_free;
|
||||||
|
}
|
||||||
|
|
||||||
newTagMap->mapLen = end;
|
newTagMap->mapLen = end;
|
||||||
|
|
||||||
if (processFile(newTagMap) != 0)
|
if (processFile(newTagMap) != 0) goto fail_unmap;
|
||||||
goto fail;
|
|
||||||
|
|
||||||
if (fd >= 0)
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
return newTagMap;
|
return newTagMap;
|
||||||
|
|
||||||
|
fail_unmap:
|
||||||
|
munmap(newTagMap->mapAddr, newTagMap->mapLen);
|
||||||
|
save_errno = EINVAL;
|
||||||
|
fail_free:
|
||||||
|
free(newTagMap);
|
||||||
|
fail_close:
|
||||||
|
close(fd);
|
||||||
|
fail_errno:
|
||||||
|
errno = save_errno;
|
||||||
fail:
|
fail:
|
||||||
android_closeEventTagMap(newTagMap);
|
|
||||||
if (fd >= 0)
|
|
||||||
close(fd);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -116,8 +127,7 @@ fail:
|
||||||
*/
|
*/
|
||||||
LIBLOG_ABI_PUBLIC void android_closeEventTagMap(EventTagMap* map)
|
LIBLOG_ABI_PUBLIC void android_closeEventTagMap(EventTagMap* map)
|
||||||
{
|
{
|
||||||
if (map == NULL)
|
if (map == NULL) return;
|
||||||
return;
|
|
||||||
|
|
||||||
munmap(map->mapAddr, map->mapLen);
|
munmap(map->mapAddr, map->mapLen);
|
||||||
free(map->tagArray);
|
free(map->tagArray);
|
||||||
|
|
@ -130,18 +140,15 @@ LIBLOG_ABI_PUBLIC void android_closeEventTagMap(EventTagMap* map)
|
||||||
* The entries are sorted by tag number, so we can do a binary search.
|
* The entries are sorted by tag number, so we can do a binary search.
|
||||||
*/
|
*/
|
||||||
LIBLOG_ABI_PUBLIC const char* android_lookupEventTag(const EventTagMap* map,
|
LIBLOG_ABI_PUBLIC const char* android_lookupEventTag(const EventTagMap* map,
|
||||||
int tag)
|
unsigned int tag)
|
||||||
{
|
{
|
||||||
int hi, lo, mid;
|
int lo = 0;
|
||||||
|
int hi = map->numTags - 1;
|
||||||
lo = 0;
|
|
||||||
hi = map->numTags-1;
|
|
||||||
|
|
||||||
while (lo <= hi) {
|
while (lo <= hi) {
|
||||||
int cmp;
|
int mid = (lo + hi) / 2;
|
||||||
|
int cmp = map->tagArray[mid].tagIndex - tag;
|
||||||
|
|
||||||
mid = (lo+hi)/2;
|
|
||||||
cmp = map->tagArray[mid].tagIndex - tag;
|
|
||||||
if (cmp < 0) {
|
if (cmp < 0) {
|
||||||
/* tag is bigger */
|
/* tag is bigger */
|
||||||
lo = mid + 1;
|
lo = mid + 1;
|
||||||
|
|
@ -154,39 +161,10 @@ LIBLOG_ABI_PUBLIC const char* android_lookupEventTag(const EventTagMap* map,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errno = ENOENT;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Determine whether "c" is a whitespace char.
|
|
||||||
*/
|
|
||||||
static inline int isCharWhitespace(char c)
|
|
||||||
{
|
|
||||||
return (c == ' ' || c == '\n' || c == '\r' || c == '\t');
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Determine whether "c" is a valid tag char.
|
|
||||||
*/
|
|
||||||
static inline int isCharValidTag(char c)
|
|
||||||
{
|
|
||||||
return ((c >= 'A' && c <= 'Z') ||
|
|
||||||
(c >= 'a' && c <= 'z') ||
|
|
||||||
(c >= '0' && c <= '9') ||
|
|
||||||
(c == '_'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Determine whether "c" is a valid decimal digit.
|
|
||||||
*/
|
|
||||||
static inline int isCharDigit(char c)
|
|
||||||
{
|
|
||||||
return (c >= '0' && c <= '9');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Crunch through the file, parsing the contents and creating a tag index.
|
* Crunch through the file, parsing the contents and creating a tag index.
|
||||||
*/
|
*/
|
||||||
|
|
@ -194,25 +172,20 @@ static int processFile(EventTagMap* map)
|
||||||
{
|
{
|
||||||
/* get a tag count */
|
/* get a tag count */
|
||||||
map->numTags = countMapLines(map);
|
map->numTags = countMapLines(map);
|
||||||
if (map->numTags < 0)
|
if (map->numTags < 0) {
|
||||||
return -1;
|
errno = ENOENT;
|
||||||
|
|
||||||
//printf("+++ found %d tags\n", map->numTags);
|
|
||||||
|
|
||||||
/* allocate storage for the tag index array */
|
|
||||||
map->tagArray = calloc(1, sizeof(EventTag) * map->numTags);
|
|
||||||
if (map->tagArray == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* parse the file, null-terminating tag strings */
|
|
||||||
if (parseMapLines(map) != 0) {
|
|
||||||
fprintf(stderr, "%s: file parse failed\n", OUT_TAG);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* allocate storage for the tag index array */
|
||||||
|
map->tagArray = (EventTag*)calloc(1, sizeof(EventTag) * map->numTags);
|
||||||
|
if (map->tagArray == NULL) return -1;
|
||||||
|
|
||||||
|
/* parse the file, null-terminating tag strings */
|
||||||
|
if (parseMapLines(map) != 0) return -1;
|
||||||
|
|
||||||
/* sort the tags and check for duplicates */
|
/* sort the tags and check for duplicates */
|
||||||
if (sortTags(map) != 0)
|
if (sortTags(map) != 0) return -1;
|
||||||
return -1;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -229,24 +202,20 @@ static int processFile(EventTagMap* map)
|
||||||
*/
|
*/
|
||||||
static int countMapLines(const EventTagMap* map)
|
static int countMapLines(const EventTagMap* map)
|
||||||
{
|
{
|
||||||
int numTags, unknown;
|
const char* cp = (const char*) map->mapAddr;
|
||||||
const char* cp;
|
const char* endp = cp + map->mapLen;
|
||||||
const char* endp;
|
int numTags = 0;
|
||||||
|
int unknown = 1;
|
||||||
|
|
||||||
cp = (const char*) map->mapAddr;
|
|
||||||
endp = cp + map->mapLen;
|
|
||||||
|
|
||||||
numTags = 0;
|
|
||||||
unknown = 1;
|
|
||||||
while (cp < endp) {
|
while (cp < endp) {
|
||||||
if (*cp == '\n') {
|
if (*cp == '\n') {
|
||||||
unknown = 1;
|
unknown = 1;
|
||||||
} else if (unknown) {
|
} else if (unknown) {
|
||||||
if (isCharDigit(*cp)) {
|
if (isdigit(*cp)) {
|
||||||
/* looks like a tag to me */
|
/* looks like a tag to me */
|
||||||
numTags++;
|
numTags++;
|
||||||
unknown = 0;
|
unknown = 0;
|
||||||
} else if (isCharWhitespace(*cp)) {
|
} else if (isspace(*cp)) {
|
||||||
/* might be leading whitespace before tag num, keep going */
|
/* might be leading whitespace before tag num, keep going */
|
||||||
} else {
|
} else {
|
||||||
/* assume comment; second pass can complain in detail */
|
/* assume comment; second pass can complain in detail */
|
||||||
|
|
@ -267,15 +236,13 @@ static int countMapLines(const EventTagMap* map)
|
||||||
static int parseMapLines(EventTagMap* map)
|
static int parseMapLines(EventTagMap* map)
|
||||||
{
|
{
|
||||||
int tagNum, lineStart, lineNum;
|
int tagNum, lineStart, lineNum;
|
||||||
char* cp;
|
char* cp = (char*) map->mapAddr;
|
||||||
char* endp;
|
char* endp = cp + map->mapLen;
|
||||||
|
|
||||||
cp = (char*) map->mapAddr;
|
|
||||||
endp = cp + map->mapLen;
|
|
||||||
|
|
||||||
/* insist on EOL at EOF; simplifies parsing and null-termination */
|
/* insist on EOL at EOF; simplifies parsing and null-termination */
|
||||||
if (*(endp-1) != '\n') {
|
if (*(endp - 1) != '\n') {
|
||||||
fprintf(stderr, "%s: map file missing EOL on last line\n", OUT_TAG);
|
fprintf(stderr, "%s: map file missing EOL on last line\n", OUT_TAG);
|
||||||
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -283,7 +250,6 @@ static int parseMapLines(EventTagMap* map)
|
||||||
lineStart = 1;
|
lineStart = 1;
|
||||||
lineNum = 1;
|
lineNum = 1;
|
||||||
while (cp < endp) {
|
while (cp < endp) {
|
||||||
//printf("{%02x}", *cp); fflush(stdout);
|
|
||||||
if (*cp == '\n') {
|
if (*cp == '\n') {
|
||||||
lineStart = 1;
|
lineStart = 1;
|
||||||
lineNum++;
|
lineNum++;
|
||||||
|
|
@ -291,24 +257,27 @@ static int parseMapLines(EventTagMap* map)
|
||||||
if (*cp == '#') {
|
if (*cp == '#') {
|
||||||
/* comment; just scan to end */
|
/* comment; just scan to end */
|
||||||
lineStart = 0;
|
lineStart = 0;
|
||||||
} else if (isCharDigit(*cp)) {
|
} else if (isdigit(*cp)) {
|
||||||
/* looks like a tag; scan it out */
|
/* looks like a tag; scan it out */
|
||||||
if (tagNum >= map->numTags) {
|
if (tagNum >= map->numTags) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"%s: more tags than expected (%d)\n", OUT_TAG, tagNum);
|
"%s: more tags than expected (%d)\n", OUT_TAG, tagNum);
|
||||||
|
errno = EMFILE;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (scanTagLine(&cp, &map->tagArray[tagNum], lineNum) != 0)
|
if (scanTagLine(&cp, &map->tagArray[tagNum], lineNum) != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
tagNum++;
|
tagNum++;
|
||||||
lineNum++; // we eat the '\n'
|
lineNum++; // we eat the '\n'
|
||||||
/* leave lineStart==1 */
|
/* leave lineStart==1 */
|
||||||
} else if (isCharWhitespace(*cp)) {
|
} else if (isspace(*cp)) {
|
||||||
/* looks like leading whitespace; keep scanning */
|
/* looks like leading whitespace; keep scanning */
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"%s: unexpected chars (0x%02x) in tag number on line %d\n",
|
"%s: unexpected chars (0x%02x) in tag number on line %d\n",
|
||||||
OUT_TAG, *cp, lineNum);
|
OUT_TAG, *cp, lineNum);
|
||||||
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -320,6 +289,7 @@ static int parseMapLines(EventTagMap* map)
|
||||||
if (tagNum != map->numTags) {
|
if (tagNum != map->numTags) {
|
||||||
fprintf(stderr, "%s: parsed %d tags, expected %d\n",
|
fprintf(stderr, "%s: parsed %d tags, expected %d\n",
|
||||||
OUT_TAG, tagNum, map->numTags);
|
OUT_TAG, tagNum, map->numTags);
|
||||||
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -337,41 +307,41 @@ static int parseMapLines(EventTagMap* map)
|
||||||
*/
|
*/
|
||||||
static int scanTagLine(char** pData, EventTag* tag, int lineNum)
|
static int scanTagLine(char** pData, EventTag* tag, int lineNum)
|
||||||
{
|
{
|
||||||
char* cp = *pData;
|
char* cp;
|
||||||
char* startp;
|
|
||||||
char* endp;
|
|
||||||
unsigned long val;
|
|
||||||
|
|
||||||
startp = cp;
|
unsigned long val = strtoul(*pData, &cp, 10);
|
||||||
while (isCharDigit(*++cp))
|
if (cp == *pData) {
|
||||||
;
|
fprintf(stderr, "%s: malformed tag number on line %d\n", OUT_TAG, lineNum);
|
||||||
*cp = '\0';
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
val = strtoul(startp, &endp, 10);
|
}
|
||||||
assert(endp == cp);
|
|
||||||
if (endp != cp)
|
|
||||||
fprintf(stderr, "ARRRRGH\n");
|
|
||||||
|
|
||||||
tag->tagIndex = val;
|
tag->tagIndex = val;
|
||||||
|
if (tag->tagIndex != val) {
|
||||||
|
fprintf(stderr, "%s: tag number too large on line %d\n", OUT_TAG, lineNum);
|
||||||
|
errno = ERANGE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
while (*++cp != '\n' && isCharWhitespace(*cp))
|
while ((*++cp != '\n') && isspace(*cp)) {
|
||||||
;
|
}
|
||||||
|
|
||||||
if (*cp == '\n') {
|
if (*cp == '\n') {
|
||||||
fprintf(stderr,
|
fprintf(stderr, "%s: missing tag string on line %d\n", OUT_TAG, lineNum);
|
||||||
"%s: missing tag string on line %d\n", OUT_TAG, lineNum);
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
tag->tagStr = cp;
|
tag->tagStr = cp;
|
||||||
|
|
||||||
while (isCharValidTag(*++cp))
|
/* Determine whether "c" is a valid tag char. */
|
||||||
;
|
while (isalnum(*++cp) || (*cp == '_')) {
|
||||||
|
}
|
||||||
|
|
||||||
if (*cp == '\n') {
|
if (*cp == '\n') {
|
||||||
/* null terminate and return */
|
/* null terminate and return */
|
||||||
*cp = '\0';
|
*cp = '\0';
|
||||||
} else if (isCharWhitespace(*cp)) {
|
} else if (isspace(*cp)) {
|
||||||
/* CRLF or trailin spaces; zap this char, then scan for the '\n' */
|
/* CRLF or trailin spaces; zap this char, then scan for the '\n' */
|
||||||
*cp = '\0';
|
*cp = '\0';
|
||||||
|
|
||||||
|
|
@ -381,14 +351,13 @@ static int scanTagLine(char** pData, EventTag* tag, int lineNum)
|
||||||
while (*++cp != '\n') {
|
while (*++cp != '\n') {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr,
|
fprintf(stderr, "%s: invalid tag chars on line %d\n", OUT_TAG, lineNum);
|
||||||
"%s: invalid tag chars on line %d\n", OUT_TAG, lineNum);
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*pData = cp;
|
*pData = cp;
|
||||||
|
|
||||||
//printf("+++ Line %d: got %d '%s'\n", lineNum, tag->tagIndex, tag->tagStr);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -416,11 +385,13 @@ static int sortTags(EventTagMap* map)
|
||||||
qsort(map->tagArray, map->numTags, sizeof(EventTag), compareEventTags);
|
qsort(map->tagArray, map->numTags, sizeof(EventTag), compareEventTags);
|
||||||
|
|
||||||
for (i = 1; i < map->numTags; i++) {
|
for (i = 1; i < map->numTags; i++) {
|
||||||
if (map->tagArray[i].tagIndex == map->tagArray[i-1].tagIndex) {
|
if (map->tagArray[i].tagIndex == map->tagArray[i - 1].tagIndex) {
|
||||||
fprintf(stderr, "%s: duplicate tag entries (%d:%s and %d:%s)\n",
|
fprintf(stderr,
|
||||||
|
"%s: duplicate tag entries (%" PRIu32 ":%s and %" PRIu32 ":%s)\n",
|
||||||
OUT_TAG,
|
OUT_TAG,
|
||||||
map->tagArray[i].tagIndex, map->tagArray[i].tagStr,
|
map->tagArray[i].tagIndex, map->tagArray[i].tagStr,
|
||||||
map->tagArray[i-1].tagIndex, map->tagArray[i-1].tagStr);
|
map->tagArray[i - 1].tagIndex, map->tagArray[i - 1].tagStr);
|
||||||
|
errno = EMLINK;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue