From 98f79b433276554e4a151e161945ed0753df7cc3 Mon Sep 17 00:00:00 2001 From: Jean-Francois Brousseau Date: Fri, 30 Jul 2004 17:37:14 +0000 Subject: * remove header cruft that belongs in file.h * be more intelligent with the file open mode. It seems rewind() doesn't work too well with a file opened in append mode --- usr.bin/cvs/cvs.h | 83 ++++-------------------------------------- usr.bin/cvs/entries.c | 99 +++++++++++++++++++++++++++++++++++++++------------ 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 * 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 field is a path relative to the - * directory in which the cvs command was executed. The 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 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 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 * 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 to the Entries file . + * Add the entry to the Entries file . 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 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); +} -- cgit v1.2.3