/*
 *
 *  BlueZ - Bluetooth protocol stack for Linux
 *
 *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
 *
 *
 *  This program is free software; you can redistribute it and/or modify
 *  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.
 *
 *  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.
 *
 *  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
 *
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/param.h>

#include "textfile.h"

static int create_dirs(const char *filename, const 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(const char *filename, const mode_t mode)
{
	int fd;

	create_dirs(filename, S_IRUSR | S_IWUSR | S_IXUSR);

	fd = open(filename, O_RDWR | O_CREAT, mode);
	if (fd < 0)
		return fd;

	close(fd);

	return 0;
}

int create_name(char *buf, size_t size, const char *path, const char *address, const char *name)
{
	return snprintf(buf, size, "%s/%s/%s", path, address, name);
}

static inline char *find_key(char *map, size_t size, const char *key, size_t len, int icase)
{
	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 NULL;
}

static inline int write_key_value(int fd, const char *key, const char *value)
{
	char *str;
	size_t size;
	int err = 0;

	size = strlen(key) + strlen(value) + 2;

	str = malloc(size + 1);
	if (!str)
		return ENOMEM;

	sprintf(str, "%s %s\n", key, value);

	if (write(fd, str, size) < 0)
		err = -errno;

	free(str);

	return err;
}

static char *strnpbrk(const char *s, ssize_t len, const char *accept)
{
	const char *p = s;
	const char *end;

	end = s + len - 1;

	while (p <= end && *p) {
		const char *a = accept;

		while (*a) {
			if (*p == *a)
				return (char *) p;
			a++;
		}

		p++;
	}

	return NULL;
}

static int write_key(const char *pathname, const char *key, const char *value, int icase)
{
	struct stat st;
	char *map, *off, *end, *str;
	off_t size;
	size_t base;
	int fd, len, 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) {
		if (value) {
			lseek(fd, size, SEEK_SET);
			err = write_key_value(fd, key, value);
		}
		goto unlock;
	}

	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, size, key, len, icase);
	if (!off) {
		munmap(map, size);
		if (value) {
			lseek(fd, size, SEEK_SET);
			err = write_key_value(fd, key, value);
		}
		goto unlock;
	}

	base = off - map;

	end = strnpbrk(off, size, "\r\n");
	if (!end) {
		err = -EILSEQ;
		goto unmap;
	}

	if (value && ((ssize_t) strlen(value) == end - off - len - 1) &&
			!strncmp(off + len + 1, value, end - off - len - 1))
		goto unmap;

	len = strspn(end, "\r\n");
	end += len;

	len = size - (end - map);
	if (!len) {
		munmap(map, size);
		if (ftruncate(fd, base) < 0) {
			err = -errno;
			goto unlock;
		}
		lseek(fd, base, SEEK_SET);
		if (value)
			err = write_key_value(fd, key, value);

		goto unlock;
	}

	if (len < 0 || len > size) {
		err = -EILSEQ;
		goto unmap;
	}

	str = malloc(len);
	if (!str) {
		err = -errno;
		goto unmap;
	}

	memcpy(str, end, len);

	munmap(map, size);
	if (ftruncate(fd, base) < 0) {
		err = -errno;
		free(str);
		goto unlock;
	}
	lseek(fd, base, SEEK_SET);
	if (value)
		err = write_key_value(fd, key, value);

	if (write(fd, str, len) < 0)
		err = -errno;

	free(str);

	goto unlock;

unmap:
	munmap(map, size);

unlock:
	flock(fd, LOCK_UN);

close:
	fdatasync(fd);

	close(fd);
	errno = -err;

	return err;
}

static char *read_key(const char *pathname, const char *key, int icase)
{
	struct stat st;
	char *map, *off, *end, *str = NULL;
	off_t size; size_t len;
	int fd, err = 0;

	fd = open(pathname, O_RDONLY);
	if (fd < 0)
		return NULL;

	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;
	}

	len = strlen(key);
	off = find_key(map, size, key, len, icase);
	if (!off) {
		err = -EILSEQ;
		goto unmap;
	}

	end = strnpbrk(off, size - (map - off), "\r\n");
	if (!end) {
		err = -EILSEQ;
		goto unmap;
	}

	str = malloc(end - off - len);
	if (!str) {
		err = -EILSEQ;
		goto unmap;
	}

	memset(str, 0, end - off - len);
	strncpy(str, off + len + 1, end - off - len - 1);

unmap:
	munmap(map, size);

unlock:
	flock(fd, LOCK_UN);

close:
	close(fd);
	errno = -err;

	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);
}

int textfile_foreach(const char *pathname, textfile_cb func, 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 (size - (off - map) > 0) {
		end = strnpbrk(off, size - (off - map), " ");
		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;

		if (size - (off - map) < 0) {
			err = -EILSEQ;
			free(key);
			break;
		}

		end = strnpbrk(off, size - (off - map), "\r\n");
		if (!end) {
			err = -EILSEQ;
			free(key);
			break;
		}

		len = end - off;

		value = malloc(len + 1);
		if (!value) {
			err = -errno;
			free(key);
			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;
}
