summaryrefslogtreecommitdiffstats
path: root/common/textfile.c
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2007-11-26 11:52:16 +0000
committerMarcel Holtmann <marcel@holtmann.org>2007-11-26 11:52:16 +0000
commit48ce703ca92056265f6f036f42c8f8843700d15f (patch)
treeeaac749caa4d2071c4fd3d79cb588d0ccd5e81a4 /common/textfile.c
parent6dda5e4081749ace9d58aae0b416f9ac86ef9f70 (diff)
Fix key search function to honor the mmap area size
Diffstat (limited to 'common/textfile.c')
-rw-r--r--common/textfile.c54
1 files changed, 40 insertions, 14 deletions
diff --git a/common/textfile.c b/common/textfile.c
index ea7e80bb..88e783a8 100644
--- a/common/textfile.c
+++ b/common/textfile.c
@@ -28,6 +28,7 @@
#define _GNU_SOURCE
#include <stdio.h>
#include <errno.h>
+#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
#include <malloc.h>
@@ -78,7 +79,8 @@ int create_file(const char *filename, const mode_t mode)
int fd;
umask(S_IWGRP | S_IWOTH);
- create_dirs(filename, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
+ create_dirs(filename, S_IRUSR | S_IWUSR | S_IXUSR |
+ S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
fd = open(filename, O_RDWR | O_CREAT, mode);
if (fd < 0)
@@ -94,19 +96,42 @@ int create_name(char *buf, size_t size, const char *path, const char *address, c
return snprintf(buf, size, "%s/%s/%s", path, address, name);
}
-static inline char *find_key(char *map, const char *key, size_t len, int icase)
+static inline char *find_key(char *map, size_t size, const char *key, size_t len, int icase)
{
- char *off = (icase) ? strcasestr(map, key) : strstr(map, key);
-
- while (off && ((off > map && *(off - 1) != '\r' &&
- *(off - 1) != '\n') || *(off + len) != ' ')) {
- if (icase)
- off = strcasestr(off + len, key);
- else
- off = strstr(off + len, key);
+ char *ptr = map;
+ size_t ptrlen = size;
+
+ while (ptrlen > len + 1) {
+ int cmp = (icase) ? strncasecmp(ptr, key, len) : strncmp(ptr, key, len);
+ if (cmp == 0) {
+ if (ptr == map)
+ return ptr;
+
+ if ((*(ptr - 1) == '\r' || *(ptr - 1) == '\n') &&
+ *(ptr + len) == ' ')
+ return ptr;
+ }
+
+ if (icase) {
+ char *p1 = memchr(ptr + 1, tolower(*key), ptrlen - 1);
+ char *p2 = memchr(ptr + 1, toupper(*key), ptrlen - 1);
+
+ if (!p1)
+ ptr = p2;
+ else if (!p2)
+ ptr = p1;
+ else
+ ptr = (p1 < p2) ? p1 : p2;
+ } else
+ ptr = memchr(ptr + 1, *key, ptrlen - 1);
+
+ if (!ptr)
+ return NULL;
+
+ ptrlen = size - (ptr - map);
}
- return off;
+ return NULL;
}
static inline int write_key_value(int fd, const char *key, const char *value)
@@ -162,14 +187,15 @@ static int write_key(const char *pathname, const char *key, const char *value, i
goto unlock;
}
- map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_LOCKED, fd, 0);
+ map = mmap(NULL, size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_LOCKED, fd, 0);
if (!map || map == MAP_FAILED) {
err = errno;
goto unlock;
}
len = strlen(key);
- off = find_key(map, key, len, icase);
+ off = find_key(map, size, key, len, icase);
if (!off) {
if (value) {
munmap(map, size);
@@ -281,7 +307,7 @@ static char *read_key(const char *pathname, const char *key, int icase)
}
len = strlen(key);
- off = find_key(map, key, len, icase);
+ off = find_key(map, size, key, len, icase);
if (!off) {
err = EILSEQ;
goto unmap;