⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 textfile.c

📁 Linux的蓝牙操作工具。配合bluez-lib使用
💻 C
字号:
/* * *  BlueZ - Bluetooth protocol stack for Linux * *  Copyright (C) 2004-2007  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 <malloc.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, 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) {		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:	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;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -