3 * BlueZ - Bluetooth protocol stack for Linux
5 * Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
39 #include <sys/param.h>
43 int create_dirs(const char *filename, const mode_t mode)
46 char dir[PATH_MAX + 1], *prev, *next;
49 err = stat(filename, &st);
50 if (!err && S_ISREG(st.st_mode))
53 memset(dir, 0, PATH_MAX + 1);
56 prev = strchr(filename, '/');
59 next = strchr(prev + 1, '/');
63 if (next - prev == 1) {
68 strncat(dir, prev + 1, next - prev);
77 int create_file(const char *filename, const mode_t mode)
81 umask(S_IWGRP | S_IWOTH);
82 create_dirs(filename, S_IRUSR | S_IWUSR | S_IXUSR |
83 S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
85 fd = open(filename, O_RDWR | O_CREAT, mode);
94 int create_name(char *buf, size_t size, const char *path, const char *address, const char *name)
96 return snprintf(buf, size, "%s/%s/%s", path, address, name);
99 static inline char *find_key(char *map, size_t size, const char *key, size_t len, int icase)
102 size_t ptrlen = size;
104 while (ptrlen > len + 1) {
105 int cmp = (icase) ? strncasecmp(ptr, key, len) : strncmp(ptr, key, len);
110 if ((*(ptr - 1) == '\r' || *(ptr - 1) == '\n') &&
116 char *p1 = memchr(ptr + 1, tolower(*key), ptrlen - 1);
117 char *p2 = memchr(ptr + 1, toupper(*key), ptrlen - 1);
124 ptr = (p1 < p2) ? p1 : p2;
126 ptr = memchr(ptr + 1, *key, ptrlen - 1);
131 ptrlen = size - (ptr - map);
137 static inline int write_key_value(int fd, const char *key, const char *value)
143 size = strlen(key) + strlen(value) + 2;
145 str = malloc(size + 1);
149 sprintf(str, "%s %s\n", key, value);
151 if (write(fd, str, size) < 0)
159 static char *strnpbrk(const char *s, ssize_t len, const char *accept)
166 while (p <= end && *p) {
167 const char *a = accept;
181 static int write_key(const char *pathname, const char *key, const char *value, int icase)
184 char *map, *off, *end, *str;
187 int fd, len, err = 0;
189 fd = open(pathname, O_RDWR);
193 if (flock(fd, LOCK_EX) < 0) {
198 if (fstat(fd, &st) < 0) {
207 lseek(fd, size, SEEK_SET);
208 err = write_key_value(fd, key, value);
213 map = mmap(NULL, size, PROT_READ | PROT_WRITE,
214 MAP_PRIVATE | MAP_LOCKED, fd, 0);
215 if (!map || map == MAP_FAILED) {
221 off = find_key(map, size, key, len, icase);
225 lseek(fd, size, SEEK_SET);
226 err = write_key_value(fd, key, value);
233 end = strnpbrk(off, size, "\r\n");
239 if (value && ((ssize_t) strlen(value) == end - off - len - 1) &&
240 !strncmp(off + len + 1, value, end - off - len - 1))
243 len = strspn(end, "\r\n");
246 len = size - (end - map);
249 if (ftruncate(fd, base) < 0) {
253 lseek(fd, base, SEEK_SET);
255 err = write_key_value(fd, key, value);
260 if (len < 0 || len > size) {
271 memcpy(str, end, len);
274 if (ftruncate(fd, base) < 0) {
279 lseek(fd, base, SEEK_SET);
281 err = write_key_value(fd, key, value);
283 if (write(fd, str, len) < 0)
305 static char *read_key(const char *pathname, const char *key, int icase)
308 char *map, *off, *end, *str = NULL;
309 off_t size; size_t len;
312 fd = open(pathname, O_RDONLY);
316 if (flock(fd, LOCK_SH) < 0) {
321 if (fstat(fd, &st) < 0) {
328 map = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
329 if (!map || map == MAP_FAILED) {
335 off = find_key(map, size, key, len, icase);
341 end = strnpbrk(off, size - (map - off), "\r\n");
347 str = malloc(end - off - len);
353 memset(str, 0, end - off - len);
354 strncpy(str, off + len + 1, end - off - len - 1);
369 int textfile_put(const char *pathname, const char *key, const char *value)
371 return write_key(pathname, key, value, 0);
374 int textfile_caseput(const char *pathname, const char *key, const char *value)
376 return write_key(pathname, key, value, 1);
379 int textfile_del(const char *pathname, const char *key)
381 return write_key(pathname, key, NULL, 0);
384 int textfile_casedel(const char *pathname, const char *key)
386 return write_key(pathname, key, NULL, 1);
389 char *textfile_get(const char *pathname, const char *key)
391 return read_key(pathname, key, 0);
394 char *textfile_caseget(const char *pathname, const char *key)
396 return read_key(pathname, key, 1);
399 int textfile_foreach(const char *pathname, textfile_cb func, void *data)
402 char *map, *off, *end, *key, *value;
403 off_t size; size_t len;
406 fd = open(pathname, O_RDONLY);
410 if (flock(fd, LOCK_SH) < 0) {
415 if (fstat(fd, &st) < 0) {
422 map = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
423 if (!map || map == MAP_FAILED) {
430 while (size - (off - map) > 0) {
431 end = strnpbrk(off, size - (off - map), " ");
439 key = malloc(len + 1);
445 memset(key, 0, len + 1);
446 memcpy(key, off, len);
450 if (size - (off - map) < 0) {
456 end = strnpbrk(off, size - (off - map), "\r\n");
465 value = malloc(len + 1);
472 memset(value, 0, len + 1);
473 memcpy(value, off, len);
475 func(key, value, data);