summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2006-02-08 05:38:38 +0000
committerMarcel Holtmann <marcel@holtmann.org>2006-02-08 05:38:38 +0000
commit85cc0c57e4fd0e44c3b270aba4f87eb28151b1a2 (patch)
tree224ae692ccbed28ac1b5657835849a5e96b267dc
parent9b993dda376d1c74575ed8984b0cf07d1d671f8c (diff)
Add textfile_foreach() function
-rw-r--r--common/test_textfile.c24
-rw-r--r--common/textfile.c89
-rw-r--r--common/textfile.h3
3 files changed, 99 insertions, 17 deletions
diff --git a/common/test_textfile.c b/common/test_textfile.c
index c2b2c993..5a5b22c5 100644
--- a/common/test_textfile.c
+++ b/common/test_textfile.c
@@ -34,6 +34,11 @@
#include "textfile.h"
+static void print_entry(char *key, char *value, void *data)
+{
+ printf("%s %s\n", key, value);
+}
+
int main(int argc, char *argv[])
{
char filename[] = "/tmp/textfile";
@@ -109,15 +114,8 @@ int main(int argc, char *argv[])
printf("\n");
- for (i = 1; i < max + 1; i++) {
- sprintf(key, "00:00:00:00:00:%02X", i);
+ textfile_foreach(filename, print_entry, NULL);
- str = textfile_get(filename, key);
- if (str) {
- printf("%s %s\n", key, str);
- free(str);
- }
- }
sprintf(key, "00:00:00:00:00:%02X", 1);
@@ -136,15 +134,7 @@ int main(int argc, char *argv[])
printf("\n");
- for (i = 1; i < max + 1; i++) {
- sprintf(key, "00:00:00:00:00:%02X", i);
-
- str = textfile_get(filename, key);
- if (str) {
- printf("%s %s\n", key, str);
- free(str);
- }
- }
+ textfile_foreach(filename, print_entry, NULL);
return 0;
}
diff --git a/common/textfile.c b/common/textfile.c
index 3aa74d9a..2ed929a3 100644
--- a/common/textfile.c
+++ b/common/textfile.c
@@ -296,3 +296,92 @@ close:
return str;
}
+
+int textfile_foreach(char *pathname,
+ void (*func)(char *key, char *value, void *data), void *data)
+{
+ struct stat st;
+ char *map, *off, *end, *key, *value;
+ off_t size; size_t len;
+ int fd, err = 0;
+
+ fd = open(pathname, O_RDONLY);
+ if (fd < 0)
+ return -errno;
+
+ if (flock(fd, LOCK_SH) < 0) {
+ err = errno;
+ goto close;
+ }
+
+ if (fstat(fd, &st) < 0) {
+ err = errno;
+ goto unlock;
+ }
+
+ size = st.st_size;
+
+ map = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
+ if (!map || map == MAP_FAILED) {
+ err = errno;
+ goto unlock;
+ }
+
+ off = map;
+
+ while (1) {
+ end = strpbrk(off, " ");
+ if (!end) {
+ err = EILSEQ;
+ break;
+ }
+
+ len = end - off;
+
+ key = malloc(len + 1);
+ if (!key) {
+ err = errno;
+ break;
+ }
+
+ memset(key, 0, len + 1);
+ memcpy(key, off, len);
+
+ off = end + 1;
+
+ end = strpbrk(off, "\r\n");
+ if (!end) {
+ err = EILSEQ;
+ break;
+ }
+
+ len = end - off;
+
+ value = malloc(len + 1);
+ if (!value) {
+ err = errno;
+ break;
+ }
+
+ memset(value, 0, len + 1);
+ memcpy(value, off, len);
+
+ func(key, value, data);
+
+ free(key);
+ free(value);
+
+ off = end + 1;
+ }
+
+ munmap(map, size);
+
+unlock:
+ flock(fd, LOCK_UN);
+
+close:
+ close(fd);
+ errno = err;
+
+ return 0;
+}
diff --git a/common/textfile.h b/common/textfile.h
index 62ad4b80..3c8b6841 100644
--- a/common/textfile.h
+++ b/common/textfile.h
@@ -27,3 +27,6 @@ int create_file(char *filename, mode_t mode);
int textfile_put(char *pathname, char *key, char *value);
int textfile_del(char *pathname, char *key);
char *textfile_get(char *pathname, char *key);
+
+int textfile_foreach(char *pathname,
+ void (*func)(char *key, char *value, void *data), void *data);