[comp.sources.unix] v19i036: A software configuration management system, Part23/33

rsalz@uunet.uu.net (Rich Salz) (06/07/89)

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
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.