[BACK]Return to entries.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / cvs

File: [local] / src / usr.bin / cvs / entries.c (download)

Revision 1.2, Wed Jul 14 04:32:42 2004 UTC (19 years, 11 months ago) by jfb
Branch: MAIN
Changes since 1.1: +1 -1 lines

prepare the entries interface so we can add entries

/*	$OpenBSD: entries.c,v 1.2 2004/07/14 04:32:42 jfb Exp $	*/
/*
 * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
 * All rights reserved. 
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions 
 * are met: 
 *
 * 1. Redistributions of source code must retain the above copyright 
 *    notice, this list of conditions and the following disclaimer. 
 * 2. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission. 
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */

#include <sys/param.h>
#include <sys/stat.h>

#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#include "log.h"
#include "cvs.h"


#define CVS_ENTRIES_NFIELDS  5
#define CVS_ENTRIES_DELIM   '/'


/*
 * cvs_ent_open()
 *
 * Open the CVS Entries file for the directory <dir>.
 * Returns a pointer to the CVSENTRIES file structure on success, or NULL
 * on failure.
 */

CVSENTRIES*
cvs_ent_open(const char *dir, int flags)
{
	size_t len;
	char entpath[MAXPATHLEN], ebuf[128];
	FILE *fp;
	struct cvs_ent *ent;
	CVSENTRIES *ep;

	snprintf(entpath, sizeof(entpath), "%s/" CVS_PATH_ENTRIES, dir);
	fp = fopen(entpath, "r");
	if (fp == NULL) {
		cvs_log(LP_ERRNO, "cannot open CVS/Entries for reading",
		    entpath);
		return (NULL);
	}

	ep = (CVSENTRIES *)malloc(sizeof(CVSENTRIES));
	if (ep == NULL) {
		cvs_log(LP_ERRNO, "failed to allocate Entries data");
		(void)fclose(fp);
		return (NULL);
	}
	ep->cef_path = strdup(dir);
	if (ep->cef_path == NULL) {
		cvs_log(LP_ERRNO, "failed to copy Entries path");
		free(ep);
		(void)fclose(fp);
		return (NULL);
	}

	ep->cef_nid = 0;
	ep->cef_entries = NULL;
	ep->cef_nbent = 0;

	while (fgets(ebuf, sizeof(ebuf), fp) != NULL) {
		len = strlen(ebuf);
		if ((len > 0) && (ebuf[len - 1] == '\n'))
			ebuf[--len] = '\0';
		ent = cvs_ent_parse(ebuf);
		if (ent == NULL)
			continue;

		if (cvs_ent_add(ep, ent) < 0) {
			cvs_ent_close(ep);
			ep = NULL;
			break;
		}
	}

	(void)fclose(fp);
	return (ep);
}


/*
 * cvs_ent_close()
 *
 * Close the Entries file <ep>.
 */

void
cvs_ent_close(CVSENTRIES *ep)
{
	free(ep);
}


/*
 * cvs_ent_add()
 *
 * Add the entry <ent>
 */

int
cvs_ent_add(CVSENTRIES *ef, struct cvs_ent *ent)
{
	void *tmp;
	struct cvs_ent *entp;

	if (cvs_ent_get(ef, ent->ce_name) != NULL)
		return (-1);

	entp = cvs_ent_parse(ent->ce_line);
	if (entp == NULL) {
		return (-1);
	}

	tmp = realloc(ef->cef_entries, (ef->cef_nbent + 1) * sizeof(entp));
	if (tmp == NULL) {
		cvs_log(LP_ERRNO, "failed to resize entries buffer");
		return (-1);
	}

	ef->cef_entries = (struct cvs_ent **)tmp;
	ef->cef_entries[ef->cef_nbent++] = entp;

	return (0);
}


/*
 * cvs_ent_get()
 *
 * Get the CVS entry from the Entries file <ef> whose 'name' portion matches
 * <file>.
 * Returns a pointer to the cvs entry structure on success, or NULL on failure.
 */

struct cvs_ent*
cvs_ent_get(CVSENTRIES *ef, const char *file)
{
	u_int i;

	for (i = 0; i < ef->cef_nbent; i++) {
		if (strcmp(ef->cef_entries[i]->ce_name, file) == 0)
			return ef->cef_entries[i]; 
	}

	return (NULL);
}


/*
 * cvs_ent_next()
 *
 * Returns a pointer to the cvs entry structure on success, or NULL on failure.
 */

struct cvs_ent*
cvs_ent_next(CVSENTRIES *ef)
{
	if (ef->cef_nid >= ef->cef_nbent)
		return (NULL);

	return (ef->cef_entries[ef->cef_nid++]);
}


/*
 * cvs_ent_parse()
 *
 * Parse a single line from a CVS/Entries file and return a cvs_entry structure
 * containing all the parsed information.
 */

struct cvs_ent*
cvs_ent_parse(const char *entry)
{
	int i;
	char *fields[CVS_ENTRIES_NFIELDS], *sp, *dp;
	struct cvs_ent *entp;

	entp = (struct cvs_ent *)malloc(sizeof(*entp));
	if (entp == NULL) {
		cvs_log(LP_ERRNO, "failed to allocate CVS entry");
		return (NULL);
	}

	entp->ce_rev = rcsnum_alloc();
	if (entp->ce_rev == NULL) {
		free(entp);
		return (NULL);
	}

	entp->ce_line = strdup(entry);
	if (entp->ce_line == NULL) {
		free(entp);
		return (NULL);
	}

	entp->ce_buf = strdup(entry);
	if (entp->ce_buf == NULL) {
		free(entp->ce_line);
		free(entp);
		return (NULL);
	}
	sp = entp->ce_buf;

	if (*sp == CVS_ENTRIES_DELIM)
		entp->ce_type = CVS_ENT_FILE;
	else if (*sp == 'D') {
		entp->ce_type = CVS_ENT_DIR;
		sp++;
	}
	else {
		/* unknown entry, ignore for future expansion */
		entp->ce_type = CVS_ENT_NONE;
		sp++;
	}

	sp++;
	i = 0;
	do {
		dp = strchr(sp, CVS_ENTRIES_DELIM);
		if (dp != NULL)
			*(dp++) = '\0';
		fields[i++] = sp;
		sp = dp;
	} while ((dp != NULL) && (i < CVS_ENTRIES_NFIELDS));

	entp->ce_name = fields[0];

	if (entp->ce_type == CVS_ENT_FILE) {
		rcsnum_aton(fields[1], NULL, entp->ce_rev);
		entp->ce_timestamp = fields[2];
		entp->ce_opts = fields[3];
		entp->ce_tag = fields[4];
	}

	return (entp);
}