home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume19
/
shape
/
part23
< prev
next >
Wrap
Text File
|
1989-05-31
|
29KB
|
1,022 lines
Subject: v19i036: A software configuration management system, Part23/33
Newsgroups: comp.sources.unix
Sender: sources
Approved: rsalz@uunet.UU.NET
Submitted-by: Axel Mahler <unido!coma!axel>
Posting-number: Volume 19, Issue 36
Archive-name: shape/part23
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 23 (of 33)."
# Contents: src/afs/afbpool.c
# Wrapped by rsalz@papaya.bbn.com on Thu Jun 1 19:27:15 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'src/afs/afbpool.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/afs/afbpool.c'\"
else
echo shar: Extracting \"'src/afs/afbpool.c'\" \(26801 characters\)
sed "s/^X//" >'src/afs/afbpool.c' <<'END_OF_FILE'
X/*
X * Copyright (C) 1989, 1990 W. Koch, A. Lampen, A. Mahler, W. Obst,
X * and U. Pralle
X *
X * This software is published on an as-is basis. There is ABSOLUTELY NO
X * WARRANTY for any part of this software to work correctly or as described
X * in the manuals. We do not accept any liability for any kind of damage
X * caused by use of this software, such as loss of data, time, money, or
X * effort.
X *
X * Permission is granted to use, copy, modify, or distribute any part of
X * this software as long as this is done without asking for charge, and
X * provided that this copyright notice is retained as part of the source
X * files. You may charge a distribution fee for the physical act of
X * transferring a copy, and you may at your option offer warranty
X * protection in exchange for a fee.
X *
X * Direct questions to: Tech. Univ. Berlin
X * Wilfried Koch
X * Sekr. FR 5-6
X * Franklinstr. 28/29
X * D-1000 Berlin 10, West Germany
X *
X * Tel: +49-30-314-22972
X * E-mail: shape@coma.uucp or shape@db0tui62.bitnet
X */
X/*
X * Shape/AFS
X *
X * afbpool.c -- read/write binary-pool control files (ndbm version)
X *
X * Author: Andreas Lampen, TU-Berlin (andy@coma.UUCP)
X * (andy@db0tui62.BITNET)
X *
X * $Header: afbpool.c[1.5] Wed Feb 22 16:27:14 1989 andy@coma published $
X *
X * EXPORT:
X * af_rbplist -- read list of files in binary pool
X * af_delbpentry -- delete file entry in binary pool
X * af_rplbpentry -- replace file entry in binary pool
X * af_isbpfile -- see if a given file belongs to binary pool
X * af_detbpool -- detach binary pool
X */
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <sys/dir.h>
X#include <sys/file.h>
X#include <sys/time.h>
X#include <string.h>
X#ifdef SUNOS_4_0
X#include <strings.h>
X#endif
X#ifdef OLDDBM
X#undef NULL
X#include <dbm.h>
X#undef NULL
X#else
X#include <ndbm.h>
X#endif
X
X#include "typeconv.h"
X#include "afsys.h"
X#include "afs.h"
X#include "afarchive.h"
X
X#ifdef MEMDEBUG
Xextern FILE *memprot;
X#endif
X
X/*==========================================================================
X * definition of binary pool revision list
X * plus hashtable for faster access
X *
X *==========================================================================*/
X
XLOCAL Af_revlist bplst;
X /* base address of all binary pool list descriptors */
XLOCAL Af_revlist *bplists = (Af_revlist *)0;
X /* base address of freelist for binary pool list descriptors */
XLOCAL Af_revlist *bpfreelist = &bplst; /* beginning of freelist */
X
XLOCAL Af_hash bphash;
X
XLOCAL Af_revlist *initlist (path, mode)
X char *path;
X int mode;
X{
X static bool hinit = FALSE; /* indicate if hashtable is yet initialized */
X int af_fhash();
X register i;
X Af_revlist *list, *oldlist, **oldptr, *tail;
X char *malloc(), *pathsym, *arname;
X
X oldptr = &oldlist;
X /* init hashtable if it is not yet done */
X if (!hinit)
X {
X (void) af_hashinit (&bphash, AF_MAXLISTS, af_fhash);
X hinit = TRUE;
X }
X
X pathsym = af_entersym (path);
X
X /* if there are open archives check if desired archive is loaded yet */
X if (bplists != (Af_revlist *)0)
X {
X if (af_symlookup (&bphash, path, (Af_revlist *)0, oldptr))
X {
X /* found something */
X /* if it is the right list */
X if (oldlist->af_cattrs.af_syspath == pathsym)
X return (oldlist);
X /* else continue the search as long as there are entries */
X while (af_symlookup (&bphash, path, oldlist, oldptr))
X {
X if (oldlist->af_cattrs.af_syspath == pathsym)
X return (oldlist);
X }
X }
X }
X
X /* check if AFS subdirectory exists */
X if ((arname = af_gbpname (path)) == (char *)0)
X {
X if (mode == AF_READ)
X SFAIL ("initlist", "", AF_ENOAFSDIR, (Af_revlist *)0)
X else
X FAIL ("initlist", "", AF_ENOAFSDIR, (Af_revlist *)0);
X }
X
X /* if there are no more descriptors available - allocate new space */
X if (bpfreelist == (Af_revlist *)0)
X {
X if ((bpfreelist = (Af_revlist *) malloc ((unsigned) (AF_LISTSEG * sizeof (Af_revlist)))) == (Af_revlist *)0)
X FAIL ("initlist", "malloc(i)", AF_ESYSERR, (Af_revlist *)0);
X
X /* build up new freelist */
X for (i=1; i<AF_LISTSEG; i++)
X bpfreelist[i-1].af_next = &(bpfreelist[i]);
X bpfreelist[AF_LISTSEG-1].af_next = (Af_revlist *)0;
X }
X
X if (bplists != (Af_revlist *)0)
X {
X tail = bplists->af_next;
X bplists->af_next = bpfreelist;
X bpfreelist = bpfreelist->af_next;
X list = bplists->af_next;
X bzero ((char *)list, sizeof (*list));
X
X list->af_next = tail;
X }
X else
X {
X list = bpfreelist;
X bpfreelist = bpfreelist->af_next;
X /* initialize whole struct (i.e. set af_next to "nil") */
X bzero ((char *)list, sizeof (*list));
X bplists = list;
X }
X
X list->af_mem = (char *)0;
X
X /* initialize list structure */
X list->af_cattrs.af_host = af_gethostname ();
X list->af_cattrs.af_syspath = pathsym;
X list->af_arfilename = arname;
X list->af_busyfilename = af_entersym ("");
X
X list->af_listlen = af_gmaxbpsize (list->af_arfilename);
X if ((list->af_list = (Af_vattrs *)af_malloc (list, (unsigned) (list->af_listlen * sizeof(Af_vattrs)))) == (Af_vattrs *)0)
X FAIL ("initlist", "malloc", AF_ESYSERR, (Af_revlist *)0);
X
X bzero ((char *)list->af_list, list->af_listlen * sizeof (Af_vattrs));
X
X list->af_extent |= AF_BPOOL;
X list->af_extent |= AF_UXWRITE;
X list->af_nrevs = 0;
X
X /* add list to hashtable */
X (void) af_hashsym (&bphash, path, list);
X#ifdef MEMDEBUG
X fprintf (memprot, "InitBP (%s)\n", path);
X#endif
X
X return (list);
X}
X
X/*==========================================================================
X * af_dbmstring -- build dbm string from attrbuf
X *
X *==========================================================================*/
X
XLOCAL datum af_dbmstring (key, size)
X Af_key *key;
X int size; /* size of dbm key element */
X{
X static datum data;
X static char string[MAXDBMLEN];
X char *ptrlist[AF_MAXUDAS], *udaptr;
X register i;
X int maxstrlen;
X
X data.dptr = string;
X
X /* enter all relevant attributes */
X#ifdef ULTRIX_2_0
X (void) sprintf (string, "%s %s %s %s %d %d %s %s \0",
X CATTR(key).af_host, CATTR(key).af_syspath, VATTR(key).af_name,
X NOTMT (VATTR(key).af_type), VATTR(key).af_gen, VATTR(key).af_rev,
X NOTMT (VATTR(key).af_variant), VATTR(key).af_auname);
X (void) sprintf (&string[strlen(string)], "%s %o %d %d %d %d \0",
X VATTR(key).af_auhost, VATTR(key).af_mode, VATTR(key).af_fsize,
X VATTR(key).af_mtime, VATTR(key).af_atime, VATTR(key).af_ctime);
X#else
X (void) sprintf (string, "%s %s %s %s %d %d %s %s %s %o %d %d %d %d \0",
X CATTR(key).af_host, CATTR(key).af_syspath, VATTR(key).af_name,
X NOTMT (VATTR(key).af_type), VATTR(key).af_gen, VATTR(key).af_rev,
X NOTMT (VATTR(key).af_variant), VATTR(key).af_auname,
X VATTR(key).af_auhost, VATTR(key).af_mode, VATTR(key).af_fsize,
X VATTR(key).af_mtime, VATTR(key).af_atime, VATTR(key).af_ctime);
X#endif
X (void) strcat (string, AF_UDAID);
X data.dsize = strlen (data.dptr) + sizeof (char);
X
X /* add user defined attributes */
X (void) af_lhashsyms (&(VATTR(key).af_uhtab), ptrlist);
X i=0;
X udaptr = string;
X maxstrlen = (MAXDBMLEN - DBMLOSS) - size;
X while (ptrlist[i])
X {
X if ((data.dsize += ((strlen (ptrlist[i])) + sizeof (char))) >= maxstrlen)
X {
X data.dptr = (char *)0;
X FAIL ("dbmstring", "", AF_ETOOLONG, data);
X }
X udaptr = &udaptr[strlen(udaptr)+1];
X (void) strcpy (udaptr, ptrlist[i]);
X i++;
X }
X
X udaptr[strlen(udaptr)+1] = '\0';
X data.dsize++;
X
X return (data);
X} /* end af_dbmstring */
X
X/*===================================================================
X * af_dbmkey -- build attrbuf from dbm entry
X *===================================================================*/
X
XLOCAL af_dbmkey (data, dbmkey, afkey)
X datum *data, *dbmkey;
X Af_key *afkey;
X{
X char name[MAXNAMLEN], type[MAXTYPLEN], variant[MAXVARLEN], *udaptr;
X char host[MAXHOSTNAMELEN], syspath[MAXNAMLEN*4];
X char auhost[MAXHOSTNAMELEN], auname[MAXNAMLEN];
X int af_fhash();
X
X /* do initializations */
X VATTR(afkey).af_state = AF_NOSTATE;
X VATTR(afkey).af_class = AF_DERIVED | AF_VALID;
X VATTR(afkey).af_stime = AF_NOTIME;
X VATTR(afkey).af_lckname = (char *)0;
X VATTR(afkey).af_lckhost = (char *)0;
X VATTR(afkey).af_ltime = AF_NOTIME;
X VATTR(afkey).af_notesize = 0;
X VATTR(afkey).af_note = (char *)0;
X VATTR(afkey).af_repr = AF_FILE;
X VATTR(afkey).af_dsize = 0;
X VATTR(afkey).af_data = (char *)0;
X VATTR(afkey).af_nlinks = 0;
X VATTR(afkey).af_succgen = AF_NOVNUM;
X VATTR(afkey).af_succrev = AF_NOVNUM;
X VATTR(afkey).af_predgen = AF_NOVNUM;
X VATTR(afkey).af_predrev = AF_NOVNUM;
X
X (void) sscanf (data->dptr, "%s%s%s%s%ld%ld%s%s%s%ho%ld%ld%ld%ld",
X host, syspath, name, type,
X &(VATTR(afkey).af_gen), &(VATTR(afkey).af_rev),
X variant, auname, auhost, &(VATTR(afkey).af_mode),
X &(VATTR(afkey).af_fsize), &(VATTR(afkey).af_mtime),
X &(VATTR(afkey).af_atime),&(VATTR(afkey).af_ctime));
X
X /* check plausibility of host and syspath */
X if (strcmp (host, CATTR(afkey).af_host) ||
X strcmp (syspath, CATTR(afkey).af_syspath))
X af_wng ("dbmkey", "location of bpool possibly not correct");
X
X if (!strcmp (type, AF_NOSTRING))
X type[0] = '\0';
X if (!strcmp (variant, AF_NOSTRING))
X variant[0] = '\0';
X
X VATTR(afkey).af_name = af_entersym (name);
X
X if (type[0])
X VATTR(afkey).af_type = af_entersym (type);
X else
X VATTR(afkey).af_type = (char *)0;
X
X if (variant[0])
X VATTR(afkey).af_variant = af_entersym (variant);
X else
X VATTR(afkey).af_variant = (char *)0;
X
X VATTR(afkey).af_auname = af_entersym (auname);
X VATTR(afkey).af_auhost = af_enterhost (auhost);
X VATTR(afkey).af_hashname = af_entersym (dbmkey->dptr);
X
X /* read user defined attributes */
X
X udaptr = rindex (data->dptr, AF_UDAID[0]);
X if (strcmp (udaptr, AF_UDAID))
X {
X /* this should not happen very often */
X udaptr = index (data->dptr, AF_UDAID[0]);
X while ((udaptr) && (!strcmp (udaptr, AF_UDAID)))
X udaptr = index (udaptr, AF_UDAID[0]);
X if (!udaptr)
X FAIL ("dbmkey", "cannot find udas", AF_EINCONSIST, ERROR);
X }
X
X /* build up hashlist and read user defined attributes */
X if (af_hashinit (&(VATTR(afkey).af_uhtab), AF_MAXUDAS, af_fhash) == ERROR)
X return (ERROR);
X
X udaptr += (AF_IDSTRLEN + sizeof (char));
X while (udaptr[0])
X {
X (void) af_hashsym (&(VATTR(afkey).af_uhtab), udaptr, (Af_revlist *)0);
X#ifdef MEMDEBUG
X fprintf (memprot, "UdaBP (%s)\n", udaptr);
X#endif
X VATTR(afkey).af_udanum++;
X udaptr = (index (udaptr, '\0') + sizeof (char));
X }
X return (AF_OK);
X} /* end af_dbmkey */
X
X/*===================================================================
X * gbpsize -- get binary pool size and owner
X *===================================================================*/
X
X#ifdef OLDDBM
XLOCAL Af_user *gbpsize (size)
X#else
XLOCAL Af_user *gbpsize (db, size)
X DBM *db;
X#endif
X short *size;
X{
X static Af_user owner;
X datum data, dbkey;
X
X static char *stdentryname = AF_BPSTDENTRY;
X
X dbkey.dptr = stdentryname;
X dbkey.dsize = strlen (AF_BPSTDENTRY);
X
X#ifdef OLDDBM
X data = fetch (dbkey);
X#else
X data = dbm_fetch (db, dbkey);
X#endif
X if (data.dptr == (char *)0)
X {
X *size = 0;
X return (af_getuser (getuid()));
X }
X else
X {
X (void) sscanf (data.dptr, "%hd%s%s", size, owner.af_username,owner.af_userhost);
X return (&owner);
X }
X}
X
X/*===================================================================
X * pbpsize -- put binary pool size and owner
X *===================================================================*/
X
X#ifdef OLDDBM
XLOCAL pbpsize (size, owner)
X#else
XLOCAL pbpsize (db, size, owner)
X DBM *db;
X#endif
X int size;
X Af_user *owner;
X{
X datum data, dbkey;
X static char str[32], *stdentryname = AF_BPSTDENTRY;
X
X dbkey.dptr = stdentryname;
X dbkey.dsize = strlen (AF_BPSTDENTRY);
X
X (void) sprintf (str, "%d %s %s\0", size, owner->af_username, owner->af_userhost);
X data.dptr = str;
X data.dsize = strlen (str) + sizeof (char);
X
X#ifdef OLDDBM
X store (dbkey, data);
X#else
X (void) dbm_store (db, dbkey, data, DBM_REPLACE);
X#endif
X return (AF_OK);
X}
X
X/*================================================================
X * af_lookupbpentry -- see if bpentry is loaded yet
X * returns position in list
X *
X *================================================================*/
X
XLOCAL af_lookupbpentry (list, hashname)
X Af_revlist *list;
X char *hashname;
X{
X int i=0, j=0;
X
X for (; i < list->af_listlen; i++)
X {
X /* if entry is not valid */
X if (!(list->af_list[i].af_class & AF_VALID))
X continue;
X if (!strcmp (list->af_list[i].af_hashname, hashname))
X return (i);
X j++;
X if (j >= list->af_nrevs)
X return (ERROR);
X }
X FAIL ("lookupbpentry", "cannot find binary pool entry", AF_EINTERNAL, ERROR);
X}
X
X#ifdef OLDDBM
Xstatic char *bpool;
Xstatic bool bpwrite = FALSE;
X#endif
X
X/*==========================================================================
X * af_rbplist -- read all binary pool entries
X *
X *==========================================================================*/
X
XEXPORT Af_revlist *af_rbplist (path)
X char *path;
X{
X datum dbkey, data;
X#ifndef OLDDBM
X DBM *db;
X#endif
X int i=0, count=0;
X Af_key entrykey;
X Af_revlist *list;
X Af_user *owner;
X
X if ((list = initlist (path, AF_READ)) == (Af_revlist *)0)
X return ((Af_revlist *)0);
X
X if (list->af_extent & AF_COMPLETE)
X return (list);
X
X#ifdef OLDDBM
X if (list->af_arfilename != bpool)
X {
X char bpfilename[MAXNAMLEN+1];
X FILE *tmpfdes;
X /* test existence of binary pool files */
X (void) sprintf (bpfilename, "%s.dir\0", list->af_arfilename);
X if (af_sysaccess (bpfilename, 0) == -1)
X {
X if (bpwrite)
X {
X /* create bpool files */
X tmpfdes = fopen (bpfilename, "w");
X (void) fclose (tmpfdes);
X (void) sprintf (bpfilename, "%s.pag\0", list->af_arfilename);
X tmpfdes = fopen (bpfilename, "w");
X (void) fclose (tmpfdes);
X }
X else
X SFAIL ("rbplist", "dbm_open", AF_ENOAFSDIR, (Af_revlist *)0);
X }
X if (dbminit (list->af_arfilename) != AF_OK)
X {
X (void) af_detbpool (list);
X SFAIL ("rbplist", "dbm_open", AF_ENOAFSDIR, (Af_revlist *)0);
X }
X bpool = list->af_arfilename;
X }
X#else
X if ((db = dbm_open (list->af_arfilename, O_RDONLY, 0664)) == (DBM *)0)
X {
X (void) af_detbpool (list);
X SFAIL ("rbplist", "dbm_open", AF_ENOAFSDIR, (Af_revlist *)0);
X }
X#endif
X
X /* if list was empty up to now */
X if (list->af_nrevs == 0)
X {
X#ifdef OLDDBM
X owner = gbpsize (&list->af_nrevs);
X#else
X owner = gbpsize (db, &list->af_nrevs);
X#endif
X list->af_cattrs.af_ownname = af_entersym (owner->af_username);
X list->af_cattrs.af_ownhost = af_enterhost (owner->af_userhost);
X }
X else
X /* if there are no references to the list, delete all entries and read */
X /* the whole binary pool. This is (hopefully) faster than updating */
X {
X if (list->af_refcount == 0)
X {
X for (i = 0; i < list->af_listlen; i++)
X {
X if (list->af_list[i].af_class & AF_VALID)
X {
X af_hashfree (&(list->af_list[i].af_uhtab));
X list->af_list[i].af_class &= ~AF_VALID;
X }
X }
X af_frmemlist (list);
X }
X }
X
X i=0;
X#ifdef OLDDBM
X for (dbkey = firstkey(); dbkey.dptr != NULL; dbkey = nextkey(dbkey))
X#else
X for (dbkey = dbm_firstkey(db); dbkey.dptr != NULL; dbkey = dbm_nextkey(db))
X#endif
X {
X if (!strncmp (dbkey.dptr, AF_BPSTDENTRY, AF_IDSTRLEN))
X continue;
X /* if there are existing references to binary pool preserve all */
X /* attribute buffers that are aleady read in and skip used places */
X if (i == list->af_listlen) /* if list is full */
X {
X if (af_lookupbpentry (list, dbkey.dptr) != ERROR)
X count++;
X else /* delete all additional entries in bpool has shrunk */
X {
X#ifdef OLDDBM
X delete (dbkey);
X#else
X (void) dbm_delete (db, dbkey);
X#endif
X (void) af_unlink (af_bpfilename (path, dbkey.dptr));
X }
X continue;
X }
X count++;
X if (list->af_refcount > 0)
X {
X while (list->af_list[i].af_class & AF_VALID)
X i++;
X if (af_lookupbpentry (list, dbkey.dptr) != ERROR)
X continue;
X }
X#ifdef OLDDBM
X data = fetch (dbkey);
X#else
X data = dbm_fetch (db, dbkey);
X#endif
X /* check if file exists. If not, ignore this entry */
X /* this check may be omitted in further releases */
X if (af_sysaccess (af_bpfilename (path, dbkey.dptr), 0) == AF_OK)
X {
X entrykey.af_ldes = list;
X entrykey.af_lpos = i;
X (void) af_dbmkey (&data, &dbkey, &entrykey);
X i++;
X }
X else
X count--;
X }
X
X list->af_nrevs = count;
X
X /* clear "incomplete" bit */
X list->af_extent |= AF_COMPLETE;
X
X#ifndef OLDDBM
X dbm_close (db);
X#endif
X return (list);
X}
X
X
X/*==========================================================================
X * af_delbpentry -- delete binary pool entry
X *
X *==========================================================================*/
X
XEXPORT af_delbpentry (key)
X Af_key *key;
X{
X datum dbkey;
X#ifndef OLDDBM
X DBM *db;
X#endif
X short listsize;
X Af_revlist *list;
X Af_user *owner;
X
X if ((list = initlist (CATTR(key).af_syspath, AF_RDWR)) == (Af_revlist *)0)
X return (ERROR);
X
X if (key->af_ldes != list)
X FAIL ("delbpentry", "", AF_EINVKEY, ERROR);
X
X#ifdef OLDDBM
X if (list->af_arfilename != bpool)
X {
X char bpfilename[MAXNAMLEN+1];
X FILE *tmpfdes;
X /* test existence of binary pool files */
X (void) sprintf (bpfilename, "%s.dir\0", list->af_arfilename);
X if (af_sysaccess (bpfilename, 0) == -1)
X {
X /* create bpool files */
X tmpfdes = fopen (bpfilename, "w");
X (void) fclose (tmpfdes);
X (void) sprintf (bpfilename, "%s.pag\0", list->af_arfilename);
X tmpfdes = fopen (bpfilename, "w");
X (void) fclose (tmpfdes);
X }
X if (dbminit (list->af_arfilename) != AF_OK)
X {
X (void) af_detbpool (list);
X FAIL ("delbpentry", "dbm_open", AF_ESYSERR, ERROR);
X }
X bpool = list->af_arfilename;
X }
X#else
X if ((db = dbm_open (list->af_arfilename, O_RDWR|O_CREAT, 0664)) == (DBM *)0)
X {
X (void) af_detbpool (list);
X FAIL ("delbpentry", "dbm_open", AF_ESYSERR, ERROR);
X }
X#endif
X
X dbkey.dptr = VATTR(key).af_hashname;
X dbkey.dsize = strlen (dbkey.dptr) + sizeof (char);
X#ifdef OLDDBM
X delete (dbkey);
X#else
X (void) dbm_delete (db, dbkey);
X#endif
X (void) af_unlink (af_bpfilename (CATTR(key).af_syspath, VATTR(key).af_hashname));
X#ifdef OLDDBM
X owner = gbpsize (&listsize);
X#else
X owner = gbpsize (db, &listsize);
X#endif
X list->af_cattrs.af_ownname = af_entersym (owner->af_username);
X list->af_cattrs.af_ownhost = af_enterhost (owner->af_userhost);
X listsize--;
X list->af_nrevs--;
X#ifdef OLDDBM
X (void) pbpsize (list->af_nrevs, owner);
X#else
X (void) pbpsize (db, list->af_nrevs, owner);
X#endif
X
X /* clear "valid" bit in attribute buffer and free allocated memory */
X af_hashfree (&(VATTR(key).af_uhtab));
X VATTR(key).af_class &= ~AF_VALID;
X
X#ifndef OLDDBM
X dbm_close (db);
X#endif
X return (AF_OK);
X}
X
X
X/*==========================================================================
X * af_rplbpentry -- replace binary pool entry
X *
X *==========================================================================*/
X
XEXPORT af_rplbpentry (oldkey, newkey, bpkey)
X Af_key *oldkey, *newkey, *bpkey;
X{
X datum dbkey, data;
X#ifndef OLDDBM
X DBM *db;
X#else
X datum exdata;
X#endif
X bool add = FALSE, found = FALSE;
X short freepos, listsize, i;
X Af_revlist *list;
X Af_user *owner;
X time_t lastacc;
X struct timeval tvp[2];
X char *bpname;
X int af_fhash();
X
X if ((list = initlist (CATTR(newkey).af_syspath, AF_RDWR)) == (Af_revlist *)0)
X return (ERROR);
X
X if ((oldkey != (Af_key *)0) && (oldkey->af_ldes != list))
X FAIL ("rplbpentry", "", AF_EINVKEY, ERROR);
X
X#ifdef OLDDBM
X if (list->af_arfilename != bpool)
X {
X char bpfilename[MAXNAMLEN+1];
X FILE *tmpfdes;
X /* test existence of binary pool files */
X (void) sprintf (bpfilename, "%s.dir\0", list->af_arfilename);
X if (af_sysaccess (bpfilename, 0) == -1)
X {
X /* create bpool files */
X tmpfdes = fopen (bpfilename, "w");
X (void) fclose (tmpfdes);
X (void) sprintf (bpfilename, "%s.pag\0", list->af_arfilename);
X tmpfdes = fopen (bpfilename, "w");
X (void) fclose (tmpfdes);
X }
X if (dbminit (list->af_arfilename) != AF_OK)
X {
X (void) af_detbpool (list);
X FAIL ("rplbpentry", "dbm_open", AF_ESYSERR, ERROR);
X }
X bpool = list->af_arfilename;
X }
X#else
X if ((db = dbm_open (list->af_arfilename, O_RDWR|O_CREAT, 0664)) == (DBM *)0)
X {
X (void) af_detbpool (list);
X FAIL ("rplbpentry", "dbm_open", AF_ESYSERR, ERROR);
X }
X#endif
X
X if (oldkey == (Af_key *)0)
X {
X /* if we actually have to "add" a file */
X#ifdef OLDDBM
X owner = gbpsize (&listsize);
X#else
X owner = gbpsize (db, &listsize);
X#endif
X list->af_cattrs.af_ownname = af_entersym (owner->af_username);
X list->af_cattrs.af_ownhost = af_enterhost (owner->af_userhost);
X if (listsize < list->af_listlen)
X {
X add = TRUE;
X /* look for free attribute buffer in bplist */
X freepos = list->af_listlen-1;
X while ((list->af_list[freepos].af_class & AF_VALID) && (freepos >=0))
X freepos--;
X if (freepos == -1)
X {
X#ifndef OLDDBM
X dbm_close (db);
X#endif
X FAIL ("rplbpentry", "no free entry in binary pool", AF_EINCONSIST, ERROR);
X }
X }
X else
X {
X /* remove the oldest (->af_atime) file */
X /* read in whole list of bpfiles */
X#ifdef OLDDBM
X bpwrite = TRUE;
X#endif
X if ((list = af_rbplist (list->af_cattrs.af_syspath))
X == (Af_revlist *)0)
X return (ERROR);
X#ifdef OLDDBM
X bpwrite = FALSE;
X#endif
X
X lastacc = (time_t)af_acttime ();
X
X for (i=0; i < list->af_nrevs; i++)
X {
X if ((!list->af_list[i].af_nlinks) &&
X (list->af_list[i].af_atime < lastacc))
X {
X freepos = i;
X lastacc = list->af_list[freepos].af_atime;
X dbkey.dptr = list->af_list[freepos].af_hashname;
X found = TRUE;
X }
X }
X
X if (!found)
X FAIL ("rplbpentry", "", AF_EBPFULL, ERROR);
X
X dbkey.dsize = strlen (dbkey.dptr) + sizeof (char);
X#ifdef OLDDBM
X delete (dbkey);
X#else
X (void) dbm_delete (db, dbkey);
X#endif
X if (oldkey != newkey)
X (void) af_unlink (af_bpfilename (list->af_cattrs.af_syspath, dbkey.dptr));
X }
X } /* if (oldkey == (Af_key *)0) then ... */
X else
X {
X if (oldkey != newkey)
X {
X dbkey.dptr = VATTR(oldkey).af_hashname;
X dbkey.dsize = strlen (dbkey.dptr) + sizeof (char);
X#ifdef OLDDBM
X delete (dbkey);
X#else
X (void) dbm_delete (db, dbkey);
X#endif
X (void) af_unlink (af_bpfilename (CATTR(oldkey).af_syspath, dbkey.dptr));
X }
X freepos = oldkey->af_lpos;
X }
X
X /* enter new entry */
X if (oldkey != newkey)
X {
X i = 0;
X do
X {
X if (++i > list->af_listlen)
X FAIL ("rplbpentry",
X "cannot build unique hashname", AF_EINTERNAL, ERROR);
X dbkey.dptr =
X af_rbphashname (VATTR(newkey).af_name,VATTR(newkey).af_type,
X VATTR(newkey).af_gen, VATTR(newkey).af_rev,
X VATTR(newkey).af_variant, newkey->af_ldes, i);
X dbkey.dsize = strlen (dbkey.dptr) + sizeof (char);
X data = af_dbmstring (newkey, dbkey.dsize);
X if (data.dptr == (char *)0)
X return (ERROR);
X#ifdef OLDDBM
X exdata = fetch (dbkey);
X#endif
X }
X /* as long as key is not unique, try another one */
X#ifdef OLDDBM
X while (exdata.dptr);
X store (dbkey, data);
X#else
X while (dbm_store (db, dbkey, data, DBM_INSERT));
X#endif
X
X VATTR(newkey).af_hashname = dbkey.dptr;
X
X /*** copy file ***/
X bpname = af_bpfilename (CATTR(newkey).af_syspath, VATTR(newkey).af_hashname);
X if (af_cpfile (newkey->af_ldes->af_busyfilename, VATTR(newkey).af_fsize, bpname) == ERROR)
X FAIL ("rplbpentry", "cpfile", AF_ESYSERR, ERROR);
X /*** set modification and access date (not necessary) ***/
X tvp[0].tv_sec = VATTR(newkey).af_atime;
X tvp[0].tv_usec = 0;
X tvp[1].tv_sec = VATTR(newkey).af_mtime;
X tvp[1].tv_usec = 0;
X if (utimes (bpname, tvp) == ERROR)
X FAIL ("rplbpentry", "utimes", AF_ESYSERR, ERROR);
X (void) af_uchmod (bpname, (int) VATTR(newkey).af_mode);
X }
X else
X {
X dbkey.dptr = VATTR(newkey).af_hashname;
X dbkey.dsize = strlen (dbkey.dptr) + sizeof (char);
X data = af_dbmstring (newkey, dbkey.dsize);
X if (data.dptr == (char *)0)
X return (ERROR);
X#ifdef OLDDBM
X store (dbkey, data);
X#else
X (void) dbm_store (db, dbkey, data, DBM_REPLACE);
X#endif
X }
X
X /* build key for new entry */
X bpkey->af_ldes = list;
X bpkey->af_lpos = freepos;
X
X if (oldkey != newkey)
X {
X /* copy attribute buffers */
X VATTR(bpkey) = VATTR(newkey);
X /* copy hash table */
X (void) af_hashinit (&(VATTR(newkey).af_uhtab), AF_MAXUDAS, af_fhash);
X (void) af_hashcopy (&(VATTR(bpkey).af_uhtab), &(VATTR(newkey).af_uhtab));
X }
X
X /* if an "add" was performed -- update bplist in database */
X if (add)
X {
X listsize++;
X list->af_nrevs++;
X#ifdef OLDDBM
X (void) pbpsize (list->af_nrevs, owner);
X#else
X (void) pbpsize (db, list->af_nrevs, owner);
X#endif
X }
X
X#ifndef OLDDBM
X dbm_close (db);
X#endif
X return (AF_OK);
X} /* af_rplbpentry */
X
X
X/*==========================================================================
X * af_isbpfile
X *
X *==========================================================================*/
X
XEXPORT af_isbpfile (name)
X char *name;
X{
X return (!strncmp (name, AF_BPFILEID, AF_IDSTRLEN));
X}
X
X
X
X/*==========================================================================
X * af_detbpool
X *
X *==========================================================================*/
X
XEXPORT af_detbpool (list)
X Af_revlist *list;
X{
X register int i;
X Af_revlist *tmplist;
X
X /* if first list descriptor should be deleted - the base (af_lists) */
X /* has to be preserved */
X if (list == bplists)
X bplists = bplists->af_next;
X else
X {
X /* if archive list has more than one entry -- close gap in list */
X if ((tmplist = bplists) != (Af_revlist *)0)
X {
X while (tmplist->af_next != list)
X if ((tmplist = tmplist->af_next) == (Af_revlist *)0)
X FAIL ("detbpool", "binary pool lost", AF_EINTERNAL, ERROR);
X tmplist->af_next = list->af_next;
X }
X }
X
X /* remove list from hash table */
X (void) af_delsym (&bphash, list->af_cattrs.af_syspath, list);
X
X /* hang free entry at the beginning of freelist */
X list->af_next = bpfreelist;
X bpfreelist = list;
X
X /* free all allocated memory */
X for (i = 0; i < list->af_listlen; i++)
X {
X if (list->af_list[i].af_class & AF_VALID)
X af_hashfree (&(list->af_list[i].af_uhtab));
X }
X af_frmemlist (list);
X
X return (AF_OK);
X}
X
END_OF_FILE
if test 26801 -ne `wc -c <'src/afs/afbpool.c'`; then
echo shar: \"'src/afs/afbpool.c'\" unpacked with wrong size!
fi
# end of 'src/afs/afbpool.c'
fi
echo shar: End of archive 23 \(of 33\).
cp /dev/null ark23isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 33 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0