dslinux/user/pixil/sys/par/lib Makefile data.c database.c database.h db_api.c index.c io.c par_api.c tree.c
amadeus
dslinux_amadeus at user.in-berlin.de
Tue Oct 3 13:27:10 CEST 2006
Update of /cvsroot/dslinux/dslinux/user/pixil/sys/par/lib
In directory antilope:/tmp/cvs-serv11916/sys/par/lib
Added Files:
Makefile data.c database.c database.h db_api.c index.c io.c
par_api.c tree.c
Log Message:
adding pristine copy of pixil to HEAD so I can branch from it
--- NEW FILE: database.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 at 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 <errno.h>
#include <par/pardb.h>
#include "database.h"
/* A local function used to grab the name off the top of the list */
char *
strip_keyword(char **name)
{
char *keyword = *name;
char *ptr = strchr(*name, '.');
if (!ptr) {
*name = 0;
} else {
*ptr = 0;
*name = ptr + 1;
if (!*name)
*name = 0;
}
return (keyword);
}
/* Recursively add the node (and any non existent parent nodes) to the database */
int
db_recursiveAdd(db_handle * db, index_t * parent, char *name,
void *data, ushort size, ushort type)
{
int ret;
char *pointer = name;
char *keyword = strip_keyword(&pointer);
index_t *index = db_getChild(db, parent);
index_t *prev = 0;
while (index) {
if (strcmp(index->keyword, keyword) == 0) {
/* If the node already exists, then just set the data and bail */
if (!pointer) {
ret = db_setData(db, index, data, size, type);
} else {
ret = db_recursiveAdd(db, index, pointer, data, size, type);
}
return (ret);
}
prev = index;
index = db_getPeer(db, index);
}
/* If we get this far, the node doesn't exist */
if (!prev) {
index = db_addChild(db, parent, keyword);
} else {
index = db_addPeer(db, prev, keyword);
}
if (!index)
return (-1);
if (!pointer) {
ret = db_setData(db, index, data, size, type);
} else
ret = db_recursiveAdd(db, index, pointer, data, size, type);
return (ret);
}
/* Recursively search the database looking for the named node */
index_t *
db_recursiveFind(db_handle * db, index_t * parent, char *name)
{
char *pointer = name;
char *keyword = strip_keyword(&pointer);
index_t *index = db_getChild(db, parent);
while (index) {
if (strcmp(index->keyword, keyword) == 0) {
/* Found it, return the node */
if (!pointer) {
SET_ERRNO(PARDB_SUCCESS);
return (index);
}
/* Move down a level */
return (db_recursiveFind(db, index, pointer));
}
index = db_getPeer(db, index);
}
SET_ERRNO(PARDB_NOTFOUND);
return (0);
}
static void
db_recursiveKill(db_handle * db, index_t * parent)
{
index_t *index = db_getChild(db, parent);
index_t *next = 0;
while (index) {
db_recursiveKill(db, index);
next = db_getPeer(db, index);
db_removeIndex(db, index); /* Kill the index and data */
index = next;
}
}
/* Recursively search the database looking for the named node */
/* When found, kill the entire tree below it and remove this */
/* node from the chain */
int
db_recursiveDel(db_handle * db, index_t * parent, char *name)
{
char *pointer = name;
char *keyword = strip_keyword(&pointer);
index_t *index = db_getChild(db, parent);
index_t *prev = 0;
while (index) {
if (strcmp(index->keyword, keyword) == 0) {
/* Once we find the pointer, then we recursively kill everything below it */
if (!pointer) {
db_recursiveKill(db, index);
if (prev)
db_setPeer(db, prev, db_getPeer(db, index));
else
db_setChild(db, prev, db_getPeer(db, index));
db_removeIndex(db, index); /* Kill the "parent" of the doomed tree */
return (0);
}
/* Move down a level */
return (db_recursiveDel(db, index, pointer));
}
prev = index;
index = db_getPeer(db, index);
}
SET_ERRNO(PARDB_SUCCESS);
return (0);
}
void
db_freeDB(db_handle * db)
{
int i;
if (!db)
return;
for (i = 0; i < db->mapSize; i++)
db_unmapBlock(db, i);
free(db->map);
free(db);
}
db_handle *
db_allocDB(int fd, int bsize, int length)
{
db_handle *local;
if (!(local = (db_handle *) calloc(sizeof(db_handle), 1))) {
SET_ERRNO(PARDB_MEMERR);
return (0);
}
local->fd = fd;
local->blkSize = bsize;
local->length = length;
if (!length) {
/* Make the inital hash */
local->map = (db_map_t *) calloc(16 * sizeof(db_map_t), 1);
if (!local->map) {
free(local);
SET_ERRNO(PARDB_MEMERR);
return (0);
}
local->mapSize = 16;
} else {
/* Alloate only enough items to hold the database */
local->map =
(db_map_t *) calloc((length / bsize) * sizeof(db_map_t), 1);
if (!local->map) {
free(local);
SET_ERRNO(PARDB_MEMERR);
return (0);
}
local->mapSize = (length / bsize);
}
SET_ERRNO(PARDB_SUCCESS);
return (local);
}
--- NEW FILE: io.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 at centurysoftware.com for information about the PIXIL
* Commercial License Agreement, or if any conditions of this licensing
* are not clear to you.
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <par/pardb.h>
#include "database.h"
#define CALC_BLOCK_NUM(db, offset) (offset / db->blkSize)
/* db_mapBlock() */
/* Given an offset into the file, either map it,
or return the address of a previous mapping
*/
void *
db_mapBlock(db_handle * db, int offset)
{
int bnum = CALC_BLOCK_NUM(db, offset);
int i, mode;
if (offset >= db->length) {
SET_ERRNO(PARDB_BADOFFSET);
return (0);
}
if (bnum >= db->mapSize) {
db_map_t *temp =
(db_map_t *) realloc(db->map, (bnum + 8) * sizeof(db_map_t));
if (!temp) {
SET_ERRNO(PARDB_MEMERR);
return (0);
}
db->map = temp;
/* Zero the new items */
for (i = db->mapSize; i < bnum + 8; i++)
bzero(&db->map[i], sizeof(db_map_t));
db->mapSize = bnum + 8;
}
if (db->map[bnum].addr && db->map[bnum].mode == db->mode) {
db->map[bnum].usage++;
SET_ERRNO(PARDB_SUCCESS);
return (db->map[bnum].addr);
}
if (db->map[bnum].addr && db->map[bnum].usage) {
SET_ERRNO(PARDB_BLOCKINUSE);
return (0);
}
/* Map the block */
if (db->mode == PAR_DB_READ_BLOCK || db->access == PAR_DB_MODE_RDONLY)
mode = PROT_READ;
else
mode = PROT_READ | PROT_WRITE;
#ifndef HAVE_MMAPBUG
db->map[bnum].addr =
mmap(0, db->blkSize, mode, MAP_SHARED, db->fd, db->blkSize * bnum);
#else
if (db->mode == PAR_DB_READ_BLOCK)
db->map[bnum].addr = mmap(0, db->blkSize, mode,
MAP_SHARED, db->fd, db->blkSize * bnum);
else {
int ret;
db->map[bnum].addr = (void *) malloc(db->blkSize);
if (db->map[bnum].addr) {
lseek(db->fd, db->blkSize * bnum, SEEK_SET);
ret =
read(db->fd, (unsigned char *) db->map[bnum].addr,
db->blkSize);
if (ret != db->blkSize)
db->map[bnum].addr = MAP_FAILED;
} else
db->map[bnum].addr = MAP_FAILED;
}
#endif
if (db->map[bnum].addr == MAP_FAILED) {
bzero(&db->map[bnum], sizeof(db_map_t));
SET_ERRNO(PARDB_BADMAP);
return (0);
}
db->map[bnum].mode = db->mode;
db->map[bnum].usage = 1;
SET_ERRNO(PARDB_SUCCESS);
return (db->map[bnum].addr);
}
void
db_unmapBlock(db_handle * db, int block)
{
if (db->map[block].usage > 0)
db->map[block].usage--;
if (db->map[block].addr && !db->map[block].usage) {
#ifndef HAVE_MMAPBUG
munmap(db->map[block].addr, db->blkSize);
#else
if (db->map[block].mode == PAR_DB_READ_BLOCK)
munmap(db->map[block].addr, db->blkSize);
else {
int ret;
lseek(db->fd, db->blkSize * block, SEEK_SET);
ret = write(db->fd, db->map[block].addr, db->blkSize);
free(db->map[block].addr);
}
#endif
}
bzero(&db->map[block], sizeof(db_map_t));
}
void
db_flushWrite(db_handle * db)
{
int i;
/* Flush all of the existing write blocks to the disk */
/* this may be painful if there are lingering links to the memory addresses */
for (i = 0; i < db->mapSize; i++) {
if (db->map[i].mode != PAR_DB_WRITE_BLOCK)
continue;
db->map[i].usage = 0;
db_unmapBlock(db, i);
}
}
/* db_mapBlock() */
/* Add a new physical block to the database */
int
db_addBlock(db_handle * db)
{
int end = db->length;
if (db->mode != PAR_DB_MODE_RW) {
SET_ERRNO(PARDB_BADMODE);
return (-1);
}
if (lseek(db->fd, db->blkSize, SEEK_END) == -1) {
SET_ERRNO(PARDB_IOERR);
return (-1);
}
if (write(db->fd, "", 1) == -1) {
SET_ERRNO(PARDB_IOERR);
return (-1);
}
db->length += db->blkSize;
SET_ERRNO(PARDB_SUCCESS);
return (end);
}
unsigned long
db_getFileOffset(db_handle * db, void *ptr)
{
int i;
unsigned long offset;
if (!db) {
SET_ERRNO(PARDB_BADHANDLE);
return (0);
}
/* Search the list of blocks and get the correct block */
for (i = 0; i < db->mapSize; i++) {
if (!db->map[i].addr)
continue;
if (ptr < db->map[i].addr)
continue;
offset = ((unsigned long) ptr) - ((unsigned long) db->map[i].addr);
/* If the block pointers match, then return the file offset */
if (BLOCK_POINTER_START(db, ptr) == db->map[i].addr) {
SET_ERRNO(PARDB_SUCCESS);
return ((unsigned long) ((i * db->blkSize) + offset));
}
}
SET_ERRNO(PARDB_BADOFFSET);
return (0);
}
void *
db_getBlockStart(db_handle * db, void *ptr)
{
int i;
unsigned long val = (unsigned long) ptr;
for (i = 0; i < db->mapSize; i++) {
unsigned long pos;
if (!db->map[i].addr)
continue;
pos = (unsigned long) db->map[i].addr;
if (val >= pos && val < pos + db->blkSize)
return (db->map[i].addr);
}
return (0);
}
unsigned long
db_getBlockOffset(db_handle * db, void *ptr)
{
int i;
unsigned long val = (unsigned long) ptr;
for (i = 0; i < db->mapSize; i++) {
unsigned long pos;
if (!db->map[i].addr)
continue;
pos = (unsigned long) db->map[i].addr;
if (val >= pos && val < pos + db->blkSize)
return ((unsigned long) (val - pos));
}
return (0);
}
void
db_lockDB(db_handle * db)
{
struct flock lock = { F_WRLCK, 0, SEEK_SET, 0 };
fcntl(db->fd, F_SETLKW, &lock);
}
void
db_unlockDB(db_handle * db)
{
struct flock lock = { F_UNLCK, 0, SEEK_SET, 0 };
fcntl(db->fd, F_SETLKW, &lock);
}
--- NEW FILE: index.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 at centurysoftware.com for information about the PIXIL
* Commercial License Agreement, or if any conditions of this licensing
* are not clear to you.
*/
/* Given a new index, this will format the block for inital use */
#include <stdlib.h>
#include <string.h>
#include <par/pardb.h>
#include "database.h"
#ifdef DEBUG
#define DPRINT(str, args...) printf("DEBUG: " str, ## args)
#else
#define DPRINT(str, args...)
#endif
#define GET_INDEX_INFO(block) ((index_info_t *) block)
void
db_formatIndex(db_handle * db, void *block, int offset, int size)
{
index_t *ptr = 0;
void *start = (void *) ((ulong) block + offset);
int pos;
int next;
index_info_t *info = (index_info_t *) start;
bzero(start, size);
info->ident = DB_INDEX_BLOCK;
info->free = offset + sizeof(index_info_t);
info->next = 0;
pos = info->free;
next = pos + sizeof(index_t);
while ((size - pos) > sizeof(index_t)) {
ptr = (index_t *) (block + pos);
ptr->peer = next;
pos += sizeof(index_t);
next += sizeof(index_t);
}
if (ptr)
ptr->peer = 0;
}
static index_t *
db_newIndexNode(db_handle * db, index_t * hint, char *keyword)
{
void *block;
index_t *index;
index_info_t *info = 0;
int offset;
if (hint)
offset = db_getFileOffset(db, hint);
else
offset = db->index;
if (!offset)
return (0);
while (offset) {
int start = GET_BLOCK(db, offset);
DPRINT("Mapping the block %d in db_newIndexMode()\n",
GET_BLOCK(db, offset));
if (!(block = db_mapBlock(db, GET_BLOCK(db, offset))))
return (0);
if (start == 0)
info = GET_INDEX_INFO((void *) ((ulong) block + db->index));
else
info = GET_INDEX_INFO(block);
if (info->free)
goto initIndex;
offset = info->next;
}
if (!(info->next = db_addBlock(db)))
return (0);
DPRINT("Mapping block %d in db_newIndexMode()\n",
GET_BLOCK(db, info->next));
block = db_mapBlock(db, GET_BLOCK(db, info->next));
if (!block)
return (0);
/* Format the new index block */
db_formatIndex(db, block, 0, db->blkSize);
info = GET_INDEX_INFO(block);
initIndex:
index = (index_t *) (block + info->free);
info->free = index->peer;
bzero(index, sizeof(index_t));
strncpy(index->keyword, keyword, PAR_DB_KEYWORD_SIZE);
index->keyword[PAR_DB_KEYWORD_SIZE] = 0;
SET_ERRNO(PARDB_SUCCESS);
return (index);
}
/* Return the first index node in the system (which is always the first index of the first block) */
index_t *
db_getFirstIndex(db_handle * db)
{
index_t *index;
void *block;
if (!db->index) {
SET_ERRNO(PARDB_BADDB);
return (0);
}
DPRINT("Mapping block %d in db_getFirstIndex()\n",
GET_BLOCK(db, db->index));
block = db_mapBlock(db, GET_BLOCK(db, db->index));
if (!block)
return (0);
index =
(index_t *) (block + GET_BLOCK_OFFSET(db, db->index) +
sizeof(index_info_t));
if (index->keyword[0] == 0) {
SET_ERRNO(PARDB_NOTFOUND);
return (0);
}
SET_ERRNO(PARDB_SUCCESS);
return (index);
}
/* Utility function to get a node living at the specified offset */
static index_t *
db_getIndexNode(db_handle * db, int offset)
{
int start = GET_BLOCK(db, offset);
index_info_t *info;
void *block;
DPRINT("Mapping block %d in db_getIndexNode()\n", start);
block = db_mapBlock(db, start);
if (!block)
return (0);
if (start == 0)
info = GET_INDEX_INFO((void *) ((ulong) block + db->index));
else
info = GET_INDEX_INFO(block);
if (info->ident != DB_INDEX_BLOCK) {
SET_ERRNO(PARDB_BADBLOCK);
return (0);
}
SET_ERRNO(PARDB_SUCCESS);
return ((index_t *) (block + GET_BLOCK_OFFSET(db, offset)));
}
/* Get the child of the given index */
index_t *
db_getChild(db_handle * db, index_t * node)
{
if (!node || !node->child)
return (0);
return (db_getIndexNode(db, node->child));
}
index_t *
db_getPeer(db_handle * db, index_t * node)
{
if (!node || !node->peer) {
SET_ERRNO(PARDB_NOTFOUND);
return (0);
}
SET_ERRNO(PARDB_SUCCESS);
return (db_getIndexNode(db, node->peer));
}
/* Set the specified index to be the child of the specified parent */
void
db_setChild(db_handle * db, index_t * node, index_t * index)
{
if (!node)
return;
if (!index)
node->child = 0;
else
node->child = db_getFileOffset(db, index);
}
/* Set the specified index to be the peer of the specified node */
void
db_setPeer(db_handle * db, index_t * node, index_t * index)
{
if (!node)
return;
if (!index)
node->peer = 0;
else
node->peer = db_getFileOffset(db, index);
}
index_t *
db_addFirstIndex(db_handle * db, char *keyword)
{
index_t *index;
index_info_t *info;
int offset;
void *block, *iptr;
if (!db->index) {
SET_ERRNO(PARDB_BADDB);
return (0);
}
DPRINT("Mapping block %d in db_addFirstIndex()\n",
GET_BLOCK(db, db->index));
block = db_mapBlock(db, GET_BLOCK(db, db->index));
if (!block)
return (0);
offset = GET_BLOCK_OFFSET(db, db->index) + sizeof(index_info_t);
iptr = (void *) ((ulong) block + GET_BLOCK_OFFSET(db, db->index));
info = GET_INDEX_INFO(iptr);
index = (index_t *) (block + offset);
if (index->keyword[0]) {
SET_ERRNO(PARDB_DATAEXISTS);
return (0); /* If the first index is set, return 0 */
}
if (info->free != offset) {
SET_ERRNO(PARDB_BADBLOCK);
return (0);
}
info->free = index->peer;
bzero(index, sizeof(index_t));
strncpy(index->keyword, keyword, PAR_DB_KEYWORD_SIZE);
index->keyword[PAR_DB_KEYWORD_SIZE] = 0;
SET_ERRNO(PARDB_SUCCESS);
return (index);
}
index_t *
db_addPeer(db_handle * db, index_t * prev, char *keyword)
{
index_t *index = db_newIndexNode(db, prev, keyword);
if (!index) {
SET_ERRNO(PARDB_NOTFOUND);
return (0);
}
db_setPeer(db, prev, index);
SET_ERRNO(PARDB_SUCCESS);
return (index);
}
index_t *
db_addChild(db_handle * db, index_t * parent, char *keyword)
{
index_t *index = db_newIndexNode(db, parent, keyword);
if (!index) {
SET_ERRNO(PARDB_NOTFOUND);
return (0);
}
db_setChild(db, parent, index);
SET_ERRNO(PARDB_SUCCESS);
return (index);
}
int
db_setIndexDataOffset(db_handle * db, int offset, int data)
{
index_t *index = db_getIndexNode(db, offset);
if (!index) {
SET_ERRNO(PARDB_NOTFOUND);
return (-1);
}
DPRINT("Setting data for %s to %d\n", index->keyword, data);
index->data = data;
SET_ERRNO(PARDB_SUCCESS);
return (0);
}
int
db_removeIndex(db_handle * db, index_t * index)
{
index_info_t *info;
if (!index) {
SET_ERRNO(PARDB_NOTFOUND);
return (-1);
}
info = GET_INDEX_INFO(BLOCK_POINTER_START(db, index));
/* Remove the data block */
db_removeData(db, index->data);
/* Now, clear out the index */
bzero(index, sizeof(index_t));
/* Set the pointer to the next free space */
index->peer = info->free;
info->free = BLOCK_POINTER_OFFSET(db, index);
SET_ERRNO(PARDB_SUCCESS);
return (0);
}
--- NEW FILE: tree.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 at centurysoftware.com for information about the PIXIL
* Commercial License Agreement, or if any conditions of this licensing
* are not clear to you.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <par/pardb.h>
#include "database.h"
void
tree_addData(tree_t * node, void *data, ushort size, ushort type)
{
unsigned short lsize = size;
if (size == 0)
return;
/* Add a byte for the NULL */
if (type == PAR_TEXT) {
if (((unsigned char *) data)[size - 1] != 0)
lsize = size + 1;
}
if (node->size && node->data) {
if (node->size != lsize) {
void *ptr = realloc(node->data, lsize);
if (!ptr)
return;
node->data = ptr;
}
} else {
node->data = (void *) calloc(lsize, 1);
}
node->size = lsize;
node->type = type;
if (node->data) {
if (type == PAR_TEXT)
strncpy((char *) node->data, data, size);
else
memcpy(node->data, data, size);
}
}
tree_t *
tree_addNode(tree_t * parent, char *keyword)
{
tree_t *node;
if (!parent) {
SET_ERRNO(PARDB_BADNODE);
return (0);
}
if (!parent->child)
node = parent->child = (tree_t *) calloc(sizeof(tree_t), 1);
else {
tree_t *ptr = parent->child;
while (ptr->peer)
ptr = ptr->peer;
node = ptr->peer = (tree_t *) calloc(sizeof(tree_t), 1);
}
if (!node) {
SET_ERRNO(PARDB_MEMERR);
return (0);
}
node->peer = 0;
node->child = 0;
strncpy(node->keyword, keyword, sizeof(node->keyword) - 1);
SET_ERRNO(PARDB_SUCCESS);
return (node);
}
tree_t *
tree_findChildNode(tree_t * parent, char *keyword)
{
tree_t *node;
if (!parent) {
SET_ERRNO(PARDB_BADNODE);
return (0);
}
node = parent->child;
while (node) {
if (!strcmp(node->keyword, keyword))
return (node);
node = node->peer;
}
return (0);
}
int
tree_recursiveBuild(db_handle * db, index_t * top, tree_t * tree)
{
int ret;
index_t *node = top;
/* At this point we are succesful. */
SET_ERRNO(PARDB_SUCCESS);
while (node) {
ushort type;
ushort size;
tree_t *local;
index_t *child;
unsigned char *data;
ret = db_getDataInfo(db, node, &size, 0);
if (ret == -1 && pardb_errno != PARDB_NODATA)
return -1;
local = tree_addNode(tree, node->keyword);
if (ret > 0) {
if (!(data = alloca(size + 1))) {
SET_ERRNO(PARDB_MEMERR);
return (-1);
}
bzero(data, size + 1);
ret = db_getData(db, node, (void *) data, size, &type);
if (ret == -1)
return -1;
tree_addData(local, data, ret, type);
}
child = db_getChild(db, node);
if (child)
ret = tree_recursiveBuild(db, db_getChild(db, node), local);
if (ret == -1)
return (-1);
node = db_getPeer(db, node);
}
return (0);
}
int
tree_recursiveSave(db_handle * db, tree_t * head, char *name)
{
tree_t *node = head;
SET_ERRNO(PARDB_SUCCESS);
while (node) {
char *lname;
if (!name) {
lname = alloca(strlen(node->keyword) + 1);
strcpy(lname, node->keyword);
} else {
lname = alloca(strlen(name) + strlen(node->keyword) + 2);
sprintf(lname, "%s.%s", name, node->keyword);
}
if (db_addNode(db, lname, node->data, node->size, node->type) == -1)
return (-1);
if (node->child)
if (tree_recursiveSave(db, node->child, lname) == -1)
return (-1);
node = node->peer;
}
return (0);
}
tree_t *
tree_newTree(void)
{
tree_t *local = (tree_t *) calloc(sizeof(tree_t), 1);
if (!local)
SET_ERRNO(PARDB_MEMERR);
else
SET_ERRNO(PARDB_SUCCESS);
return (local);
}
void
tree_recursiveFree(tree_t * tree)
{
tree_t *node = tree->child;
/* Free my children */
while (node) {
tree_t *peer = node->peer;
tree_recursiveFree(node);
node = peer;
}
/* Free my data */
if (tree->data)
free(tree->data);
/* Finally, free this node */
free(tree);
}
--- NEW FILE: data.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 at centurysoftware.com for information about the PIXIL
* Commercial License Agreement, or if any conditions of this licensing
* are not clear to you.
*/
/* Given a new data block, this will format the block for inital use */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <par/pardb.h>
#include "database.h"
#ifdef DEBUG
#define DPRINT(str, args...) printf("DEBUG: " str, ## args)
#else
#define DPRINT(str, args...)
#endif
#define GET_DATA_INFO(block) ((data_info_t *) block)
#define GET_FREE_SPACE(db, offset) (db->blkSize - offset)
void
db_formatData(db_handle * db, void *block, int offset, int size)
{
void *start = (void *) (block + offset);
data_info_t *info = (data_info_t *) start;
bzero(start, size);
info->ident = DB_DATA_BLOCK;
info->free = offset + sizeof(data_info_t);
info->next = 0;
}
/* Add a new data node to the system */
static data_t *
db_newDataNode(db_handle * db, index_t * index, unsigned short size,
unsigned short type)
{
void *block;
data_t *data;
data_info_t *info = 0;
int offset;
#ifdef HAVE_MMAPBUG
/* We need to align the size so malloc accesses are correct */
if ((size % 4))
size += (4 - (size % 4));
#endif
if (db->dataCache)
offset = db->dataCache;
else
offset = db->data;
while (offset) {
DPRINT("Mapping block %d in db_newDataNode()\n",
GET_BLOCK(db, offset));
if (!(block = db_mapBlock(db, GET_BLOCK(db, offset))))
return (0);
info = GET_DATA_INFO(block);
if (GET_FREE_SPACE(db, info->free) > (size + DATA_ITEM_LEN))
goto initData;
offset = info->next;
}
if (!info)
return (0);
if (!(info->next = db_addBlock(db)))
return (0);
DPRINT("Mapping block %d in db_newDataNode()\n",
GET_BLOCK(db, info->next));
block = db_mapBlock(db, GET_BLOCK(db, info->next));
if (!block)
return (0);
/* Format the new index block */
db_formatData(db, block, 0, db->blkSize);
info = GET_DATA_INFO(block);
initData:
data = (data_t *) ((ulong) block + info->free);
data->type = type;
data->size = (unsigned short) size;
data->index = db_getFileOffset(db, index);
index->data = db_getFileOffset(db, data);
info->free += size + DATA_ITEM_LEN;
SET_ERRNO(PARDB_SUCCESS);
return (data);
}
static data_t *
db_getDataNode(db_handle * db, int offset)
{
void *block;
if (!offset)
return (0);
DPRINT("Mapping block %d in db_getDataNode()\n", GET_BLOCK(db, offset));
block = db_mapBlock(db, GET_BLOCK(db, offset));
if (!block)
return (0);
SET_ERRNO(PARDB_SUCCESS);
return ((data_t *) (block + GET_BLOCK_OFFSET(db, offset)));
}
/* Given a start and a offset, move the rest of the data block */
static void
db_moveData(db_handle * db, void *block, int start, int offset)
{
int ptr = start;
data_info_t *info = GET_DATA_INFO(block);
int length;
void *src, *dest;
/* First, go through and update all of the index blocks */
ptr = GET_BLOCK_OFFSET(db, start);
while (ptr < info->free) {
data_t *local = (data_t *) (block + ptr);
db_setIndexDataOffset(db, local->index,
GET_BLOCK(db, start) + ptr + offset);
ptr += (local->size + DATA_ITEM_LEN);
}
length = info->free - GET_BLOCK_OFFSET(db, start);
src = (void *) (block + GET_BLOCK_OFFSET(db, start));
dest = (void *) (block + GET_BLOCK_OFFSET(db, start) + offset);
/* Now, actually move the block */
memmove(dest, src, length);
/* Update the free block here */
info->free += offset;
}
int
db_removeData(db_handle * db, int offset)
{
void *block;
data_t *data;
if (!offset) {
SET_ERRNO(PARDB_BADOFFSET);
return (-1);
}
DPRINT("Mapping block %d in db_removeData()\n", GET_BLOCK(db, offset));
block = db_mapBlock(db, GET_BLOCK(db, offset));
if (!block)
return (-1);
data = (data_t *) (block + GET_BLOCK_OFFSET(db, offset));
db_moveData(db, block, offset + data->size + DATA_ITEM_LEN,
-(data->size + DATA_ITEM_LEN));
SET_ERRNO(PARDB_SUCCESS);
return (0);
}
int
db_setData(db_handle * db, index_t * index, void *value, unsigned short size,
unsigned short type)
{
data_t *data = 0;
if (!index->data) {
if (!(data = db_newDataNode(db, index, size, type)))
return (-1);
} else {
/* Try to modify the existing node */
if (!(data = db_getDataNode(db, index->data)))
return (-1);
if ((size > data->size)) {
int diff = size - data->size;
void *block = BLOCK_POINTER_START(db, data);
data_info_t *info = GET_DATA_INFO(block);
/* Check to see if we have the appropriate space available */
if (GET_FREE_SPACE(db, info->free) > diff) {
db_moveData(db, block,
index->data + data->size + DATA_ITEM_LEN, diff);
data->size = size;
} else {
/* Delete the current data block */
db_removeData(db, index->data);
index->data = 0;
/* And get a new one */
data = db_newDataNode(db, index, size, type);
if (!data)
return (-1);
}
}
}
if ((data->type != type)) {
SET_ERRNO(PARDB_BADTYPE);
return (-1);
}
/* Zero out the existing space */
if (size) {
bzero((unsigned char *) &data->value, size);
memcpy(&data->value, value, size);
}
SET_ERRNO(PARDB_SUCCESS);
return (size);
}
int
db_getData(db_handle * db, index_t * index, void *value, unsigned short size,
unsigned short *type)
{
unsigned short copy_size = 0;
data_t *data = 0;
if (!index->data) {
SET_ERRNO(PARDB_NODATA);
return (-1);
}
data = db_getDataNode(db, index->data);
if (!data) {
SET_ERRNO(PARDB_NODATA);
return (-1);
}
/* If there is no data, than thats not an error */
if (!value || !size) {
SET_ERRNO(PARDB_SUCCESS);
return (0);
}
if (data->size > size)
copy_size = size;
else
copy_size = data->size;
if (!copy_size) {
SET_ERRNO(PARDB_SUCCESS);
return (0);
}
memcpy(value, &data->value, copy_size);
if (type)
*type = data->type;
SET_ERRNO(PARDB_SUCCESS);
return (copy_size);
}
int
db_getDataInfo(db_handle * db, index_t * index, unsigned short *size,
unsigned short *type)
{
data_t *data;
if (!index->data) {
SET_ERRNO(PARDB_NODATA);
return (-1);
}
data = db_getDataNode(db, index->data);
if (!data)
return (-1);
if (size)
*size = data->size;
if (type)
*type = data->type;
SET_ERRNO(PARDB_SUCCESS);
return (0);
}
--- NEW FILE: Makefile ---
#par/lib/Makefile
LIB_STATIC=platform-objs/libpar.a
LIB_SHARED=platform-objs/libpar.so
NATIVE_LIB_STATIC=native-objs/libpar.a
PREBUILD_EXTRAS = $(CURDIR)/native-objs $(CURDIR)/platform-objs
SRC := ${shell ls *.c}
OBJS := $(SRC:%.c=platform-objs/%.o)
NATIVE_OBJS := $(SRC:%.c=native-objs/%.o)
INCLUDES=-I./include
CFLAGS ?=
CFLAGS +=-DHAVE_MMAPBUG -DDEFPARDB="\"$(PAR_DB)\""
NATIVE_CFLAGS=-DHAVE_MMAPBUG -DDEFPARDB="\"$(PAR_DB)\""
include $(BASE_DIR)/Rules.make
$(CURDIR)/platform-objs $(CURDIR)/native-objs:
@ mkdir -p $@
clean:
@ rm -rf $(CURDIR)/native-objs $(CURDIR)/platform-objs
--- NEW FILE: db_api.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 at 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 */
int
db_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);
}
int
db_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);
}
int
db_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);
}
int
db_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);
}
int
db_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 */
int
db_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));
}
int
db_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);
}
void
db_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 */
int
db_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;
}
int
db_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);
}
void
db_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 */
int
db_loadTree(db_handle * db, tree_t * head)
{
return (tree_recursiveBuild(db, db_getFirstIndex(db), head));
}
/* Save a tree into the database file */
int
db_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);
}
--- NEW FILE: database.h ---
/*
* 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 at centurysoftware.com for information about the PIXIL
* Commercial License Agreement, or if any conditions of this licensing
* are not clear to you.
*/
#ifndef _DATABASE_H_
#define _DATABASE_H_
#include <stddef.h>
#define PARDB_MAGIC 0x2323 /* FNORD! */
#undef DEBUG
#ifdef DEBUG
#include <stdio.h>
#define DPRINT(str, args...) printf("DEBUG: " str, ## args)
#else
#define DPRINT(str, args...)
#endif
#define DB_DATA_BLOCK 0x01
#define DB_INDEX_BLOCK 0x02
/* Contains all the important information about the database */
typedef struct
{
unsigned short ident;
short free;
unsigned long next;
unsigned long padding[6];
}
index_info_t;
typedef struct
{
unsigned short ident;
unsigned short free;
unsigned long next;
}
data_info_t;
typedef struct
{
char keyword[PAR_DB_KEYWORD_SIZE + 1];
unsigned long peer;
unsigned long child;
unsigned long data;
}
index_t;
typedef struct
{
unsigned short type;
unsigned short size;
unsigned long index;
unsigned char value;
}
data_t;
/* This is the length of the "header" on data structure (not including the length) */
/* #define DATA_ITEM_LEN ( sizeof(unsigned short) + sizeof(unsigned short) + sizeof(unsigned long) */
#define DATA_ITEM_LEN ( offsetof(data_t, value) )
typedef struct
{
unsigned short magic;
unsigned short blksize;
unsigned long index;
unsigned long data;
unsigned long padding[5];
}
db_info_t;
#ifdef HAVE_MMAPBUG
void *db_getBlockStart(db_handle * db, void *ptr);
unsigned long db_getBlockOffset(db_handle * db, void *ptr);
#endif
#ifdef HAVE_MMAPBUG
#define BLOCK_POINTER_START(db, value) (db_getBlockStart(db, value))
#else
#define BLOCK_POINTER_START(db, value) ((void *) ((ulong) value - ((ulong) value % db->blkSize)))
#endif
#ifdef HAVE_MMAPBUG
#define BLOCK_POINTER_OFFSET(db, value) (db_getBlockOffset(db, value))
#else
#define BLOCK_POINTER_OFFSET(db, value) ((unsigned long) value % db->blkSize)
#endif
#define GET_BLOCK(db, offset) (offset - (offset % db->blkSize))
#define GET_BLOCK_OFFSET(db, offset) (offset % db->blkSize)
/* Utilities */
char *strip_keyword(char **name);
#define db_setMode(db, m) db->mode = m
#define db_setAccess(db, acc) db->access = acc
#define db_getAccess(db) (db->access)
/* database.c */
int db_recursiveAdd(db_handle *, index_t *, char *name, void *data,
ushort size, ushort type);
index_t *db_recursiveFind(db_handle *, index_t *, char *name);
int db_recursiveDel(db_handle *, index_t *, char *name);
void db_freeDB(db_handle * db);
db_handle *db_allocDB(int fd, int bsize, int length);
/* index.c */
index_t *db_getFirstIndex(db_handle * db);
index_t *db_getPeer(db_handle * db, index_t * peer);
index_t *db_getChild(db_handle * db, index_t * parent);
index_t *db_addChild(db_handle * db, index_t * parent, char *keyword);
index_t *db_addPeer(db_handle * db, index_t * prev, char *keyword);
index_t *db_addFirstIndex(db_handle * db, char *keyword);
void db_setPeer(db_handle * db, index_t * peer, index_t * index);
void db_setChild(db_handle * db, index_t * node, index_t * index);
void db_formatIndex(db_handle * db, void *block, int offset, int size);
int db_setIndexDataOffset(db_handle * db, int offset, int data);
int db_removeIndex(db_handle * db, index_t * index);
/* data.c */
void db_formatData(db_handle * db, void *block, int offset, int size);
int db_setData(db_handle * db, index_t * index, void *value, ushort size,
ushort type);
int db_getData(db_handle * db, index_t * index, void *value, ushort size,
ushort * type);
int db_removeData(db_handle * db, int offset);
int db_getDataInfo(db_handle * db, index_t * index, ushort * size,
ushort * type);
/* io.c */
int db_addBlock(db_handle * db);
void *db_mapBlock(db_handle * db, int offset);
void db_unmapBlock(db_handle * db, int block);
unsigned long db_getFileOffset(db_handle * db, void *ptr);
void db_flushWrite(db_handle * db);
void db_lockDB(db_handle * db);
void db_unlockDB(db_handle * db);
/* tree.c */
tree_t *tree_newTree(void);
void tree_freeTree(tree_t * tree);
int tree_recursiveBuild(db_handle * db, index_t * top, tree_t * tree);
int tree_recursiveSave(db_handle * db, tree_t * head, char *name);
void tree_recursiveFree(tree_t * tree);
tree_t *tree_addNode(tree_t * parent, char *keyword);
void tree_addData(tree_t * node, void *data, ushort size, ushort type);
tree_t *tree_findChildNode(tree_t * parent, char *keyword);
#endif
--- NEW FILE: par_api.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 at centurysoftware.com for information about the PIXIL
* Commercial License Agreement, or if any conditions of this licensing
* are not clear to you.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <par/pardb.h>
#include <par/par.h>
#define APPLICATION_NAME "application"
#define CAPABILITY_NAME "capabilities"
#define SCREENTOP_NAME "screentop"
#define GLOBAL_PREF_NAME "global.preferences"
/* Get a global preference from the system */
/* Size here is really only for the text type */
int
par_getGlobalPref(db_handle * db, char *category, char *keyword, int type,
void *dest, int size)
{
int ret;
unsigned short gsize;
unsigned short gtype;
char *name =
alloca(strlen(GLOBAL_PREF_NAME) + strlen(category) + strlen(keyword) +
2 + 1);
if (!name)
return (-1);
sprintf(name, "%s.%s.%s", GLOBAL_PREF_NAME, category, keyword);
switch (type) {
case PAR_TEXT:
gsize = size;
break;
case PAR_INT:
gsize = sizeof(int);
break;
case PAR_FLOAT:
gsize = sizeof(double);
break;
case PAR_BOOL:
gsize = sizeof(unsigned char);
break;
default:
gsize = size;
}
ret = db_findNode(db, name, dest, gsize, >ype);
if (ret < 0)
return (ret);
if (gtype != type)
return (-1);
return (ret);
}
/* Add/modify a global preference */
int
par_setGlobalPref(db_handle * db, char *category, char *keyword, int type,
char *value, int size)
{
char *name =
alloca(strlen(GLOBAL_PREF_NAME) + strlen(category) + strlen(keyword) +
2 + 1);
if (!name)
return (-1);
sprintf(name, "%s.%s.%s", GLOBAL_PREF_NAME, category, keyword);
return (db_addNode(db, name, value, size, type));
}
int
par_removeGlobalPref(db_handle * db, char *category, char *keyword,
char *value, int size, int type)
{
char *name =
alloca(strlen(GLOBAL_PREF_NAME) + strlen(category) + strlen(keyword) +
2 + 1);
if (!name)
return (-1);
sprintf(name, "%s.%s.%s", GLOBAL_PREF_NAME, category, keyword);
return (db_delNode(db, name));
}
inline int
par_getGlobalColor(db_handle * db, char *keyword, unsigned long *dest)
{
return (par_getGlobalPref
(db, "appcolors", keyword, PAR_COLOR, (void *) dest,
sizeof(unsigned long)));
}
int
par_getAppField(db_handle * db, char *app, char *keyword, void *data,
int size)
{
int ret;
char *local =
alloca(strlen(APPLICATION_NAME) + strlen(app) + strlen(keyword) + 3);
if (!local)
return (-1);
sprintf(local, "%s.%s.%s", APPLICATION_NAME, app, keyword);
bzero((char *) data, size);
ret = db_findNode(db, local, data, size - 1, 0);
return (ret);
}
#define GET_FIELD(db, app, title, field) \
par_getAppField(db, app, title, field, sizeof(field))
int
par_getApplication(db_handle * db, char *app, par_app_t * local)
{
int ret = 0;
if (!app || !local)
return -1;
memset(local, 0, sizeof(par_app_t));
/* It should not be an error not to have all the fields. Really,
isn't only exec needed? */
/* So this has been changed. If par_getAppField returns any error
except "not found" then return an error. Otherwise, ignore it.
*/
ret = GET_FIELD(db, app, "title", local->title);
if (ret == -1 && pardb_errno != PARDB_NOTFOUND) return -1;
ret = GET_FIELD(db, app, "exec", local->path);
if (ret == -1 && pardb_errno != PARDB_NOTFOUND) return -1;
ret = GET_FIELD(db, app, "workdir", local->workdir);
if (ret == -1 && pardb_errno != PARDB_NOTFOUND) return -1;
ret = GET_FIELD(db, app, "icon", local->icon);
if (ret == -1 && pardb_errno != PARDB_NOTFOUND) return -1;
ret = GET_FIELD(db, app, "defargs", local->defargs);
if (ret == -1 && pardb_errno != PARDB_NOTFOUND) return -1;
return 0;
}
int
par_getAppPref(db_handle * db, char *application, char *category,
char *keyword, char *dest, unsigned short size)
{
int len = strlen(APPLICATION_NAME) + strlen(application)
+ strlen("preferences") + strlen(category) + strlen(keyword) + 4 + 1;
char *name = alloca(len);
if (!name)
return (-1);
sprintf(name, "%s.%s.preferences.%s.%s",
APPLICATION_NAME, application, category, keyword);
return (db_findNode(db, name, dest, size, 0));
}
int
par_addAppPref(db_handle * db, char *application, char *category,
char *keyword, char *dest, unsigned short size,
unsigned short type)
{
int len = strlen(APPLICATION_NAME) + strlen(application)
+ strlen("preferences") + strlen(category) + strlen(keyword) + 4 + 1;
char *name = alloca(len);
if (!name)
return (-1);
sprintf(name, "%s.%s.preferences.%s.%s",
APPLICATION_NAME, application, category, keyword);
return (db_addNode(db, name, dest, size, type));
}
int
par_delAppPref(db_handle * db, char *application, char *category,
char *keyword)
{
int len = strlen(APPLICATION_NAME) + strlen(application)
+ strlen("preferences") + strlen(category) + strlen(keyword) + 4 + 1;
char *name = alloca(len);
if (!name)
return (-1);
sprintf(name, "%s.%s.preferences.%s.%s",
APPLICATION_NAME, application, category, keyword);
return (db_delNode(db, name));
}
int
par_getCapability(db_handle * db, char *capability, void **dest)
{
int size;
char *name = alloca(strlen(CAPABILITY_NAME) + strlen(capability) + 2);
if (!name)
return (-1);
sprintf(name, "%s.%s", CAPABILITY_NAME, capability);
size = db_getDataSize(db, name);
if (size <= 0) {
*dest = 0;
return (size);
}
*dest = (char *) malloc(size);
db_findNode(db, name, *dest, size, 0);
return (size);
}
int
par_getScreentopSetting(db_handle * db, char *setting, void *dest, int size)
{
char *name = alloca(strlen("screentop.settings.") + strlen(setting) + 1);
if (!name)
return (-1);
sprintf(name, "screentop.settings.%s", setting);
return (db_findNode(db, name, dest, size, 0));
}
int
par_getScreentopDir(db_handle * db, char *dir, char *dest, int size)
{
int len = strlen("screentop.directories") + strlen(dir);
char *name = alloca(len + 2);
if (!name)
return (-1);
sprintf(name, "screentop.directories.%s", dir);
return (db_findNode(db, name, dest, size, 0));
}
int
par_getScreentopInput(db_handle * db, char *input, par_input_t * data)
{
int len = strlen("screentop.inputs") + strlen(input) + strlen("title");
char *name = alloca(len + 3);
if (!name)
return (-1);
sprintf(name, "screentop.inputs.%s.title", input);
if (db_findNode(db, name, data->title, sizeof(data->title), 0) < 0)
return (-1);
sprintf(name, "screentop.inputs.%s.app", input);
if (db_findNode(db, name, data->app, sizeof(data->app), 0) < 0)
return (-1);
sprintf(name, "screentop.inputs.%s.icon", input);
if (db_findNode(db, name, data->icon, sizeof(data->icon), 0) < 0)
return (-1);
return (0);
}
int
par_getScreentopCategory(db_handle * db, char *category,
char **title, char **applist)
{
int size;
int len =
strlen("screentop.categories") + strlen(category) + strlen("applist");
char *name = alloca(len + 3);
if (!name)
return (-1);
/* First, get the title */
sprintf(name, "screentop.categories.%s.title", category);
size = db_getDataSize(db, name);
if (size <= 0)
return (-1);
*title = (char *) malloc(size);
db_findNode(db, name, *title, size, 0);
/* Next, get the full app list */
sprintf(name, "screentop.categories.%s.applist", category);
size = db_getDataSize(db, name);
if (size <= 0) {
*applist = 0;
return (0);
}
*applist = (char *) malloc(size);
db_findNode(db, name, *applist, size, 0);
return (0);
}
/* List functions */
static int
local_getList(db_handle * db, char *name, itemlist_t * local)
{
int count = db_getChildCount(db, name);
if (count <= 0)
return (count);
local->list = (char **) calloc(count * sizeof(char *), 1);
if (!local->list)
return (-1);
/* Now, send the list in and get the child names */
local->count = db_getChildList(db, name, local->list, count);
if (local->count == -1) {
int i;
for (i = 0; i < count; i++) {
if (local->list[i])
free(local->list[i]);
}
free(local->list);
local->list = 0;
}
return (local->count);
}
int
par_getList(db_handle * db, char *name, itemlist_t ** list)
{
itemlist_t *local = (itemlist_t *) malloc(sizeof(itemlist_t));
int ret = local_getList(db, name, local);
if (ret == -1)
free(local);
else
*list = local;
return (ret);
}
void
par_freeItemList(itemlist_t * list)
{
int i;
if (!list)
return;
for (i = 0; i < list->count; i++) {
if (list->list[i])
free(list->list[i]);
}
if (list->list)
free(list->list);
free(list);
}
int
par_getListItem(itemlist_t * list, int index, char *item, int *size)
{
int lsize;
if (!list)
return (0);
if (index >= list->count)
return (0);
if (*size > strlen(list->list[index]))
lsize = strlen(list->list[index]);
else
lsize = *size;
strncpy(item, list->list[index], lsize);
*size = lsize;
return (list->count > (index + 1) ? index + 1 : 0);
}
int
par_getStringListCount(char *str, char delim)
{
int count = 1;
char *p = str;
if (!*p)
return (0);
while (1) {
p = strchr(p, delim);
if (!p)
return (count);
while (*p == delim)
p++;
if (!*p)
return (count);
count++;
}
}
char *
par_parseStringList(char **str, char delim)
{
char *start, *n;
if (!&str)
return (0);
start = *str;
n = strchr(*str, delim);
if (!n)
*str = 0;
else {
char *p = n + 1;
*n = 0;
while (*p == delim)
p++;
if (!*p)
*str = 0;
else
*str = p;
}
return (start);
}
More information about the dslinux-commit
mailing list