Пример #1
0
 bool write_key_values(size_t count, const key_value* key_values)
 {
     bool result = true;
     while (count-->0) {
         result = result && write_key_value(key_values++);
     }
     return result;
 }
Пример #2
0
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;
}