From a66a22cd29417810d91c057c6febe817f3d7b26a Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 22 Apr 2005 12:15:36 +0000 Subject: Add the textfile library for ASCII based file access --- common/textfile.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 common/textfile.c (limited to 'common/textfile.c') diff --git a/common/textfile.c b/common/textfile.c new file mode 100644 index 00000000..6f84cfa9 --- /dev/null +++ b/common/textfile.c @@ -0,0 +1,100 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2005 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY + * CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, + * COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS + * SOFTWARE IS DISCLAIMED. + * + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +char *textfile_get(const char *pathname, const char *key) +{ + struct stat st; + char *map, *off, *end, *str = NULL; + off_t size; size_t len; + int fd; + + fd = open(pathname, O_RDONLY); + if (fd < 0) + return NULL; + + if (flock(fd, LOCK_SH) < 0) + goto close; + + if (fstat(fd, &st) < 0) + goto unlock; + + size = st.st_size; + + map = mmap(0, size, PROT_READ, MAP_SHARED, fd, 0); + if (map == MAP_FAILED) + goto close; + + off = strstr(map, key); + if (!off) + goto unmap; + + if (off > map) { + while (*(off - 1) != '\r' && *(off - 1) != '\n') { + off = strstr(map, key); + if (!off) + goto unmap; + } + } + + end = strpbrk(off, "\r\n"); + if (!end) + goto unmap; + + len = strlen(key); + str = malloc(end - off - len); + memset(str, 0, end - off - len); + if (!str) + goto unmap; + + strncpy(str, off + len + 1, end - off - len - 1); + +unmap: + munmap(map, size); + +unlock: + flock(fd, LOCK_UN); + +close: + close(fd); + + return str; +} -- cgit From c6f99123f1269ad3742100eec084902a31e774bd Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 6 May 2005 19:56:46 +0000 Subject: Implement textfile writing support --- common/textfile.c | 160 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 148 insertions(+), 12 deletions(-) (limited to 'common/textfile.c') diff --git a/common/textfile.c b/common/textfile.c index 6f84cfa9..0bda2a94 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -40,51 +40,186 @@ #include #include +static int write_key_value(const int fd, const char *key, const char *value) +{ + char *str; + int size, err = 0; + + size = strlen(key) + strlen(value) + 2; + + str = malloc(size); + if (!str) + return ENOMEM; + + sprintf(str, "%s %s\n", key, value); + + if (write(fd, str, size) < 0) + err = errno; + + free(str); + + return err; +} + +int textfile_put(const char *pathname, const char *key, const char *value) +{ + struct stat st; + char *map, *off, *end, *str; + off_t size, pos; size_t base, len; + int fd, err = 0; + + fd = open(pathname, O_RDWR); + if (fd < 0) + return -errno; + + if (flock(fd, LOCK_EX) < 0) { + err = errno; + goto close; + } + + if (fstat(fd, &st) < 0) { + err = errno; + goto unlock; + } + + size = st.st_size; + + if (!size) { + pos = lseek(fd, size, SEEK_SET); + err = write_key_value(fd, key, value); + goto unlock; + } + + map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (map == MAP_FAILED) { + err = errno; + goto unlock; + } + + off = strstr(map, key); + if (!off) { + munmap(map, size); + pos = lseek(fd, size, SEEK_SET); + err = write_key_value(fd, key, value); + goto unlock; + } + + if (off > map) { + while (*(off - 1) != '\r' && *(off - 1) != '\n') { + off = strstr(off, key); + if (!off) { + munmap(map, size); + pos = lseek(fd, size, SEEK_SET); + err = write_key_value(fd, key, value); + goto unlock; + } + } + } + + base = off - map; + + end = strpbrk(off, "\r\n"); + if (!end) { + err = EILSEQ; + goto unmap; + } + + len = strspn(end, "\r\n"); + end += len; + + len = size - (end - map); + + str = malloc(len); + if (!str) { + err = errno; + goto unmap; + } + + memcpy(str, end, len); + munmap(map, size); + + ftruncate(fd, base); + pos = lseek(fd, base, SEEK_SET); + + write_key_value(fd, key, value); + write(fd, str, len); + + free(str); + + goto unlock; + +unmap: + munmap(map, size); + +unlock: + flock(fd, LOCK_UN); + +close: + close(fd); + errno = err; + + return -err; +} + char *textfile_get(const char *pathname, const char *key) { struct stat st; char *map, *off, *end, *str = NULL; off_t size; size_t len; - int fd; + int fd, err = 0; fd = open(pathname, O_RDONLY); if (fd < 0) return NULL; - if (flock(fd, LOCK_SH) < 0) + if (flock(fd, LOCK_SH) < 0) { + err = errno; goto close; + } - if (fstat(fd, &st) < 0) + if (fstat(fd, &st) < 0) { + err = errno; goto unlock; + } size = st.st_size; - map = mmap(0, size, PROT_READ, MAP_SHARED, fd, 0); - if (map == MAP_FAILED) - goto close; + map = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); + if (map == MAP_FAILED) { + err = errno; + goto unlock; + } off = strstr(map, key); - if (!off) + if (!off) { + err = EILSEQ; goto unmap; + } if (off > map) { while (*(off - 1) != '\r' && *(off - 1) != '\n') { - off = strstr(map, key); - if (!off) + off = strstr(off, key); + if (!off) { + err = EILSEQ; goto unmap; + } } } end = strpbrk(off, "\r\n"); - if (!end) + if (!end) { + err = EILSEQ; goto unmap; + } len = strlen(key); str = malloc(end - off - len); - memset(str, 0, end - off - len); - if (!str) + if (!str) { + err = EILSEQ; goto unmap; + } + memset(str, 0, end - off - len); strncpy(str, off + len + 1, end - off - len - 1); unmap: @@ -95,6 +230,7 @@ unlock: close: close(fd); + errno = err; return str; } -- cgit From 1b67c5337c0704d147ed5e2ce143e553a79a43c5 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 5 Aug 2005 08:43:42 +0000 Subject: Update the textfile library --- common/textfile.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 4 deletions(-) (limited to 'common/textfile.c') diff --git a/common/textfile.c b/common/textfile.c index 0bda2a94..ca6f08f3 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -39,12 +39,51 @@ #include #include #include +#include -static int write_key_value(const int fd, const char *key, const char *value) +static int create_dirs(char *filename, mode_t mode) +{ + struct stat st; + char dir[PATH_MAX + 1], *prev, *next; + int err; + + err = stat(filename, &st); + if (!err && S_ISREG(st.st_mode)) + return 0; + + memset(dir, 0, PATH_MAX + 1); + strcat(dir, "/"); + + prev = strchr(filename, '/'); + + while (prev) { + next = strchr(prev + 1, '/'); + if (!next) + break; + + if (next - prev == 1) { + prev = next; + continue; + } + + strncat(dir, prev + 1, next - prev); + mkdir(dir, mode); + + prev = next; + } + + return 0; +} + +static int write_key_value(int fd, char *key, char *value) { char *str; int size, err = 0; + /* This check is needed, because other it will segfault */ + if (strlen(value) == 9) + return -EIO; + size = strlen(key) + strlen(value) + 2; str = malloc(size); @@ -61,7 +100,7 @@ static int write_key_value(const int fd, const char *key, const char *value) return err; } -int textfile_put(const char *pathname, const char *key, const char *value) +int textfile_put(char *pathname, char *key, char *value) { struct stat st; char *map, *off, *end, *str; @@ -90,7 +129,7 @@ int textfile_put(const char *pathname, const char *key, const char *value) goto unlock; } - map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED, fd, 0); if (map == MAP_FAILED) { err = errno; goto unlock; @@ -129,6 +168,11 @@ int textfile_put(const char *pathname, const char *key, const char *value) len = size - (end - map); + if (len <= 0 || len > size) { + err = EILSEQ; + goto unmap; + } + str = malloc(len); if (!str) { err = errno; @@ -161,7 +205,7 @@ close: return -err; } -char *textfile_get(const char *pathname, const char *key) +char *textfile_get(char *pathname, char *key) { struct stat st; char *map, *off, *end, *str = NULL; -- cgit From 7d19ed074bfea793e960c4f86af8085251ba613a Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 6 Aug 2005 06:27:05 +0000 Subject: Fix off by one memory allocation error --- common/textfile.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'common/textfile.c') diff --git a/common/textfile.c b/common/textfile.c index ca6f08f3..08cd5a9f 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -75,18 +75,15 @@ static int create_dirs(char *filename, mode_t mode) return 0; } -static int write_key_value(int fd, char *key, char *value) +static inline int write_key_value(int fd, char *key, char *value) { char *str; - int size, err = 0; - - /* This check is needed, because other it will segfault */ - if (strlen(value) == 9) - return -EIO; + size_t size; + int err = 0; size = strlen(key) + strlen(value) + 2; - str = malloc(size); + str = malloc(size + 1); if (!str) return ENOMEM; -- cgit From 81b4c05b47e57505f56742b9349bee21116ba704 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 6 Aug 2005 07:00:03 +0000 Subject: Remove the create_dirs() function --- common/textfile.c | 34 ---------------------------------- 1 file changed, 34 deletions(-) (limited to 'common/textfile.c') diff --git a/common/textfile.c b/common/textfile.c index 08cd5a9f..a5d0a58b 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -41,40 +41,6 @@ #include #include -static int create_dirs(char *filename, mode_t mode) -{ - struct stat st; - char dir[PATH_MAX + 1], *prev, *next; - int err; - - err = stat(filename, &st); - if (!err && S_ISREG(st.st_mode)) - return 0; - - memset(dir, 0, PATH_MAX + 1); - strcat(dir, "/"); - - prev = strchr(filename, '/'); - - while (prev) { - next = strchr(prev + 1, '/'); - if (!next) - break; - - if (next - prev == 1) { - prev = next; - continue; - } - - strncat(dir, prev + 1, next - prev); - mkdir(dir, mode); - - prev = next; - } - - return 0; -} - static inline int write_key_value(int fd, char *key, char *value) { char *str; -- cgit From 44385c0baa98b0e27dad39cb8bd0e33ce5a027f6 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 30 Aug 2005 00:35:39 +0000 Subject: Move create_dirs() and create_file() into the textfile library --- common/textfile.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'common/textfile.c') diff --git a/common/textfile.c b/common/textfile.c index a5d0a58b..26cbbea7 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -41,6 +41,56 @@ #include #include +int create_dirs(char *filename, mode_t mode) +{ + struct stat st; + char dir[PATH_MAX + 1], *prev, *next; + int err; + + err = stat(filename, &st); + if (!err && S_ISREG(st.st_mode)) + return 0; + + memset(dir, 0, PATH_MAX + 1); + strcat(dir, "/"); + + prev = strchr(filename, '/'); + + while (prev) { + next = strchr(prev + 1, '/'); + if (!next) + break; + + if (next - prev == 1) { + prev = next; + continue; + } + + strncat(dir, prev + 1, next - prev); + mkdir(dir, mode); + + prev = next; + } + + return 0; +} + +int create_file(char *filename, 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); + + fd = open(filename, O_RDWR | O_CREAT, mode); + if (fd < 0) + return fd; + + close(fd); + + return 0; +} + static inline int write_key_value(int fd, char *key, char *value) { char *str; -- cgit From 50195243cfcac56a039480c3506acd0f5c5f80e0 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 7 Sep 2005 17:31:56 +0000 Subject: Let textfile_put() also replace the last key value pair --- common/textfile.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'common/textfile.c') diff --git a/common/textfile.c b/common/textfile.c index 26cbbea7..095e0355 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -180,8 +180,15 @@ int textfile_put(char *pathname, char *key, char *value) end += len; len = size - (end - map); + if (!len) { + munmap(map, size); + ftruncate(fd, base); + pos = lseek(fd, base, SEEK_SET); + err = write_key_value(fd, key, value); + goto unlock; + } - if (len <= 0 || len > size) { + if (len < 0 || len > size) { err = EILSEQ; goto unmap; } @@ -193,12 +200,12 @@ int textfile_put(char *pathname, char *key, char *value) } memcpy(str, end, len); - munmap(map, size); + munmap(map, size); ftruncate(fd, base); pos = lseek(fd, base, SEEK_SET); + err = write_key_value(fd, key, value); - write_key_value(fd, key, value); write(fd, str, len); free(str); -- cgit From b4b75b29434226f97505afa14a9b8838d9b93f61 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 10 Sep 2005 09:44:19 +0000 Subject: Fix infinite loops and false positive matches --- common/textfile.c | 39 ++++++++++++++------------------------- 1 file changed, 14 insertions(+), 25 deletions(-) (limited to 'common/textfile.c') diff --git a/common/textfile.c b/common/textfile.c index 095e0355..f15d439c 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -113,6 +113,17 @@ static inline int write_key_value(int fd, char *key, char *value) return err; } +static inline char *find_key(char *map, char *key, size_t len) +{ + char *off = strstr(map, key); + + while (off && ((off > map && *(off - 1) != '\r' && + *(off - 1) != '\n') || *(off + len) != ' ')) + off = strstr(off + len, key); + + return off; +} + int textfile_put(char *pathname, char *key, char *value) { struct stat st; @@ -148,7 +159,7 @@ int textfile_put(char *pathname, char *key, char *value) goto unlock; } - off = strstr(map, key); + off = find_key(map, key, strlen(key)); if (!off) { munmap(map, size); pos = lseek(fd, size, SEEK_SET); @@ -156,18 +167,6 @@ int textfile_put(char *pathname, char *key, char *value) goto unlock; } - if (off > map) { - while (*(off - 1) != '\r' && *(off - 1) != '\n') { - off = strstr(off, key); - if (!off) { - munmap(map, size); - pos = lseek(fd, size, SEEK_SET); - err = write_key_value(fd, key, value); - goto unlock; - } - } - } - base = off - map; end = strpbrk(off, "\r\n"); @@ -254,29 +253,19 @@ char *textfile_get(char *pathname, char *key) goto unlock; } - off = strstr(map, key); + len = strlen(key); + off = find_key(map, key, len); if (!off) { err = EILSEQ; goto unmap; } - if (off > map) { - while (*(off - 1) != '\r' && *(off - 1) != '\n') { - off = strstr(off, key); - if (!off) { - err = EILSEQ; - goto unmap; - } - } - } - end = strpbrk(off, "\r\n"); if (!end) { err = EILSEQ; goto unmap; } - len = strlen(key); str = malloc(end - off - len); if (!str) { err = EILSEQ; -- cgit From 632a9432774ff3a0c6e556e8f32a565b38890767 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 29 Oct 2005 22:36:31 +0000 Subject: Big cleanup of CVS relics --- common/textfile.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) (limited to 'common/textfile.c') diff --git a/common/textfile.c b/common/textfile.c index f15d439c..dd77980c 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -6,24 +6,19 @@ * * * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY - * CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, - * COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS - * SOFTWARE IS DISCLAIMED. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * - * - * $Id$ */ #ifdef HAVE_CONFIG_H -- cgit From db176529529c142333f668f2c1334753f7f406bf Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 9 Nov 2005 00:04:15 +0000 Subject: Include checks for mmap() returning NULL --- common/textfile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'common/textfile.c') diff --git a/common/textfile.c b/common/textfile.c index dd77980c..b2134562 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -149,7 +149,7 @@ int textfile_put(char *pathname, char *key, char *value) } map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED, fd, 0); - if (map == MAP_FAILED) { + if (!map || map == MAP_FAILED) { err = errno; goto unlock; } @@ -243,7 +243,7 @@ char *textfile_get(char *pathname, char *key) size = st.st_size; map = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); - if (map == MAP_FAILED) { + if (!map || map == MAP_FAILED) { err = errno; goto unlock; } -- cgit From f2e48c44a7e4c9ee31b8ce2e302186f6047cfeab Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 3 Jan 2006 13:28:56 +0000 Subject: Update copyright information --- common/textfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'common/textfile.c') diff --git a/common/textfile.c b/common/textfile.c index b2134562..906c230d 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2005 Marcel Holtmann + * Copyright (C) 2004-2006 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify -- cgit From 454c7500c64ab132f44aebbd7086a9748e5c4436 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 17 Jan 2006 10:52:35 +0000 Subject: Use MAP_PRIVATE instead of MAP_SHARED for textfile_put() --- common/textfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'common/textfile.c') diff --git a/common/textfile.c b/common/textfile.c index 906c230d..ec445b1a 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -148,7 +148,7 @@ int textfile_put(char *pathname, char *key, char *value) goto unlock; } - map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | 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; -- cgit From 71dc4067220c5b994885f63127b4b7eb947002fd Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 7 Feb 2006 09:10:07 +0000 Subject: Add support for deleting keys --- common/textfile.c | 48 +++++++++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 17 deletions(-) (limited to 'common/textfile.c') diff --git a/common/textfile.c b/common/textfile.c index ec445b1a..3aa74d9a 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -86,6 +86,17 @@ int create_file(char *filename, mode_t mode) return 0; } +static inline char *find_key(char *map, char *key, size_t len) +{ + char *off = strstr(map, key); + + while (off && ((off > map && *(off - 1) != '\r' && + *(off - 1) != '\n') || *(off + len) != ' ')) + off = strstr(off + len, key); + + return off; +} + static inline int write_key_value(int fd, char *key, char *value) { char *str; @@ -108,18 +119,7 @@ static inline int write_key_value(int fd, char *key, char *value) return err; } -static inline char *find_key(char *map, char *key, size_t len) -{ - char *off = strstr(map, key); - - while (off && ((off > map && *(off - 1) != '\r' && - *(off - 1) != '\n') || *(off + len) != ' ')) - off = strstr(off + len, key); - - return off; -} - -int textfile_put(char *pathname, char *key, char *value) +static int write_key(char *pathname, char *key, char *value) { struct stat st; char *map, *off, *end, *str; @@ -156,9 +156,11 @@ int textfile_put(char *pathname, char *key, char *value) off = find_key(map, key, strlen(key)); if (!off) { - munmap(map, size); - pos = lseek(fd, size, SEEK_SET); - err = write_key_value(fd, key, value); + if (value) { + munmap(map, size); + pos = lseek(fd, size, SEEK_SET); + err = write_key_value(fd, key, value); + } goto unlock; } @@ -178,7 +180,8 @@ int textfile_put(char *pathname, char *key, char *value) munmap(map, size); ftruncate(fd, base); pos = lseek(fd, base, SEEK_SET); - err = write_key_value(fd, key, value); + if (value) + err = write_key_value(fd, key, value); goto unlock; } @@ -198,7 +201,8 @@ int textfile_put(char *pathname, char *key, char *value) munmap(map, size); ftruncate(fd, base); pos = lseek(fd, base, SEEK_SET); - err = write_key_value(fd, key, value); + if (value) + err = write_key_value(fd, key, value); write(fd, str, len); @@ -219,6 +223,16 @@ close: return -err; } +int textfile_put(char *pathname, char *key, char *value) +{ + return write_key(pathname, key, value); +} + +int textfile_del(char *pathname, char *key) +{ + return write_key(pathname, key, NULL); +} + char *textfile_get(char *pathname, char *key) { struct stat st; -- cgit From 85cc0c57e4fd0e44c3b270aba4f87eb28151b1a2 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 8 Feb 2006 05:38:38 +0000 Subject: Add textfile_foreach() function --- common/textfile.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) (limited to 'common/textfile.c') 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; +} -- cgit From 2fa395ac7d4bd9d0108194c375bf69839f4d62ec Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 11 Feb 2006 12:12:27 +0000 Subject: Use const qualifier for textfile library --- common/textfile.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'common/textfile.c') diff --git a/common/textfile.c b/common/textfile.c index 2ed929a3..bb55109c 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -36,7 +36,7 @@ #include #include -int create_dirs(char *filename, mode_t mode) +int create_dirs(const char *filename, const mode_t mode) { struct stat st; char dir[PATH_MAX + 1], *prev, *next; @@ -70,7 +70,7 @@ int create_dirs(char *filename, mode_t mode) return 0; } -int create_file(char *filename, mode_t mode) +int create_file(const char *filename, const mode_t mode) { int fd; @@ -86,7 +86,7 @@ int create_file(char *filename, mode_t mode) return 0; } -static inline char *find_key(char *map, char *key, size_t len) +static inline char *find_key(char *map, const char *key, size_t len) { char *off = strstr(map, key); @@ -97,7 +97,7 @@ static inline char *find_key(char *map, char *key, size_t len) return off; } -static inline int write_key_value(int fd, char *key, char *value) +static inline int write_key_value(int fd, const char *key, const char *value) { char *str; size_t size; @@ -119,7 +119,7 @@ static inline int write_key_value(int fd, char *key, char *value) return err; } -static int write_key(char *pathname, char *key, char *value) +static int write_key(const char *pathname, const char *key, const char *value) { struct stat st; char *map, *off, *end, *str; @@ -223,17 +223,17 @@ close: return -err; } -int textfile_put(char *pathname, char *key, char *value) +int textfile_put(const char *pathname, const char *key, const char *value) { return write_key(pathname, key, value); } -int textfile_del(char *pathname, char *key) +int textfile_del(const char *pathname, const char *key) { return write_key(pathname, key, NULL); } -char *textfile_get(char *pathname, char *key) +char *textfile_get(const char *pathname, const char *key) { struct stat st; char *map, *off, *end, *str = NULL; @@ -297,7 +297,7 @@ close: return str; } -int textfile_foreach(char *pathname, +int textfile_foreach(const char *pathname, void (*func)(char *key, char *value, void *data), void *data) { struct stat st; -- cgit From 8bc26371882b7ebaaa25ca0c2ce81b1f719daeea Mon Sep 17 00:00:00 2001 From: Eduardo Rocha Date: Fri, 24 Mar 2006 14:36:27 +0000 Subject: Fix a SEGFAULT that happens when textfile_del is called using an empty file. --- common/textfile.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'common/textfile.c') diff --git a/common/textfile.c b/common/textfile.c index bb55109c..84a72b3c 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -143,8 +143,10 @@ static int write_key(const char *pathname, const char *key, const char *value) size = st.st_size; if (!size) { - pos = lseek(fd, size, SEEK_SET); - err = write_key_value(fd, key, value); + if (value) { + pos = lseek(fd, size, SEEK_SET); + err = write_key_value(fd, key, value); + } goto unlock; } -- cgit From 7d573c7ae14bbbb2d924837413879c71f8c385f4 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 30 Apr 2006 20:40:25 +0000 Subject: Include header file --- common/textfile.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'common/textfile.c') diff --git a/common/textfile.c b/common/textfile.c index 84a72b3c..7814513a 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -36,6 +36,8 @@ #include #include +#include "textfile.h" + int create_dirs(const char *filename, const mode_t mode) { struct stat st; -- cgit From f616523e5cdc65726d36dad404ed2f66a2fc8fd8 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 26 Jul 2006 12:53:48 +0000 Subject: Check return values of write() and ftruncate() --- common/textfile.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'common/textfile.c') diff --git a/common/textfile.c b/common/textfile.c index 7814513a..cdb42d13 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -182,10 +182,14 @@ static int write_key(const char *pathname, const char *key, const char *value) len = size - (end - map); if (!len) { munmap(map, size); - ftruncate(fd, base); + if (ftruncate(fd, base) < 0) { + err = errno; + goto unlock; + } pos = lseek(fd, base, SEEK_SET); if (value) err = write_key_value(fd, key, value); + goto unlock; } @@ -203,12 +207,16 @@ static int write_key(const char *pathname, const char *key, const char *value) memcpy(str, end, len); munmap(map, size); - ftruncate(fd, base); + if (ftruncate(fd, base) < 0) { + err = errno; + goto unlock; + } pos = lseek(fd, base, SEEK_SET); if (value) err = write_key_value(fd, key, value); - write(fd, str, len); + if (write(fd, str, len) < 0) + err = errno; free(str); -- cgit From ab767dcf7cf79a3411a5199b97b42e97ef80dbfc Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 26 Jul 2006 12:58:09 +0000 Subject: Add create_name() helper function --- common/textfile.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'common/textfile.c') diff --git a/common/textfile.c b/common/textfile.c index cdb42d13..076ec35b 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -88,6 +88,11 @@ int create_file(const char *filename, const mode_t mode) return 0; } +int create_name(char *buf, size_t size, char *address, char *name) +{ + return snprintf(buf, size, "%s/%s/%s", STORAGEDIR, address, name); +} + static inline char *find_key(char *map, const char *key, size_t len) { char *off = strstr(map, key); -- cgit From 86d19dcfa04879c863a1248851cd7854b68242cb Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 26 Jul 2006 13:03:13 +0000 Subject: Add a paramter for the path to create_name() --- common/textfile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'common/textfile.c') diff --git a/common/textfile.c b/common/textfile.c index 076ec35b..f8b9545e 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -88,9 +88,9 @@ int create_file(const char *filename, const mode_t mode) return 0; } -int create_name(char *buf, size_t size, char *address, char *name) +int create_name(char *buf, size_t size, const char *path, const char *address, const char *name) { - return snprintf(buf, size, "%s/%s/%s", STORAGEDIR, address, name); + return snprintf(buf, size, "%s/%s/%s", path, address, name); } static inline char *find_key(char *map, const char *key, size_t len) -- cgit From 406212bb1c90b4454167d0ed9984d4f6c6a4efe0 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 31 Aug 2006 08:31:39 +0000 Subject: Add textfile_caseget() function --- common/textfile.c | 51 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 18 deletions(-) (limited to 'common/textfile.c') diff --git a/common/textfile.c b/common/textfile.c index f8b9545e..d76398c4 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -25,6 +25,7 @@ #include #endif +#define _GNU_SOURCE #include #include #include @@ -93,13 +94,17 @@ 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) +static inline char *find_key(char *map, const char *key, size_t len, int icase) { - char *off = strstr(map, key); + char *off = (icase) ? strcasestr(map, key) : strstr(map, key); while (off && ((off > map && *(off - 1) != '\r' && - *(off - 1) != '\n') || *(off + len) != ' ')) - off = strstr(off + len, key); + *(off - 1) != '\n') || *(off + len) != ' ')) { + if (icase) + off = strcasestr(off + len, key); + else + off = strstr(off + len, key); + } return off; } @@ -126,7 +131,7 @@ static inline int write_key_value(int fd, const char *key, const char *value) return err; } -static int write_key(const char *pathname, const char *key, const char *value) +static int write_key(const char *pathname, const char *key, const char *value, int icase) { struct stat st; char *map, *off, *end, *str; @@ -163,7 +168,7 @@ static int write_key(const char *pathname, const char *key, const char *value) goto unlock; } - off = find_key(map, key, strlen(key)); + off = find_key(map, key, strlen(key), icase); if (!off) { if (value) { munmap(map, size); @@ -240,17 +245,7 @@ close: return -err; } -int textfile_put(const char *pathname, const char *key, const char *value) -{ - return write_key(pathname, key, value); -} - -int textfile_del(const char *pathname, const char *key) -{ - return write_key(pathname, key, NULL); -} - -char *textfile_get(const char *pathname, const char *key) +static char *read_key(const char *pathname, const char *key, int icase) { struct stat st; char *map, *off, *end, *str = NULL; @@ -280,7 +275,7 @@ char *textfile_get(const char *pathname, const char *key) } len = strlen(key); - off = find_key(map, key, len); + off = find_key(map, key, len, icase); if (!off) { err = EILSEQ; goto unmap; @@ -314,6 +309,26 @@ close: return str; } +int textfile_put(const char *pathname, const char *key, const char *value) +{ + return write_key(pathname, key, value, 0); +} + +int textfile_del(const char *pathname, const char *key) +{ + return write_key(pathname, key, NULL, 0); +} + +char *textfile_get(const char *pathname, const char *key) +{ + return read_key(pathname, key, 0); +} + +char *textfile_caseget(const char *pathname, const char *key) +{ + return read_key(pathname, key, 1); +} + int textfile_foreach(const char *pathname, void (*func)(char *key, char *value, void *data), void *data) { -- cgit From 50d400b1de38cbf75a2004a53e412dc6343d82bb Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 13 Sep 2006 14:58:58 +0000 Subject: Fix some memory leaks in textfile.c --- common/textfile.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'common/textfile.c') diff --git a/common/textfile.c b/common/textfile.c index d76398c4..8c46563c 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -219,6 +219,7 @@ static int write_key(const char *pathname, const char *key, const char *value, i munmap(map, size); if (ftruncate(fd, base) < 0) { err = errno; + free(str); goto unlock; } pos = lseek(fd, base, SEEK_SET); @@ -384,6 +385,7 @@ int textfile_foreach(const char *pathname, end = strpbrk(off, "\r\n"); if (!end) { err = EILSEQ; + free(key); break; } @@ -392,6 +394,7 @@ int textfile_foreach(const char *pathname, value = malloc(len + 1); if (!value) { err = errno; + free(key); break; } -- cgit From a59e6d0bdc38728c96254f589fa2e64f0542a8a8 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 7 Nov 2006 20:34:46 +0000 Subject: Add textfile_casedel() function --- common/textfile.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'common/textfile.c') diff --git a/common/textfile.c b/common/textfile.c index 8c46563c..795c99a3 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -320,6 +320,11 @@ int textfile_del(const char *pathname, const char *key) return write_key(pathname, key, NULL, 0); } +int textfile_casedel(const char *pathname, const char *key) +{ + return write_key(pathname, key, NULL, 1); +} + char *textfile_get(const char *pathname, const char *key) { return read_key(pathname, key, 0); -- cgit From 607695ed109340f4b7a5628420e0a8e8aee34f4e Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 13 Jan 2007 17:48:12 +0000 Subject: Update copyright information --- common/textfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'common/textfile.c') diff --git a/common/textfile.c b/common/textfile.c index 795c99a3..36bde03f 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2006 Marcel Holtmann + * Copyright (C) 2004-2007 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify -- cgit From 6561447cafc0b9a857094c8aa43c0aeb0aa7adb2 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 21 Jan 2007 18:01:39 +0000 Subject: Check if value has changed before writing it --- common/textfile.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'common/textfile.c') diff --git a/common/textfile.c b/common/textfile.c index 36bde03f..895e3f3d 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -168,7 +168,8 @@ static int write_key(const char *pathname, const char *key, const char *value, i goto unlock; } - off = find_key(map, key, strlen(key), icase); + len = strlen(key); + off = find_key(map, key, len, icase); if (!off) { if (value) { munmap(map, size); @@ -186,6 +187,10 @@ static int write_key(const char *pathname, const char *key, const char *value, i goto unmap; } + if (value && (strlen(value) == end - off - len - 1) && + !strncmp(off + len + 1, value, end - off - len - 1)) + goto unmap; + len = strspn(end, "\r\n"); end += len; -- cgit From d9aa4a2058eace37d5c2d15508b4c4d9962c2bb5 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 26 Feb 2007 20:48:15 +0000 Subject: Add textfile_caseput function --- common/textfile.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'common/textfile.c') diff --git a/common/textfile.c b/common/textfile.c index 895e3f3d..ea7e80bb 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -320,6 +320,11 @@ int textfile_put(const char *pathname, const char *key, const char *value) return write_key(pathname, key, value, 0); } +int textfile_caseput(const char *pathname, const char *key, const char *value) +{ + return write_key(pathname, key, value, 1); +} + int textfile_del(const char *pathname, const char *key) { return write_key(pathname, key, NULL, 0); -- cgit From 48ce703ca92056265f6f036f42c8f8843700d15f Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 26 Nov 2007 11:52:16 +0000 Subject: Fix key search function to honor the mmap area size --- common/textfile.c | 54 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 14 deletions(-) (limited to 'common/textfile.c') 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 #include +#include #include #include #include @@ -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; -- cgit From e823c15e43a6f924779e466d434c51157002d9ee Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 2 Feb 2008 03:37:05 +0000 Subject: Update copyright information --- common/textfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'common/textfile.c') diff --git a/common/textfile.c b/common/textfile.c index 88e783a8..021fc8fb 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -2,7 +2,7 @@ * * BlueZ - Bluetooth protocol stack for Linux * - * Copyright (C) 2004-2007 Marcel Holtmann + * Copyright (C) 2004-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify -- cgit From 45c36dbd276501aa76d9798a8fafe6c202db7276 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 11 Jun 2008 13:20:50 +0000 Subject: Avoid direct inclusion of malloc.h --- common/textfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'common/textfile.c') diff --git a/common/textfile.c b/common/textfile.c index 021fc8fb..eef0f96a 100644 --- a/common/textfile.c +++ b/common/textfile.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include #include -- cgit