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

📄 ndbm.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
#if !defined(lint) && defined(SCCSIDS)#endif /* ndef lint */static char sccsid[] = "@(#)ndbm.c 1.1 92/07/30 SMI";	/* from UCB 4.3 6/19/85 *//* * Copyright (c) 1983 Regents of the University of California. * All rights reserved.  The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */#include <sys/types.h>#include <sys/stat.h>#include <sys/file.h>#include <stdio.h>#include <errno.h>#include <ndbm.h>datum dbm_do_nextkey(/*db, key*/);/*add support for batched writing for NIS*/#define _DBM_DEFWRITE 0x4#define _DBM_DIRTY 0x8#define _DBM_DIRDIRTY 0x10#define dbm_dirty(db) ((db)->dbm_flags & _DBM_DIRTY)#define dbm_dirdirty(db) ((db)->dbm_flags & _DBM_DIRDIRTY)#define dbm_defwrite(db) ((db)->dbm_flags & _DBM_DEFWRITE)#define dbm_setdirty(db) (db)->dbm_flags |= _DBM_DIRTY#define dbm_clrdirty(db) (db)->dbm_flags &= ~_DBM_DIRTY#define dbm_setdirdirty(db) (db)->dbm_flags |= _DBM_DIRDIRTY#define dbm_clrdirdirty(db) (db)->dbm_flags &= ~_DBM_DIRDIRTY/*used to make a dbm file all at once instead of incrementally*/dbm_setdefwrite(db)	DBM *db;{	db->dbm_flags |= _DBM_DEFWRITE;}dbm_flush(db)	DBM *db;{	int ok=0;	if (dbm_flushpag(db)<0) ok= -1;	if (dbm_flushdir(db)<0) ok= -1;	return(ok);}dbm_flushpag(db)	DBM *db;{	int ok=0;	if (dbm_dirty(db)){ /*must page out the page*/		(void) lseek(db->dbm_pagf, (long)(db->dbm_pagbno*PBLKSIZ), L_SET);		if (write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) {			db->dbm_flags |= _DBM_IOERR;			ok= -1;			}		dbm_clrdirty(db);	}	return(ok);}dbm_flushdir(db)	DBM *db;{	int ok=0;	if (dbm_dirdirty(db)){ /*must page out the dir*/	(void) lseek(db->dbm_dirf, (long)(db->dbm_dirbno*DBLKSIZ), L_SET);	if (write(db->dbm_dirf, db->dbm_dirbuf, DBLKSIZ) != DBLKSIZ) {		ok= -1;		}	dbm_clrdirdirty(db);	}	return(ok);}#define BYTESIZ 8#undef setbitstatic  datum makdatum();static  long dcalchash();extern  int errno;extern	char *malloc();extern	long lseek();extern	char *strcpy();extern	char *strcat();DBM *dbm_open(file, flags, mode)	char *file;	int flags, mode;{	struct stat statb;	register DBM *db;	if ((db = (DBM *)malloc(sizeof *db)) == 0) {		errno = ENOMEM;		return ((DBM *)0);	}	db->dbm_flags = (flags & 03) == O_RDONLY ? _DBM_RDONLY : 0;	if ((flags & 03) == O_WRONLY)		flags = (flags & ~03) | O_RDWR;	(void) strcpy(db->dbm_pagbuf, file);	(void) strcat(db->dbm_pagbuf, ".pag");	db->dbm_pagf = open(db->dbm_pagbuf, flags, mode);	if (db->dbm_pagf < 0)		goto bad;	(void) strcpy(db->dbm_pagbuf, file);	(void) strcat(db->dbm_pagbuf, ".dir");	db->dbm_dirf = open(db->dbm_pagbuf, flags, mode);	if (db->dbm_dirf < 0)		goto bad1;	(void) fstat(db->dbm_dirf, &statb);	db->dbm_maxbno = statb.st_size*BYTESIZ-1;	db->dbm_pagbno = db->dbm_dirbno = -1;	return (db);bad1:	(void) close(db->dbm_pagf);bad:	free((char *)db);	return ((DBM *)0);}voiddbm_close(db)	DBM *db;{(void) dbm_close_status(db);}/*close with return code*/intdbm_close_status(db)	DBM *db;{	int ok;	ok=0;	if (dbm_flush(db) <0)   ok = -1;	if (close(db->dbm_dirf)<0) ok= -1;	if ( close(db->dbm_pagf)<0) ok= -1;	free((char *)db);	return(ok);}longdbm_forder(db, key)	register DBM *db;	datum key;{	long hash;	hash = dcalchash(key);	for (db->dbm_hmask=0;; db->dbm_hmask=(db->dbm_hmask<<1)+1) {		db->dbm_blkno = hash & db->dbm_hmask;		db->dbm_bitno = db->dbm_blkno + db->dbm_hmask;		if (getbit(db) == 0)			break;	}	return (db->dbm_blkno);}datumdbm_fetch(db, key)	register DBM *db;	datum key;{	register i;	datum item;	if (dbm_error(db))		goto err;	dbm_access(db, dcalchash(key));	if ((i = finddatum(db->dbm_pagbuf, key)) >= 0) {		item = makdatum(db->dbm_pagbuf, i+1);		if (item.dptr != NULL)			return (item);	}err:	item.dptr = NULL;	item.dsize = 0;	return (item);}dbm_delete(db, key)	register DBM *db;	datum key;{	register i;	if (dbm_error(db))		return (-1);	if (dbm_rdonly(db)) {		errno = EPERM;		return (-1);	}	dbm_access(db, dcalchash(key));	if ((i = finddatum(db->dbm_pagbuf, key)) < 0)		return (-1);	if (!delitem(db->dbm_pagbuf, i))		goto err;	db->dbm_pagbno = db->dbm_blkno;	if (dbm_defwrite(db)) {		dbm_setdirty(db);	}	else {	(void) lseek(db->dbm_pagf, (long)(db->dbm_blkno*PBLKSIZ), L_SET);	if (write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) {	err:		db->dbm_flags |= _DBM_IOERR;		return (-1);	}	}	return (0);}dbm_store(db, key, dat, replace)	register DBM *db;	datum key, dat;	int replace;{	register i;	datum item, item1;	char ovfbuf[PBLKSIZ];	if (dbm_error(db))		return (-1);	if (dbm_rdonly(db)) {		errno = EPERM;		return (-1);	}loop:	dbm_access(db, dcalchash(key));	if ((i = finddatum(db->dbm_pagbuf, key)) >= 0) {		if (!replace)			return (1);		if (!delitem(db->dbm_pagbuf, i)) {			db->dbm_flags |= _DBM_IOERR;			return (-1);		}	}	if (!additem(db->dbm_pagbuf, key, dat))		goto split;	db->dbm_pagbno = db->dbm_blkno;	if (dbm_defwrite(db)) {		dbm_setdirty(db);	}	else {		(void) lseek(db->dbm_pagf, (long)(db->dbm_blkno*PBLKSIZ), L_SET);		if (write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) {			db->dbm_flags |= _DBM_IOERR;			return (-1);		}	}	return (0);split:	if (key.dsize+dat.dsize+3*sizeof(short) >= PBLKSIZ) {		db->dbm_flags |= _DBM_IOERR;		errno = ENOSPC;		return (-1);	}	bzero(ovfbuf, PBLKSIZ);	for (i=0;;) {		item = makdatum(db->dbm_pagbuf, i);		if (item.dptr == NULL)			break;		if (dcalchash(item) & (db->dbm_hmask+1)) {			item1 = makdatum(db->dbm_pagbuf, i+1);			if (item1.dptr == NULL) {				/*(void) fprintf(stderr, "ndbm: split not paired\n");*/				db->dbm_flags |= _DBM_IOERR;				break;			}			if (!additem(ovfbuf, item, item1) ||			    !delitem(db->dbm_pagbuf, i)) {				db->dbm_flags |= _DBM_IOERR;				return (-1);			}			continue;		}		i += 2;	}	db->dbm_pagbno = db->dbm_blkno;	(void) lseek(db->dbm_pagf, (long)(db->dbm_blkno*PBLKSIZ), L_SET);	if (write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) {		db->dbm_flags |= _DBM_IOERR;		return (-1);	}	dbm_clrdirty(db); /*clear dirty*/	(void) lseek(db->dbm_pagf, 		(long)((db->dbm_blkno+db->dbm_hmask+1)*PBLKSIZ), L_SET);	if (write(db->dbm_pagf, ovfbuf, PBLKSIZ) != PBLKSIZ) {		db->dbm_flags |= _DBM_IOERR;		return (-1);	}	if (setbit(db) < 0) {		db->dbm_flags |= _DBM_IOERR;		return (-1);	}	goto loop;}static longdbm_hashinc(db,hash)	DBM *db;	long hash;{	long bit;	hash &= db->dbm_hmask;	bit = db->dbm_hmask+1;	for(;;) {		bit >>= 1;		if(bit == 0)			return(0L);		if((hash&bit) == 0)			return(hash|bit);		hash &= ~bit;	}}static datum nullkey= {NULL, 0};datumdbm_firsthash(db,hash)register DBM *db;long hash;{	register i,j;	datum item, bitem;loop:	dbm_access(db, hash);	j=0;	bitem = makdatum(db->dbm_pagbuf, 0);	for(i=2;; i+=2) {		item = makdatum(db->dbm_pagbuf, i);		if(item.dptr == NULL)			break;		if(cmpdatum(bitem, item) < 0) {			j=i;			bitem = item;			}	}	if(bitem.dptr != NULL) {	        db->dbm_keyptr = j + 2;	        db->dbm_blkptr = db->dbm_blkno;		return(bitem);	}	hash = dbm_hashinc(db,hash);	if(hash == 0)		return(item); /*null item*/	goto loop;}datumdbm_firstkey(db)	DBM *db;{	db->dbm_blkptr = 0L;	db->dbm_keyptr = 0;	return (dbm_firsthash(db, 0L));}datumdbm_nextkey(db)	DBM *db;{	return (dbm_do_nextkey(db, nullkey));}/*this is used if keyptr-2,blocknum doesn't point to the previousspecific key allowing the fast hash order search --its use indicates user tampering with our state variables,which some evil users might do to search from some specific place.It finds the first key at or after blkptr,keyptr in block seq orderthis requires looking at all sorts of emtpy blocks in many cases*/static datumdbm_slow_nextkey(db)	register DBM *db;{	struct stat statb;	datum item;	if (dbm_error(db) || fstat(db->dbm_pagf, &statb) < 0)		goto err;	statb.st_size /= PBLKSIZ;       for (;;) {		if (db->dbm_blkptr != db->dbm_pagbno) {			if (dbm_dirty(db)) dbm_flushpag(db);			db->dbm_pagbno = db->dbm_blkptr;			(void) lseek(db->dbm_pagf, (long)(db->dbm_blkptr*PBLKSIZ), L_SET);			if (read(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ)				bzero(db->dbm_pagbuf, PBLKSIZ);#ifdef DEBUG			else if (chkblk(db->dbm_pagbuf) < 0)				db->dbm_flags |= _DBM_IOERR;#endif		}		/*Am I an empty block?*/		if (((short *)db->dbm_pagbuf)[0] != 0) {			item = makdatum(db->dbm_pagbuf, db->dbm_keyptr);			if (item.dptr != NULL) {				db->dbm_keyptr += 2;				return (item);			}			db->dbm_keyptr = 0;		}		/*go to next sequential block*/		if (++db->dbm_blkptr >= statb.st_size)			break;	}err:	item.dptr = NULL;	item.dsize = 0;	return (item);}datumdbm_do_nextkey(db, inkey)	register DBM *db;	datum inkey;{	datum item,bitem;	long hash;	datum key;	int f;	register i;	register j;	register short *sp;	register n;	register char *p1, *p2;	if ( dbm_error(db) ) {		item.dptr = NULL;		item.dsize = 0;		return (item);	}	/*user has supplied lastkey*/	if(inkey.dptr != NULL) {

⌨️ 快捷键说明

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