ftp.nice.ch/pub/next/unix/developer/cvs.950905.s.tar.gz#/cvs-1.5.1/src/entries.c

This is entries.c in view mode; [Download] [Up]

/*
 * Copyright (c) 1992, Brian Berliner and Jeff Polk
 * Copyright (c) 1989-1992, Brian Berliner
 * 
 * You may distribute under the terms of the GNU General Public License as
 * specified in the README file that comes with the CVS 1.4 kit.
 * 
 * Entries file to Files file
 * 
 * Creates the file Files containing the names that comprise the project, from
 * the Entries file.
 */

#include "cvs.h"

#ifndef lint
static const char rcsid[] = "$CVSid: @(#)entries.c 1.44 94/10/07 $";
USE(rcsid)
#endif

static Node *AddEntryNode PROTO((List * list, char *name, char *version,
			   char *timestamp, char *options, char *tag,
			   char *date, char *conflict));

static FILE *entfile;
static char *entfilename;		/* for error messages */

/*
 * Write out the line associated with a node of an entries file
 */
static int write_ent_proc PROTO ((Node *, void *));
static int
write_ent_proc (node, closure)
     Node *node;
     void *closure;
{
    Entnode *p;

    p = (Entnode *) node->data;
    if (fprintf (entfile, "/%s/%s/%s", node->key, p->version,
		 p->timestamp) == EOF)
	error (1, errno, "cannot write %s", entfilename);
    if (p->conflict)
    {
	if (fprintf (entfile, "+%s", p->conflict) < 0)
	    error (1, errno, "cannot write %s", entfilename);
    }
    if (fprintf (entfile, "/%s/", p->options) < 0)
	error (1, errno, "cannot write %s", entfilename);

    if (p->tag)
    {
	if (fprintf (entfile, "T%s\n", p->tag) < 0)
	    error (1, errno, "cannot write %s", entfilename);
    }
    else if (p->date)
    {
	if (fprintf (entfile, "D%s\n", p->date) < 0)
	    error (1, errno, "cannot write %s", entfilename);
    }
    else if (fprintf (entfile, "\n") < 0)
	error (1, errno, "cannot write %s", entfilename);
    return (0);
}

/*
 * write out the current entries file given a list,  making a backup copy
 * first of course
 */
static void
write_entries (list)
    List *list;
{
    /* open the new one and walk the list writing entries */
    entfilename = CVSADM_ENTBAK;
    entfile = open_file (entfilename, "w+");
    (void) walklist (list, write_ent_proc, NULL);
    if (fclose (entfile) == EOF)
	error (1, errno, "error closing %s", entfilename);

    /* now, atomically (on systems that support it) rename it */
    rename_file (entfilename, CVSADM_ENT);

    /* now, remove the log file */
    unlink_file (CVSADM_ENTLOG);
}

/*
 * Removes the argument file from the Entries file if necessary.
 */
void
Scratch_Entry (list, fname)
    List *list;
    char *fname;
{
    Node *node;

    if (trace)
#ifdef SERVER_SUPPORT
	(void) fprintf (stderr, "%c-> Scratch_Entry(%s)\n",
			(server_active) ? 'S' : ' ', fname);
#else
	(void) fprintf (stderr, "-> Scratch_Entry(%s)\n", fname);
#endif

    /* hashlookup to see if it is there */
    if ((node = findnode (list, fname)) != NULL)
    {
	delnode (node);			/* delete the node */
#ifdef SERVER_SUPPORT
	if (server_active)
	    server_scratch (fname);
#endif
	if (!noexec)
	    write_entries (list);	/* re-write the file */
    }
}

/*
 * Enters the given file name/version/time-stamp into the Entries file,
 * removing the old entry first, if necessary.
 */
void
Register (list, fname, vn, ts, options, tag, date, ts_conflict)
    List *list;
    char *fname;
    char *vn;
    char *ts;
    char *options;
    char *tag;
    char *date;
    char *ts_conflict;
{
    Node *node;

#ifdef SERVER_SUPPORT
    if (server_active)
    {
	server_register (fname, vn, ts, options, tag, date, ts_conflict);
    }
#endif

    if (trace)
    {
#ifdef SERVER_SUPPORT
	(void) fprintf (stderr, "%c-> Register(%s, %s, %s%s%s, %s, %s %s)\n",
			(server_active) ? 'S' : ' ',
			fname, vn, ts ? ts : "",
			ts_conflict ? "+" : "", ts_conflict ? ts_conflict : "",
			options, tag ? tag : "", date ? date : "");
#else
	(void) fprintf (stderr, "-> Register(%s, %s, %s%s%s, %s, %s %s)\n",
			fname, vn, ts ? ts : "",
			ts_conflict ? "+" : "", ts_conflict ? ts_conflict : "",
			options, tag ? tag : "", date ? date : "");
#endif
    }

    node = AddEntryNode (list, fname, vn, ts, options, tag, date, ts_conflict);

    if (!noexec)
    {
	entfile = open_file (CVSADM_ENTLOG, "a");
	
	write_ent_proc (node, NULL);

        if (fclose (entfile) == EOF)
            error (1, errno, "error closing %s", CVSADM_ENTLOG);
    }
}

