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

📄 db_api.c

📁 PIXIL is a small footprint operating environment, complete with PDA PIM applications, a browser and
💻 C
字号:
/*                                                                        * Copyright (c) 2003 Century Software, Inc.   All Rights Reserved.      *                                                                        * This file is part of the PIXIL Operating Environment                  *                                                                        * The use, copying and distribution of this file is governed by one     * of two licenses, the PIXIL Commercial License, or the GNU General     * Public License, version 2.                                            *                                                                        * Licensees holding a valid PIXIL Commercial License may use this file  * in accordance with the PIXIL Commercial License Agreement provided    * with the Software. Others are governed under the terms of the GNU    * General Public License version 2.                                     *                                                                        * This file may be distributed and/or modified under the terms of the   * GNU General Public License version 2 as published by the Free         * Software Foundation and appearing in the file LICENSE.GPL included    * in the packaging of this file.                                       *                                                                        * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING   * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A             * PARTICULAR PURPOSE.                                                   *                                                                        * RESTRICTED RIGHTS LEGEND                                              *                                                                      * Use, duplication, or disclosure by the government is subject to       * restriction as set forth in paragraph (b)(3)(b) of the Rights in      * Technical Data and Computer Software clause in DAR 7-104.9(a).        *                                                                       * See http://www.pixil.org/gpl/ for GPL licensing        * information.                                                          *                                                                       * See http://www.pixil.org/license.html or               * email cetsales@centurysoftware.com for information about the PIXIL    * Commercial License Agreement, or if any conditions of this licensing  * are not clear to you.                                                 */#include <stdlib.h>#include <string.h>#include <unistd.h>#include <fcntl.h>#include <errno.h>#include <sys/types.h>#include <sys/stat.h>#include <par/pardb.h>#include "database.h"/* This is the global error code variable */int pardb_errno = PARDB_SUCCESS;/* Add a new node to the system */intdb_addNode(db_handle * db, char *name, void *data, unsigned short size,	   unsigned short type){    int ret = 0;    char *localname, *pointer, *keyword;    index_t *index = 0, *prev = 0;    if (db_getAccess(db) != PAR_DB_MODE_RW) {	SET_ERRNO(PARDB_BADMODE);	return (-1);    }    /* Lock the whole database at this point */    /* And set the system up for writing     */    db_lockDB(db);    db_setMode(db, PAR_DB_WRITE_BLOCK);    index = db_getFirstIndex(db);    /* The recursive function will mangle the name */    /* so we need to save a backup */    localname = (char *) malloc(strlen(name) + 1);    pointer = strcpy(localname, name);    /* The first keyword is the toplevel */    keyword = strip_keyword(&pointer);    /* Find the correct toplevel node */    while (index) {	if (index->keyword[0] == 0)	    break;	if (strcmp(index->keyword, keyword) == 0) {	    if (pointer)		ret = db_recursiveAdd(db, index, pointer, data, size, type);	    else		ret = db_setData(db, index, data, size, type);	    free(localname);	    /* Ensure that all of the open write blocks are freed at this point */	    db_flushWrite(db);	    db_setMode(db, PAR_DB_READ_BLOCK);	    db_unlockDB(db);	    return (ret);	}	prev = index;	index = db_getPeer(db, index);    }    if (!prev)	index = db_addFirstIndex(db, keyword);    else	index = db_addPeer(db, prev, keyword);    if (!index)	return (-1);    if (pointer)	ret = db_recursiveAdd(db, index, pointer, data, size, type);    else	ret = db_setData(db, index, data, size, type);    free(localname);    db_flushWrite(db);    db_setMode(db, PAR_DB_READ_BLOCK);    db_unlockDB(db);    return (ret);}static index_t *db_getNode(db_handle * db, char *name){    char *local = name, *keyword;    index_t *index = db_getFirstIndex(db);    /* Find the toplevel node */    keyword = strip_keyword(&local);    while (index) {	if (strcmp(index->keyword, keyword) == 0) {	    if (local)		return (db_recursiveFind(db, index, local));	    else {		SET_ERRNO(PARDB_SUCCESS);		return (index);	    }	}	index = db_getPeer(db, index);    }    SET_ERRNO(PARDB_NOTFOUND);    return (0);}intdb_getChildCount(db_handle * db, char *parent){    index_t *child, *index;    int count = 0;    char *localname = (char *) malloc(strlen(parent) + 1);    strcpy(localname, parent);    index = db_getNode(db, localname);    free(localname);    if (!index)	return (-1);    child = db_getChild(db, index);    while (child) {	count++;	child = db_getPeer(db, child);    }    return (count);}intdb_getChildList(db_handle * db, char *parent, char **list, int maxsize){    int count = 0;    index_t *child, *index;    char *localname = (char *) malloc(strlen(parent) + 1);    strcpy(localname, parent);    index = db_getNode(db, localname);    free(localname);    child = db_getChild(db, index);    while (child && count < maxsize) {	list[count] = (char *) calloc(strlen(child->keyword) + 1, 1);	if (!list[count])	    return (-1);	strcpy(list[count], child->keyword);	child = db_getPeer(db, child);	count++;    }    return (count);}intdb_getFirstChild(db_handle * db, char *parent, char *name, int size){    int csize;    index_t *index, *child;    char *localname = (char *) malloc(strlen(parent) + 1);    strcpy(localname, parent);    index = db_getNode(db, localname);    free(localname);    if (!index)	return (-1);    child = db_getChild(db, index);    if (!child)	return (0);    if (size > strlen(child->keyword))	csize = strlen(child->keyword);    else	csize = size;    strncpy(name, child->keyword, csize);    return (size);}intdb_getNextChild(db_handle * db, char *parent, char *child, char *name,		int size){    index_t *index, *cindex;    char *localname = (char *) malloc(strlen(parent) + 1);    strcpy(localname, parent);    index = db_getNode(db, localname);    free(localname);    if (!index)	return (-1);    cindex = db_getChild(db, index);    while (cindex) {	int csize;	if (strcmp(cindex->keyword, child) == 0) {	    cindex = db_getPeer(db, cindex);	    if (!cindex)		return (0);	    if (size > strlen(cindex->keyword))		csize = strlen(cindex->keyword);	    else		csize = size;	    strncpy(name, cindex->keyword, csize);	    return (size);	}	cindex = db_getPeer(db, cindex);    }    return (0);}/* Search the database for the specified node */intdb_findNode(db_handle * db, char *name, void *data,	    unsigned short size, unsigned short *type){    index_t *index;    char *localname;    /* Save the name because we will mangle it */    localname = (char *) malloc(strlen(name) + 1);    strcpy(localname, name);    index = db_getNode(db, localname);    free(localname);    if (!index) {	SET_ERRNO(PARDB_NOTFOUND);	return (-1);    }    return (db_getData(db, index, data, size, type));}intdb_nodeExists(db_handle * db, char *name){    index_t *index;    char *localname;    /* Save the name because we will mangle it */    localname = (char *) malloc(strlen(name) + 1);    strcpy(localname, name);    index = db_getNode(db, localname);    free(localname);    if (!index)	return (0);    return (1);}db_handle *db_newDB(char *filename, int open_mode){    int mode = 0;    int perm = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;    db_info_t *info;    db_handle *local;    void *index, *data;    int fd, offset;    /* Get the optimal block size for this system */    int blkSize = getpagesize();    /* Create the exclusive file, and give it user and group write access */    if (mode == PAR_DB_EXCLUSIVE)	mode = O_RDWR | O_CREAT | O_EXCL;    else	mode = O_RDWR | O_CREAT | O_TRUNC;    fd = open(filename, mode, perm);    /* Set the appropriate error code */    if (!fd) {	switch (errno) {	case EEXIST:	    SET_ERRNO(PARDB_FILEEXISTS);	    break;	case EACCES:	    SET_ERRNO(PARDB_FILEACCESS);	    break;	default:	    SET_ERRNO(PARDB_FILEERR);	    break;	}	return (0);    }    /* Allocate the database structure */    if (!(local = db_allocDB(fd, blkSize, 0))) {	close(fd);	return (0);    }    /* When a new database is created, it is always read/write */    db_setAccess(local, PAR_DB_MODE_RW);    /* Lock it to be on the safe side */    db_lockDB(local);    db_setMode(local, PAR_DB_WRITE_BLOCK);    /* Create and map the first index block */    if ((offset = db_addBlock(local)) == -1)	goto exitNewDB;    if (!(index = db_mapBlock(local, offset)))	goto exitNewDB;    /* Now, add the inital header stuff for the first index block */    info = (db_info_t *) index;    info->magic = PARDB_MAGIC;    info->blksize = blkSize;    info->index = sizeof(db_info_t);    if ((info->data = db_addBlock(local)) == -1)	goto exitNewDB;    if (!(data = db_mapBlock(local, info->data)))	goto exitNewDB;    /* Next, format the first index and data blocks */    db_formatIndex(local, index, sizeof(db_info_t),		   blkSize - sizeof(db_info_t));    db_formatData(local, data, 0, blkSize);    local->index = info->index;    local->data = info->data;    db_flushWrite(local);    db_setMode(local, PAR_DB_READ_BLOCK);    db_unlockDB(local);    SET_ERRNO(PARDB_SUCCESS);    return (local);  exitNewDB:    db_freeDB(local);    close(fd);    /* The errno will be set by the appropriate call */    return (0);}db_handle *db_openDB(char *filename, unsigned short mode){    db_handle *local;    db_info_t info;    int fd;    struct stat statt;    /* Stat the file, make sure it exists and get a maximum file size */    if (stat(filename, &statt) < 0) {	SET_ERRNO(PARDB_NOFILE);	return (0);    }    /* Open the file */    if (mode == PAR_DB_MODE_RW)	fd = open(filename, O_RDWR);    else	fd = open(filename, O_RDONLY);    if (!fd) {	SET_ERRNO(PARDB_FILEERR);	return (0);    }    /* Read the first index info block */    if (read(fd, &info, sizeof(info)) == -1) {	SET_ERRNO(PARDB_IOERR);	close(fd);	return (0);    }    if (info.magic != PARDB_MAGIC) {	SET_ERRNO(PARDB_BADDB);	close(fd);	return (0);    }    /* Allocate the database structure */    if (!(local = db_allocDB(fd, info.blksize, statt.st_size))) {	close(fd);	return (0);    }    /* Set the pointers to the data */    local->index = info.index;    local->data = info.data;    db_setAccess(local, mode);    db_setMode(local, PAR_DB_READ_BLOCK);    SET_ERRNO(PARDB_SUCCESS);    return (local);}voiddb_closeDB(db_handle * db){    int i;    if (!db)	return;    /* Close the database */    /* First step, unmap all the mapped items */    for (i = 0; i < db->mapSize; i++)	if (db->map[i].addr)	    db_unmapBlock(db, i);    free(db->map);    close(db->fd);    free(db);}/* Search the database for the specified node */intdb_delNode(db_handle * db, char *name){    char *localname, *pointer, *keyword;    index_t *index = 0, *prev = 0;    if (db_getAccess(db) != PAR_DB_MODE_RW) {	SET_ERRNO(PARDB_BADMODE);	return (-1);    }    /* Lock the DB while we are doing this */    db_lockDB(db);    db_setMode(db, PAR_DB_WRITE_BLOCK);    index = db_getFirstIndex(db);    /* Save the name because we will mangle it */    localname = (char *) malloc(strlen(name) + 1);    pointer = strcpy(localname, name);    /* Find the toplevel node */    keyword = strip_keyword(&pointer);    while (index) {	if (strcmp(index->keyword, keyword) == 0) {	    if (pointer)		db_recursiveDel(db, index, pointer);	    else {		index_t *peer = db_getPeer(db, index);		db_removeIndex(db, index);		if (prev)		    db_setPeer(db, prev, peer);	    }	    db_flushWrite(db);	    db_setMode(db, PAR_DB_READ_BLOCK);	    db_unlockDB(db);	    free(localname);	    return (0);	}	prev = index;	index = db_getPeer(db, index);    }    db_flushWrite(db);    db_setMode(db, PAR_DB_READ_BLOCK);    db_unlockDB(db);    free(localname);    return (0);}/* Random utility functions */char *db_getDefaultDB(void){    char *ptr = getenv("PARDB");    return ptr ? ptr : DEFPARDB;}intdb_getDataSize(db_handle * db, char *name){    unsigned short size = 0;    index_t *index;    char *localname = (char *) malloc(strlen(name) + 1);    strcpy(localname, name);    index = db_getNode(db, localname);    free(localname);    if (!index)	return (-1);    if (db_getDataInfo(db, index, &size, 0) == -1)	return (-1);    else	return (size);}tree_t *db_newTree(tree_t ** head){    *head = tree_newTree();    return (*head);}voiddb_freeTree(tree_t * tree){    tree_recursiveFree(tree);}/* Load the entire database into a tree *//* The top node in the tree is just a place holder to unify *//* all of the various toplevel nodes */intdb_loadTree(db_handle * db, tree_t * head){    return (tree_recursiveBuild(db, db_getFirstIndex(db), head));}/* Save a tree into the database file */intdb_saveTree(db_handle * db, tree_t * head){    int ret;    tree_t *child = head->child;    if (db_getAccess(db) != PAR_DB_MODE_RW) {	SET_ERRNO(PARDB_BADMODE);	return (-1);    }    if (!child)	return (-1);    db_lockDB(db);    db_setMode(db, PAR_DB_WRITE_BLOCK);    ret = tree_recursiveSave(db, child, 0);    db_flushWrite(db);    db_setMode(db, PAR_DB_READ_BLOCK);    db_unlockDB(db);    return (ret);}

⌨️ 快捷键说明

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