summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.bin/cvs/cvs.h83
-rw-r--r--usr.bin/cvs/entries.c99
2 files changed, 82 insertions, 100 deletions
diff --git a/usr.bin/cvs/cvs.h b/usr.bin/cvs/cvs.h
index 0b36051b374..4a8b1681c40 100644
--- a/usr.bin/cvs/cvs.h
+++ b/usr.bin/cvs/cvs.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cvs.h,v 1.16 2004/07/30 01:49:22 jfb Exp $ */
+/* $OpenBSD: cvs.h,v 1.17 2004/07/30 17:37:13 jfb Exp $ */
/*
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
* All rights reserved.
@@ -140,59 +140,6 @@ struct cvsroot {
};
-#define CF_STAT 0x01 /* allocate space for file stats */
-#define CF_IGNORE 0x02 /* apply regular ignore rules */
-#define CF_RECURSE 0x04 /* recurse on directory operations */
-#define CF_SORT 0x08 /* all files are sorted alphabetically */
-#define CF_KNOWN 0x10 /* only recurse in directories known to CVS */
-#define CF_CREATE 0x20 /* create if file does not exist */
-
-
-/*
- * The cvs_file structure is used to represent any file or directory within
- * the CVS tree's hierarchy. The <cf_path> field is a path relative to the
- * directory in which the cvs command was executed. The <cf_parent> field
- * points back to the parent node in the directory tree structure (it is
- * NULL if the directory is at the wd of the command).
- *
- * The <cf_cvstat> field gives the file's status with regards to the CVS
- * repository. The file can be in any one of the CVS_FST_* states.
- * If the file's type is DT_DIR, then the <cf_ddat> pointer will point to
- * a cvs_dir structure containing data specific to the directory (such as
- * the contents of the directory's CVS/Entries, CVS/Root, etc.).
- */
-
-#define CVS_FST_UNKNOWN 0
-#define CVS_FST_UPTODATE 1
-#define CVS_FST_MODIFIED 2
-#define CVS_FST_ADDED 3
-#define CVS_FST_REMOVED 4
-#define CVS_FST_CONFLICT 5
-#define CVS_FST_PATCHED 6
-
-
-TAILQ_HEAD(cvs_flist, cvs_file);
-
-
-typedef struct cvs_file {
- char *cf_path;
- struct cvs_file *cf_parent; /* parent directory (NULL if none) */
- char *cf_name;
- u_int16_t cf_cvstat; /* cvs status of the file */
- u_int16_t cf_type; /* uses values from dirent.h */
- struct stat *cf_stat; /* only available with CF_STAT flag */
- struct cvs_dir *cf_ddat; /* only for directories */
-
- TAILQ_ENTRY(cvs_file) cf_list;
-} CVSFILE;
-
-
-struct cvs_dir {
- struct cvsroot *cd_root;
- char *cd_repo;
- struct cvs_flist cd_files;
-};
-
#define CVS_HIST_ADDED 'A'
#define CVS_HIST_EXPORT 'E'
#define CVS_HIST_RELEASE 'F'
@@ -206,6 +153,9 @@ struct cvs_dir {
#define CVS_ENT_FILE 1
#define CVS_ENT_DIR 2
+#define CVS_ENTF_SYNC 0x01 /* contents of disk and memory match */
+#define CVS_ENTF_WR 0x02 /* file is opened for writing too */
+
struct cvs_ent {
char *ce_line;
@@ -222,6 +172,7 @@ struct cvs_ent {
typedef struct cvs_entries {
char *cef_path;
FILE *cef_file;
+ u_int cef_flags;
TAILQ_HEAD(, cvs_ent) cef_ent;
struct cvs_ent *cef_cur;
@@ -278,35 +229,12 @@ int cvs_update (int, char **);
int cvs_version (int, char **);
-/* from client.c */
-int cvs_client_connect (struct cvsroot *);
-void cvs_client_disconnect (struct cvsroot *);
-int cvs_client_sendreq (u_int, const char *, int);
-int cvs_client_sendarg (const char *, int);
-int cvs_client_sendln (const char *);
-int cvs_client_sendraw (const void *, size_t);
-ssize_t cvs_client_recvraw (void *, size_t);
-int cvs_client_getln (char *, size_t);
-int cvs_client_senddir (const char *);
-
-
/* from root.c */
struct cvsroot* cvsroot_parse (const char *);
void cvsroot_free (struct cvsroot *);
struct cvsroot* cvsroot_get (const char *);
-/* from file.c */
-int cvs_file_init (void);
-int cvs_file_ignore (const char *);
-int cvs_file_chkign (const char *);
-CVSFILE* cvs_file_create (const char *, u_int, mode_t);
-CVSFILE* cvs_file_get (const char *, int);
-CVSFILE* cvs_file_getspec (char **, int, int);
-void cvs_file_free (struct cvs_file *);
-int cvs_file_examine (CVSFILE *, int (*)(CVSFILE *, void *), void *);
-
-
/* Entries API */
CVSENTRIES* cvs_ent_open (const char *, int);
struct cvs_ent* cvs_ent_get (CVSENTRIES *, const char *);
@@ -314,6 +242,7 @@ struct cvs_ent* cvs_ent_next (CVSENTRIES *);
int cvs_ent_add (CVSENTRIES *, struct cvs_ent *);
int cvs_ent_addln (CVSENTRIES *, const char *);
int cvs_ent_remove (CVSENTRIES *, const char *);
+int cvs_ent_write (CVSENTRIES *);
struct cvs_ent* cvs_ent_parse (const char *);
void cvs_ent_close (CVSENTRIES *);
void cvs_ent_free (struct cvs_ent *);
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);
+}