/*
 * Node delete procedure for list-private sticky dir tag/date info
 */
static void
freesdt (p)
    Node *p;
{
    struct stickydirtag *sdtp;

    sdtp = (struct stickydirtag *) p->data;
    if (sdtp->tag)
	free (sdtp->tag);
    if (sdtp->date)
	free (sdtp->date);
    if (sdtp->options)
	free (sdtp->options);
    free ((char *) sdtp);
}

struct entent {
    char *user;
    char *vn;
    char *ts;
    char *options;
    char *tag;
    char *date;
    char *ts_conflict;
};

struct entent *
fgetentent(fpin)
    FILE *fpin;
{
    static struct entent ent;
    static char line[MAXLINELEN];
    register char *cp;
    char *user, *vn, *ts, *options;
    char *tag_or_date, *tag, *date, *ts_conflict;

    while (fgets (line, sizeof (line), fpin) != NULL)
    {
	if (line[0] != '/')
	    continue;

	user = line + 1;
	if ((cp = strchr (user, '/')) == NULL)
	    continue;
	*cp++ = '\0';
	vn = cp;
	if ((cp = strchr (vn, '/')) == NULL)
	    continue;
	*cp++ = '\0';
	ts = cp;
	if ((cp = strchr (ts, '/')) == NULL)
	    continue;
	*cp++ = '\0';
	options = cp;
	if ((cp = strchr (options, '/')) == NULL)
	    continue;
	*cp++ = '\0';
	tag_or_date = cp;
	if ((cp = strchr (tag_or_date, '\n')) == NULL)
	    continue;
	*cp = '\0';
	tag = (char *) NULL;
	date = (char *) NULL;
	if (*tag_or_date == 'T')
	    tag = tag_or_date + 1;
	else if (*tag_or_date == 'D')
	    date = tag_or_date + 1;
	
	if ((ts_conflict = strchr (ts, '+')))
	    *ts_conflict++ = '\0';
	    
	/*
	 * XXX - Convert timestamp from old format to new format.
	 *
	 * If the timestamp doesn't match the file's current
	 * mtime, we'd have to generate a string that doesn't
	 * match anyways, so cheat and base it on the existing
	 * string; it doesn't have to match the same mod time.
	 *
	 * For an unmodified file, write the correct timestamp.
	 */
	{
	    struct stat sb;
	    if (strlen (ts) > 30 && stat (user, &sb) == 0)
	    {
		extern char *ctime ();
		char *c = ctime (&sb.st_mtime);
		
		if (!strncmp (ts + 25, c, 24))
		    ts = time_stamp (user);
		else
		{
		    ts += 24;
		    ts[0] = '*';
		}
	    }
	}

	ent.user = user;
	ent.vn = vn;
	ent.ts = ts;
	ent.options = options;
	ent.tag = tag;
	ent.date = date;
	ent.ts_conflict = ts_conflict;

	return &ent;
    }

    return NULL;
}


/*
 * Read the entries file into a list, hashing on the file name.
 */
List *
Entries_Open (aflag)
    int aflag;
{
    List *entries;
    struct entent *ent;
    char *dirtag, *dirdate;
    int do_rewrite = 0;
    FILE *fpin;

    /* get a fresh list... */
    entries = getlist ();

    /*
     * Parse the CVS/Tag file, to get any default tag/date settings. Use
     * list-private storage to tuck them away for Version_TS().
     */
    ParseTag (&dirtag, &dirdate);
    if (aflag || dirtag || dirdate)
    {
	struct stickydirtag *sdtp;

	sdtp = (struct stickydirtag *) xmalloc (sizeof (*sdtp));
	memset ((char *) sdtp, 0, sizeof (*sdtp));
	sdtp->aflag = aflag;
	sdtp->tag = xstrdup (dirtag);
	sdtp->date = xstrdup (dirdate);

	/* feed it into the list-private area */
	entries->list->data = (char *) sdtp;
	entries->list->delproc = freesdt;
    }

    fpin = fopen (CVSADM_ENT, "r");
    if (fpin == NULL)
	error (0, errno, "cannot open %s for reading", CVSADM_ENT);
    else
    {
	while ((ent = fgetentent (fpin)) != NULL) 
	{
	    (void) AddEntryNode (entries, 
				 ent->user,
				 ent->vn,
				 ent->ts,
				 ent->options,
				 ent->tag,
				 ent->date,
				 ent->ts_conflict);
	}

	fclose (fpin);
    }

    fpin = fopen (CVSADM_ENTLOG, "r");
    if (fpin != NULL) {
	while ((ent = fgetentent (fpin)) != NULL) 
	{
	    (void) AddEntryNode (entries, 
				 ent->user,
				 ent->vn,
				 ent->ts,
				 ent->options,
				 ent->tag,
				 ent->date,
				 ent->ts_conflict);
	}
	do_rewrite = 1;
	fclose (fpin);
    }

    if (do_rewrite && !noexec)
	write_entries (entries);

    /* clean up and return */
    if (fpin)
	(void) fclose (fpin);
    if (dirtag)
	free (dirtag);
    if (dirdate)
	free (dirdate);
    return (entries);
}

