home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume19
/
shape
/
part29
< prev
next >
Wrap
Text File
|
1989-05-31
|
38KB
|
1,136 lines
Subject: v19i042: A software configuration management system, Part29/33
Newsgroups: comp.sources.unix
Sender: sources
Approved: rsalz@uunet.UU.NET
Submitted-by: Axel Mahler <unido!coma!axel>
Posting-number: Volume 19, Issue 42
Archive-name: shape/part29
#! /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 29 (of 33)."
# Contents: src/afs/afarchive.c
# Wrapped by rsalz@papaya.bbn.com on Thu Jun 1 19:27:19 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'src/afs/afarchive.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/afs/afarchive.c'\"
else
echo shar: Extracting \"'src/afs/afarchive.c'\" \(35334 characters\)
sed "s/^X//" >'src/afs/afarchive.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 * afarchive.c -- read/write archives of attribute filesystem
X *
X * Author: Andreas Lampen, TU-Berlin (andy@coma.UUCP)
X * (andy@db0tui62.BITNET)
X *
X * $Header: afarchive.c[1.6] Wed Feb 22 16:27:01 1989 andy@coma published $
X *
X * EXPORT:
X * af_detarchive -- free descriptor for archive
X * af_readdata -- read data from archive
X * af_readattrs -- read attributes from archive
X * af_writearchive -- write it
X */
X
X#include <stdio.h>
X#include <string.h>
X#ifdef SUNOS_4_0
X#include <strings.h>
X#endif
X#include <sys/types.h>
X#include <sys/stat.h>
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
Xint af_fhash();
XUid_t getuid();
X
X/*==========================================================================
X * List of list-descriptors + hash table for faster access
X *
X * Allocated memory will never be freed up to now
X *
X *==========================================================================*/
X
X/* these two pointers should be local -- EXPORT only for debugging */
XLOCAL Af_revlist lst;
XEXPORT Af_revlist *af_lists = (Af_revlist *)0;
X /* base address of all list descriptors */
X
XEXPORT Af_revlist *af_freelist = &lst; /* beginning of freelist */
X
XLOCAL Af_hash af_arhash;
Xbool hinit = FALSE; /* indicate if hashtable is yet initialized */
X
X/*======================== init_ldes =======================================*/
X
XLOCAL Af_revlist *init_ldes (path, name, type)
X char *path, *name, *type;
X{
X register i;
X Af_revlist *list, *oldlist, **oldptr, *tail;
X char hashsymbol[MAXNAMLEN], *malloc(), *pathsym;
X
X oldptr = &oldlist;
X /* init hashtable if it is not yet done */
X if (!hinit)
X {
X (void) af_hashinit (&af_arhash, AF_MAXLISTS, af_fhash);
X hinit = TRUE;
X }
X
X pathsym = af_entersym (path);
X
X (void) strcpy (hashsymbol, name);
X if (type)
X if (type[0])
X {
X (void) strcat (hashsymbol, ".");
X (void) strcat (hashsymbol, type);
X }
X
X /* if there are open archives check if desired archive is loaded yet */
X if (af_lists != (Af_revlist *)0)
X {
X if (af_symlookup (&af_arhash, hashsymbol, (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 (&af_arhash, hashsymbol, oldlist, oldptr))
X {
X if (oldlist->af_cattrs.af_syspath == pathsym)
X return (oldlist);
X }
X }
X }
X
X /* if there are no more descriptors available - allocate new space */
X if (af_freelist == (Af_revlist *)0)
X {
X if ((af_freelist = (Af_revlist *) malloc ((unsigned) (AF_LISTSEG * sizeof (Af_revlist)))) == (Af_revlist *)0)
X FAIL ("readattrs", "malloc(i)", AF_ESYSERR, (Af_revlist *)0);
X
X /* build up new freelist */
X for (i=1; i<AF_LISTSEG; i++)
X af_freelist[i-1].af_next = &(af_freelist[i]);
X af_freelist[AF_LISTSEG-1].af_next = (Af_revlist *)0;
X }
X
X if (af_lists != (Af_revlist *)0)
X {
X tail = af_lists->af_next;
X af_lists->af_next = af_freelist;
X af_freelist = af_freelist->af_next;
X list = af_lists->af_next;
X bzero ((char *)list, sizeof (*list));
X
X list->af_next = tail;
X }
X else
X {
X list = af_freelist;
X af_freelist = af_freelist->af_next;
X /* initialize whole struct (i.e. set af_next to "nil") */
X bzero ((char *)list, sizeof (*list));
X af_lists = list;
X }
X
X list->af_mem = (char *)0;
X list->af_cattrs.af_host = af_gethostname ();
X list->af_cattrs.af_syspath = pathsym;
X list->af_lastmod = (time_t) 0;
X
X /* add list to hashtable */
X (void) af_hashsym (&af_arhash, hashsymbol, list);
X#ifdef MEMDEBUG
X fprintf (memprot, "InitArch (%s)\n", hashsymbol);
X#endif
X
X return (list);
X}
X
X
X/*==========================================================================
X * af_detarchive -- free descriptor for archive
X *
X *
X *==========================================================================*/
X
XEXPORT af_detarchive (archive)
X Af_revlist *archive;
X{
X register int i;
X Af_revlist *list;
X char hashsymbol[MAXNAMLEN], *type;
X
X /* if first list descriptor should be deleted - the base (af_lists) */
X /* has to be preserved */
X if (archive == af_lists)
X af_lists = af_lists->af_next;
X else
X {
X /* if archive list has more than one entry -- close gap in list */
X if ((list = af_lists) != (Af_revlist *)0)
X {
X while (list->af_next != archive)
X if ((list = list->af_next) == (Af_revlist *)0)
X FAIL ("detarchive", "archive lost", AF_EINTERNAL, ERROR);
X list->af_next = archive->af_next;
X }
X }
X
X /* remove list from hash table */
X type = af_aftype (archive->af_arfilename);
X (void) strcpy (hashsymbol, af_afname (archive->af_arfilename));
X if (type)
X if (type[0])
X {
X (void) strcat (hashsymbol, ".");
X (void) strcat (hashsymbol, type);
X }
X (void) af_delsym (&af_arhash, hashsymbol, archive);
X
X /* hang free entry at the beginning of freelist */
X archive->af_next = af_freelist;
X af_freelist = archive;
X
X /* free all allocated memory */
X for (i=0; i<archive->af_listlen; i++)
X {
X if (archive->af_list[i].af_class & AF_VALID)
X af_hashfree (&(archive->af_list[i].af_uhtab));
X }
X af_frmemlist (archive);
X
X return (AF_OK);
X}
X
X/*==========================================================================
X * firstitem, nextitem -- isolate items in input line
X *==========================================================================*/
X
XLOCAL char *firstitem (line)
X char *line;
X{
X char *sptr;
X
X /* skip leading blank */
X if ((sptr = index (&line[1], ' ')) == (char *)0)
X sptr = index (&line[1], '\n');
X
X *sptr = '\0';
X return (&line[1]);
X}
X
XLOCAL char *nextitem (line)
X char *line;
X{
X char *sptr, *finptr;
X
X sptr = &line[strlen(line)]+1; /* move to next entry */
X if ((finptr = index (sptr, ' ')) == (char *)0)
X finptr = index (sptr, '\n');
X *finptr = '\0';
X
X return (sptr);
X}
X
X/*======================= rddata ====================================*/
X
XLOCAL af_rddata (file, dbuf, list)
X FILE *file;
X char *dbuf;
X Af_revlist *list;
X{
X char idstr[AF_IDSTRLEN+1], *itemptr, line[AF_LINESIZ];
X int i, gen, rev, maxindex;
X off_t size, dpos = 0;
X
X /* if there is a valid busy version */
X if (list->af_list[0].af_class & AF_VALID)
X maxindex = list->af_nrevs;
X else
X maxindex = list->af_nrevs+1;
X
X idstr[AF_IDSTRLEN] = '\0';
X /* skip busy version */
X for (i=1; i < maxindex; i++)
X {
X (void) fgets (idstr, AF_IDSTRLEN+1, file);
X if (strcmp (idstr, AF_NOTEID))
X FAIL ("rddata", "wrong note-ID in datafile", AF_EINCONSIST, ERROR);
X (void) fgets (line, AF_LINESIZ, file);
X itemptr = firstitem (line);
X gen = atoi (itemptr);
X itemptr = nextitem (itemptr);
X rev = atoi (itemptr);
X itemptr = nextitem (itemptr);
X size = (off_t) atoi (itemptr);
X
X if ((list->af_list[i].af_gen != gen) || (list->af_list[i].af_rev != rev))
X FAIL ("rddata", "wrong version in datafile", AF_EINCONSIST, ERROR);
X
X /* read note */
X (void) fread (&(dbuf[dpos]), sizeof(char), (Size_t) size, file);
X list->af_list[i].af_notesize = size;
X list->af_list[i].af_note = &(dbuf[dpos]);
X /* replace newline by nullbyte */
X list->af_list[i].af_note[size-sizeof(char)] = '\0';
X dpos = dpos+size;
X
X (void) fgets (idstr, AF_IDSTRLEN+1, file);
X if (strcmp (idstr, AF_DATAID))
X FAIL ("rddata", "wrong data-ID in datafile", AF_EINCONSIST, ERROR);
X (void) fgets (line, AF_LINESIZ, file);
X itemptr = firstitem (line);
X gen = atoi (itemptr);
X itemptr = nextitem (itemptr);
X rev = atoi (itemptr);
X itemptr = nextitem (itemptr);
X itemptr = nextitem (itemptr);
X size = (off_t) atoi (itemptr);
X
X if ((list->af_list[i].af_gen != gen) || (list->af_list[i].af_rev != rev))
X FAIL ("rddata", "wrong version in datafile", AF_EINCONSIST, ERROR);
X
X /* read data */
X (void) fread (&(dbuf[dpos]), sizeof(char), (Size_t) size, file);
X list->af_list[i].af_data = &(dbuf[dpos]);
X dpos = dpos+size;
X }
X return (AF_OK);
X} /* af_rddata */
X
X/*==========================================================================
X * af_readdata -- read notes and data section of archive file
X *
X *
X *==========================================================================*/
X
XEXPORT af_readdata (list)
X Af_revlist *list;
X{
X char *data, idstr[AF_SEGSTRLEN+1], archname[MAXNAMLEN], line[AF_LINESIZ];
X FILE *archfile;
X short version;
X
X /* if notes are already loaded */
X if ((list->af_extent & AF_DATA) == AF_DATA)
X return (AF_OK);
X
X (void) strcpy (archname, list->af_arfilename);
X archname[strlen(archname)-sizeof(char)] = AF_DATAEXT;
X if ((archfile = fopen (archname, "r")) == (FILE *)0)
X FAIL ("readdata", "", AF_ENOAFSFILE, ERROR);
X
X idstr[AF_SEGSTRLEN] = '\0';
X (void) fgets (idstr, AF_SEGSTRLEN+1, archfile);
X if (strncmp (idstr, AF_DATAHEADER, AF_SEGSTRLEN))
X FAIL ("readdata", "wrong header in datafile", AF_EINCONSIST, ERROR);
X
X (void) fgets (line, AF_LINESIZ, archfile);
X version = atoi (line);
X if (version != AF_ARCURVERS)
X FAIL ("readdata", "unknown archive format version", AF_EINCONSIST, ERROR);
X
X /* allocate memory for data */
X if ((data = af_malloc (list, (unsigned) list->af_datasize)) == (char *)0)
X FAIL ("readdata", "malloc", AF_ESYSERR, ERROR);
X
X if (af_rddata (archfile, data, list) != AF_OK)
X return (ERROR);
X
X list->af_extent |= AF_DATA;
X (void) fclose (archfile);
X return (AF_OK);
X}
X
X/*======================= rdattrs ====================================*/
X
XLOCAL af_rdattrs (file, list, bibufptr)
X FILE *file;
X Af_revlist *list;
X struct stat *bibufptr;
X{
X char idstr[AF_IDSTRLEN+1], *itemptr, line[AF_LINESIZ];
X int i;
X bool writeok;
X Af_user *user, *owner, *af_garown();
X
X /* skip idstring */
X idstr[AF_IDSTRLEN] = '\0';
X (void) fgets (idstr, AF_IDSTRLEN+1, file);
X
X /* read constant attributes and variant of busy version */
X (void) fgets (line, AF_LINESIZ, file);
X
X /* check location (only host is checked up to now) */
X /* path, name and type could be checked too */
X
X itemptr = firstitem (line); /* host */
X if (strcmp (list->af_cattrs.af_host, itemptr))
X {
X /* FAIL ("rdattrs", "", AF_ELOC, ERROR); -- replaced by: */
X af_wng ("readattrs", "wrong hostname in archive file");
X list->af_cattrs.af_host = af_entersym (itemptr);
X }
X itemptr = nextitem (itemptr); /* path - skipped ... */
X itemptr = nextitem (itemptr); /* name - skipped ... */
X itemptr = nextitem (itemptr); /* type - skipped ... */
X
X itemptr = nextitem (itemptr); /* variant */
X if (strcmp (itemptr, AF_NOSTRING))
X list->af_list[0].af_variant = af_entersym (itemptr);
X else
X list->af_list[0].af_variant = (char *)0;
X
X /* get owner of archive directory */
X if ((owner = af_garown (list->af_arfilename, &writeok)) == (Af_user *)0)
X FAIL ("rdattrs", "cannot get owner of archive", AF_EINTERNAL, ERROR);
X list->af_cattrs.af_ownname = af_entersym (owner->af_username);
X list->af_cattrs.af_ownhost = af_enterhost (owner->af_userhost);
X
X if (writeok)
X list->af_extent |= AF_UXWRITE;
X
X /* read owner from archive */
X (void) fgets (idstr, AF_IDSTRLEN+1, file);
X (void) fgets (line, AF_LINESIZ, file); /* name and host of owner */
X /* plausibility of owner should be checked here */
X
X (void) fgets (idstr, AF_IDSTRLEN+1, file);
X (void) fgets (line, AF_LINESIZ, file); /* predecessor of busy object */
X itemptr = firstitem (line);
X list->af_list[0].af_predgen = atoi (itemptr);
X itemptr = nextitem (itemptr);
X list->af_list[0].af_predrev = atoi (itemptr);
X
X (void) fgets (idstr, AF_IDSTRLEN+1, file);
X (void) fgets (line, AF_LINESIZ, file); /* locker */
X itemptr = firstitem (line);
X if (strcmp (itemptr, AF_NOSTRING))
X {
X list->af_list[0].af_lckname = af_entersym (itemptr);
X itemptr = nextitem (itemptr);
X list->af_list[0].af_lckhost = af_enterhost (itemptr);
X }
X else
X {
X list->af_list[0].af_lckname = (char *)0;
X itemptr = nextitem (itemptr);
X list->af_list[0].af_lckhost = (char *)0;
X }
X itemptr = nextitem (itemptr);
X list->af_list[0].af_ltime = (time_t)atoi(itemptr);
X
X /* initialize and attributes for busy version */
X list->af_list[0].af_gen = AF_BUSYVERS;
X list->af_list[0].af_rev = AF_BUSYVERS;
X list->af_list[0].af_state = AF_BUSY;
X list->af_list[0].af_stime = AF_NOTIME;
X list->af_list[0].af_udanum = 0;
X list->af_list[0].af_repr = AF_FILE;
X list->af_list[0].af_dsize = (off_t) 0;
X list->af_list[0].af_data = (char *)0;
X list->af_list[0].af_hashname = (char *)0;
X list->af_list[0].af_nlinks = 0;
X list->af_list[0].af_succgen = AF_NOVNUM;
X list->af_list[0].af_succrev = AF_NOVNUM;
X
X if (bibufptr->st_ino) /* if there is a busy version */
X {
X list->af_list[0].af_class = AF_VALID;
X if ((user = af_getuser (bibufptr->st_uid)) == (Af_user *)0)
X {
X af_wng ("rdattrs", "invalid userID in inode of busy file");
X user = af_getuser (getuid());
X }
X list->af_list[0].af_auname = af_entersym (user->af_username);
X list->af_list[0].af_auhost = af_enterhost (user->af_userhost);
X list->af_list[0].af_mode = (u_short) bibufptr->st_mode;
X list->af_list[0].af_mtime = (time_t) af_cvttime (bibufptr->st_mtime);
X list->af_list[0].af_atime = (time_t) af_cvttime (bibufptr->st_atime);
X list->af_list[0].af_ctime = (time_t) af_cvttime (bibufptr->st_ctime);
X list->af_list[0].af_fsize = (off_t) bibufptr->st_size;
X }
X else
X {
X list->af_list[0].af_class = 0;
X list->af_list[0].af_auname = (char *)0;
X list->af_list[0].af_auhost = (char *)0;
X list->af_list[0].af_mode = AF_NOMODE;
X list->af_list[0].af_mtime = AF_NOTIME;
X list->af_list[0].af_atime = AF_NOTIME;
X list->af_list[0].af_ctime = AF_NOTIME;
X list->af_list[0].af_fsize = AF_NOTIME;
X }
X
X /* read list */
X for (i=1; i < list->af_nrevs; i++)
X {
X /* do initializations */
X list->af_list[i].af_class = AF_VALID;
X list->af_list[i].af_notesize = 0;
X list->af_list[i].af_note = (char *)0;
X list->af_list[i].af_data = (char *)0;
X list->af_list[i].af_nlinks = 0;
X list->af_list[i].af_hashname = (char *)0;
X
X /* enter name (set a pointer to the name-field of af_list[0]) */
X /* skip position 0 */
X if (i != 0)
X {
X list->af_list[i].af_name = list->af_list[0].af_name;
X list->af_list[i].af_type = list->af_list[0].af_type;
X }
X
X /* read revision ID */
X (void) fgets (idstr, AF_IDSTRLEN+1, file);
X if (strcmp (idstr, AF_REVID)) /* could be done for every field */
X FAIL ("rdattrs",
X "wrong revision-ID in archive file", AF_EINCONSIST, ERROR);
X (void) fgets (line, AF_LINESIZ, file);
X itemptr = firstitem (line);
X list->af_list[i].af_gen = atoi (itemptr);
X itemptr = nextitem (itemptr);
X list->af_list[i].af_rev = atoi (itemptr);
X itemptr = nextitem (itemptr);
X list->af_list[i].af_state = (short) atoi (itemptr);
X itemptr = nextitem (itemptr);
X (void) sscanf (itemptr, "%ho", &(list->af_list[i].af_mode));
X itemptr = nextitem (itemptr);
X if (strcmp (itemptr, AF_NOSTRING))
X list->af_list[i].af_variant = af_entersym (itemptr);
X else
X list->af_list[i].af_variant = (char *)0;
X
X /* read author*/
X (void) fgetc (file); /* skip tab */
X (void) fgets (idstr, AF_IDSTRLEN+1, file);
X (void) fgets (line, AF_LINESIZ, file); /* predecessor of busy object */
X itemptr = firstitem (line);
X list->af_list[i].af_auname = af_entersym (itemptr);
X itemptr = nextitem (itemptr);
X list->af_list[i].af_auhost = af_enterhost (itemptr);
X itemptr = nextitem (itemptr);
X if (strcmp (itemptr, AF_NOSTRING))
X {
X list->af_list[i].af_lckname = af_entersym (itemptr);
X itemptr = nextitem (itemptr);
X list->af_list[i].af_lckhost = af_enterhost (itemptr);
X }
X else
X {
X list->af_list[i].af_lckname = (char *)0;
X itemptr = nextitem (itemptr);
X list->af_list[i].af_lckhost = (char *)0;
X }
X
X /* read dates */
X (void) fgetc (file); /* skip tab */
X (void) fgets (idstr, AF_IDSTRLEN+1, file);
X (void) fgets (line, AF_LINESIZ, file);
X itemptr = firstitem (line);
X list->af_list[i].af_mtime = (time_t) atoi (itemptr);
X itemptr = nextitem (itemptr);
X list->af_list[i].af_atime = (time_t) atoi (itemptr);
X itemptr = nextitem (itemptr);
X list->af_list[i].af_ctime = (time_t) atoi (itemptr);
X itemptr = nextitem (itemptr);
X list->af_list[i].af_stime = (time_t) atoi (itemptr);
X itemptr = nextitem (itemptr);
X list->af_list[i].af_ltime = (time_t) atoi (itemptr);
X
X /* read kind of representation */
X (void) fgetc (file); /* skip tab */
X (void) fgets (idstr, AF_IDSTRLEN+1, file);
X (void) fgets (line, AF_LINESIZ, file);
X itemptr = firstitem (line);
X list->af_list[i].af_repr = (short) atoi (itemptr);
X itemptr = nextitem (itemptr);
X list->af_list[i].af_fsize = (off_t) atoi (itemptr);
X itemptr = nextitem (itemptr);
X list->af_list[i].af_dsize = (off_t) atoi (itemptr);
X itemptr = nextitem (itemptr);
X list->af_list[i].af_succgen = atoi (itemptr);
X itemptr = nextitem (itemptr);
X list->af_list[i].af_succrev = atoi (itemptr);
X itemptr = nextitem (itemptr);
X list->af_list[i].af_predgen = atoi (itemptr);
X itemptr = nextitem (itemptr);
X list->af_list[i].af_predrev = atoi (itemptr);
X }
X if (!(bibufptr->st_ino)) /* if there is no busy version */
X list->af_nrevs--;
X
X return (AF_OK);
X} /* af_rdattrs */
X
X/*======================= rdudas ====================================*/
X
X#define AF_UDASEGSIZ 8
X
XLOCAL af_rdudas (file, list)
X FILE *file;
X Af_revlist *list;
X{
X char idstr[AF_IDSTRLEN+1], *udabuf, *malloc(), *realloc();
X char *itemptr, line[AF_LINESIZ];
X int c, i, j, gen, rev, maxindex;
X
X /* if there is a valid busy version */
X if (list->af_list[0].af_class & AF_VALID)
X maxindex = list->af_nrevs;
X else
X maxindex = list->af_nrevs+1;
X
X (void) getc (file); /* skip newline */
X idstr[AF_IDSTRLEN] = '\0';
X for (i=0; i < maxindex; i++)
X {
X (void) fgets (idstr, AF_IDSTRLEN+1, file);
X if (strcmp (idstr, AF_UDAID))
X FAIL ("rdudas", "wrong uda-ID in archive file", AF_EINCONSIST, ERROR);
X (void) fgets (line, AF_LINESIZ, file);
X itemptr = firstitem (line);
X gen = atoi (itemptr);
X itemptr = nextitem (itemptr);
X rev = atoi (itemptr);
X
X if ((list->af_list[i].af_gen != gen) || (list->af_list[i].af_rev != rev))
X FAIL ("rdudas", "wrong version in archive file", AF_EINCONSIST, ERROR);
X
X /* build up hashlist and read user define attributes */
X if (af_hashinit (&list->af_list[i].af_uhtab, AF_MAXUDAS, af_fhash)
X == ERROR)
X return (ERROR);
X
X if (i == 0) /* initalize only once */
X {
X if ((udabuf = malloc ((unsigned) (AF_UDASEGSIZ * sizeof (char)))) == (char *)0)
X FAIL ("rdudas", "malloc", AF_ESYSERR, ERROR);
X }
X
X /* if there is *no* valid busy version, skip the user defined */
X /* attributes for the busy version */
X if ((i==0) && !(list->af_list[0].af_class & AF_VALID))
X {
X while (TRUE)
X {
X if ((c = getc (file)) == '\0')
X {
X if ((c = getc (file)) == '\0')
X break;
X }
X }
X (void) getc (file); /* skip trailing newline char */
X continue;
X }
X
X j = 0;
X while (TRUE)
X {
X if ((udabuf[j] = getc (file)) == '\0')
X {
X if (j != 0)
X {
X (void) af_hashsym (&list->af_list[i].af_uhtab, udabuf, (Af_revlist *)0);
X#ifdef MEMDEBUG
X fprintf (memprot, "Uda (%s)\n", udabuf);
X#endif
X list->af_list[i].af_udanum++;
X }
X /* a second nullbyte indicates the end of the list of udas */
X if ((c = getc (file)) == '\0')
X break;
X udabuf[0] = c;
X j = 1;
X }
X else
X {
X j++;
X if ((j % AF_UDASEGSIZ) == 0) /* if segment is full */
X {
X if ((udabuf = realloc (udabuf, (unsigned) ((j + AF_UDASEGSIZ) * sizeof (char)))) == (char *)0)
X FAIL ("rdudas", "realloc", AF_ESYSERR, ERROR);
X }
X }
X }
X (void) getc (file); /* skip trailing newline char */
X }
X free (udabuf);
X return (AF_OK);
X} /* af_rdudas */
X
X/*==========================================================================
X * af_readattrs -- read attributes from archive file
X *
X *
X *==========================================================================*/
X
XEXPORT Af_revlist *af_readattrs (path, name, type, mode)
X char *path, *name, *type;
X bool *mode;
X{
X char idstr[AF_SEGSTRLEN+1], line[AF_LINESIZ], *itemptr;
X FILE *archfile;
X struct stat bibuf, aibuf;
X Af_revlist *list, *init_ldes();
X short version;
X bool writeok;
X Af_user *user, *owner, *af_garown();
X
X if ((list = init_ldes (path, name, type)) == (Af_revlist *)0)
X return ((Af_revlist *)0);
X
X /* if attributes are already loaded */
X if ((list->af_extent & AF_ATTRS) == AF_ATTRS)
X {
X if (*mode == FALSE)
X {
X /* see if busy version has changed */
X if (lstat (list->af_busyfilename, &bibuf) == ERROR)
X bibuf.st_ctime = AF_NOTIME;
X if (bibuf.st_ctime != list->af_list[0].af_ctime)
X {
X /* update busy version */
X if (!(list->af_list[0].af_class & AF_VALID))
X {
X list->af_nrevs++;
X if (af_hashinit (&list->af_list[0].af_uhtab,
X AF_MAXUDAS, af_fhash) == ERROR)
X return ((Af_revlist *)0);
X list->af_list[0].af_class = AF_VALID;
X }
X if ((user = af_getuser (bibuf.st_uid)) == (Af_user *)0)
X {
X af_wng ("readattrs", "invalid userID in inode of busy file");
X user = af_getuser (getuid());
X }
X list->af_list[0].af_auname = af_entersym (user->af_username);
X list->af_list[0].af_auhost = af_enterhost (user->af_userhost);
X list->af_list[0].af_mode = (u_short) bibuf.st_mode;
X list->af_list[0].af_mtime = (time_t) af_cvttime (bibuf.st_mtime);
X list->af_list[0].af_atime = (time_t) af_cvttime (bibuf.st_atime);
X list->af_list[0].af_ctime = (time_t) af_cvttime (bibuf.st_ctime);
X list->af_list[0].af_fsize = (off_t) bibuf.st_size;
X }
X }
X *mode = TRUE;
X return (list);
X }
X else
X {
X *mode = FALSE;
X }
X
X if ((list->af_busyfilename = af_gbusname (list->af_cattrs.af_syspath,
X name, type)) == (char *)0)
X return ((Af_revlist *)0);
X
X list->af_arfilename = af_garname (list->af_cattrs.af_syspath, name, type);
X list->af_extent |= AF_ARCHIVE;
X
X if (lstat (list->af_busyfilename, &bibuf) == ERROR)
X bibuf.st_ino = 0;
X
X /* open archive */
X if ((list->af_arfilename == (char *)0) ||
X ((archfile = fopen (list->af_arfilename, "r")) == (FILE *)0))
X {
X if (bibuf.st_ino == 0) /* no busy file */
X {
X (void) af_detarchive (list);
X SFAIL ("readattrs", "", AF_ENOAFSFILE, (Af_revlist *)0);
X }
X list->af_nrevs = 1;
X list->af_listlen = AF_NEWREVS;
X list->af_extent |= AF_ALLSEGS;
X list->af_datasize = 0;
X
X /* determine author of busy file */
X if ((user = af_getuser (bibuf.st_uid)) == (Af_user *)0)
X {
X af_wng ("readattrs", "invalid userID in inode of busy file");
X user = af_getuser (getuid());
X }
X
X /* if an archive-directory exists, get its owner */
X if ((owner = af_garown (list->af_arfilename, &writeok)) == (Af_user *)0)
X {
X list->af_cattrs.af_ownname = af_entersym (user->af_username);
X list->af_cattrs.af_ownhost = af_enterhost (user->af_userhost);
X }
X else
X {
X list->af_cattrs.af_ownname = af_entersym (owner->af_username);
X list->af_cattrs.af_ownhost = af_enterhost (owner->af_userhost);
X }
X if (writeok)
X list->af_extent |= AF_UXWRITE;
X
X if ((list->af_list = (Af_vattrs *)af_malloc (list, (unsigned) (list->af_listlen * sizeof(Af_vattrs)))) == (Af_vattrs *)0)
X FAIL ("readattrs", "malloc,1", AF_ESYSERR, (Af_revlist *)0);
X
X bzero ((char *)list->af_list, list->af_listlen * sizeof (Af_vattrs));
X /* init attrbuf for busy version (relevant attrs only) */
X list->af_list[0].af_name = af_entersym (name);
X list->af_list[0].af_type = af_entersym (type);
X list->af_list[0].af_gen = AF_BUSYVERS;
X list->af_list[0].af_rev = AF_BUSYVERS;
X list->af_list[0].af_variant = (char *)0;
X list->af_list[0].af_state = AF_BUSY;
X list->af_list[0].af_class = AF_VALID;
X list->af_list[0].af_auname = af_entersym (user->af_username);
X list->af_list[0].af_auhost = af_enterhost (user->af_userhost);
X list->af_list[0].af_mode = (u_short) bibuf.st_mode;
X list->af_list[0].af_lckname = (char *)0;
X list->af_list[0].af_lckhost = (char *)0;
X list->af_list[0].af_mtime = (time_t) af_cvttime (bibuf.st_mtime);
X list->af_list[0].af_atime = (time_t) af_cvttime (bibuf.st_atime);
X list->af_list[0].af_ctime = (time_t) af_cvttime (bibuf.st_ctime);
X list->af_list[0].af_stime = AF_NOTIME;
X list->af_list[0].af_ltime = AF_NOTIME;
X list->af_list[0].af_notesize = 1;
X list->af_list[0].af_note = (char *)0;
X list->af_list[0].af_udanum = 0;
X if (af_hashinit (&list->af_list[0].af_uhtab, AF_MAXUDAS, af_fhash)
X == ERROR)
X return ((Af_revlist *)0);
X list->af_list[0].af_repr = AF_FILE;
X list->af_list[0].af_fsize = (off_t) bibuf.st_size;
X list->af_list[0].af_dsize = 0;
X list->af_list[0].af_data = (char *)0;
X list->af_list[0].af_hashname = (char *)0;
X list->af_list[0].af_nlinks = 0;
X list->af_list[0].af_succgen = AF_NOVNUM;
X list->af_list[0].af_succrev = AF_NOVNUM;
X list->af_list[0].af_predgen = AF_NOVNUM;
X list->af_list[0].af_predrev = AF_NOVNUM;
X return (list);
X }
X
X /* record date of last modification */
X (void) lstat (list->af_arfilename, &aibuf);
X list->af_lastmod = (time_t) af_cvttime (aibuf.st_mtime);
X
X /* archive file ??? */
X idstr[AF_SEGSTRLEN] = '\0';
X (void) fgets (idstr, AF_SEGSTRLEN+1, archfile);
X if (strncmp (idstr, AF_ARHEADER, AF_SEGSTRLEN))
X FAIL ("readattrs",
X "wrong header in archive file", AF_EINCONSIST, (Af_revlist *)0);
X
X /* read header */
X (void) fgets (line, AF_LINESIZ, archfile);
X itemptr = firstitem (line);
X version = atoi (itemptr);
X if (version != AF_ARCURVERS)
X FAIL ("readattrs",
X "unknown archive format version", AF_EINCONSIST, (Af_revlist *)0);
X itemptr = nextitem (itemptr);
X list->af_nrevs = atoi (itemptr);
X itemptr = nextitem (itemptr);
X list->af_datasize = atoi (itemptr);
X
X /* alloc memory for revision list (plus space for new revs) */
X list->af_listlen = list->af_nrevs + AF_NEWREVS;
X if ((list->af_list = (Af_vattrs *)af_malloc (list, (unsigned) (list->af_listlen * sizeof(Af_vattrs)))) == (Af_vattrs *)0)
X FAIL ("readattrs", "malloc,2", AF_ESYSERR, (Af_revlist *)0);
X
X bzero ((char *) list->af_list, list->af_listlen * sizeof (Af_vattrs));
X
X /* enter name and type */
X list->af_list[0].af_name = af_entersym (name);
X list->af_list[0].af_type = af_entersym (type);
X
X if (af_rdattrs (archfile, list, &bibuf) != AF_OK)
X return ((Af_revlist *)0);
X
X /* read id string for user defined attributes section*/
X (void) fgets (idstr, AF_SEGSTRLEN+1, archfile);
X if (strncmp (idstr, AF_UDASEG, AF_SEGSTRLEN))
X FAIL ("readattrs",
X "wrong udaseg-ID in archive file", AF_EINCONSIST, (Af_revlist *)0);
X
X if (af_rdudas (archfile, list) != AF_OK)
X return ((Af_revlist *)0);
X
X list->af_extent |= (AF_ATTRS | AF_COMPLETE);
X (void) fclose (archfile);
X return (list);
X} /* af_readattrs */
X
X
X/*==========================================================================
X * writearchive -- write archive file
X *
X *
X *==========================================================================*/
X
XEXPORT af_writearchive (list)
X Af_revlist *list;
X{
X int i, j, maxindex;
X FILE *tmpfile, *datafile;
X char tmpname[MAXNAMLEN], dataname[MAXNAMLEN], *ptrlist[AF_MAXUDAS];
X char archname[MAXNAMLEN];
X off_t datasize;
X Af_key *busyptr, *af_gbuskey();
X
X /* File locking mechanism should be inserted here */
X
X /* if all revisions have been removed */
X if (list->af_nrevs == 0)
X {
X (void) af_unlink (list->af_arfilename);
X (void) strcpy (archname, list->af_arfilename);
X archname[strlen(archname)-sizeof(char)] = AF_DATAEXT;
X (void) af_unlink (archname);
X return (AF_OK);
X }
X
X (void) strcpy (tmpname, list->af_arfilename);
X tmpname[strlen(tmpname) - sizeof(char)] = AF_ARCHTMP;
X af_regtmpfile (tmpname);
X /* open tmpfile */
X if ((tmpfile = fopen (tmpname, "w")) == (FILE *)0)
X FAIL ("writearchive", "fopen", AF_ESYSERR, ERROR);
X
X /* if there is no busy version - increase "nrevs" temporarily */
X busyptr = af_gbuskey (list);
X if (!(VATTR(busyptr).af_class & AF_VALID))
X list->af_nrevs++;
X
X /* write header */
X fprintf (tmpfile, "%s %d %d %ld\n", AF_ARHEADER, AF_ARCURVERS,
X list->af_nrevs, list->af_datasize);
X
X /* write constant attributes */
X fprintf (tmpfile, "%s %s %s %s %s %s\n", AF_NAMEID,
X list->af_cattrs.af_host,
X list->af_cattrs.af_syspath,
X list->af_list[0].af_name,
X NOTMT (list->af_list[0].af_type),
X NOTMT (list->af_list[0].af_variant));
X
X /* write owner */
X fprintf (tmpfile, "%s %s %s\n", AF_OWNID,
X list->af_cattrs.af_ownname,
X list->af_cattrs.af_ownhost);
X
X
X /* write predecessor and locker of busy version */
X fprintf (tmpfile, "%s %d %d\n%s %s %s %d\n", AF_PRDID,
X VATTR(busyptr).af_predgen,
X VATTR(busyptr).af_predrev, AF_LOCKID,
X NOTMT (VATTR(busyptr).af_lckname),
X NOTMT (VATTR(busyptr).af_lckhost),
X VATTR(busyptr).af_ltime);
X
X /* write list of version attributes */
X maxindex = list->af_nrevs;
X for (i=1; i < maxindex; i++)
X {
X /* skip deleted versions */
X if (!(list->af_list[i].af_class & AF_VALID))
X {
X maxindex++;
X continue;
X }
X
X /* write revision ID */
X fprintf (tmpfile, "%s %d %d %d %o %s\n", AF_REVID,
X list->af_list[i].af_gen,
X list->af_list[i].af_rev,
X list->af_list[i].af_state,
X list->af_list[i].af_mode,
X NOTMT (list->af_list[i].af_variant));
X
X /* write author */
X fprintf (tmpfile, "\t%s %s %s %s %s\n", AF_AUTHORID,
X list->af_list[i].af_auname,
X list->af_list[i].af_auhost,
X NOTMT (list->af_list[i].af_lckname),
X NOTMT (list->af_list[i].af_lckhost));
X
X /* write dates */
X fprintf (tmpfile, "\t%s %ld %ld %ld %ld %ld\n", AF_DATEID,
X list->af_list[i].af_mtime,
X list->af_list[i].af_atime,
X list->af_list[i].af_ctime,
X list->af_list[i].af_stime,
X list->af_list[i].af_ltime);
X
X /* write kind of representation and tree connects */
X fprintf (tmpfile, "\t%s %d %ld %ld %d %d %d %d\n", AF_REPRID,
X list->af_list[i].af_repr,
X list->af_list[i].af_fsize,
X list->af_list[i].af_dsize,
X list->af_list[i].af_succgen,
X list->af_list[i].af_succrev,
X list->af_list[i].af_predgen,
X list->af_list[i].af_predrev);
X }
X
X /* write user defined attributes */
X fprintf (tmpfile, "%s\n", AF_UDASEG);
X maxindex = list->af_nrevs;
X for (i=0; i < maxindex; i++)
X {
X /* skip deleted versions but not the busy version */
X if (!(list->af_list[i].af_class & AF_VALID) &&
X (list->af_list[i].af_state != AF_BUSY))
X { maxindex++; continue; }
X
X fprintf (tmpfile, "%s %d %d\n", AF_UDAID,
X list->af_list[i].af_gen,
X list->af_list[i].af_rev);
X (void) af_lhashsyms (&list->af_list[i].af_uhtab, ptrlist);
X j=0;
X while (ptrlist[j])
X fprintf (tmpfile, "%s%c", ptrlist[j++], '\0');
X if (j==0) /* if no user defined attribute has been written */
X (void) putc ('\0', tmpfile);
X (void) putc ('\0', tmpfile);
X (void) putc ('\n', tmpfile);
X }
X (void) fclose (tmpfile);
X
X /* if data have been manipulated - write data file */
X if ((list->af_extent & AF_DATA) == AF_DATA)
X {
X (void) strcpy (dataname, list->af_arfilename);
X dataname[strlen(dataname) - sizeof(char)] = AF_DATATMP;
X af_regtmpfile (dataname);
X /* open tmpfile for data */
X if ((datafile = fopen (dataname, "w")) == (FILE *)0)
X FAIL ("writearchive", "fopen", AF_ESYSERR, ERROR);
X
X /* write notes and data */
X fprintf (datafile, "%s %d\n", AF_DATAHEADER, AF_ARCURVERS);
X
X maxindex = list->af_nrevs;
X for (i=1; i < maxindex; i++)
X {
X /* skip deleted versions */
X if (!(list->af_list[i].af_class & AF_VALID))
X { maxindex++; continue; }
X
X fprintf (datafile, "%s %d %d %ld\n", AF_NOTEID,
X list->af_list[i].af_gen,
X list->af_list[i].af_rev,
X list->af_list[i].af_notesize);
X (void) fwrite (list->af_list[i].af_note, sizeof(char), (Size_t) list->af_list[i].af_notesize - sizeof(char), datafile);
X (void) putc ('\n', datafile);
X
X if (list->af_list[i].af_repr == AF_CHUNK)
X datasize = list->af_list[i].af_fsize;
X else datasize = list->af_list[i].af_dsize;
X fprintf (datafile, "%s %d %d %d %ld\n", AF_DATAID,
X list->af_list[i].af_gen,
X list->af_list[i].af_rev,
X list->af_list[i].af_repr, datasize);
X
X (void) fwrite (list->af_list[i].af_data, sizeof(char), (Size_t) datasize, datafile);
X }
X (void) fclose (datafile);
X }
X
X af_unregtmpfile (tmpname);
X (void) af_unlink (list->af_arfilename);
X if (af_syslink (tmpname, list->af_arfilename) == ERROR)
X FAIL ("writearchive", "link", AF_ESYSERR, ERROR);
X
X (void) af_uchmod (list->af_arfilename, AF_ARCHMODE);
X (void) af_unlink (tmpname);
X
X /* if the data file has been written */
X if ((list->af_extent & AF_DATA) == AF_DATA)
X {
X (void) strcpy (archname, list->af_arfilename);
X archname[strlen(archname)-sizeof(char)] = AF_DATAEXT;
X af_unregtmpfile (dataname);
X (void) af_unlink (archname);
X if (af_syslink (dataname, archname) == ERROR)
X FAIL ("writearchive", "link", AF_ESYSERR, ERROR);
X (void) af_uchmod (archname, AF_ARCHMODE);
X (void) af_unlink (dataname);
X }
X
X /* decrease "nrevs" again (see beginning of procedure */
X if (!(VATTR(busyptr).af_class & AF_VALID))
X list->af_nrevs--;
X
X return (AF_OK);
X} /* af_writearchive */
X
END_OF_FILE
if test 35334 -ne `wc -c <'src/afs/afarchive.c'`; then
echo shar: \"'src/afs/afarchive.c'\" unpacked with wrong size!
fi
# end of 'src/afs/afarchive.c'
fi
echo shar: End of archive 29 \(of 33\).
cp /dev/null ark29isdone
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