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.c99
1 files changed, 76 insertions, 23 deletions
diff --git a/usr.bin/cvs/entries.c b/usr.bin/cvs/entries.c
index 58d823f3ff5..8e7efd1e4e9 100644
--- a/usr.bin/cvs/entries.c
+++ b/usr.bin/cvs/entries.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: entries.c,v 1.7 2004/07/27 13:12:10 jfb Exp $ */
+/* $OpenBSD: entries.c,v 1.8 2004/07/30 17:37:13 jfb Exp $ */
/*
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
* All rights reserved.
@@ -60,27 +60,35 @@ cvs_ent_open(const char *dir, int flags)
size_t len;
char entpath[MAXPATHLEN], ebuf[128], mode[4];
FILE *fp;
+ struct stat st;
struct cvs_ent *ent;
CVSENTRIES *ep;
memset(mode, 0, sizeof(mode));
+
+ snprintf(entpath, sizeof(entpath), "%s/" CVS_PATH_ENTRIES, dir);
+
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] = '+';
- /* fallthrough */
+ break;
case O_RDONLY:
mode[0] = 'r';
break;
- case O_WRONLY:
- mode[0] = 'a';
- break;
}
- snprintf(entpath, sizeof(entpath), "%s/" CVS_PATH_ENTRIES, dir);
+ /* we can use 'r' if the file already exists */
+ if (stat(entpath, &st) == 0)
+ mode[0] = 'r';
+
+
fp = fopen(entpath, mode);
if (fp == NULL) {
- cvs_log(LP_ERRNO, "cannot open CVS/Entries for reading",
- entpath);
+ cvs_log(LP_ERRNO, "cannot open %s for %s", entpath,
+ mode[1] == '+' ? "writing" : "reading");
return (NULL);
}
@@ -103,6 +111,8 @@ cvs_ent_open(const char *dir, int flags)
ep->cef_cur = NULL;
TAILQ_INIT(&(ep->cef_ent));
+ rewind(fp);
+
while (fgets(ebuf, sizeof(ebuf), fp) != NULL) {
len = strlen(ebuf);
if ((len > 0) && (ebuf[len - 1] == '\n'))
@@ -117,11 +127,14 @@ cvs_ent_open(const char *dir, int flags)
}
/* only keep a pointer to the open file if we're in writing mode */
- if ((flags & O_WRONLY) || (flags & O_RDWR))
+ if ((flags & O_WRONLY) || (flags & O_RDWR)) {
+ ep->cef_flags |= CVS_ENTF_WR;
ep->cef_file = fp;
+ }
else
(void)fclose(fp);
+ ep->cef_flags |= CVS_ENTF_SYNC;
return (ep);
}
@@ -138,6 +151,12 @@ cvs_ent_close(CVSENTRIES *ep)
{
struct cvs_ent *ent;
+ if ((ep->cef_flags & CVS_ENTF_WR) &&
+ !(ep->cef_flags & CVS_ENTF_SYNC)) {
+ /* implicit sync with disk */
+ (void)cvs_ent_write(ep);
+ }
+
if (ep->cef_file != NULL)
(void)fclose(ep->cef_file);
if (ep->cef_path != NULL)
@@ -156,16 +175,16 @@ cvs_ent_close(CVSENTRIES *ep)
/*
* cvs_ent_add()
*
- * Add the entry <ent> to the Entries file <ef>.
+ * 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)
{
- void *tmp;
- char nbuf[64];
-
if (ef->cef_file == NULL) {
cvs_log(LP_ERR, "Entries file is opened in read-only mode");
return (-1);
@@ -174,15 +193,10 @@ cvs_ent_add(CVSENTRIES *ef, struct cvs_ent *ent)
if (cvs_ent_get(ef, ent->ce_name) != NULL)
return (-1);
- if (fseek(ef->cef_file, (long)0, SEEK_END) == -1) {
- cvs_log(LP_ERRNO, "failed to seek to end of CVS/Entries file");
- return (-1);
- }
- rcsnum_tostr(ent->ce_rev, nbuf, sizeof(nbuf));
- fprintf(ef->cef_file, "/%s/%s/%s/%s/\n", ent->ce_name, nbuf,
- ent->ce_timestamp, ent->ce_opts);
-
TAILQ_INSERT_TAIL(&(ef->cef_ent), ent, ce_list);
+
+ ef->cef_flags &= ~CVS_ENTF_SYNC;
+
return (0);
}
@@ -196,7 +210,6 @@ cvs_ent_add(CVSENTRIES *ef, struct cvs_ent *ent)
int
cvs_ent_addln(CVSENTRIES *ef, const char *line)
{
- void *tmp;
struct cvs_ent *ent;
if (ef->cef_file == NULL) {
@@ -212,6 +225,8 @@ cvs_ent_addln(CVSENTRIES *ef, const char *line)
return (-1);
TAILQ_INSERT_TAIL(&(ef->cef_ent), ent, ce_list);
+ ef->cef_flags &= ~CVS_ENTF_SYNC;
+
return (0);
}
@@ -227,7 +242,6 @@ cvs_ent_addln(CVSENTRIES *ef, const char *line)
struct cvs_ent*
cvs_ent_get(CVSENTRIES *ef, const char *file)
{
- u_int i;
struct cvs_ent *ep;
TAILQ_FOREACH(ep, &(ef->cef_ent), ce_list)
@@ -382,3 +396,42 @@ cvs_ent_getent(const char *path)
cvs_ent_close(entf);
return (ep);
}
+
+
+/*
+ * 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)
+{
+ char revbuf[64];
+ struct cvs_ent *ent;
+
+ if (ef->cef_file == NULL)
+ return (-1);
+
+ if (ef->cef_flags & CVS_ENTF_SYNC)
+ return (0);
+
+ /* reposition ourself at beginning of file */
+ rewind(ef->cef_file);
+ TAILQ_FOREACH(ent, &(ef->cef_ent), ce_list) {
+ if (ent->ce_type == CVS_ENT_DIR)
+ putc('D', ef->cef_file);
+
+ rcsnum_tostr(ent->ce_rev, revbuf, sizeof(revbuf));
+ fprintf(ef->cef_file, "/%s/%s/%s/%s/%s\n", ent->ce_name,
+ revbuf, ent->ce_timestamp, "", "");
+ }
+
+ /* terminating line */
+ fprintf(ef->cef_file, "D\n");
+
+ ef->cef_flags |= CVS_ENTF_SYNC;
+
+ return (0);
+}