summaryrefslogtreecommitdiff
path: root/usr.bin/cvs
diff options
context:
space:
mode:
authorJoris Vink <joris@cvs.openbsd.org>2008-03-09 03:14:53 +0000
committerJoris Vink <joris@cvs.openbsd.org>2008-03-09 03:14:53 +0000
commit57bbfd67e0c60361607f0fe9754b6e180f256a89 (patch)
treeb45a59fb8b02d8075813ec716330f0644f13f769 /usr.bin/cvs
parenta57a4c04aca279828055a89d7d8f1207957a706c (diff)
proper repository locking:
- all read operations now look for a lock, and wait if present but never try to lock the tree themselfs anymore. - all write operations lock the tree where needed. - commit locks all relevant directories before even attempting to start.
Diffstat (limited to 'usr.bin/cvs')
-rw-r--r--usr.bin/cvs/admin.c4
-rw-r--r--usr.bin/cvs/checkout.c4
-rw-r--r--usr.bin/cvs/commit.c20
-rw-r--r--usr.bin/cvs/cvs.h5
-rw-r--r--usr.bin/cvs/file.c23
-rw-r--r--usr.bin/cvs/repository.c15
-rw-r--r--usr.bin/cvs/repository.h2
-rw-r--r--usr.bin/cvs/tag.c6
8 files changed, 60 insertions, 19 deletions
diff --git a/usr.bin/cvs/admin.c b/usr.bin/cvs/admin.c
index 1a858a0a755..452af8f1615 100644
--- a/usr.bin/cvs/admin.c
+++ b/usr.bin/cvs/admin.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: admin.c,v 1.56 2008/03/09 01:54:03 joris Exp $ */
+/* $OpenBSD: admin.c,v 1.57 2008/03/09 03:14:52 joris Exp $ */
/*
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
* Copyright (c) 2005 Joris Vink <joris@openbsd.org>
@@ -34,7 +34,7 @@
void cvs_admin_local(struct cvs_file *);
struct cvs_cmd cvs_cmd_admin = {
- CVS_OP_ADMIN, CVS_USE_WDIR, "admin",
+ CVS_OP_ADMIN, CVS_USE_WDIR | CVS_LOCK_REPO, "admin",
{ "adm", "rcs" },
"Administrative front-end for RCS",
"[-ILqU] [-A oldfile] [-a users] [-b branch]\n"
diff --git a/usr.bin/cvs/checkout.c b/usr.bin/cvs/checkout.c
index d2c64e104ac..cedc6a3fe26 100644
--- a/usr.bin/cvs/checkout.c
+++ b/usr.bin/cvs/checkout.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: checkout.c,v 1.142 2008/03/08 20:26:34 joris Exp $ */
+/* $OpenBSD: checkout.c,v 1.143 2008/03/09 03:14:52 joris Exp $ */
/*
* Copyright (c) 2006 Joris Vink <joris@openbsd.org>
*
@@ -416,7 +416,7 @@ checkout_repository(const char *repobase, const char *wdbase)
cr.fileproc = cvs_update_local;
cr.flags = flags;
- cvs_repository_lock(repobase);
+ cvs_repository_lock(repobase, 0);
cvs_repository_getdir(repobase, wdbase, &fl, &dl,
flags & CR_RECURSE_DIRS ? 1 : 0);
diff --git a/usr.bin/cvs/commit.c b/usr.bin/cvs/commit.c
index e7464cf5271..f785a425b6e 100644
--- a/usr.bin/cvs/commit.c
+++ b/usr.bin/cvs/commit.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: commit.c,v 1.131 2008/02/27 22:34:04 joris Exp $ */
+/* $OpenBSD: commit.c,v 1.132 2008/03/09 03:14:52 joris Exp $ */
/*
* Copyright (c) 2006 Joris Vink <joris@openbsd.org>
* Copyright (c) 2006 Xavier Santolaria <xsa@openbsd.org>
@@ -29,6 +29,7 @@
void cvs_commit_local(struct cvs_file *);
void cvs_commit_check_files(struct cvs_file *);
+void cvs_commit_lock_dirs(struct cvs_file *);
static BUF *commit_diff(struct cvs_file *, RCSNUM *, int);
static void commit_desc_set(struct cvs_file *);
@@ -42,7 +43,7 @@ int conflicts_found;
char *logmsg = NULL;
struct cvs_cmd cvs_cmd_commit = {
- CVS_OP_COMMIT, CVS_USE_WDIR, "commit",
+ CVS_OP_COMMIT, CVS_USE_WDIR | CVS_LOCK_REPO, "commit",
{ "ci", "com" },
"Check files into the repository",
"[-flR] [-F logfile | -m msg] [-r rev] ...",
@@ -154,6 +155,9 @@ cvs_commit(int argc, char **argv)
cvs_client_send_request("ci");
cvs_client_get_responses();
} else {
+ cr.fileproc = cvs_commit_lock_dirs;
+ cvs_file_walklist(&files_affected, &cr);
+
cr.fileproc = cvs_commit_local;
cvs_file_walklist(&files_affected, &cr);
cvs_file_freelist(&files_affected);
@@ -170,6 +174,18 @@ cvs_commit(int argc, char **argv)
}
void
+cvs_commit_lock_dirs(struct cvs_file *cf)
+{
+ char repo[MAXPATHLEN];
+
+ cvs_get_repository_path(cf->file_wd, repo, sizeof(repo));
+ cvs_log(LP_TRACE, "cvs_commit_lock_dirs: %s", repo);
+
+ /* locks stay in place until we are fully done and exit */
+ cvs_repository_lock(repo, 1);
+}
+
+void
cvs_commit_check_files(struct cvs_file *cf)
{
char *tag;
diff --git a/usr.bin/cvs/cvs.h b/usr.bin/cvs/cvs.h
index d9aa05f96b9..bab48b84acc 100644
--- a/usr.bin/cvs/cvs.h
+++ b/usr.bin/cvs/cvs.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cvs.h,v 1.163 2008/03/08 20:26:34 joris Exp $ */
+/* $OpenBSD: cvs.h,v 1.164 2008/03/09 03:14:52 joris Exp $ */
/*
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
* All rights reserved.
@@ -103,7 +103,8 @@
#define CVS_CMD_MAXARG 128
/* flags */
-#define CVS_USE_WDIR 1
+#define CVS_USE_WDIR 0x01
+#define CVS_LOCK_REPO 0x02
/* defaults */
#define CVS_SERVER_DEFAULT "cvs"
diff --git a/usr.bin/cvs/file.c b/usr.bin/cvs/file.c
index e7dfc0467ea..53a81946b1e 100644
--- a/usr.bin/cvs/file.c
+++ b/usr.bin/cvs/file.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: file.c,v 1.233 2008/03/09 03:06:56 joris Exp $ */
+/* $OpenBSD: file.c,v 1.234 2008/03/09 03:14:52 joris Exp $ */
/*
* Copyright (c) 2006 Joris Vink <joris@openbsd.org>
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
@@ -238,6 +238,7 @@ cvs_file_get_cf(const char *d, const char *f, int fd,
cf->file_type = type;
cf->file_status = cf->file_flags = 0;
cf->user_supplied = user_supplied;
+ cf->in_attic = 0;
cf->file_ent = NULL;
if (current_cvsroot->cr_method != CVS_METHOD_LOCAL ||
@@ -341,10 +342,21 @@ cvs_file_walklist(struct cvs_flisthead *fl, struct cvs_recursion *cr)
if (cvs_directory_tag == NULL &&
cvs_specified_tag != NULL)
cvs_directory_tag = cvs_specified_tag;
+
+ if (current_cvsroot->cr_method ==
+ CVS_METHOD_LOCAL) {
+ cvs_get_repository_path(cf->file_wd,
+ repo, MAXPATHLEN);
+ cvs_repository_lock(repo,
+ (cmdp->cmd_flags & CVS_LOCK_REPO));
+ }
}
if (cr->fileproc != NULL)
cr->fileproc(cf);
+
+ if (l->user_supplied && cmdp->cmd_flags & CVS_LOCK_REPO)
+ cvs_repository_unlock(repo);
}
cvs_file_free(cf);
@@ -556,10 +568,12 @@ cvs_file_walkdir(struct cvs_file *cf, struct cvs_recursion *cr)
cvs_ent_close(entlist, ENT_NOSYNC);
walkrepo:
- if (cr->flags & CR_REPO) {
+ if (current_cvsroot->cr_method == CVS_METHOD_LOCAL) {
cvs_get_repository_path(cf->file_path, repo, MAXPATHLEN);
- cvs_repository_lock(repo);
+ cvs_repository_lock(repo, (cmdp->cmd_flags & CVS_LOCK_REPO));
+ }
+ if (cr->flags & CR_REPO) {
xsnprintf(fpath, sizeof(fpath), "%s/%s", cf->file_path,
CVS_PATH_STATICENTRIES);
@@ -571,7 +585,8 @@ walkrepo:
cvs_file_walklist(&fl, cr);
cvs_file_freelist(&fl);
- if (cr->flags & CR_REPO)
+ if (current_cvsroot->cr_method == CVS_METHOD_LOCAL &&
+ (cmdp->cmd_flags & CVS_LOCK_REPO))
cvs_repository_unlock(repo);
cvs_file_walklist(&dl, cr);
diff --git a/usr.bin/cvs/repository.c b/usr.bin/cvs/repository.c
index b5718ec3f2c..bc002c7f448 100644
--- a/usr.bin/cvs/repository.c
+++ b/usr.bin/cvs/repository.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: repository.c,v 1.19 2008/02/03 23:34:41 joris Exp $ */
+/* $OpenBSD: repository.c,v 1.20 2008/03/09 03:14:52 joris Exp $ */
/*
* Copyright (c) 2006 Joris Vink <joris@openbsd.org>
*
@@ -41,9 +41,10 @@ cvs_repository_unlock(const char *repo)
}
void
-cvs_repository_lock(const char *repo)
+cvs_repository_lock(const char *repo, int wantlock)
{
int i;
+ uid_t myuid;
struct stat st;
char fpath[MAXPATHLEN];
struct passwd *pw;
@@ -51,10 +52,12 @@ cvs_repository_lock(const char *repo)
if (cvs_noexec == 1 || cvs_readonlyfs == 1)
return;
- cvs_log(LP_TRACE, "cvs_repository_lock(%s)", repo);
+ cvs_log(LP_TRACE, "cvs_repository_lock(%s, %d)", repo, wantlock);
(void)xsnprintf(fpath, sizeof(fpath), "%s/%s", repo, CVS_LOCK);
+ myuid = getuid();
+
for (i = 0; i < CVS_LOCK_TRIES; i++) {
if (cvs_quit)
fatal("received signal %d", sig_received);
@@ -62,6 +65,9 @@ cvs_repository_lock(const char *repo)
if (stat(fpath, &st) == -1)
break;
+ if (st.st_uid == myuid)
+ return;
+
if ((pw = getpwuid(st.st_uid)) == NULL)
fatal("cvs_repository_lock: %s", strerror(errno));
@@ -73,6 +79,9 @@ cvs_repository_lock(const char *repo)
if (i == CVS_LOCK_TRIES)
fatal("maximum wait time for lock inside '%s' reached", repo);
+ if (wantlock == 0)
+ return;
+
if ((i = open(fpath, O_WRONLY|O_CREAT|O_TRUNC, 0755)) < 0) {
if (errno == EEXIST)
fatal("cvs_repository_lock: somebody beat us");
diff --git a/usr.bin/cvs/repository.h b/usr.bin/cvs/repository.h
index 6375f3c4780..7ac540e02dd 100644
--- a/usr.bin/cvs/repository.h
+++ b/usr.bin/cvs/repository.h
@@ -25,7 +25,7 @@
extern struct cvs_wklhead repo_locks;
void cvs_repository_unlock(const char *);
-void cvs_repository_lock(const char *);
+void cvs_repository_lock(const char *, int);
void cvs_repository_getdir(const char *, const char *,
struct cvs_flisthead *, struct cvs_flisthead *, int);
diff --git a/usr.bin/cvs/tag.c b/usr.bin/cvs/tag.c
index 0e3bbf0540f..7e6eebf2559 100644
--- a/usr.bin/cvs/tag.c
+++ b/usr.bin/cvs/tag.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tag.c,v 1.70 2008/03/02 19:05:34 tobias Exp $ */
+/* $OpenBSD: tag.c,v 1.71 2008/03/09 03:14:52 joris Exp $ */
/*
* Copyright (c) 2006 Xavier Santolaria <xsa@openbsd.org>
*
@@ -39,7 +39,7 @@ static char *tag_name = NULL;
static char *tag_oldname = NULL;
struct cvs_cmd cvs_cmd_rtag = {
- CVS_OP_RTAG, 0, "rtag",
+ CVS_OP_RTAG, CVS_LOCK_REPO, "rtag",
{ "rt", "rfreeze" },
"Add a symbolic tag to a module",
"[-bcdFflR] [-D date | -r rev] tag modules ...",
@@ -49,7 +49,7 @@ struct cvs_cmd cvs_cmd_rtag = {
};
struct cvs_cmd cvs_cmd_tag = {
- CVS_OP_TAG, CVS_USE_WDIR, "tag",
+ CVS_OP_TAG, CVS_USE_WDIR | CVS_LOCK_REPO, "tag",
{ "ta", "freeze" },
"Add a symbolic tag to checked out version of files",
"[-bcdFflR] [-D date | -r rev] tag [file ...]",