summaryrefslogtreecommitdiff
path: root/usr.bin/cvs/entries.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/cvs/entries.c')
-rw-r--r--usr.bin/cvs/entries.c631
1 files changed, 225 insertions, 406 deletions
diff --git a/usr.bin/cvs/entries.c b/usr.bin/cvs/entries.c
index d3dfe84e5cb..8db8457b787 100644
--- a/usr.bin/cvs/entries.c
+++ b/usr.bin/cvs/entries.c
@@ -1,27 +1,18 @@
-/* $OpenBSD: entries.c,v 1.56 2006/04/14 02:45:35 deraadt Exp $ */
+/* $OpenBSD: entries.c,v 1.57 2006/05/27 03:30:30 joris Exp $ */
/*
- * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
- * All rights reserved.
+ * Copyright (c) 2006 Joris Vink <joris@openbsd.org>
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
*
- * 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.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
@@ -29,486 +20,314 @@
#include "cvs.h"
#include "log.h"
-
#define CVS_ENTRIES_NFIELDS 6
#define CVS_ENTRIES_DELIM '/'
+static struct cvs_ent_line *ent_get_line(CVSENTRIES *, const char *);
-/*
- * 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)
+cvs_ent_open(const char *dir)
{
- size_t len;
- int exists, nodir;
- char bpath[MAXPATHLEN], *p;
- char cdpath[MAXPATHLEN], ebuf[CVS_ENT_MAXLINELEN], entpath[MAXPATHLEN];
- char mode[4];
FILE *fp;
- struct stat st;
- struct cvs_ent *ent;
+ size_t len;
CVSENTRIES *ep;
+ char *p, buf[MAXPATHLEN];
+ struct cvs_ent *ent;
+ struct cvs_ent_line *line;
- exists = 0;
- nodir = 1;
- memset(mode, 0, sizeof(mode));
-
- /*
- * Check if the CVS/ dir does exist. If it does,
- * maybe the Entries file was deleted by accident,
- * display error message. Else we might be doing a fresh
- * update or checkout of a module.
- */
- len = cvs_path_cat(dir, CVS_PATH_CVSDIR, cdpath, sizeof(cdpath));
- if (len >= sizeof(cdpath))
- return (NULL);
-
- if (stat(cdpath, &st) == 0 && S_ISDIR(st.st_mode))
- nodir = 0; /* the CVS/ directory does exist */
-
- len = cvs_path_cat(dir, CVS_PATH_BACKUPENTRIES, bpath, sizeof(bpath));
- if (len >= sizeof(entpath))
- return (NULL);
-
- len = cvs_path_cat(dir, CVS_PATH_ENTRIES, entpath, sizeof(entpath));
- if (len >= sizeof(entpath))
- return (NULL);
+ ep = (CVSENTRIES *)xmalloc(sizeof(*ep));
+ memset(ep, 0, sizeof(*ep));
- switch (flags & O_ACCMODE) {
- case O_WRONLY:
- case O_RDWR:
- /* we have to use append otherwise the file gets truncated */
- mode[0] = 'w';
- mode[1] = '+';
- break;
- case O_RDONLY:
- mode[0] = 'r';
- break;
- }
+ cvs_path_cat(dir, CVS_PATH_ENTRIES, buf, sizeof(buf));
+ ep->cef_path = xstrdup(buf);
- /* we can use 'r' if the file already exists */
- if (stat(entpath, &st) == 0) {
- exists = 1;
- mode[0] = 'r';
- }
-
- fp = fopen(entpath, mode);
- if (fp == NULL) {
- if (nodir == 0)
- cvs_log(LP_ERRNO, "cannot open %s for %s", entpath,
- mode[1] == '+' ? "writing" : "reading");
- return (NULL);
- }
+ cvs_path_cat(dir, CVS_PATH_BACKUPENTRIES, buf, sizeof(buf));
+ ep->cef_bpath = xstrdup(buf);
- ep = xcalloc(1, sizeof(*ep));
+ cvs_path_cat(dir, CVS_PATH_LOGENTRIES, buf, sizeof(buf));
+ ep->cef_lpath = xstrdup(buf);
- ep->cef_path = xstrdup(entpath);
- ep->cef_bpath = xstrdup(bpath);
- ep->cef_cur = NULL;
TAILQ_INIT(&(ep->cef_ent));
- while (fgets(ebuf, (int)sizeof(ebuf), fp) != NULL) {
- len = strlen(ebuf);
- if (len > 0 && ebuf[len - 1] == '\n')
- ebuf[--len] = '\0';
- if (ebuf[0] == 'D' && ebuf[1] == '\0')
- break;
- ent = cvs_ent_parse(ebuf);
- if (ent == NULL)
- continue;
-
- TAILQ_INSERT_TAIL(&(ep->cef_ent), ent, ce_list);
- }
-
- if (ferror(fp)) {
- cvs_log(LP_ERRNO, "read error on %s", entpath);
- (void)fclose(fp);
- cvs_ent_close(ep);
- return (NULL);
- }
+ if ((fp = fopen(ep->cef_path, "r")) != NULL) {
+ while (fgets(buf, sizeof(buf), fp)) {
+ len = strlen(buf);
+ if (len > 0 && buf[len - 1] == '\n')
+ buf[len - 1] = '\0';
- /* only keep a pointer to the open file if we're in writing mode */
- if ((flags & O_WRONLY) || (flags & O_RDWR))
- ep->cef_flags |= CVS_ENTF_WR;
+ if (buf[0] == 'D' && buf[1] == '\0')
+ break;
- (void)fclose(fp);
+ line = (struct cvs_ent_line *)xmalloc(sizeof(*line));
+ line->buf = xstrdup(buf);
+ TAILQ_INSERT_TAIL(&(ep->cef_ent), line, entries_list);
+ }
- /*
- * look for Entries.Log and add merge it together with our
- * list of things.
- */
- len = cvs_path_cat(dir, CVS_PATH_LOGENTRIES, entpath, sizeof(entpath));
- if (len >= sizeof(entpath)) {
- cvs_ent_close(ep);
- return (NULL);
+ (void)fclose(fp);
}
- fp = fopen(entpath, "r");
- if (fp != NULL) {
- while (fgets(ebuf, (int)sizeof(ebuf), fp) != NULL) {
- len = strlen(ebuf);
- if (len > 0 && ebuf[len - 1] == '\n')
- ebuf[--len] = '\0';
-
- p = &ebuf[2];
- ent = cvs_ent_parse(p);
- if (ent == NULL)
- continue;
-
- if (ebuf[0] == 'A')
- cvs_ent_add(ep, ent);
- else if (ebuf[0] == 'R')
- cvs_ent_remove(ep, ent->ce_name, 0);
+ if ((fp = fopen(ep->cef_lpath, "r")) != NULL) {
+ while (fgets(buf, sizeof(buf), fp)) {
+ len = strlen(buf);
+ if (len > 0 && buf[strlen(buf) - 1] == '\n')
+ buf[strlen(buf) - 1] = '\0';
+
+ p = &buf[1];
+
+ if (buf[0] == 'A') {
+ line = xmalloc(sizeof(*line));
+ line->buf = xstrdup(p);
+ TAILQ_INSERT_TAIL(&(ep->cef_ent), line,
+ entries_list);
+ } else if (buf[0] == 'R') {
+ ent = cvs_ent_parse(p);
+ line = ent_get_line(ep, ent->ce_name);
+ if (line != NULL)
+ TAILQ_REMOVE(&(ep->cef_ent), line,
+ entries_list);
+ cvs_ent_free(ent);
+ }
}
- (void)fclose(fp);
- /* always un-synced here, because we
- * just added or removed entries.
- */
- ep->cef_flags &= ~CVS_ENTF_SYNC;
- } else {
- if (exists == 1)
- ep->cef_flags |= CVS_ENTF_SYNC;
+ (void)fclose(fp);
}
return (ep);
}
-
-/*
- * cvs_ent_close()
- *
- * Close the Entries file <ep> and free all data. Any reference to entries
- * structure within that file become invalid.
- */
-void
-cvs_ent_close(CVSENTRIES *ep)
+struct cvs_ent *
+cvs_ent_parse(const char *entry)
{
+ int i;
struct cvs_ent *ent;
+ char *fields[CVS_ENTRIES_NFIELDS], *buf, *sp, *dp;
- if (cvs_noexec == 0 && (ep->cef_flags & CVS_ENTF_WR) &&
- !(ep->cef_flags & CVS_ENTF_SYNC)) {
- /* implicit sync with disk */
- (void)cvs_ent_write(ep);
- }
+ buf = xstrdup(entry);
+ sp = buf;
+ 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);
- if (ep->cef_path != NULL)
- xfree(ep->cef_path);
+ if (i < CVS_ENTRIES_NFIELDS)
+ fatal("missing fields in entry line '%s'", entry);
- if (ep->cef_bpath != NULL)
- xfree(ep->cef_bpath);
+ ent = (struct cvs_ent *)xmalloc(sizeof(*ent));
+ ent->ce_buf = buf;
- while (!TAILQ_EMPTY(&(ep->cef_ent))) {
- ent = TAILQ_FIRST(&(ep->cef_ent));
- TAILQ_REMOVE(&(ep->cef_ent), ent, ce_list);
- cvs_ent_free(ent);
- }
+ if (*fields[0] == '\0')
+ ent->ce_type = CVS_ENT_FILE;
+ else if (*fields[0] == 'D')
+ ent->ce_type = CVS_ENT_DIR;
+ else
+ ent->ce_type = CVS_ENT_NONE;
- xfree(ep);
-}
+ ent->ce_status = CVS_ENT_REG;
+ ent->ce_name = fields[1];
+ ent->ce_rev = NULL;
+ if (ent->ce_type == CVS_ENT_FILE) {
+ if (*fields[2] == '-') {
+ ent->ce_status = CVS_ENT_REMOVED;
+ sp = fields[2] + 1;
+ } else {
+ sp = fields[2];
+ if (fields[2][0] == '0' && fields[2][1] == '\0')
+ ent->ce_status = CVS_ENT_ADDED;
+ }
-/*
- * cvs_ent_add()
- *
- * Add the entry <ent> to the Entries file <ef>. The disk contents are not
- * modified until a call to cvs_ent_write() is performed. This is done
- * implicitly on a call to cvs_ent_close() on an Entries file that has been
- * opened for writing.
- * Returns 0 on success, or -1 on failure.
- */
-int
-cvs_ent_add(CVSENTRIES *ef, struct cvs_ent *ent)
-{
- if (!(ef->cef_flags & CVS_ENTF_WR)) {
- cvs_log(LP_ERR, "Entries file is opened in read-only mode");
- return (-1);
- }
+ if ((ent->ce_rev = rcsnum_parse(sp)) == NULL)
+ fatal("failed to parse entry revision '%s'", entry);
- if (cvs_ent_get(ef, ent->ce_name) != NULL) {
- cvs_log(LP_ERR, "attempt to add duplicate entry for `%s'",
- ent->ce_name);
- return (-1);
+ if (strcmp(fields[3], CVS_DATE_DUMMY) == 0 ||
+ strncmp(fields[3], "Initial ", 8) == 0 ||
+ strncmp(fields[3], "Result of merge", 15) == 0)
+ ent->ce_mtime = CVS_DATE_DMSEC;
+ else
+ ent->ce_mtime = cvs_date_parse(fields[3]);
}
- TAILQ_INSERT_TAIL(&(ef->cef_ent), ent, ce_list);
+ ent->ce_conflict = fields[3];
+ if ((dp = strchr(ent->ce_conflict, '+')) != NULL)
+ *dp = '\0';
+ else
+ ent->ce_conflict = NULL;
- ef->cef_flags &= ~CVS_ENTF_SYNC;
+ if (strcmp(fields[4], ""))
+ ent->ce_opts = fields[4];
+ else
+ ent->ce_opts = NULL;
- return (0);
-}
+ if (strcmp(fields[5], ""))
+ ent->ce_tag = fields[5];
+ else
+ ent->ce_tag = NULL;
+ return (ent);
+}
-/*
- * cvs_ent_addln()
- *
- * Add a line to the Entries file.
- */
-int
-cvs_ent_addln(CVSENTRIES *ef, const char *line)
+struct cvs_ent *
+cvs_ent_get(CVSENTRIES *ep, const char *name)
{
struct cvs_ent *ent;
+ struct cvs_ent_line *l;
- if (!(ef->cef_flags & CVS_ENTF_WR)) {
- cvs_log(LP_ERR, "Entries file is opened in read-only mode");
- return (-1);
- }
+ l = ent_get_line(ep, name);
+ if (l == NULL)
+ return (NULL);
- ent = cvs_ent_parse(line);
- if (ent == NULL)
- return (-1);
+ ent = cvs_ent_parse(l->buf);
+ return (ent);
+}
- if (cvs_ent_get(ef, ent->ce_name) != NULL)
- return (-1);
+int
+cvs_ent_exists(CVSENTRIES *ep, const char *name)
+{
+ struct cvs_ent_line *l;
- TAILQ_INSERT_TAIL(&(ef->cef_ent), ent, ce_list);
- ef->cef_flags &= ~CVS_ENTF_SYNC;
+ l = ent_get_line(ep, name);
+ if (l == NULL)
+ return (0);
- return (0);
+ return (1);
}
-
-/*
- * cvs_ent_remove()
- *
- * Remove an entry from the Entries file <ef>. The entry's name is given
- * by <name>.
- */
-int
-cvs_ent_remove(CVSENTRIES *ef, const char *name, int useprev)
+void
+cvs_ent_close(CVSENTRIES *ep, int writefile)
{
- struct cvs_ent *ent;
-
- cvs_log(LP_TRACE, "cvs_ent_remove(%s)", name);
+ FILE *fp;
+ struct cvs_ent_line *l;
- ent = cvs_ent_get(ef, name);
- if (ent == NULL)
- return (-1);
+ if (writefile) {
+ if ((fp = fopen(ep->cef_bpath, "w")) == NULL)
+ fatal("cvs_ent_close: failed to write %s",
+ ep->cef_path);
+ }
- if (ef->cef_cur == ent) {
- /* if this element was the last one retrieved through a
- * call to cvs_ent_next(), point to the next element to avoid
- * keeping an invalid reference.
- */
- if (useprev) {
- ef->cef_cur = TAILQ_PREV(ef->cef_cur,
- cvsentrieshead, ce_list);
- } else {
- ef->cef_cur = TAILQ_NEXT(ef->cef_cur, ce_list);
+ while ((l = TAILQ_FIRST(&(ep->cef_ent))) != NULL) {
+ if (writefile) {
+ fputs(l->buf, fp);
+ fputc('\n', fp);
}
+
+ TAILQ_REMOVE(&(ep->cef_ent), l, entries_list);
+ xfree(l->buf);
+ xfree(l);
}
- TAILQ_REMOVE(&(ef->cef_ent), ent, ce_list);
- cvs_ent_free(ent);
- ef->cef_flags &= ~CVS_ENTF_SYNC;
+ if (writefile) {
+ fputc('D', fp);
+ (void)fclose(fp);
- return (0);
-}
+ if (rename(ep->cef_bpath, ep->cef_path) == -1)
+ fatal("cvs_ent_close: %s: %s", ep->cef_path,
+ strerror(errno));
+ (void)unlink(ep->cef_lpath);
+ }
-/*
- * 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)
+ xfree(ep->cef_path);
+ xfree(ep->cef_bpath);
+ xfree(ep->cef_lpath);
+ xfree(ep);
+}
+
+void
+cvs_ent_add(CVSENTRIES *ep, const char *line)
{
+ FILE *fp;
+ struct cvs_ent_line *l;
struct cvs_ent *ent;
- TAILQ_FOREACH(ent, &(ef->cef_ent), ce_list)
- if (strcmp(ent->ce_name, file) == 0)
- return (ent);
+ if ((ent = cvs_ent_parse(line)) == NULL)
+ fatal("cvs_ent_add: parsing failed '%s'", line);
- return (NULL);
-}
+ l = ent_get_line(ep, ent->ce_name);
+ if (l != NULL)
+ cvs_ent_remove(ep, ent->ce_name);
+ cvs_ent_free(ent);
-/*
- * cvs_ent_next()
- *
- * This function is used to iterate over the entries in an Entries file. The
- * first call will return the first entry of the file and each subsequent call
- * will return the entry following the last one returned.
- * 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_cur == NULL)
- ef->cef_cur = TAILQ_FIRST(&(ef->cef_ent));
- else
- ef->cef_cur = TAILQ_NEXT(ef->cef_cur, ce_list);
- return (ef->cef_cur);
-}
+ cvs_log(LP_TRACE, "cvs_ent_add(%s, %s)", ep->cef_path, line);
+ if ((fp = fopen(ep->cef_lpath, "a")) == NULL)
+ fatal("cvs_ent_add: failed to open '%s'", ep->cef_lpath);
-/*
- * cvs_ent_parse()
- *
- * Parse a single line from a CVS/Entries file and return a cvs_ent structure
- * containing all the parsed information.
- */
-struct cvs_ent*
-cvs_ent_parse(const char *entry)
-{
- int i;
- char *fields[CVS_ENTRIES_NFIELDS], *buf, *sp, *dp;
- struct cvs_ent *ent;
+ fputc('A', fp);
+ fputs(line, fp);
+ fputc('\n', fp);
- buf = xstrdup(entry);
- sp = buf;
- 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);
+ (void)fclose(fp);
- if (i < CVS_ENTRIES_NFIELDS) {
- cvs_log(LP_ERR, "missing fields in entry line `%s'", entry);
- return (NULL);
- }
+ l = (struct cvs_ent_line *)xmalloc(sizeof(*l));
+ l->buf = xstrdup(line);
+ TAILQ_INSERT_TAIL(&(ep->cef_ent), l, entries_list);
+}
- ent = xcalloc(1, sizeof(*ent));
- ent->ce_buf = buf;
+void
+cvs_ent_remove(CVSENTRIES *ep, const char *name)
+{
+ FILE *fp;
+ struct cvs_ent_line *l;
- if (*fields[0] == '\0')
- ent->ce_type = CVS_ENT_FILE;
- else if (*fields[0] == 'D')
- ent->ce_type = CVS_ENT_DIR;
- else
- ent->ce_type = CVS_ENT_NONE;
+ cvs_log(LP_TRACE, "cvs_ent_remove(%s, %s)", ep->cef_path, name);
- ent->ce_status = CVS_ENT_REG;
- ent->ce_name = fields[1];
- ent->processed = 0;
+ l = ent_get_line(ep, name);
+ if (l == NULL)
+ return;
- if (ent->ce_type == CVS_ENT_FILE) {
- if (*fields[2] == '-') {
- ent->ce_status = CVS_ENT_REMOVED;
- sp = fields[2] + 1;
- } else {
- sp = fields[2];
- if (fields[2][0] == '0' && fields[2][1] == '\0')
- ent->ce_status = CVS_ENT_ADDED;
- }
+ if ((fp = fopen(ep->cef_lpath, "a")) == NULL)
+ fatal("cvs_ent_remove: failed to open '%s'",
+ ep->cef_lpath);
- if ((ent->ce_rev = rcsnum_parse(sp)) == NULL) {
- cvs_ent_free(ent);
- return (NULL);
- }
+ fputc('R', fp);
+ fputs(l->buf, fp);
+ fputc('\n', fp);
- if (cvs_cmdop == CVS_OP_SERVER) {
- if (!strcmp(fields[3], "up to date"))
- ent->ce_status = CVS_ENT_UPTODATE;
- } else {
- if (strcmp(fields[3], CVS_DATE_DUMMY) == 0 ||
- strncmp(fields[3], "Initial ", 8) == 0)
- ent->ce_mtime = CVS_DATE_DMSEC;
- else
- ent->ce_mtime = cvs_date_parse(fields[3]);
- }
- }
+ (void)fclose(fp);
- ent->ce_opts = fields[4];
- ent->ce_tag = fields[5];
- return (ent);
+ TAILQ_REMOVE(&(ep->cef_ent), l, entries_list);
+ xfree(l->buf);
+ xfree(l);
}
-/*
- * cvs_ent_free()
- *
- * Free a single CVS entries structure.
- */
void
cvs_ent_free(struct cvs_ent *ent)
{
if (ent->ce_rev != NULL)
rcsnum_free(ent->ce_rev);
- if (ent->ce_buf != NULL)
- xfree(ent->ce_buf);
+ xfree(ent->ce_buf);
xfree(ent);
}
-/*
- * cvs_ent_write()
- *
- * Explicitly write the contents of the Entries file <ef> to disk.
- * Returns 0 on success, or -1 on failure.
- */
-int
-cvs_ent_write(CVSENTRIES *ef)
+static struct cvs_ent_line *
+ent_get_line(CVSENTRIES *ep, const char *name)
{
- size_t len;
- char revbuf[64], timebuf[32];
- struct cvs_ent *ent;
- FILE *fp;
+ char *p, *s;
+ struct cvs_ent_line *l;
- if (ef->cef_flags & CVS_ENTF_SYNC)
- return (0);
+ TAILQ_FOREACH(l, &(ep->cef_ent), entries_list) {
+ if (l->buf[0] == 'D')
+ p = &(l->buf[2]);
+ else
+ p = &(l->buf[1]);
- if ((fp = fopen(ef->cef_bpath, "w")) == NULL) {
- cvs_log(LP_ERRNO, "failed to open Entries `%s'", ef->cef_bpath);
- return (-1);
- }
+ if ((s = strchr(p, '/')) == NULL)
+ fatal("ent_get_line: bad entry line '%s'", l->buf);
- TAILQ_FOREACH(ent, &(ef->cef_ent), ce_list) {
- if (ent->ce_type == CVS_ENT_DIR) {
- putc('D', fp);
- timebuf[0] = '\0';
- revbuf[0] = '\0';
- } else {
- rcsnum_tostr(ent->ce_rev, revbuf, sizeof(revbuf));
- if (ent->ce_mtime == CVS_DATE_DMSEC &&
- ent->ce_status != CVS_ENT_ADDED)
- strlcpy(timebuf, CVS_DATE_DUMMY,
- sizeof(timebuf));
- else if (ent->ce_status == CVS_ENT_ADDED) {
- strlcpy(timebuf, "Initial ", sizeof(timebuf));
- strlcat(timebuf, ent->ce_name, sizeof(timebuf));
- } else {
- ctime_r(&(ent->ce_mtime), timebuf);
- len = strlen(timebuf);
- if (len > 0 && timebuf[len - 1] == '\n')
- timebuf[--len] = '\0';
- }
- }
+ *s = '\0';
- if (cvs_cmdop == CVS_OP_SERVER) {
- if (ent->ce_status == CVS_ENT_UPTODATE)
- strlcpy(timebuf, "up to date", sizeof(timebuf));
- else
- timebuf[0] = '\0';
+ if (!strcmp(p, name)) {
+ *s = '/';
+ return (l);
}
- fprintf(fp, "/%s/%s%s/%s/%s/%s\n", ent->ce_name,
- (ent->ce_status == CVS_ENT_REMOVED) ? "-" : "", revbuf,
- timebuf, (ent->ce_opts != NULL) ? ent->ce_opts : "",
- (ent->ce_tag != NULL) ? ent->ce_tag : "");
+ *s = '/';
}
- /* terminating line */
- putc('D', fp);
- putc('\n', fp);
-
- ef->cef_flags |= CVS_ENTF_SYNC;
- fclose(fp);
-
- /* rename Entries.Backup to Entries */
- cvs_rename(ef->cef_bpath, ef->cef_path);
-
- /* remove Entries.Log */
- cvs_unlink(CVS_PATH_LOGENTRIES);
-
- return (0);
+ return (NULL);
}