/*
 *
 *  BlueZ - Bluetooth protocol stack for Linux
 *
 *  Copyright (C) 2004-2008  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

#define _GNU_SOURCE
#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"

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;

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

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 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, pos; 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) {
			pos = 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) {
		if (value) {
			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;
	}

	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;

	len = size - (end - map);
	if (!len) {
		munmap(map, size);
		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;
	}

	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;
	}
	pos = 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 = strpbrk(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_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);
}

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

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