void
Entries_Close(list)
    List *list;
{
    if (list)
    {
	if (!noexec) 
        {
            if (isfile (CVSADM_ENTLOG))
		write_entries (list);
	}
	dellist(&list);
    }
}


/*
 * Free up the memory associated with the data section of an ENTRIES type
 * node
 */
static void
Entries_delproc (node)
    Node *node;
{
    Entnode *p;

    p = (Entnode *) node->data;
    free (p->version);
    free (p->timestamp);
    free (p->options);
    if (p->tag)
	free (p->tag);
    if (p->date)
	free (p->date);
    if (p->conflict)
	free (p->conflict);
    free ((char *) p);
}

/*
 * Get an Entries file list node, initialize it, and add it to the specified
 * list
 */
static Node *
AddEntryNode (list, name, version, timestamp, options, tag, date, conflict)
    List *list;
    char *name;
    char *version;
    char *timestamp;
    char *options;
    char *tag;
    char *date;
    char *conflict;
{
    Node *p;
    Entnode *entdata;

    /* was it already there? */
    if ((p  = findnode (list, name)) != NULL)
    {
	/* take it out */
	delnode (p);
    }

    /* get a node and fill in the regular stuff */
    p = getnode ();
    p->type = ENTRIES;
    p->delproc = Entries_delproc;

    /* this one gets a key of the name for hashing */
    p->key = xstrdup (name);

    /* malloc the data parts and fill them in */
    p->data = xmalloc (sizeof (Entnode));
    entdata = (Entnode *) p->data;
    entdata->version = xstrdup (version);
    entdata->timestamp = xstrdup (timestamp);
    if (entdata->timestamp == NULL)
       entdata->timestamp = xstrdup ("");/* must be non-NULL */
    entdata->options = xstrdup (options);
    if (entdata->options == NULL)
	entdata->options = xstrdup ("");/* must be non-NULL */
    entdata->conflict = xstrdup (conflict);
    entdata->tag = xstrdup (tag);
    entdata->date = xstrdup (date);

    /* put the node into the list */
    addnode (list, p);
    return (p);
}

/*
 * Write out/Clear the CVS/Tag file.
 */
void
WriteTag (dir, tag, date)
    char *dir;
    char *tag;
    char *date;
{
    FILE *fout;
    char tmp[PATH_MAX];

    if (noexec)
	return;

    if (dir == NULL)
	(void) strcpy (tmp, CVSADM_TAG);
    else
	(void) sprintf (tmp, "%s/%s", dir, CVSADM_TAG);

    if (tag || date)
    {
	fout = open_file (tmp, "w+");
	if (tag)
	{
	    if (fprintf (fout, "T%s\n", tag) < 0)
		error (1, errno, "write to %s failed", tmp);
	}
	else
	{
	    if (fprintf (fout, "D%s\n", date) < 0)
		error (1, errno, "write to %s failed", tmp);
	}
	if (fclose (fout) == EOF)
	    error (1, errno, "cannot close %s", tmp);
    }
    else
	if (unlink_file (tmp) < 0 && errno != ENOENT)
	    error (1, errno, "cannot remove %s", tmp);
}

/*
 * Parse the CVS/Tag file for the current directory.
 */
void
ParseTag (tagp, datep)
    char **tagp;
    char **datep;
{
    FILE *fp;
    char line[MAXLINELEN];
    char *cp;

    if (tagp)
	*tagp = (char *) NULL;
    if (datep)
	*datep = (char *) NULL;
    fp = fopen (CVSADM_TAG, "r");
    if (fp)
    {
	if (fgets (line, sizeof (line), fp) != NULL)
	{
	    if ((cp = strrchr (line, '\n')) != NULL)
		*cp = '\0';
	    if (*line == 'T' && tagp)
		*tagp = xstrdup (line + 1);
	    else if (*line == 'D' && datep)
		*datep = xstrdup (line + 1);
	}
	(void) fclose (fp);
    }
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.