diff options
author | Joris Vink <joris@cvs.openbsd.org> | 2008-03-09 03:14:53 +0000 |
---|---|---|
committer | Joris Vink <joris@cvs.openbsd.org> | 2008-03-09 03:14:53 +0000 |
commit | 57bbfd67e0c60361607f0fe9754b6e180f256a89 (patch) | |
tree | b45a59fb8b02d8075813ec716330f0644f13f769 /usr.bin/cvs | |
parent | a57a4c04aca279828055a89d7d8f1207957a706c (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.c | 4 | ||||
-rw-r--r-- | usr.bin/cvs/checkout.c | 4 | ||||
-rw-r--r-- | usr.bin/cvs/commit.c | 20 | ||||
-rw-r--r-- | usr.bin/cvs/cvs.h | 5 | ||||
-rw-r--r-- | usr.bin/cvs/file.c | 23 | ||||
-rw-r--r-- | usr.bin/cvs/repository.c | 15 | ||||
-rw-r--r-- | usr.bin/cvs/repository.h | 2 | ||||
-rw-r--r-- | usr.bin/cvs/tag.c | 6 |
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 ...]", |