summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Francois Brousseau <jfb@cvs.openbsd.org>2004-07-30 17:39:28 +0000
committerJean-Francois Brousseau <jfb@cvs.openbsd.org>2004-07-30 17:39:28 +0000
commita1ef3c1ccef8ac040bfe1be7447e06a9fb5c13f7 (patch)
treea94fc93821fdfb10ab7f4656471c8c65b5cf5c6d
parentfa6a5fd74aa617d59360beb1d31b121d7eef148c (diff)
Lots of cleanup, and add an internal version of cvs_file_get() so we can
link parent directories before the file info is being retrieved. This allows us to open most of the CVS administrative files only once
-rw-r--r--usr.bin/cvs/file.c234
-rw-r--r--usr.bin/cvs/file.h132
2 files changed, 152 insertions, 214 deletions
diff --git a/usr.bin/cvs/file.c b/usr.bin/cvs/file.c
index e9df757714a..a7b55ba4ffb 100644
--- a/usr.bin/cvs/file.c
+++ b/usr.bin/cvs/file.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: file.c,v 1.13 2004/07/30 11:50:33 jfb Exp $ */
+/* $OpenBSD: file.c,v 1.14 2004/07/30 17:39:27 jfb Exp $ */
/*
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
* All rights reserved.
@@ -40,16 +40,14 @@
#include "cvs.h"
#include "log.h"
+#include "file.h"
#define CVS_IGN_STATIC 0x01 /* pattern is static, no need to glob */
-
-
#define CVS_CHAR_ISMETA(c) ((c == '*') || (c == '?') || (c == '['))
-
/* ignore pattern */
struct cvs_ignpat {
char ip_pat[MAXNAMLEN];
@@ -97,11 +95,12 @@ static RCSNUM *cvs_addedrev;
TAILQ_HEAD(, cvs_ignpat) cvs_ign_pats;
-static int cvs_file_getdir (struct cvs_file *, int);
+static int cvs_file_getdir (CVSFILE *, int);
static void cvs_file_freedir (struct cvs_dir *);
static int cvs_file_sort (struct cvs_flist *);
static int cvs_file_cmp (const void *, const void *);
static CVSFILE* cvs_file_alloc (const char *, u_int);
+static CVSFILE* cvs_file_lget (const char *, int, CVSFILE *);
@@ -272,90 +271,10 @@ cvs_file_create(const char *path, u_int type, mode_t mode)
* with cvs_file_free().
*/
-struct cvs_file*
+CVSFILE*
cvs_file_get(const char *path, int flags)
{
- int cwd;
- size_t len;
- char buf[32];
- struct stat st;
- struct tm lmtm;
- struct cvs_file *cfp;
- struct cvs_ent *ent;
-
- if (strcmp(path, ".") == 0)
- cwd = 1;
- else
- cwd = 0;
-
- if (stat(path, &st) == -1) {
- cvs_log(LP_ERRNO, "failed to stat %s", path);
- return (NULL);
- }
-
- cfp = cvs_file_alloc(path, IFTODT(st.st_mode));
- if (cfp == NULL) {
- cvs_log(LP_ERRNO, "failed to allocate CVS file data");
- return (NULL);
- }
-
- ent = cvs_ent_getent(path);
- if (ent == NULL)
- cfp->cf_cvstat = (cwd == 1) ?
- CVS_FST_UPTODATE : CVS_FST_UNKNOWN;
- else {
- /* always show directories as up-to-date */
- if (ent->ce_type == CVS_ENT_DIR)
- cfp->cf_cvstat = CVS_FST_UPTODATE;
- else if (rcsnum_cmp(ent->ce_rev, cvs_addedrev, 2) == 0)
- cfp->cf_cvstat = CVS_FST_ADDED;
- else {
- /* check last modified time */
- if ((gmtime_r((time_t *)&(st.st_mtime), &lmtm) == NULL) ||
- (asctime_r(&lmtm, buf) == NULL)) {
- cvs_log(LP_ERR,
- "failed to generate file timestamp");
- /* fake an up to date file */
- strlcpy(buf, ent->ce_timestamp, sizeof(buf));
- }
- len = strlen(buf);
- if ((len > 0) && (buf[len - 1] == '\n'))
- buf[--len] = '\0';
-
- if (strcmp(buf, ent->ce_timestamp) == 0)
- cfp->cf_cvstat = CVS_FST_UPTODATE;
- else
- cfp->cf_cvstat = CVS_FST_MODIFIED;
- }
-
- cvs_ent_free(ent);
- }
-
- /* convert from stat mode to dirent values */
- cfp->cf_type = IFTODT(st.st_mode);
- if ((cfp->cf_type == DT_DIR) && ((flags & CF_RECURSE) || cwd)) {
- if ((flags & CF_KNOWN) && (cfp->cf_cvstat == CVS_FST_UNKNOWN)) {
- free(cfp->cf_ddat);
- cfp->cf_ddat = NULL;
- }
- else if (cvs_file_getdir(cfp, flags) < 0) {
- cvs_file_free(cfp);
- return (NULL);
- }
- }
-
- if (flags & CF_STAT) {
- cfp->cf_stat = (struct stat *)malloc(sizeof(struct stat));
- if (cfp->cf_stat == NULL) {
- cvs_log(LP_ERRNO, "failed to allocate stat structure");
- cvs_file_free(cfp);
- return (NULL);
- }
-
- memcpy(cfp->cf_stat, &st, sizeof(struct stat));
- }
-
- return (cfp);
+ return cvs_file_lget(path, flags, NULL);
}
@@ -373,7 +292,7 @@ cvs_file_getspec(char **fspec, int fsn, int flags)
{
int i, c;
char common[MAXPATHLEN];
- struct cvs_file *cfp;
+ CVSFILE *cfp;
/* first find the common subdir */
strlcpy(common, fspec[0], sizeof(common));
@@ -459,14 +378,14 @@ cvs_file_find(CVSFILE *hier, const char *path)
*/
static int
-cvs_file_getdir(struct cvs_file *cf, int flags)
+cvs_file_getdir(CVSFILE *cf, int flags)
{
int ret, fd;
long base;
void *dp, *ep;
char fbuf[2048], pbuf[MAXPATHLEN];
struct dirent *ent;
- struct cvs_file *cfp;
+ CVSFILE *cfp;
struct cvs_dir *cdp;
struct cvs_flist dirs;
@@ -482,11 +401,17 @@ cvs_file_getdir(struct cvs_file *cf, int flags)
}
cdp->cd_root = cvsroot_get(cf->cf_path);
+ printf("cvsroot = %s\n", cdp->cd_root->cr_str);
if (cdp->cd_root == NULL) {
cvs_file_freedir(cdp);
return (-1);
}
+ if (flags & CF_MKADMIN)
+ cvs_mkadmin(cf, 0755);
+
+ cdp->cd_ent = cvs_ent_open(cf->cf_path, O_RDONLY);
+
fd = open(cf->cf_path, O_RDONLY);
if (fd == -1) {
cvs_log(LP_ERRNO, "failed to open `%s'", cf->cf_path);
@@ -514,7 +439,7 @@ cvs_file_getdir(struct cvs_file *cf, int flags)
snprintf(pbuf, sizeof(pbuf), "%s/%s",
cf->cf_path, ent->d_name);
- cfp = cvs_file_get(pbuf, flags);
+ cfp = cvs_file_lget(pbuf, flags, cf);
if (cfp != NULL) {
cfp->cf_parent = cf;
if (cfp->cf_type == DT_DIR)
@@ -526,6 +451,12 @@ cvs_file_getdir(struct cvs_file *cf, int flags)
}
} while (ret > 0);
+ /* we can now close our Entries file */
+ if (cdp->cd_ent != NULL) {
+ cvs_ent_close(cdp->cd_ent);
+ cdp->cd_ent = NULL;
+ }
+
if (flags & CF_SORT) {
cvs_file_sort(&(cdp->cd_files));
cvs_file_sort(&dirs);
@@ -547,7 +478,7 @@ cvs_file_getdir(struct cvs_file *cf, int flags)
*/
void
-cvs_file_free(struct cvs_file *cf)
+cvs_file_free(CVSFILE *cf)
{
if (cf->cf_path != NULL)
free(cf->cf_path);
@@ -571,7 +502,7 @@ int
cvs_file_examine(CVSFILE *cf, int (*exam)(CVSFILE *, void *), void *arg)
{
int ret;
- struct cvs_file *fp;
+ CVSFILE *fp;
if (cf->cf_type == DT_DIR) {
ret = (*exam)(cf, arg);
@@ -597,13 +528,16 @@ cvs_file_examine(CVSFILE *cf, int (*exam)(CVSFILE *, void *), void *arg)
static void
cvs_file_freedir(struct cvs_dir *cd)
{
- struct cvs_file *cfp;
+ CVSFILE *cfp;
if (cd->cd_root != NULL)
cvsroot_free(cd->cd_root);
if (cd->cd_repo != NULL)
free(cd->cd_repo);
+ if (cd->cd_ent != NULL)
+ cvs_ent_close(cd->cd_ent);
+
while (!TAILQ_EMPTY(&(cd->cd_files))) {
cfp = TAILQ_FIRST(&(cd->cd_files));
TAILQ_REMOVE(&(cd->cd_files), cfp, cf_list);
@@ -623,12 +557,12 @@ cvs_file_sort(struct cvs_flist *flp)
{
int i;
size_t nb;
- struct cvs_file *cf, *cfvec[256];
+ CVSFILE *cf, *cfvec[256];
i = 0;
TAILQ_FOREACH(cf, flp, cf_list) {
cfvec[i++] = cf;
- if (i == sizeof(cfvec)/sizeof(struct cvs_file *)) {
+ if (i == sizeof(cfvec)/sizeof(CVSFILE *)) {
cvs_log(LP_WARN, "too many files to sort");
return (-1);
}
@@ -656,9 +590,9 @@ cvs_file_sort(struct cvs_flist *flp)
static int
cvs_file_cmp(const void *f1, const void *f2)
{
- struct cvs_file *cf1, *cf2;
- cf1 = *(struct cvs_file **)f1;
- cf2 = *(struct cvs_file **)f2;
+ CVSFILE *cf1, *cf2;
+ cf1 = *(CVSFILE **)f1;
+ cf2 = *(CVSFILE **)f2;
return strcmp(cf1->cf_name, cf2->cf_name);
}
@@ -671,7 +605,7 @@ cvs_file_alloc(const char *path, u_int type)
CVSFILE *cfp;
struct cvs_dir *ddat;
- cfp = (struct cvs_file *)malloc(sizeof(*cfp));
+ cfp = (CVSFILE *)malloc(sizeof(*cfp));
if (cfp == NULL) {
cvs_log(LP_ERRNO, "failed to allocate CVS file data");
return (NULL);
@@ -711,3 +645,103 @@ cvs_file_alloc(const char *path, u_int type)
}
return (cfp);
}
+
+
+/*
+ * cvs_file_lget()
+ *
+ * Get the file and link it with the parent right away.
+ */
+
+static CVSFILE*
+cvs_file_lget(const char *path, int flags, CVSFILE *parent)
+{
+ int cwd;
+ size_t len;
+ char buf[32];
+ struct stat st;
+ struct tm lmtm;
+ CVSFILE *cfp;
+ struct cvs_ent *ent;
+
+ ent = NULL;
+
+ if (strcmp(path, ".") == 0)
+ cwd = 1;
+ else
+ cwd = 0;
+
+ if (stat(path, &st) == -1) {
+ cvs_log(LP_ERRNO, "failed to stat %s", path);
+ return (NULL);
+ }
+
+ cfp = cvs_file_alloc(path, IFTODT(st.st_mode));
+ if (cfp == NULL) {
+ cvs_log(LP_ERRNO, "failed to allocate CVS file data");
+ return (NULL);
+ }
+ cfp->cf_parent = parent;
+
+ if ((parent != NULL) && (CVS_DIR_ENTRIES(parent) != NULL)) {
+ ent = cvs_ent_get(CVS_DIR_ENTRIES(parent), path);
+ }
+
+ if (ent == NULL)
+ cfp->cf_cvstat = (cwd == 1) ?
+ CVS_FST_UPTODATE : CVS_FST_UNKNOWN;
+ else {
+ /* always show directories as up-to-date */
+ if (ent->ce_type == CVS_ENT_DIR)
+ cfp->cf_cvstat = CVS_FST_UPTODATE;
+ else if (rcsnum_cmp(ent->ce_rev, cvs_addedrev, 2) == 0)
+ cfp->cf_cvstat = CVS_FST_ADDED;
+ else {
+ /* check last modified time */
+ if ((gmtime_r((time_t *)&(st.st_mtime),
+ &lmtm) == NULL) ||
+ (asctime_r(&lmtm, buf) == NULL)) {
+ cvs_log(LP_ERR,
+ "failed to generate file timestamp");
+ /* fake an up to date file */
+ strlcpy(buf, ent->ce_timestamp, sizeof(buf));
+ }
+ len = strlen(buf);
+ if ((len > 0) && (buf[len - 1] == '\n'))
+ buf[--len] = '\0';
+
+ if (strcmp(buf, ent->ce_timestamp) == 0)
+ cfp->cf_cvstat = CVS_FST_UPTODATE;
+ else
+ cfp->cf_cvstat = CVS_FST_MODIFIED;
+ }
+
+ cvs_ent_free(ent);
+ }
+
+ if ((cfp->cf_type == DT_DIR) && ((flags & CF_RECURSE) || cwd)) {
+ if ((flags & CF_KNOWN) && (cfp->cf_cvstat == CVS_FST_UNKNOWN)) {
+ free(cfp->cf_ddat);
+ cfp->cf_ddat = NULL;
+ }
+ else if (cvs_file_getdir(cfp, flags) < 0) {
+ cvs_file_free(cfp);
+ return (NULL);
+ }
+ }
+
+ if (flags & CF_STAT) {
+ cfp->cf_stat = (struct stat *)malloc(sizeof(struct stat));
+ if (cfp->cf_stat == NULL) {
+ cvs_log(LP_ERRNO, "failed to allocate stat structure");
+ cvs_file_free(cfp);
+ return (NULL);
+ }
+
+ memcpy(cfp->cf_stat, &st, sizeof(struct stat));
+ }
+
+ return (cfp);
+}
+
+
diff --git a/usr.bin/cvs/file.h b/usr.bin/cvs/file.h
index 0dd8cc52144..0b19674982e 100644
--- a/usr.bin/cvs/file.h
+++ b/usr.bin/cvs/file.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: file.h,v 1.2 2004/07/30 11:50:33 jfb Exp $ */
+/* $OpenBSD: file.h,v 1.3 2004/07/30 17:39:27 jfb Exp $ */
/*
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
* All rights reserved.
@@ -28,124 +28,20 @@
#define FILE_H
#include <sys/param.h>
-#include <stdio.h>
-#include <dirent.h>
-
-#include "rcs.h"
-
-#define CVS_VERSION "OpenCVS 0.1"
-
-
-#define FILE_HIST_CACHE 128
-#define FILE_HIST_NBFLD 6
-
-
-#define CVS_CKSUM_LEN 33 /* length of a CVS checksum string */
-
-
-/* operations */
-#define CVS_OP_ANY 0 /* all operations */
-#define CVS_OP_ADD 1
-#define CVS_OP_ANNOTATE 2
-#define CVS_OP_CHECKOUT 3
-#define CVS_OP_COMMIT 4
-#define CVS_OP_DIFF 5
-#define CVS_OP_HISTORY 6
-#define CVS_OP_IMPORT 7
-#define CVS_OP_INIT 8
-#define CVS_OP_LOG 9
-#define CVS_OP_REMOVE 10
-#define CVS_OP_SERVER 11
-#define CVS_OP_STATUS 12
-#define CVS_OP_TAG 13
-#define CVS_OP_UPDATE 14
-#define CVS_OP_VERSION 15
-
-
-
-
-/* methods */
-#define CVS_METHOD_NONE 0
-#define CVS_METHOD_LOCAL 1 /* local access */
-#define CVS_METHOD_SERVER 2 /* tunnel through CVS_RSH */
-#define CVS_METHOD_PSERVER 3 /* cvs pserver */
-#define CVS_METHOD_KSERVER 4 /* kerberos */
-#define CVS_METHOD_GSERVER 5 /* gssapi server */
-#define CVS_METHOD_EXT 6
-#define CVS_METHOD_FORK 7 /* local but fork */
-
-#define CVS_CMD_MAXNAMELEN 16
-#define CVS_CMD_MAXALIAS 2
-#define CVS_CMD_MAXDESCRLEN 64
-
-
-/* defaults */
-#define CVS_RSH_DEFAULT "ssh"
-#define CVS_EDITOR_DEFAULT "vi"
-
-
-/* server-side paths */
-#define CVS_PATH_ROOT "CVSROOT"
-#define CVS_PATH_COMMITINFO CVS_PATH_ROOT "/commitinfo"
-#define CVS_PATH_CONFIG CVS_PATH_ROOT "/config"
-#define CVS_PATH_CVSIGNORE CVS_PATH_ROOT "/cvsignore"
-#define CVS_PATH_CVSWRAPPERS CVS_PATH_ROOT "/cvswrappers"
-#define CVS_PATH_EDITINFO CVS_PATH_ROOT "/editinfo"
-#define CVS_PATH_HISTORY CVS_PATH_ROOT "/history"
-#define CVS_PATH_LOGINFO CVS_PATH_ROOT "/loginfo"
-#define CVS_PATH_MODULES CVS_PATH_ROOT "/modules"
-#define CVS_PATH_NOTIFY CVS_PATH_ROOT "/notify"
-#define CVS_PATH_RCSINFO CVS_PATH_ROOT "/rcsinfo"
-#define CVS_PATH_TAGINFO CVS_PATH_ROOT "/taginfo"
-#define CVS_PATH_VERIFYMSG CVS_PATH_ROOT "/verifymsg"
-
-
-/* client-side paths */
-#define CVS_PATH_RC ".cvsrc"
-#define CVS_PATH_CVSDIR "CVS"
-#define CVS_PATH_ENTRIES CVS_PATH_CVSDIR "/Entries"
-#define CVS_PATH_STATICENTRIES CVS_PATH_CVSDIR "/Entries.Static"
-#define CVS_PATH_LOGENTRIES CVS_PATH_CVSDIR "/Entries.Log"
-#define CVS_PATH_ROOTSPEC CVS_PATH_CVSDIR "/Root"
-#define CVS_PATH_REPOSITORY CVS_PATH_CVSDIR "/Repository"
+#include <dirent.h>
struct cvs_file;
struct cvs_dir;
-struct cvs_op {
- u_int co_op;
- uid_t co_uid; /* user performing the operation */
- char *co_path; /* target path of the operation */
- char *co_tag; /* tag or branch, NULL if HEAD */
-};
-
-
-
-struct cvsroot {
- char *cr_str;
- u_int cr_method;
- char *cr_buf;
- char *cr_user;
- char *cr_pass;
- char *cr_host;
- char *cr_dir;
- u_int cr_port;
- u_int cr_ref;
-
- /* connection data */
- FILE *cr_srvin;
- FILE *cr_srvout;
-};
-
-
-#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 */
+#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 */
+#define CF_MKADMIN 0x40 /* create administrative files if they're missing */
/*
@@ -190,14 +86,22 @@ typedef struct cvs_file {
struct cvs_dir {
struct cvsroot *cd_root;
char *cd_repo;
+ CVSENTRIES *cd_ent;
struct cvs_flist cd_files;
};
-#define CVS_DIR_ROOT(f) (((f)->cf_type == DTDIR) ? \
+#define CVS_DIR_ROOT(f) (((f)->cf_type == DT_DIR) ? \
(f)->cf_ddat->cd_root : (((f)->cf_parent == NULL) ? \
NULL : (f)->cf_parent->cf_ddat->cd_root))
+#define CVS_DIR_ENTRIES(f) (((f)->cf_type == DT_DIR) ? \
+ (f)->cf_ddat->cd_ent : (((f)->cf_parent == NULL) ? \
+ NULL : (f)->cf_parent->cf_ddat->cd_ent))
+
+#define CVS_DIR_REPO(f) (((f)->cf_type == DT_DIR) ? \
+ (f)->cf_ddat->cd_repo : (((f)->cf_parent == NULL) ? \
+ NULL : (f)->cf_parent->cf_ddat->cd_repo))
int cvs_file_init (void);
int cvs_file_ignore (const char *);