Merge rev 1.2 (do not check val-tags if the repository is read-only)
into version 1.11.22.
This commit is contained in:
parent
5508baed23
commit
d304d2a774
@ -1,6 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 1992, Brian Berliner and Jeff Polk
|
||||
* Copyright (c) 1989-1992, Brian Berliner
|
||||
* Copyright (C) 1986-2005 The Free Software Foundation, Inc.
|
||||
*
|
||||
* Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
|
||||
* and others.
|
||||
*
|
||||
* Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
|
||||
* Portions Copyright (C) 1989-1992, Brian Berliner
|
||||
*
|
||||
* You may distribute under the terms of the GNU General Public License as
|
||||
* specified in the README file that comes with the CVS source distribution.
|
||||
@ -152,11 +157,9 @@ cvstag (argc, argv)
|
||||
break;
|
||||
case 'Q':
|
||||
case 'q':
|
||||
#ifdef SERVER_SUPPORT
|
||||
/* The CVS 1.5 client sends these options (in addition to
|
||||
Global_option requests), so we must ignore them. */
|
||||
if (!server_active)
|
||||
#endif
|
||||
error (1, 0,
|
||||
"-q or -Q must be specified before \"%s\"",
|
||||
cvs_cmd_name);
|
||||
@ -354,11 +357,12 @@ rtag_proc (argc, argv, xwhere, mwhere, mfile, shorten, local_specified,
|
||||
{
|
||||
error (0, errno, "cannot chdir to %s", repository);
|
||||
free (repository);
|
||||
free (where);
|
||||
return (1);
|
||||
}
|
||||
/* End section which is identical to patch_proc. */
|
||||
|
||||
if (delete_flag || attic_too || (force_tag_match && numtag))
|
||||
if (delete_flag || force_tag_move || attic_too || numtag)
|
||||
which = W_REPOS | W_ATTIC;
|
||||
else
|
||||
which = W_REPOS;
|
||||
@ -1134,6 +1138,170 @@ val_fileproc (callerdat, finfo)
|
||||
|
||||
|
||||
|
||||
/* This routine determines whether a tag appears in CVSROOT/val-tags.
|
||||
*
|
||||
* The val-tags file will be open read-only when IDB is NULL. Since writes to
|
||||
* val-tags always append to it, the lack of locking is okay. The worst case
|
||||
* race condition might misinterpret a partially written "foobar" matched, for
|
||||
* instance, a request for "f", "foo", of "foob". Such a mismatch would be
|
||||
* caught harmlessly later.
|
||||
*
|
||||
* Before CVS adds a tag to val-tags, it will lock val-tags for write and
|
||||
* verify that the tag is still not present to avoid adding it twice.
|
||||
*
|
||||
* NOTES
|
||||
* This function expects its parent to handle any necessary locking of the
|
||||
* val-tags file.
|
||||
*
|
||||
* INPUTS
|
||||
* idb When this value is NULL, the val-tags file is opened in
|
||||
* in read-only mode. When present, the val-tags file is opened
|
||||
* in read-write mode and the DBM handle is stored in *IDB.
|
||||
* name The tag to search for.
|
||||
*
|
||||
* OUTPUTS
|
||||
* *idb The val-tags file opened for read/write, or NULL if it couldn't
|
||||
* be opened.
|
||||
*
|
||||
* ERRORS
|
||||
* Exits with an error message if the val-tags file cannot be opened for
|
||||
* read (failure to open val-tags read/write is harmless - see below).
|
||||
*
|
||||
* RETURNS
|
||||
* true 1. If NAME exists in val-tags.
|
||||
* 2. If IDB is non-NULL and val-tags cannot be opened for write.
|
||||
* This allows callers to ignore the harmless inability to
|
||||
* update the val-tags cache.
|
||||
* false If the file could be opened and the tag is not present.
|
||||
*/
|
||||
static int is_in_val_tags PROTO((DBM **idb, const char *name));
|
||||
static int
|
||||
is_in_val_tags (idb, name)
|
||||
DBM **idb;
|
||||
const char *name;
|
||||
{
|
||||
DBM *db = NULL;
|
||||
char *valtags_filename;
|
||||
datum mytag;
|
||||
int status;
|
||||
|
||||
/* Casting out const should be safe here - input datums are not
|
||||
* written to by the myndbm functions.
|
||||
*/
|
||||
mytag.dptr = (char *)name;
|
||||
mytag.dsize = strlen (name);
|
||||
|
||||
valtags_filename = xmalloc (strlen (current_parsed_root->directory)
|
||||
+ sizeof CVSROOTADM
|
||||
+ sizeof CVSROOTADM_VALTAGS + 3);
|
||||
sprintf (valtags_filename, "%s/%s/%s", current_parsed_root->directory,
|
||||
CVSROOTADM, CVSROOTADM_VALTAGS);
|
||||
|
||||
if (idb)
|
||||
{
|
||||
db = dbm_open (valtags_filename, O_RDWR, 0666);
|
||||
if (!db)
|
||||
{
|
||||
mode_t omask;
|
||||
|
||||
if (!existence_error (errno))
|
||||
{
|
||||
error (0, errno, "warning: cannot open %s read/write",
|
||||
valtags_filename);
|
||||
*idb = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
omask = umask (cvsumask);
|
||||
db = dbm_open (valtags_filename, O_RDWR | O_CREAT | O_TRUNC, 0666);
|
||||
umask (omask);
|
||||
if (!db)
|
||||
{
|
||||
error (0, errno, "warning: cannot create %s",
|
||||
valtags_filename);
|
||||
*idb = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
*idb = db;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*idb = db;
|
||||
}
|
||||
else
|
||||
{
|
||||
db = dbm_open (valtags_filename, O_RDONLY, 0444);
|
||||
if (!db && !existence_error (errno))
|
||||
error (1, errno, "cannot read %s", valtags_filename);
|
||||
}
|
||||
|
||||
/* If the file merely fails to exist, we just keep going and create
|
||||
it later if need be. */
|
||||
|
||||
status = 0;
|
||||
if (db)
|
||||
{
|
||||
datum val;
|
||||
|
||||
val = dbm_fetch (db, mytag);
|
||||
if (val.dptr != NULL)
|
||||
/* Found. The tag is valid. */
|
||||
status = 1;
|
||||
|
||||
/* FIXME: should check errors somehow (add dbm_error to myndbm.c?). */
|
||||
|
||||
if (!idb) dbm_close (db);
|
||||
}
|
||||
|
||||
free (valtags_filename);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Add a tag to the CVSROOT/val-tags cache. Establishes a write lock and
|
||||
* reverifies that the tag does not exist before adding it.
|
||||
*/
|
||||
static void add_to_val_tags PROTO((const char *name));
|
||||
static void
|
||||
add_to_val_tags (name)
|
||||
const char *name;
|
||||
{
|
||||
DBM *db;
|
||||
datum mytag;
|
||||
datum value;
|
||||
|
||||
if (noexec) return;
|
||||
|
||||
val_tags_lock (current_parsed_root->directory);
|
||||
|
||||
/* Check for presence again since we have a lock now. */
|
||||
if (is_in_val_tags (&db, name))
|
||||
{
|
||||
clear_val_tags_lock ();
|
||||
if (db)
|
||||
dbm_close (db);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Casting out const should be safe here - input datums are not
|
||||
* written to by the myndbm functions.
|
||||
*/
|
||||
mytag.dptr = (char *)name;
|
||||
mytag.dsize = strlen (name);
|
||||
value.dptr = "y";
|
||||
value.dsize = 1;
|
||||
|
||||
if (dbm_store (db, mytag, value, DBM_REPLACE) < 0)
|
||||
error (0, errno, "failed to store %s into val-tags", name);
|
||||
dbm_close (db);
|
||||
|
||||
clear_val_tags_lock ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
static Dtype val_direntproc PROTO ((void *, const char *, const char *,
|
||||
const char *, List *));
|
||||
|
||||
@ -1175,10 +1343,6 @@ tag_check_valid (name, argc, argv, local, aflag, repository)
|
||||
int aflag;
|
||||
char *repository;
|
||||
{
|
||||
DBM *db;
|
||||
char *valtags_filename;
|
||||
int nowrite = 0;
|
||||
datum mytag;
|
||||
struct val_args the_val_args;
|
||||
struct saved_cwd cwd;
|
||||
int which;
|
||||
@ -1204,49 +1368,12 @@ Numeric tag %s contains characters other than digits and '.'", name);
|
||||
if (readonlyfs)
|
||||
return;
|
||||
|
||||
/* FIXME: This routine doesn't seem to do any locking whatsoever
|
||||
(and it is called from places which don't have locks in place).
|
||||
If two processes try to write val-tags at the same time, it would
|
||||
seem like we are in trouble. */
|
||||
/* Verify that the tag is valid syntactically. Some later code once made
|
||||
* assumptions about this.
|
||||
*/
|
||||
RCS_check_tag (name);
|
||||
|
||||
mytag.dptr = name;
|
||||
mytag.dsize = strlen (name);
|
||||
|
||||
valtags_filename = xmalloc (strlen (current_parsed_root->directory)
|
||||
+ sizeof CVSROOTADM
|
||||
+ sizeof CVSROOTADM_VALTAGS + 3);
|
||||
sprintf (valtags_filename, "%s/%s/%s", current_parsed_root->directory,
|
||||
CVSROOTADM, CVSROOTADM_VALTAGS);
|
||||
db = dbm_open (valtags_filename, O_RDWR, 0666);
|
||||
if (db == NULL)
|
||||
{
|
||||
if (!existence_error (errno))
|
||||
{
|
||||
error (0, errno, "warning: cannot open %s read/write",
|
||||
valtags_filename);
|
||||
db = dbm_open (valtags_filename, O_RDONLY, 0666);
|
||||
if (db != NULL)
|
||||
nowrite = 1;
|
||||
else if (!existence_error (errno))
|
||||
error (1, errno, "cannot read %s", valtags_filename);
|
||||
}
|
||||
/* If the file merely fails to exist, we just keep going and create
|
||||
it later if need be. */
|
||||
}
|
||||
if (db != NULL)
|
||||
{
|
||||
datum val;
|
||||
|
||||
val = dbm_fetch (db, mytag);
|
||||
if (val.dptr != NULL)
|
||||
{
|
||||
/* Found. The tag is valid. */
|
||||
dbm_close (db);
|
||||
free (valtags_filename);
|
||||
return;
|
||||
}
|
||||
/* FIXME: should check errors somehow (add dbm_error to myndbm.c?). */
|
||||
}
|
||||
if (is_in_val_tags (NULL, name)) return;
|
||||
|
||||
/* We didn't find the tag in val-tags, so look through all the RCS files
|
||||
to see whether it exists there. Yes, this is expensive, but there
|
||||
@ -1291,42 +1418,12 @@ Numeric tag %s contains characters other than digits and '.'", name);
|
||||
if (!the_val_args.found)
|
||||
error (1, 0, "no such tag %s", name);
|
||||
else
|
||||
{
|
||||
/* The tags is valid but not mentioned in val-tags. Add it. */
|
||||
datum value;
|
||||
|
||||
if (noexec || nowrite)
|
||||
{
|
||||
if (db != NULL)
|
||||
dbm_close (db);
|
||||
free (valtags_filename);
|
||||
return;
|
||||
}
|
||||
|
||||
if (db == NULL)
|
||||
{
|
||||
mode_t omask;
|
||||
omask = umask (cvsumask);
|
||||
db = dbm_open (valtags_filename, O_RDWR | O_CREAT | O_TRUNC, 0666);
|
||||
(void)umask (omask);
|
||||
|
||||
if (db == NULL)
|
||||
{
|
||||
error (0, errno, "warning: cannot create %s", valtags_filename);
|
||||
free (valtags_filename);
|
||||
return;
|
||||
}
|
||||
}
|
||||
value.dptr = "y";
|
||||
value.dsize = 1;
|
||||
if (dbm_store (db, mytag, value, DBM_REPLACE) < 0)
|
||||
error (0, errno, "cannot store %s into %s", name,
|
||||
valtags_filename);
|
||||
dbm_close (db);
|
||||
}
|
||||
free (valtags_filename);
|
||||
add_to_val_tags (name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Check whether a join tag is valid. This is just like
|
||||
* tag_check_valid, but we must stop before the colon if there is one.
|
||||
|
Loading…
x
Reference in New Issue
Block a user