Initial merge of 1.11.1p1 -> 1.11.2 changes onto mainline
This commit is contained in:
parent
0471b259a4
commit
8df8fc83d5
@ -178,13 +178,12 @@ foreach sfile (SCCS/s.*)
|
||||
if ($status != 0) goto ERROR
|
||||
|
||||
# get file into current dir and get stats
|
||||
set date = `sccs prs -r$rev $file | grep "^D " | awk '{printf("19%s %s", $3, $4); exit}'`
|
||||
set year = `echo $date | cut -c3-4`
|
||||
if ($year < 70) then
|
||||
# Y2K Bug, change century to 20
|
||||
set date = `echo $date | sed -e s/19/20/`
|
||||
endif
|
||||
set author = `sccs prs -r$rev $file | grep "^D " | awk '{print $5; exit}'`
|
||||
|
||||
# Is the substr stuff and the +0 in the following awk script really
|
||||
# necessary? It seems to me that if we didn't find the date format
|
||||
# we expected in the output we have other problems.
|
||||
set date = `sccs prs -r$rev $file | awk '/^D / {print (substr($3,0,2)+0<70?20:19) $3, $4; exit}'`
|
||||
set author = `sccs prs -r$rev $file | awk '/^D / {print $5; exit}'`
|
||||
echo ""
|
||||
echo "==> file $file, rev=$rev, date=$date, author=$author"
|
||||
sccs edit -r$rev $file >>& $logfile
|
||||
|
@ -447,7 +447,7 @@ diff3_run (argc, argv, out, callbacks_arg)
|
||||
outfile = fopen (out, "w");
|
||||
if (outfile == NULL)
|
||||
{
|
||||
perror_with_name ("could not open output file");
|
||||
perror_with_name (out);
|
||||
return 2;
|
||||
}
|
||||
opened_file = 1;
|
||||
@ -1850,10 +1850,10 @@ myread (fd, ptr, size)
|
||||
char *ptr;
|
||||
size_t size;
|
||||
{
|
||||
size_t result = read (fd, ptr, size);
|
||||
ssize_t result = read (fd, ptr, size);
|
||||
if (result == -1)
|
||||
diff3_perror_with_exit ("read failed");
|
||||
return result;
|
||||
return (size_t)result;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -27,8 +27,12 @@ cvs \- Concurrent Versions System
|
||||
.SH "NOTE"
|
||||
This manpage is a summary of some of the features of
|
||||
.B cvs
|
||||
but for more in-depth documentation, consult the Cederqvist manual (as
|
||||
described in the SEE ALSO section of this manpage).
|
||||
but it may no longer be kept up-to-date.
|
||||
For more current and in-depth documentation, please consult the
|
||||
Cederqvist manual (via the
|
||||
.B info cvs
|
||||
command or otherwise,
|
||||
as described in the SEE ALSO section of this manpage).
|
||||
.SH "DESCRIPTION"
|
||||
.IX "revision control system" "\fLcvs\fR"
|
||||
.IX cvs "" "\fLcvs\fP \- concurrent versions system"
|
||||
@ -958,7 +962,7 @@ the
|
||||
.B \-s
|
||||
option within the modules file.
|
||||
.TP
|
||||
\fBcommit\fP [\fB\-lnR\fP] [\fB\-m\fP '\fIlog_message\fP' | \fB\-f\fP \fIfile\fP] [\fB\-r\fP \fIrevision\fP] [\fIfiles.\|.\|.\fP]
|
||||
\fBcommit\fP [\fB\-lnR\fP] [\fB\-m\fP '\fIlog_message\fP' | \fB\-F\fP \fIfile\fP] [\fB\-r\fP \fIrevision\fP] [\fIfiles.\|.\|.\fP]
|
||||
.I Requires:
|
||||
working directory, repository.
|
||||
.br
|
||||
@ -1494,7 +1498,7 @@ Working directory.
|
||||
Working directory, history log.
|
||||
.br
|
||||
This command is meant to safely cancel the effect of
|
||||
.` "cvs checkout'.
|
||||
.` "cvs checkout".
|
||||
Since
|
||||
.B cvs
|
||||
doesn't lock files, it isn't strictly necessary to use this command.
|
||||
@ -1677,6 +1681,13 @@ Use this command to assign symbolic tags to the nearest repository
|
||||
versions to your working sources. The tags are applied immediately to
|
||||
the repository, as with \fBrtag\fP.
|
||||
.SP
|
||||
One potentially surprising aspect of the fact that \fBcvs tag\fP
|
||||
operates on the repository is that you are tagging the checked-in
|
||||
revisions, which may differ from locally modified files in your working
|
||||
directory. If you want to avoid doing this by mistake, specify the
|
||||
\fB-c\fP option to \fBcvs tag\fP. If there are any locally modified files, CVS
|
||||
will abort with an error before it tags any files.
|
||||
.SP
|
||||
One use for tags is to record a ``snapshot'' of the current sources
|
||||
when the software freeze date of a project arrives. As bugs are fixed
|
||||
after the freeze date, only those changed sources that are to be part
|
||||
@ -1762,7 +1773,7 @@ or
|
||||
.B update
|
||||
keeps you informed of its progress by printing a line for each file,
|
||||
prefaced with one of the characters
|
||||
.` "U A R M C ?"
|
||||
.` "U P A R M C ?"
|
||||
to indicate the status of the file:
|
||||
.TP 1i
|
||||
\fBU\fP \fIfile\fP
|
||||
@ -1771,6 +1782,10 @@ This is done for any file that exists in the repository but not in
|
||||
your source, and for files that you haven't changed but are not the most
|
||||
recent versions available in the repository.
|
||||
.TP 1i
|
||||
\fBP\fP \fIfile\fP
|
||||
Like \fBU\fP, but the CVS server sends a patch instead of an entire file.
|
||||
This accomplishes the same thing as \fBU\fP using less bandwidth.
|
||||
.TP 1i
|
||||
\fBA\fP \fIfile\fP
|
||||
The file has been \fIadded\fP to your private copy of the sources, and
|
||||
will be added to the
|
||||
@ -2180,7 +2195,7 @@ command or it may be available as cvs.ps (postscript), cvs.texinfo
|
||||
For CVS updates, more information on documentation, software related
|
||||
to CVS, development of CVS, and more, see:
|
||||
.in +1i
|
||||
.B http://www.cyclic.com
|
||||
.B http://cvshome.org
|
||||
.B http://www.loria.fr/~molli/cvs-index.html
|
||||
.in -1i
|
||||
.SP
|
||||
|
@ -87,19 +87,19 @@ static const char *const export_usage[] =
|
||||
};
|
||||
|
||||
static int checkout_prune_dirs;
|
||||
static int force_tag_match = 1;
|
||||
static int force_tag_match;
|
||||
static int pipeout;
|
||||
static int aflag;
|
||||
static char *options = NULL;
|
||||
static char *tag = NULL;
|
||||
static int tag_validated = 0;
|
||||
static char *date = NULL;
|
||||
static char *join_rev1 = NULL;
|
||||
static char *join_rev2 = NULL;
|
||||
static int join_tags_validated = 0;
|
||||
static int pull_template = 0;
|
||||
static char *preload_update_dir = NULL;
|
||||
static char *history_name = NULL;
|
||||
static char *options;
|
||||
static char *tag;
|
||||
static int tag_validated;
|
||||
static char *date;
|
||||
static char *join_rev1;
|
||||
static char *join_rev2;
|
||||
static int join_tags_validated;
|
||||
static int pull_template;
|
||||
static char *preload_update_dir;
|
||||
static char *history_name;
|
||||
static enum mtype m_type;
|
||||
|
||||
int
|
||||
@ -118,6 +118,18 @@ checkout (argc, argv)
|
||||
char *valid_options;
|
||||
const char *const *valid_usage;
|
||||
|
||||
/* initialize static options */
|
||||
force_tag_match = 1;
|
||||
if (options)
|
||||
{
|
||||
free (options);
|
||||
options = NULL;
|
||||
}
|
||||
tag = date = join_rev1 = join_rev2 = preload_update_dir = NULL;
|
||||
history_name = NULL;
|
||||
tag_validated = join_tags_validated = 0;
|
||||
|
||||
|
||||
/*
|
||||
* A smaller subset of options are allowed for the export command, which
|
||||
* is essentially like checkout, except that it hard-codes certain
|
||||
@ -257,7 +269,7 @@ checkout (argc, argv)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!cat && !safe_location()) {
|
||||
if (!cat && !pipeout && !safe_location( where )) {
|
||||
error(1, 0, "Cannot check out files into the repository itself");
|
||||
}
|
||||
|
||||
@ -342,7 +354,10 @@ checkout (argc, argv)
|
||||
{
|
||||
cat_module (status);
|
||||
if (options)
|
||||
{
|
||||
free (options);
|
||||
options = NULL;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
db = open_module ();
|
||||
@ -360,17 +375,17 @@ checkout (argc, argv)
|
||||
|
||||
/* If we will be calling history_write, work out the name to pass
|
||||
it. */
|
||||
if (m_type == CHECKOUT && !pipeout)
|
||||
if (!pipeout)
|
||||
{
|
||||
if (tag && date)
|
||||
if (!date)
|
||||
history_name = tag;
|
||||
else if (!tag)
|
||||
history_name = date;
|
||||
else
|
||||
{
|
||||
history_name = xmalloc (strlen (tag) + strlen (date) + 2);
|
||||
sprintf (history_name, "%s:%s", tag, date);
|
||||
}
|
||||
else if (tag)
|
||||
history_name = tag;
|
||||
else
|
||||
history_name = date;
|
||||
}
|
||||
|
||||
|
||||
@ -380,7 +395,12 @@ checkout (argc, argv)
|
||||
(char *) NULL);
|
||||
close_module (db);
|
||||
if (options)
|
||||
{
|
||||
free (options);
|
||||
options = NULL;
|
||||
}
|
||||
if (history_name != tag && history_name != date && history_name != NULL)
|
||||
free (history_name);
|
||||
return (err);
|
||||
}
|
||||
|
||||
@ -388,9 +408,11 @@ checkout (argc, argv)
|
||||
reasons, probably want to move them. */
|
||||
|
||||
int
|
||||
safe_location ()
|
||||
safe_location (where)
|
||||
char *where;
|
||||
{
|
||||
char *current;
|
||||
char *where_location;
|
||||
char hardpath[PATH_MAX+5];
|
||||
size_t hardpath_len;
|
||||
int x;
|
||||
@ -412,9 +434,68 @@ safe_location ()
|
||||
{
|
||||
hardpath[x] = '\0';
|
||||
}
|
||||
|
||||
/* set current - even if where is set we'll need to cd back... */
|
||||
current = xgetwd ();
|
||||
if (current == NULL)
|
||||
error (1, errno, "could not get working directory");
|
||||
|
||||
/* if where is set, set current to where, where - last_component( where ),
|
||||
* or fail, depending on whether the directories exist or not.
|
||||
*/
|
||||
if( where != NULL )
|
||||
{
|
||||
if( chdir( where ) != -1 )
|
||||
{
|
||||
/* where */
|
||||
where_location = xgetwd();
|
||||
if( where_location == NULL )
|
||||
error( 1, errno, "could not get working directory" );
|
||||
|
||||
if( chdir( current ) == -1 )
|
||||
error( 1, errno, "could not change directory to `%s'", current );
|
||||
|
||||
free( current );
|
||||
current = where_location;
|
||||
}
|
||||
else if( errno == ENOENT )
|
||||
{
|
||||
if ( last_component( where ) != where )
|
||||
{
|
||||
/* where - last_component( where ) */
|
||||
char *parent;
|
||||
|
||||
/* strip the last_component */
|
||||
where_location = strdup( where );
|
||||
parent = last_component( where_location );
|
||||
parent[-1] = '\0';
|
||||
|
||||
if( chdir( where_location ) != -1 )
|
||||
{
|
||||
where_location = xgetwd();
|
||||
if( where_location == NULL )
|
||||
error( 1, errno, "could not get working directory (nominally `%s')", where_location );
|
||||
|
||||
if( chdir( current ) == -1 )
|
||||
error( 1, errno, "could not change directory to `%s'", current );
|
||||
|
||||
free( current );
|
||||
current = where_location;
|
||||
}
|
||||
else
|
||||
/* fail */
|
||||
error( 1, errno, "could not change directory to requested checkout directory `%s'", where_location );
|
||||
}
|
||||
/* else: ERRNO == ENOENT & last_component(where) == where
|
||||
* for example, 'cvs co -d newdir module', where newdir hasn't
|
||||
* been created yet, so leave current set to '.' and check that
|
||||
*/
|
||||
}
|
||||
else
|
||||
/* fail */
|
||||
error( 1, errno, "could not change directory to requested checkout directory `%s'", where );
|
||||
}
|
||||
|
||||
hardpath_len = strlen (hardpath);
|
||||
if (strlen (current) >= hardpath_len
|
||||
&& strncmp (current, hardpath, hardpath_len) == 0)
|
||||
@ -860,7 +941,7 @@ internal error: %s doesn't start with %s in checkout_proc",
|
||||
build_one_dir whenever the -d command option was specified
|
||||
to checkout. */
|
||||
|
||||
if (! where_is_absolute && top_level_admin)
|
||||
if (! where_is_absolute && top_level_admin && m_type == CHECKOUT)
|
||||
{
|
||||
/* It may be argued that we shouldn't set any sticky
|
||||
bits for the top-level repository. FIXME? */
|
||||
@ -1007,12 +1088,9 @@ internal error: %s doesn't start with %s in checkout_proc",
|
||||
*/
|
||||
if (!(local_specified || argc > 1))
|
||||
{
|
||||
if (m_type == CHECKOUT && !pipeout)
|
||||
history_write ('O', preload_update_dir, history_name, where,
|
||||
repository);
|
||||
else if (m_type == EXPORT && !pipeout)
|
||||
history_write ('E', preload_update_dir, tag ? tag : date, where,
|
||||
repository);
|
||||
if (!pipeout)
|
||||
history_write (m_type == CHECKOUT ? 'O' : 'E', preload_update_dir,
|
||||
history_name, where, repository);
|
||||
err += do_update (0, (char **) NULL, options, tag, date,
|
||||
force_tag_match, 0 /* !local */ ,
|
||||
1 /* update -d */ , aflag, checkout_prune_dirs,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -352,9 +352,10 @@ commit (argc, argv)
|
||||
struct passwd *pw;
|
||||
|
||||
if ((pw = (struct passwd *) getpwnam (getcaller ())) == NULL)
|
||||
error (1, 0, "you are unknown to this system");
|
||||
error (1, 0, "your apparent username (%s) is unknown to this system",
|
||||
getcaller ());
|
||||
if (pw->pw_uid == (uid_t) 0)
|
||||
error (1, 0, "cannot commit files as 'root'");
|
||||
error (1, 0, "'root' is not allowed to commit files");
|
||||
}
|
||||
#endif /* CVS_BADROOT */
|
||||
|
||||
@ -496,11 +497,6 @@ commit (argc, argv)
|
||||
if (use_editor)
|
||||
do_editor (".", &saved_message, (char *)NULL, find_args.ulist);
|
||||
|
||||
/* Run the user-defined script to verify/check information in
|
||||
*the log message
|
||||
*/
|
||||
do_verify (&saved_message, (char *)NULL);
|
||||
|
||||
/* We always send some sort of message, even if empty. */
|
||||
/* FIXME: is that true? There seems to be some code in do_editor
|
||||
which can leave the message NULL. */
|
||||
@ -1576,7 +1572,7 @@ commit_dirleaveproc (callerdat, dir, err, update_dir, entries)
|
||||
this being a confusing feature! */
|
||||
if (err == 0 && write_dirtag != NULL)
|
||||
{
|
||||
char *repos = Name_Repository (dir, update_dir);
|
||||
char *repos = Name_Repository (NULL, update_dir);
|
||||
WriteTag (NULL, write_dirtag, NULL, write_dirnonbranch,
|
||||
update_dir, repos);
|
||||
free (repos);
|
||||
@ -1810,7 +1806,7 @@ unlockrcs (rcs)
|
||||
{
|
||||
int retcode;
|
||||
|
||||
if ((retcode = RCS_unlock (rcs, NULL, 0)) != 0)
|
||||
if ((retcode = RCS_unlock (rcs, NULL, 1)) != 0)
|
||||
error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0,
|
||||
"could not unlock %s", rcs->path);
|
||||
else
|
||||
|
@ -82,8 +82,11 @@ extern int errno;
|
||||
#include "system.h"
|
||||
|
||||
#include "hash.h"
|
||||
|
||||
#include "root.h"
|
||||
|
||||
#if defined(SERVER_SUPPORT) || defined(CLIENT_SUPPORT)
|
||||
#include "client.h"
|
||||
# include "client.h"
|
||||
#endif
|
||||
|
||||
#ifdef MY_NDBM
|
||||
@ -369,26 +372,7 @@ extern int cvswrite;
|
||||
extern mode_t cvsumask;
|
||||
extern char *RCS_citag;
|
||||
|
||||
/* Access method specified in CVSroot. */
|
||||
typedef enum {
|
||||
null_method, local_method, server_method, pserver_method, kserver_method, gserver_method,
|
||||
ext_method, fork_method
|
||||
} CVSmethod;
|
||||
extern char *method_names[]; /* change this in root.c if you change
|
||||
the enum above */
|
||||
|
||||
typedef struct cvsroot_s {
|
||||
char *original; /* the complete source CVSroot string */
|
||||
CVSmethod method; /* one of the enum values above */
|
||||
char *username; /* the username or NULL if method == local */
|
||||
char *password; /* the username or NULL if method == local */
|
||||
char *hostname; /* the hostname or NULL if method == local */
|
||||
int port; /* the port or zero if method == local */
|
||||
char *directory; /* the directory name */
|
||||
#ifdef CLIENT_SUPPORT
|
||||
unsigned char isremote; /* nonzero if we are doing remote access */
|
||||
#endif /* CLIENT_SUPPORT */
|
||||
} cvsroot_t;
|
||||
|
||||
/* This global variable holds the global -d option. It is NULL if -d
|
||||
was not used, which means that we must get the CVSroot information
|
||||
@ -401,7 +385,7 @@ extern List *root_directories;
|
||||
extern cvsroot_t *current_parsed_root;
|
||||
|
||||
extern char *emptydir_name PROTO ((void));
|
||||
extern int safe_location PROTO ((void));
|
||||
extern int safe_location PROTO ((char *));
|
||||
|
||||
extern int trace; /* Show all commands */
|
||||
extern int noexec; /* Don't modify disk anywhere */
|
||||
@ -411,6 +395,12 @@ extern int require_real_user; /* skip CVSROOT/passwd, /etc/passwd users only*/
|
||||
|
||||
extern int top_level_admin;
|
||||
|
||||
|
||||
#define LOGMSG_REREAD_NEVER 0 /* do_verify - never reread message */
|
||||
#define LOGMSG_REREAD_ALWAYS 1 /* do_verify - always reread message */
|
||||
#define LOGMSG_REREAD_STAT 2 /* do_verify - reread message if changed */
|
||||
extern int RereadLogAfterVerify;
|
||||
|
||||
#ifdef CLIENT_SUPPORT
|
||||
extern List *dirs_sent_to_server; /* used to decide which "Argument
|
||||
xxx" commands to send to each
|
||||
@ -482,7 +472,7 @@ char *time_stamp PROTO((char *file));
|
||||
void *xmalloc PROTO((size_t bytes));
|
||||
void *xrealloc PROTO((void *ptr, size_t bytes));
|
||||
void expand_string PROTO ((char **, size_t *, size_t));
|
||||
void allocate_and_strcat PROTO ((char **, size_t *, const char *));
|
||||
void xrealloc_and_strcat PROTO ((char **, size_t *, const char *));
|
||||
char *xstrdup PROTO((const char *str));
|
||||
void strip_trailing_newlines PROTO((char *str));
|
||||
int pathname_levels PROTO ((char *path));
|
||||
|
@ -64,24 +64,71 @@ static size_t opts_allocated = 1;
|
||||
static int diff_errors;
|
||||
static int empty_files = 0;
|
||||
|
||||
/* FIXME: should be documenting all the options here. They don't
|
||||
perfectly match rcsdiff options (for example, we always support
|
||||
--ifdef and --context, but rcsdiff only does if diff does). */
|
||||
static const char *const diff_usage[] =
|
||||
{
|
||||
"Usage: %s %s [-lNR] [rcsdiff-options]\n",
|
||||
"Usage: %s %s [-lR] [-k kopt] [format_options]\n",
|
||||
" [[-r rev1 | -D date1] [-r rev2 | -D date2]] [files...] \n",
|
||||
"\t-l\tLocal directory only, not recursive\n",
|
||||
"\t-R\tProcess directories recursively.\n",
|
||||
"\t-k kopt\tSpecify keyword expansion mode.\n",
|
||||
"\t-D d1\tDiff revision for date against working file.\n",
|
||||
"\t-D d2\tDiff rev1/date1 against date2.\n",
|
||||
"\t-N\tinclude diffs for added and removed files.\n",
|
||||
"\t-r rev1\tDiff revision for rev1 against working file.\n",
|
||||
"\t-r rev2\tDiff rev1/date1 against rev2.\n",
|
||||
"\t--ifdef=arg\tOutput diffs in ifdef format.\n",
|
||||
"(consult the documentation for your diff program for rcsdiff-options.\n",
|
||||
"The most popular is -c for context diffs but there are many more).\n",
|
||||
"(Specify the --help global option for a list of other help options)\n",
|
||||
"\nformat_options:\n",
|
||||
" -i --ignore-case Consider upper- and lower-case to be the same.\n",
|
||||
" -w --ignore-all-space Ignore all white space.\n",
|
||||
" -b --ignore-space-change Ignore changes in the amount of white space.\n",
|
||||
" -B --ignore-blank-lines Ignore changes whose lines are all blank.\n",
|
||||
" -I RE --ignore-matching-lines=RE Ignore changes whose lines all match RE.\n",
|
||||
" --binary Read and write data in binary mode.\n",
|
||||
" -a --text Treat all files as text.\n\n",
|
||||
" -c -C NUM --context[=NUM] Output NUM (default 2) lines of copied context.\n",
|
||||
" -u -U NUM --unified[=NUM] Output NUM (default 2) lines of unified context.\n",
|
||||
" -NUM Use NUM context lines.\n",
|
||||
" -L LABEL --label LABEL Use LABEL instead of file name.\n",
|
||||
" -p --show-c-function Show which C function each change is in.\n",
|
||||
" -F RE --show-function-line=RE Show the most recent line matching RE.\n",
|
||||
" --brief Output only whether files differ.\n",
|
||||
" -e --ed Output an ed script.\n",
|
||||
" -f --forward-ed Output something like an ed script in forward order.\n",
|
||||
" -n --rcs Output an RCS format diff.\n",
|
||||
" -y --side-by-side Output in two columns.\n",
|
||||
" -W NUM --width=NUM Output at most NUM (default 130) characters per line.\n",
|
||||
" --left-column Output only the left column of common lines.\n",
|
||||
" --suppress-common-lines Do not output common lines.\n",
|
||||
" --ifdef=NAME Output merged file to show `#ifdef NAME' diffs.\n",
|
||||
" --GTYPE-group-format=GFMT Similar, but format GTYPE input groups with GFMT.\n",
|
||||
" --line-format=LFMT Similar, but format all input lines with LFMT.\n",
|
||||
" --LTYPE-line-format=LFMT Similar, but format LTYPE input lines with LFMT.\n",
|
||||
" LTYPE is `old', `new', or `unchanged'. GTYPE is LTYPE or `changed'.\n",
|
||||
" GFMT may contain:\n",
|
||||
" %%< lines from FILE1\n",
|
||||
" %%> lines from FILE2\n",
|
||||
" %%= lines common to FILE1 and FILE2\n",
|
||||
" %%[-][WIDTH][.[PREC]]{doxX}LETTER printf-style spec for LETTER\n",
|
||||
" LETTERs are as follows for new group, lower case for old group:\n",
|
||||
" F first line number\n",
|
||||
" L last line number\n",
|
||||
" N number of lines = L-F+1\n",
|
||||
" E F-1\n",
|
||||
" M L+1\n",
|
||||
" LFMT may contain:\n",
|
||||
" %%L contents of line\n",
|
||||
" %%l contents of line, excluding any trailing newline\n",
|
||||
" %%[-][WIDTH][.[PREC]]{doxX}n printf-style spec for input line number\n",
|
||||
" Either GFMT or LFMT may contain:\n",
|
||||
" %%%% %%\n",
|
||||
" %%c'C' the single character C\n",
|
||||
" %%c'\\OOO' the character with octal code OOO\n\n",
|
||||
" -t --expand-tabs Expand tabs to spaces in output.\n",
|
||||
" -T --initial-tab Make tabs line up by prepending a tab.\n\n",
|
||||
" -N --new-file Treat absent files as empty.\n",
|
||||
" -s --report-identical-files Report when two files are the same.\n",
|
||||
" --horizon-lines=NUM Keep NUM lines of the common prefix and suffix.\n",
|
||||
" -d --minimal Try hard to find a smaller set of changes.\n",
|
||||
" -H --speed-large-files Assume large files and many scattered small changes.\n",
|
||||
"\n(Specify the --help global option for a list of other help options)\n",
|
||||
NULL
|
||||
};
|
||||
|
||||
@ -89,19 +136,20 @@ static const char *const diff_usage[] =
|
||||
removing the following entries, none of which seem relevant to use
|
||||
with CVS:
|
||||
--help
|
||||
--version
|
||||
--recursive
|
||||
--unidirectional-new-file
|
||||
--starting-file
|
||||
--exclude
|
||||
--exclude-from
|
||||
--version (-v)
|
||||
--recursive (-r)
|
||||
--unidirectional-new-file (-P)
|
||||
--starting-file (-S)
|
||||
--exclude (-x)
|
||||
--exclude-from (-X)
|
||||
--sdiff-merge-assist
|
||||
--paginate (-l) (doesn't work with library callbacks)
|
||||
|
||||
I changed the options which take optional arguments (--context and
|
||||
--unified) to return a number rather than a letter, so that the
|
||||
optional argument could be handled more easily. I changed the
|
||||
--paginate and --brief options to return a number, since -l and -q
|
||||
mean something else to cvs diff.
|
||||
--brief and --ifdef options to return numbers, since -q and -D mean
|
||||
something else to cvs diff.
|
||||
|
||||
The numbers 129- that appear in the fourth element of some entries
|
||||
tell the big switch in `diff' how to process those options. -- Ian
|
||||
@ -128,7 +176,6 @@ static struct option const longopts[] =
|
||||
{"ed", 0, 0, 'e'},
|
||||
{"forward-ed", 0, 0, 'f'},
|
||||
{"ignore-case", 0, 0, 'i'},
|
||||
{"paginate", 0, 0, 144},
|
||||
{"rcs", 0, 0, 'n'},
|
||||
{"show-c-function", 0, 0, 'p'},
|
||||
|
||||
@ -229,19 +276,22 @@ diff (argc, argv)
|
||||
|
||||
optind = 0;
|
||||
while ((c = getopt_long (argc, argv,
|
||||
"+abcdefhilnpstuwy0123456789BHNRTC:D:F:I:L:U:V:W:k:r:j:",
|
||||
"+abcdefhilnpstuwy0123456789BHNRTC:D:F:I:L:U:W:k:r:j:",
|
||||
longopts, &option_index)) != -1)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'y':
|
||||
xrealloc_and_strcat (&opts, &opts_allocated, " --side-by-side");
|
||||
break;
|
||||
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
|
||||
case 'h': case 'i': case 'n': case 'p': case 's': case 't':
|
||||
case 'u': case 'w': case 'y':
|
||||
case 'u': case 'w':
|
||||
case '0': case '1': case '2': case '3': case '4': case '5':
|
||||
case '6': case '7': case '8': case '9':
|
||||
case 'B': case 'H': case 'T':
|
||||
(void) sprintf (tmp, " -%c", (char) c);
|
||||
allocate_and_strcat (&opts, &opts_allocated, tmp);
|
||||
xrealloc_and_strcat (&opts, &opts_allocated, tmp);
|
||||
break;
|
||||
case 'L':
|
||||
if (have_rev1_label++)
|
||||
@ -251,31 +301,31 @@ diff (argc, argv)
|
||||
break;
|
||||
}
|
||||
|
||||
allocate_and_strcat (&opts, &opts_allocated, " -L");
|
||||
allocate_and_strcat (&opts, &opts_allocated, optarg);
|
||||
xrealloc_and_strcat (&opts, &opts_allocated, " -L");
|
||||
xrealloc_and_strcat (&opts, &opts_allocated, optarg);
|
||||
break;
|
||||
case 'C': case 'F': case 'I': case 'U': case 'V': case 'W':
|
||||
case 'C': case 'F': case 'I': case 'U': case 'W':
|
||||
(void) sprintf (tmp, " -%c", (char) c);
|
||||
allocate_and_strcat (&opts, &opts_allocated, tmp);
|
||||
allocate_and_strcat (&opts, &opts_allocated, optarg);
|
||||
xrealloc_and_strcat (&opts, &opts_allocated, tmp);
|
||||
xrealloc_and_strcat (&opts, &opts_allocated, optarg);
|
||||
break;
|
||||
case 131:
|
||||
/* --ifdef. */
|
||||
allocate_and_strcat (&opts, &opts_allocated, " --ifdef=");
|
||||
allocate_and_strcat (&opts, &opts_allocated, optarg);
|
||||
xrealloc_and_strcat (&opts, &opts_allocated, " --ifdef=");
|
||||
xrealloc_and_strcat (&opts, &opts_allocated, optarg);
|
||||
break;
|
||||
case 129: case 130: case 132: case 133: case 134:
|
||||
case 135: case 136: case 137: case 138: case 139: case 140:
|
||||
case 141: case 142: case 143: case 144: case 145: case 146:
|
||||
allocate_and_strcat (&opts, &opts_allocated, " --");
|
||||
allocate_and_strcat (&opts, &opts_allocated,
|
||||
case 141: case 142: case 143: case 145: case 146:
|
||||
xrealloc_and_strcat (&opts, &opts_allocated, " --");
|
||||
xrealloc_and_strcat (&opts, &opts_allocated,
|
||||
longopts[option_index].name);
|
||||
if (longopts[option_index].has_arg == 1
|
||||
|| (longopts[option_index].has_arg == 2
|
||||
&& optarg != NULL))
|
||||
{
|
||||
allocate_and_strcat (&opts, &opts_allocated, "=");
|
||||
allocate_and_strcat (&opts, &opts_allocated, optarg);
|
||||
xrealloc_and_strcat (&opts, &opts_allocated, "=");
|
||||
xrealloc_and_strcat (&opts, &opts_allocated, optarg);
|
||||
}
|
||||
break;
|
||||
case 'R':
|
||||
@ -470,8 +520,7 @@ diff_fileproc (callerdat, finfo)
|
||||
(vers->vn_rcs == NULL
|
||||
? NULL
|
||||
: RCS_branch_head (vers->srcfile, vers->vn_rcs));
|
||||
exists = (head != NULL
|
||||
&& !RCS_isdead (vers->srcfile, head));
|
||||
exists = head != NULL && !RCS_isdead(vers->srcfile, head);
|
||||
if (head != NULL)
|
||||
free (head);
|
||||
}
|
||||
@ -481,8 +530,7 @@ diff_fileproc (callerdat, finfo)
|
||||
|
||||
xvers = Version_TS (finfo, NULL, diff_rev1, diff_date1,
|
||||
1, 0);
|
||||
exists = (xvers->vn_rcs != NULL
|
||||
&& !RCS_isdead (xvers->srcfile, xvers->vn_rcs));
|
||||
exists = xvers->vn_rcs != NULL && !RCS_isdead(xvers->srcfile, xvers->vn_rcs);
|
||||
freevers_ts (&xvers);
|
||||
}
|
||||
if (exists)
|
||||
|
@ -335,8 +335,7 @@ mkdir_if_needed (name)
|
||||
{
|
||||
if (mkdir (name, 0777) < 0)
|
||||
{
|
||||
if (!(errno == EEXIST
|
||||
|| (errno == EACCES && isdir (name))))
|
||||
if (errno != EEXIST && !isdir (name))
|
||||
error (1, errno, "cannot make directory %s", name);
|
||||
return 1;
|
||||
}
|
||||
|
@ -220,7 +220,11 @@ import (argc, argv)
|
||||
|
||||
if (use_editor)
|
||||
{
|
||||
do_editor ((char *) NULL, &message, repository,
|
||||
do_editor ((char *) NULL, &message,
|
||||
#ifdef CLIENT_SUPPORT
|
||||
current_parsed_root->isremote ? (char *) NULL :
|
||||
#endif
|
||||
repository,
|
||||
(List *) NULL);
|
||||
}
|
||||
do_verify (&message, repository);
|
||||
@ -280,7 +284,7 @@ import (argc, argv)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!safe_location ())
|
||||
if (!safe_location ( NULL ))
|
||||
{
|
||||
error (1, 0, "attempt to import the repository");
|
||||
}
|
||||
@ -313,7 +317,6 @@ import (argc, argv)
|
||||
if (!really_quiet)
|
||||
{
|
||||
char buf[20];
|
||||
char *buf2;
|
||||
|
||||
cvs_output_tagged ("+importmergecmd", NULL);
|
||||
cvs_output_tagged ("newline", NULL);
|
||||
@ -333,12 +336,9 @@ import (argc, argv)
|
||||
cvs_output_tagged ("text", CVSroot_cmdline);
|
||||
}
|
||||
cvs_output_tagged ("text", " checkout -j");
|
||||
buf2 = xmalloc (strlen (argv[1]) + 20);
|
||||
sprintf (buf2, "%s:yesterday", argv[1]);
|
||||
cvs_output_tagged ("mergetag1", buf2);
|
||||
free (buf2);
|
||||
cvs_output_tagged ("mergetag1", "<prev_rel_tag>");
|
||||
cvs_output_tagged ("text", " -j");
|
||||
cvs_output_tagged ("mergetag2", argv[1]);
|
||||
cvs_output_tagged ("mergetag2", argv[2]);
|
||||
cvs_output_tagged ("text", " ");
|
||||
cvs_output_tagged ("repository", argv[0]);
|
||||
cvs_output_tagged ("newline", NULL);
|
||||
@ -620,6 +620,7 @@ update_rcs_file (message, vfile, vtag, targc, targv, inattic)
|
||||
Vers_TS *vers;
|
||||
int letter;
|
||||
char *tocvsPath;
|
||||
char *expand;
|
||||
struct file_info finfo;
|
||||
|
||||
memset (&finfo, 0, sizeof finfo);
|
||||
@ -649,7 +650,9 @@ update_rcs_file (message, vfile, vtag, targc, targv, inattic)
|
||||
tocvsPath = wrap_tocvs_process_file (vfile);
|
||||
/* FIXME: Why don't we pass tocvsPath to RCS_cmp_file if it is
|
||||
not NULL? */
|
||||
different = RCS_cmp_file (vers->srcfile, vers->vn_rcs, "-ko", vfile);
|
||||
expand = vers->srcfile->expand != NULL &&
|
||||
vers->srcfile->expand[0] == 'b' ? "-kb" : "-ko";
|
||||
different = RCS_cmp_file (vers->srcfile, vers->vn_rcs, expand, vfile);
|
||||
if (tocvsPath)
|
||||
if (unlink_file_dir (tocvsPath) < 0)
|
||||
error (0, errno, "cannot remove %s", tocvsPath);
|
||||
@ -1153,7 +1156,7 @@ add_rcs_file (message, rcs, user, add_vhead, key_opt,
|
||||
goto write_error;
|
||||
}
|
||||
|
||||
if (local_opt != NULL)
|
||||
if (local_opt != NULL && strcmp (local_opt, "kv") != 0)
|
||||
{
|
||||
if (fprintf (fprcs, "expand @%s@;\012", local_opt) < 0)
|
||||
{
|
||||
|
@ -293,6 +293,9 @@ Lock_Cleanup ()
|
||||
/* FIXME-reentrancy: the workaround isn't reentrant. */
|
||||
static int in_lock_cleanup = 0;
|
||||
|
||||
if (trace)
|
||||
(void) fprintf (stderr, "%s-> Lock_Cleanup()\n", CLIENT_SERVER_STR);
|
||||
|
||||
if (in_lock_cleanup)
|
||||
return;
|
||||
in_lock_cleanup = 1;
|
||||
@ -398,6 +401,10 @@ Reader_Lock (xrepository)
|
||||
FILE *fp;
|
||||
char *tmp;
|
||||
|
||||
if (trace)
|
||||
(void) fprintf (stderr, "%s-> Reader_Lock(%s)\n", CLIENT_SERVER_STR,
|
||||
xrepository);
|
||||
|
||||
if (noexec || readonlyfs)
|
||||
return (0);
|
||||
|
||||
@ -561,6 +568,10 @@ write_lock (lock)
|
||||
FILE *fp;
|
||||
char *tmp;
|
||||
|
||||
if (trace)
|
||||
(void) fprintf (stderr, "%s-> write_lock(%s)\n",
|
||||
CLIENT_SERVER_STR, lock->repository);
|
||||
|
||||
if (writelock == NULL)
|
||||
{
|
||||
writelock = xmalloc (strlen (hostname) + sizeof (CVSWFL) + 40);
|
||||
|
@ -324,8 +324,8 @@ password_entry_operation (operation, root, newpassword)
|
||||
fp = CVS_FOPEN (passfile, "r");
|
||||
if (fp == NULL)
|
||||
{
|
||||
error (0, errno, "failed to open %s for reading", passfile);
|
||||
goto error_exit;
|
||||
error (0, errno, "warning: failed to open %s for reading", passfile);
|
||||
goto process;
|
||||
}
|
||||
|
||||
cvsroot_canonical = normalize_cvsroot (root);
|
||||
@ -363,6 +363,8 @@ password_entry_operation (operation, root, newpassword)
|
||||
password = xstrdup (password);
|
||||
}
|
||||
|
||||
process:
|
||||
|
||||
/* might as well return now */
|
||||
if (operation == password_entry_lookup)
|
||||
goto out;
|
||||
@ -552,6 +554,12 @@ login (argc, argv)
|
||||
{
|
||||
char *tmp;
|
||||
tmp = GETPASS ("CVS password: ");
|
||||
/* Must deal with a NULL return value here. I haven't managed to
|
||||
* disconnect the CVS process from the tty and force a NULL return
|
||||
* in sanity.sh, but the Linux version of getpass is documented
|
||||
* to return NULL when it can't open /dev/tty...
|
||||
*/
|
||||
if (!tmp) error (1, errno, "login: Failed to read password.");
|
||||
typed_password = scramble (tmp);
|
||||
memset (tmp, 0, strlen (tmp));
|
||||
}
|
||||
@ -562,7 +570,7 @@ login (argc, argv)
|
||||
* will get zeroed by connect_to_server(). */
|
||||
cvs_password = xstrdup (typed_password);
|
||||
|
||||
connect_to_pserver (NULL, NULL, 1, 0);
|
||||
connect_to_pserver (current_parsed_root, NULL, NULL, 1, 0);
|
||||
|
||||
password_entry_operation (password_entry_add, current_parsed_root, typed_password);
|
||||
|
||||
|
@ -8,6 +8,8 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "cvs.h"
|
||||
#include "getline.h"
|
||||
|
||||
@ -29,6 +31,15 @@ static char *editinfo_editor;
|
||||
static char *verifymsg_script;
|
||||
static Ctype type;
|
||||
|
||||
/*
|
||||
* Should the logmsg be re-read during the do_verify phase?
|
||||
* RereadLogAfterVerify=no|stat|yes
|
||||
* LOGMSG_REREAD_NEVER - never re-read the logmsg
|
||||
* LOGMSG_REREAD_STAT - re-read the logmsg only if it has changed
|
||||
* LOGMSG_REREAD_ALWAYS - always re-read the logmsg
|
||||
*/
|
||||
int RereadLogAfterVerify = LOGMSG_REREAD_ALWAYS;
|
||||
|
||||
/*
|
||||
* Puts a standard header on the output which is either being prepared for an
|
||||
* editor session, or being sent to a logfile program. The modified, added,
|
||||
@ -168,7 +179,8 @@ fmt_proc (p, closure)
|
||||
* stripped and the log message is stored in the "message" argument.
|
||||
*
|
||||
* If REPOSITORY is non-NULL, process rcsinfo for that repository; if it
|
||||
* is NULL, use the CVSADM_TEMPLATE file instead.
|
||||
* is NULL, use the CVSADM_TEMPLATE file instead. REPOSITORY should be
|
||||
* NULL when running in client mode.
|
||||
*/
|
||||
void
|
||||
do_editor (dir, messagep, repository, changes)
|
||||
@ -185,6 +197,9 @@ do_editor (dir, messagep, repository, changes)
|
||||
struct stat pre_stbuf, post_stbuf;
|
||||
int retcode = 0;
|
||||
|
||||
assert (current_parsed_root->isremote && !repository
|
||||
|| !current_parsed_root->isremote && repository);
|
||||
|
||||
if (noexec || reuse_log_message)
|
||||
return;
|
||||
|
||||
@ -309,7 +324,7 @@ do_editor (dir, messagep, repository, changes)
|
||||
/* On NT, we might read less than st_size bytes, but we won't
|
||||
read more. So this works. */
|
||||
*messagep = (char *) xmalloc (post_stbuf.st_size + 1);
|
||||
*messagep[0] = '\0';
|
||||
(*messagep)[0] = '\0';
|
||||
}
|
||||
|
||||
line = NULL;
|
||||
@ -342,8 +357,14 @@ do_editor (dir, messagep, repository, changes)
|
||||
|
||||
if (pre_stbuf.st_mtime == post_stbuf.st_mtime ||
|
||||
*messagep == NULL ||
|
||||
(*messagep)[0] == '\0' ||
|
||||
strcmp (*messagep, "\n") == 0)
|
||||
{
|
||||
if (*messagep)
|
||||
{
|
||||
free (*messagep);
|
||||
*messagep = NULL;
|
||||
}
|
||||
for (;;)
|
||||
{
|
||||
(void) printf ("\nLog message unchanged or not specified\n");
|
||||
@ -399,11 +420,7 @@ do_verify (messagep, repository)
|
||||
char *fname;
|
||||
int retcode = 0;
|
||||
|
||||
char *line;
|
||||
int line_length;
|
||||
size_t line_chars_allocated;
|
||||
char *p;
|
||||
struct stat stbuf;
|
||||
struct stat pre_stbuf, post_stbuf;
|
||||
|
||||
#ifdef CLIENT_SUPPORT
|
||||
if (current_parsed_root->isremote)
|
||||
@ -429,78 +446,104 @@ do_verify (messagep, repository)
|
||||
|
||||
if ((fp = cvs_temp_file (&fname)) == NULL)
|
||||
error (1, errno, "cannot create temporary file %s", fname);
|
||||
else
|
||||
|
||||
fprintf (fp, "%s", *messagep);
|
||||
if ((*messagep)[0] == '\0' ||
|
||||
(*messagep)[strlen (*messagep) - 1] != '\n')
|
||||
(void) fprintf (fp, "%s", "\n");
|
||||
if (fclose (fp) == EOF)
|
||||
error (1, errno, "%s", fname);
|
||||
|
||||
if (RereadLogAfterVerify == LOGMSG_REREAD_STAT)
|
||||
{
|
||||
fprintf (fp, "%s", *messagep);
|
||||
if ((*messagep)[0] == '\0' ||
|
||||
(*messagep)[strlen (*messagep) - 1] != '\n')
|
||||
(void) fprintf (fp, "%s", "\n");
|
||||
if (fclose (fp) == EOF)
|
||||
error (1, errno, "%s", fname);
|
||||
/* Remember the status of the temp file for later */
|
||||
if ( CVS_STAT (fname, &pre_stbuf) != 0 )
|
||||
error (1, errno, "cannot stat temp file %s", fname);
|
||||
|
||||
/* Get the name of the verification script to run */
|
||||
/*
|
||||
* See if we need to sleep before running the verification
|
||||
* script to avoid time-stamp races.
|
||||
*/
|
||||
sleep_past (pre_stbuf.st_mtime);
|
||||
}
|
||||
|
||||
if (repository != NULL)
|
||||
(void) Parse_Info (CVSROOTADM_VERIFYMSG, repository,
|
||||
verifymsg_proc, 0);
|
||||
/* Get the name of the verification script to run */
|
||||
|
||||
/* Run the verification script */
|
||||
if (repository != NULL)
|
||||
(void) Parse_Info (CVSROOTADM_VERIFYMSG, repository,
|
||||
verifymsg_proc, 0);
|
||||
|
||||
if (verifymsg_script)
|
||||
/* Run the verification script */
|
||||
|
||||
if (verifymsg_script)
|
||||
{
|
||||
run_setup (verifymsg_script);
|
||||
run_arg (fname);
|
||||
if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY,
|
||||
RUN_NORMAL | RUN_SIGIGNORE)) != 0)
|
||||
{
|
||||
run_setup (verifymsg_script);
|
||||
run_arg (fname);
|
||||
if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY,
|
||||
RUN_NORMAL | RUN_SIGIGNORE)) != 0)
|
||||
{
|
||||
/* Since following error() exits, delete the temp file
|
||||
now. */
|
||||
if (unlink_file (fname) < 0)
|
||||
error (0, errno, "cannot remove %s", fname);
|
||||
/* Since following error() exits, delete the temp file now. */
|
||||
if (unlink_file (fname) < 0)
|
||||
error (0, errno, "cannot remove %s", fname);
|
||||
|
||||
error (1, retcode == -1 ? errno : 0,
|
||||
"Message verification failed");
|
||||
}
|
||||
error (1, retcode == -1 ? errno : 0,
|
||||
"Message verification failed");
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the mod time and size of the possibly new log message
|
||||
* in always and stat modes.
|
||||
*/
|
||||
if (RereadLogAfterVerify == LOGMSG_REREAD_ALWAYS ||
|
||||
RereadLogAfterVerify == LOGMSG_REREAD_STAT)
|
||||
{
|
||||
if ( CVS_STAT (fname, &post_stbuf) != 0 )
|
||||
error (1, errno, "cannot find size of temp file %s", fname);
|
||||
}
|
||||
|
||||
/* And reread the log message in `always' mode or in `stat' mode when it's
|
||||
* changed
|
||||
*/
|
||||
if (RereadLogAfterVerify == LOGMSG_REREAD_ALWAYS ||
|
||||
(RereadLogAfterVerify == LOGMSG_REREAD_STAT &&
|
||||
(pre_stbuf.st_mtime != post_stbuf.st_mtime ||
|
||||
pre_stbuf.st_size != post_stbuf.st_size)))
|
||||
{
|
||||
/* put the entire message back into the *messagep variable */
|
||||
|
||||
fp = open_file (fname, "r");
|
||||
if (fp == NULL)
|
||||
{
|
||||
if ( (fp = open_file (fname, "r")) == NULL )
|
||||
error (1, errno, "cannot open temporary file %s", fname);
|
||||
return;
|
||||
}
|
||||
|
||||
if (*messagep)
|
||||
free (*messagep);
|
||||
if (*messagep) free (*messagep);
|
||||
|
||||
if ( CVS_STAT (fname, &stbuf) != 0)
|
||||
error (1, errno, "cannot find size of temp file %s", fname);
|
||||
|
||||
if (stbuf.st_size == 0)
|
||||
if (post_stbuf.st_size == 0)
|
||||
*messagep = NULL;
|
||||
else
|
||||
{
|
||||
/* On NT, we might read less than st_size bytes, but we won't
|
||||
read more. So this works. */
|
||||
*messagep = (char *) xmalloc (stbuf.st_size + 1);
|
||||
/* On NT, we might read less than st_size bytes,
|
||||
but we won't read more. So this works. */
|
||||
*messagep = (char *) xmalloc (post_stbuf.st_size + 1);
|
||||
*messagep[0] = '\0';
|
||||
}
|
||||
|
||||
line = NULL;
|
||||
line_chars_allocated = 0;
|
||||
|
||||
if (*messagep)
|
||||
{
|
||||
p = *messagep;
|
||||
char *line = NULL;
|
||||
int line_length;
|
||||
size_t line_chars_allocated = 0;
|
||||
char *p = *messagep;
|
||||
|
||||
while (1)
|
||||
{
|
||||
line_length = getline (&line, &line_chars_allocated, fp);
|
||||
line_length = getline (&line,
|
||||
&line_chars_allocated,
|
||||
fp);
|
||||
if (line_length == -1)
|
||||
{
|
||||
if (ferror (fp))
|
||||
error (0, errno, "warning: cannot read %s", fname);
|
||||
/* Fail in this case because otherwise we will have no
|
||||
* log message
|
||||
*/
|
||||
error (1, errno, "cannot read %s", fname);
|
||||
break;
|
||||
}
|
||||
if (strncmp (line, CVSEDITPREFIX, CVSEDITPREFIXLEN) == 0)
|
||||
@ -508,16 +551,17 @@ do_verify (messagep, repository)
|
||||
(void) strcpy (p, line);
|
||||
p += line_length;
|
||||
}
|
||||
if (line) free (line);
|
||||
}
|
||||
if (fclose (fp) < 0)
|
||||
error (0, errno, "warning: cannot close %s", fname);
|
||||
|
||||
/* Delete the temp file */
|
||||
|
||||
if (unlink_file (fname) < 0)
|
||||
error (0, errno, "cannot remove %s", fname);
|
||||
free (fname);
|
||||
}
|
||||
|
||||
/* Delete the temp file */
|
||||
|
||||
if (unlink_file (fname) < 0)
|
||||
error (0, errno, "cannot remove %s", fname);
|
||||
free (fname);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -156,7 +156,7 @@ static const char *const usg[] =
|
||||
putting metavariables in uppercase. I don't know whether that
|
||||
is a good convention or not, but if it changes it would have to
|
||||
change in all the usage messages. For now, they consistently
|
||||
use lowercase, as far as I know. Puncutation is pretty funky,
|
||||
use lowercase, as far as I know. Punctuation is pretty funky,
|
||||
though. Sometimes they use none, as here. Sometimes they use
|
||||
single quotes (not the TeX-ish `' stuff), as in --help-options.
|
||||
Sometimes they use double quotes, as in cvs -H add.
|
||||
@ -338,6 +338,8 @@ lookup_command_attribute (cmd_name)
|
||||
if (strcmp (cmd_name, cm->fullname) == 0)
|
||||
break;
|
||||
}
|
||||
if (!cm->fullname)
|
||||
error (1, 0, "unknown command: %s", cmd_name);
|
||||
return cm->attr;
|
||||
}
|
||||
|
||||
@ -868,7 +870,7 @@ Copyright (c) 1989-2001 Brian Berliner, david d `zoo' zuhn, \n\
|
||||
error (0, 0,
|
||||
"CVSROOT is set but empty! Make sure that the");
|
||||
error (0, 0,
|
||||
"specification of CVSROOT is legal, either via the");
|
||||
"specification of CVSROOT is valid, either via the");
|
||||
error (0, 0,
|
||||
"`-d' option, the %s environment variable, or the",
|
||||
CVSROOT_ENV);
|
||||
@ -928,7 +930,7 @@ Copyright (c) 1989-2001 Brian Berliner, david d `zoo' zuhn, \n\
|
||||
if (current_parsed_root != NULL)
|
||||
free_cvsroot_t (current_parsed_root);
|
||||
if ((current_parsed_root = parse_cvsroot (current_root)) == NULL)
|
||||
error (1, 0, "Bad CVSROOT.");
|
||||
error (1, 0, "Bad CVSROOT: `%s'.", current_root);
|
||||
|
||||
if (trace)
|
||||
fprintf (stderr, "%s-> main loop with CVSROOT=%s\n",
|
||||
|
@ -209,10 +209,12 @@ static const char *const checkoutlist_contents[] = {
|
||||
static const char *const cvswrappers_contents[] = {
|
||||
"# This file affects handling of files based on their names.\n",
|
||||
"#\n",
|
||||
#if 0 /* see comments in wrap_add in wrapper.c */
|
||||
"# The -t/-f options allow one to treat directories of files\n",
|
||||
"# as a single file, or to transform a file in other ways on\n",
|
||||
"# its way in and out of CVS.\n",
|
||||
"#\n",
|
||||
#endif
|
||||
"# The -m option specifies whether CVS attempts to merge files.\n",
|
||||
"#\n",
|
||||
"# The -k option specifies keyword expansion (e.g. -kb for binary).\n",
|
||||
@ -245,7 +247,7 @@ static const char *const notify_contents[] = {
|
||||
"# \"ALL\" or \"DEFAULT\" can be used in place of the regular expression.\n",
|
||||
"#\n",
|
||||
"# For example:\n",
|
||||
"#ALL mail %s -s \"CVS notification\"\n",
|
||||
"#ALL mail -s \"CVS notification\" %s\n",
|
||||
NULL
|
||||
};
|
||||
|
||||
@ -300,6 +302,14 @@ static const char *const config_contents[] = {
|
||||
"# Set `LogHistory' to `all' or `TOFEWGCMAR' to log all transactions to the\n",
|
||||
"# history file, or a subset as needed (ie `TMAR' logs all write operations)\n",
|
||||
"#LogHistory=TOFEWGCMAR\n",
|
||||
"\n",
|
||||
"# Set `RereadLogAfterVerify' to `always' (the default) to allow the verifymsg\n",
|
||||
"# script to change the log message. Set it to `stat' to force CVS to verify",
|
||||
"# that the file has changed before reading it (this can take up to an extra\n",
|
||||
"# second per directory being committed, so it is not recommended for large\n",
|
||||
"# repositories. Set it to `never' (the previous CVS behavior) to prevent\n",
|
||||
"# verifymsg scripts from changing the log message.\n",
|
||||
"#RereadLogAfterVerify=always\n",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -15,6 +15,14 @@
|
||||
#include "edit.h"
|
||||
#include "hardlink.h"
|
||||
|
||||
/* These need to be source after cvs.h or HAVE_MMAP won't be set... */
|
||||
#ifdef HAVE_MMAP
|
||||
# include <sys/mman.h>
|
||||
# ifndef HAVE_GETPAGESIZE
|
||||
# include "getpagesize.h"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
int preserve_perms = 0;
|
||||
|
||||
/* The RCS -k options, and a set of enums that must match the array.
|
||||
@ -60,8 +68,10 @@ static void rcsbuf_close PROTO ((struct rcsbuffer *));
|
||||
static int rcsbuf_getkey PROTO ((struct rcsbuffer *, char **keyp,
|
||||
char **valp));
|
||||
static int rcsbuf_getrevnum PROTO ((struct rcsbuffer *, char **revp));
|
||||
#ifndef HAVE_MMAP
|
||||
static char *rcsbuf_fill PROTO ((struct rcsbuffer *, char *ptr, char **keyp,
|
||||
char **valp));
|
||||
#endif
|
||||
static int rcsbuf_valcmp PROTO ((struct rcsbuffer *));
|
||||
static char *rcsbuf_valcopy PROTO ((struct rcsbuffer *, char *val, int polish,
|
||||
size_t *lenp));
|
||||
@ -734,8 +744,8 @@ RCS_fully_parse (rcs)
|
||||
vers = findnode (rcs->versions, key);
|
||||
if (vers == NULL)
|
||||
error (1, 0,
|
||||
"mismatch in rcs file %s between deltas and deltatexts",
|
||||
rcs->path);
|
||||
"mismatch in rcs file %s between deltas and deltatexts (%s)",
|
||||
rcs->path, key);
|
||||
|
||||
vnode = (RCSVers *) vers->data;
|
||||
|
||||
@ -793,12 +803,12 @@ unrecognized operation '\\x%x' in %s",
|
||||
op, rcs->path);
|
||||
(void) strtoul (cp, (char **) &cp, 10);
|
||||
if (*cp++ != ' ')
|
||||
error (1, 0, "space expected in %s",
|
||||
rcs->path);
|
||||
error (1, 0, "space expected in %s revision %s",
|
||||
rcs->path, vnode->version);
|
||||
count = strtoul (cp, (char **) &cp, 10);
|
||||
if (*cp++ != '\012')
|
||||
error (1, 0, "linefeed expected in %s",
|
||||
rcs->path);
|
||||
error (1, 0, "linefeed expected in %s revision %s",
|
||||
rcs->path, vnode->version);
|
||||
|
||||
if (op == 'd')
|
||||
del += count;
|
||||
@ -813,8 +823,8 @@ unrecognized operation '\\x%x' in %s",
|
||||
{
|
||||
if (count != 1)
|
||||
error (1, 0, "\
|
||||
invalid rcs file %s: premature end of value",
|
||||
rcs->path);
|
||||
premature end of value in %s revision %s",
|
||||
rcs->path, vnode->version);
|
||||
else
|
||||
break;
|
||||
}
|
||||
@ -991,14 +1001,45 @@ rcsbuf_open (rcsbuf, fp, filename, pos)
|
||||
error (1, 0, "rcsbuf_open: internal error");
|
||||
rcsbuf_inuse = 1;
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
{
|
||||
/* When we have mmap, it is much more efficient to let the system do the
|
||||
* buffering and caching for us
|
||||
*/
|
||||
struct stat fs;
|
||||
size_t mmap_off = 0;
|
||||
|
||||
if ( fstat (fileno(fp), &fs) < 0 )
|
||||
error ( 1, errno, "Could not stat RCS archive %s for mapping", filename );
|
||||
|
||||
if (pos)
|
||||
{
|
||||
size_t ps = getpagesize ();
|
||||
mmap_off = ( pos / ps ) * ps;
|
||||
}
|
||||
|
||||
/* Map private here since this particular buffer is read only */
|
||||
rcsbuf_buffer = mmap ( NULL, fs.st_size - mmap_off,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE, fileno(fp), mmap_off );
|
||||
if ( rcsbuf_buffer == NULL || rcsbuf_buffer == MAP_FAILED )
|
||||
error ( 1, errno, "Could not map memory to RCS archive %s", filename );
|
||||
|
||||
rcsbuf_buffer_size = fs.st_size - mmap_off;
|
||||
rcsbuf->ptr = rcsbuf_buffer + pos - mmap_off;
|
||||
rcsbuf->ptrend = rcsbuf_buffer + fs.st_size - mmap_off;
|
||||
rcsbuf->pos = mmap_off;
|
||||
}
|
||||
#else /* HAVE_MMAP */
|
||||
if (rcsbuf_buffer_size < RCSBUF_BUFSIZE)
|
||||
expand_string (&rcsbuf_buffer, &rcsbuf_buffer_size, RCSBUF_BUFSIZE);
|
||||
|
||||
rcsbuf->ptr = rcsbuf_buffer;
|
||||
rcsbuf->ptrend = rcsbuf_buffer;
|
||||
rcsbuf->pos = pos;
|
||||
#endif /* HAVE_MMAP */
|
||||
rcsbuf->fp = fp;
|
||||
rcsbuf->filename = filename;
|
||||
rcsbuf->pos = pos;
|
||||
rcsbuf->vlen = 0;
|
||||
rcsbuf->at_string = 0;
|
||||
rcsbuf->embedded_at = 0;
|
||||
@ -1012,6 +1053,9 @@ rcsbuf_close (rcsbuf)
|
||||
{
|
||||
if (! rcsbuf_inuse)
|
||||
error (1, 0, "rcsbuf_close: internal error");
|
||||
#ifdef HAVE_MMAP
|
||||
munmap ( rcsbuf_buffer, rcsbuf_buffer_size );
|
||||
#endif
|
||||
rcsbuf_inuse = 0;
|
||||
}
|
||||
|
||||
@ -1052,9 +1096,9 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
|
||||
ptrend = rcsbuf->ptrend;
|
||||
|
||||
/* Sanity check. */
|
||||
if (ptr < rcsbuf_buffer || ptr > rcsbuf_buffer + rcsbuf_buffer_size)
|
||||
abort ();
|
||||
assert (ptr >= rcsbuf_buffer && ptr < rcsbuf_buffer + rcsbuf_buffer_size);
|
||||
|
||||
#ifndef HAVE_MMAP
|
||||
/* If the pointer is more than RCSBUF_BUFSIZE bytes into the
|
||||
buffer, move back to the start of the buffer. This keeps the
|
||||
buffer from growing indefinitely. */
|
||||
@ -1066,8 +1110,7 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
|
||||
|
||||
/* Sanity check: we don't read more than RCSBUF_BUFSIZE bytes
|
||||
at a time, so we can't have more bytes than that past PTR. */
|
||||
if (len > RCSBUF_BUFSIZE)
|
||||
abort ();
|
||||
assert (len <= RCSBUF_BUFSIZE);
|
||||
|
||||
/* Update the POS field, which holds the file offset of the
|
||||
first byte in the RCSBUF_BUFFER buffer. */
|
||||
@ -1078,18 +1121,23 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
|
||||
ptrend = ptr + len;
|
||||
rcsbuf->ptrend = ptrend;
|
||||
}
|
||||
#endif /* ndef HAVE_MMAP */
|
||||
|
||||
/* Skip leading whitespace. */
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (ptr >= ptrend)
|
||||
#ifndef HAVE_MMAP
|
||||
{
|
||||
ptr = rcsbuf_fill (rcsbuf, ptr, (char **) NULL, (char **) NULL);
|
||||
if (ptr == NULL)
|
||||
#endif
|
||||
return 0;
|
||||
#ifndef HAVE_MMAP
|
||||
ptrend = rcsbuf->ptrend;
|
||||
}
|
||||
#endif
|
||||
|
||||
c = *ptr;
|
||||
if (! my_whitespace (c))
|
||||
@ -1108,13 +1156,17 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
|
||||
{
|
||||
++ptr;
|
||||
if (ptr >= ptrend)
|
||||
#ifndef HAVE_MMAP
|
||||
{
|
||||
ptr = rcsbuf_fill (rcsbuf, ptr, keyp, (char **) NULL);
|
||||
if (ptr == NULL)
|
||||
#endif
|
||||
error (1, 0, "EOF in key in RCS file %s",
|
||||
rcsbuf->filename);
|
||||
#ifndef HAVE_MMAP
|
||||
ptrend = rcsbuf->ptrend;
|
||||
}
|
||||
#endif
|
||||
c = *ptr;
|
||||
if (c == ';' || my_whitespace (c))
|
||||
break;
|
||||
@ -1143,13 +1195,17 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
|
||||
while (1)
|
||||
{
|
||||
if (ptr >= ptrend)
|
||||
#ifndef HAVE_MMAP
|
||||
{
|
||||
ptr = rcsbuf_fill (rcsbuf, ptr, keyp, (char **) NULL);
|
||||
if (ptr == NULL)
|
||||
#endif
|
||||
error (1, 0, "EOF while looking for value in RCS file %s",
|
||||
rcsbuf->filename);
|
||||
#ifndef HAVE_MMAP
|
||||
ptrend = rcsbuf->ptrend;
|
||||
}
|
||||
#endif
|
||||
c = *ptr;
|
||||
if (c == ';')
|
||||
{
|
||||
@ -1184,6 +1240,7 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
|
||||
while (1)
|
||||
{
|
||||
while ((pat = memchr (ptr, '@', ptrend - ptr)) == NULL)
|
||||
#ifndef HAVE_MMAP
|
||||
{
|
||||
/* Note that we pass PTREND as the PTR value to
|
||||
rcsbuf_fill, so that we will wind up setting PTR to
|
||||
@ -1191,25 +1248,31 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
|
||||
that we don't search the same bytes again. */
|
||||
ptr = rcsbuf_fill (rcsbuf, ptrend, keyp, valp);
|
||||
if (ptr == NULL)
|
||||
#endif
|
||||
error (1, 0,
|
||||
"EOF while looking for end of string in RCS file %s",
|
||||
rcsbuf->filename);
|
||||
#ifndef HAVE_MMAP
|
||||
ptrend = rcsbuf->ptrend;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Handle the special case of an '@' right at the end of
|
||||
the known bytes. */
|
||||
if (pat + 1 >= ptrend)
|
||||
#ifndef HAVE_MMAP
|
||||
{
|
||||
/* Note that we pass PAT, not PTR, here. */
|
||||
pat = rcsbuf_fill (rcsbuf, pat, keyp, valp);
|
||||
if (pat == NULL)
|
||||
{
|
||||
#endif
|
||||
/* EOF here is OK; it just means that the last
|
||||
character of the file was an '@' terminating a
|
||||
value for a key type which does not require a
|
||||
trailing ';'. */
|
||||
pat = rcsbuf->ptrend - 1;
|
||||
#ifndef HAVE_MMAP
|
||||
|
||||
}
|
||||
ptrend = rcsbuf->ptrend;
|
||||
@ -1217,6 +1280,7 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
|
||||
/* Note that the value of PTR is bogus here. This is
|
||||
OK, because we don't use it. */
|
||||
}
|
||||
#endif
|
||||
|
||||
if (pat + 1 >= ptrend || pat[1] != '@')
|
||||
break;
|
||||
@ -1266,13 +1330,17 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
|
||||
char n;
|
||||
|
||||
if (ptr >= ptrend)
|
||||
#ifndef HAVE_MMAP
|
||||
{
|
||||
ptr = rcsbuf_fill (rcsbuf, ptr, keyp, valp);
|
||||
if (ptr == NULL)
|
||||
#endif
|
||||
error (1, 0, "EOF in value in RCS file %s",
|
||||
rcsbuf->filename);
|
||||
#ifndef HAVE_MMAP
|
||||
ptrend = rcsbuf->ptrend;
|
||||
}
|
||||
#endif
|
||||
n = *ptr;
|
||||
if (n == ';')
|
||||
{
|
||||
@ -1307,6 +1375,7 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
|
||||
/* Find the ';' which must end the value. */
|
||||
start = ptr;
|
||||
while ((psemi = memchr (ptr, ';', ptrend - ptr)) == NULL)
|
||||
#ifndef HAVE_MMAP
|
||||
{
|
||||
int slen;
|
||||
|
||||
@ -1317,10 +1386,13 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
|
||||
slen = start - *valp;
|
||||
ptr = rcsbuf_fill (rcsbuf, ptrend, keyp, valp);
|
||||
if (ptr == NULL)
|
||||
#endif
|
||||
error (1, 0, "EOF in value in RCS file %s", rcsbuf->filename);
|
||||
#ifndef HAVE_MMAP
|
||||
start = *valp + slen;
|
||||
ptrend = rcsbuf->ptrend;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* See if there are any '@' strings in the value. */
|
||||
pat = memchr (start, '@', psemi - start);
|
||||
@ -1364,6 +1436,7 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
|
||||
while (1)
|
||||
{
|
||||
while ((pat = memchr (ptr, '@', ptrend - ptr)) == NULL)
|
||||
#ifndef HAVE_MMAP
|
||||
{
|
||||
/* Note that we pass PTREND as the PTR value to
|
||||
rcsbuff_fill, so that we will wind up setting PTR
|
||||
@ -1371,22 +1444,29 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
|
||||
that we don't search the same bytes again. */
|
||||
ptr = rcsbuf_fill (rcsbuf, ptrend, keyp, valp);
|
||||
if (ptr == NULL)
|
||||
#endif
|
||||
error (1, 0,
|
||||
"EOF while looking for end of string in RCS file %s",
|
||||
rcsbuf->filename);
|
||||
#ifndef HAVE_MMAP
|
||||
ptrend = rcsbuf->ptrend;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Handle the special case of an '@' right at the end of
|
||||
the known bytes. */
|
||||
if (pat + 1 >= ptrend)
|
||||
#ifndef HAVE_MMAP
|
||||
{
|
||||
ptr = rcsbuf_fill (rcsbuf, ptr, keyp, valp);
|
||||
if (ptr == NULL)
|
||||
#endif
|
||||
error (1, 0, "EOF in value in RCS file %s",
|
||||
rcsbuf->filename);
|
||||
#ifndef HAVE_MMAP
|
||||
ptrend = rcsbuf->ptrend;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (pat[1] != '@')
|
||||
break;
|
||||
@ -1429,12 +1509,16 @@ rcsbuf_getrevnum (rcsbuf, revp)
|
||||
while (1)
|
||||
{
|
||||
if (ptr >= ptrend)
|
||||
#ifndef HAVE_MMAP
|
||||
{
|
||||
ptr = rcsbuf_fill (rcsbuf, ptr, (char **) NULL, (char **) NULL);
|
||||
if (ptr == NULL)
|
||||
#endif
|
||||
return 0;
|
||||
#ifndef HAVE_MMAP
|
||||
ptrend = rcsbuf->ptrend;
|
||||
}
|
||||
#endif
|
||||
|
||||
c = *ptr;
|
||||
if (! whitespace (c))
|
||||
@ -1455,14 +1539,18 @@ unexpected '\\x%x' reading revision number in RCS file %s",
|
||||
{
|
||||
++ptr;
|
||||
if (ptr >= ptrend)
|
||||
#ifndef HAVE_MMAP
|
||||
{
|
||||
ptr = rcsbuf_fill (rcsbuf, ptr, revp, (char **) NULL);
|
||||
if (ptr == NULL)
|
||||
#endif
|
||||
error (1, 0,
|
||||
"unexpected EOF reading revision number in RCS file %s",
|
||||
rcsbuf->filename);
|
||||
#ifndef HAVE_MMAP
|
||||
ptrend = rcsbuf->ptrend;
|
||||
}
|
||||
#endif
|
||||
|
||||
c = *ptr;
|
||||
}
|
||||
@ -1480,6 +1568,7 @@ unexpected '\\x%x' reading revision number in RCS file %s",
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef HAVE_MMAP
|
||||
/* Fill RCSBUF_BUFFER with bytes from the file associated with RCSBUF,
|
||||
updating PTR and the PTREND field. If KEYP and *KEYP are not NULL,
|
||||
then *KEYP points into the buffer, and must be adjusted if the
|
||||
@ -1531,6 +1620,7 @@ rcsbuf_fill (rcsbuf, ptr, keyp, valp)
|
||||
|
||||
return ptr;
|
||||
}
|
||||
#endif /* HAVE_MMAP */
|
||||
|
||||
/* Test whether the last value returned by rcsbuf_getkey is a composite
|
||||
value or not. */
|
||||
@ -1687,7 +1777,19 @@ rcsbuf_valpolish_internal (rcsbuf, to, from, lenp)
|
||||
{
|
||||
++from;
|
||||
|
||||
/* Sanity check. */
|
||||
/* Sanity check.
|
||||
*
|
||||
* FIXME: I restored this to an abort from an assert based on
|
||||
* advice from Larry Jones that asserts should not be used to
|
||||
* confirm the validity of an RCS file... This leaves two
|
||||
* issues here: 1) I am uncertain that the fact that we will
|
||||
* only find double '@'s hasn't already been confirmed; and:
|
||||
* 2) If this is the proper place to spot the error in the RCS
|
||||
* file, then we should print a much clearer error here for the
|
||||
* user!!!!!!!
|
||||
*
|
||||
* - DRP
|
||||
*/
|
||||
if (*from != '@' || clen == 0)
|
||||
abort ();
|
||||
|
||||
@ -1711,11 +1813,8 @@ rcsbuf_valpolish_internal (rcsbuf, to, from, lenp)
|
||||
}
|
||||
|
||||
/* Sanity check. */
|
||||
if (from != orig_from + len
|
||||
|| to != orig_to + (len - rcsbuf->embedded_at))
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
assert (from == orig_from + len
|
||||
&& to == orig_to + (len - rcsbuf->embedded_at));
|
||||
|
||||
*to = '\0';
|
||||
}
|
||||
@ -1736,7 +1835,7 @@ rcsbuf_valword (rcsbuf, valp)
|
||||
register char *ptr, *pat;
|
||||
char c;
|
||||
|
||||
#define my_whitespace(c) (my_spacetab[(unsigned char)c] != 0)
|
||||
# define my_whitespace(c) (my_spacetab[(unsigned char)c] != 0)
|
||||
|
||||
if (*valp == NULL)
|
||||
return NULL;
|
||||
@ -1794,7 +1893,7 @@ rcsbuf_valword (rcsbuf, valp)
|
||||
or an id. Make sure it is not another special character. */
|
||||
if (c == '$' || c == '.' || c == ',')
|
||||
{
|
||||
error (1, 0, "illegal special character in RCS field in %s",
|
||||
error (1, 0, "invalid special character in RCS field in %s",
|
||||
rcsbuf->filename);
|
||||
}
|
||||
|
||||
@ -1814,7 +1913,7 @@ rcsbuf_valword (rcsbuf, valp)
|
||||
the character in its memory cell. Check to make sure that it
|
||||
is a legitimate word delimiter -- whitespace or end. */
|
||||
if (c != '\0' && !my_whitespace (c))
|
||||
error (1, 0, "illegal special character in RCS field in %s",
|
||||
error (1, 0, "invalid special character in RCS field in %s",
|
||||
rcsbuf->filename);
|
||||
|
||||
*pat = '\0';
|
||||
@ -1822,7 +1921,7 @@ rcsbuf_valword (rcsbuf, valp)
|
||||
*valp = pat;
|
||||
return xstrdup (ptr);
|
||||
|
||||
#undef my_whitespace
|
||||
# undef my_whitespace
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1833,7 +1932,7 @@ static unsigned long
|
||||
rcsbuf_ftell (rcsbuf)
|
||||
struct rcsbuffer *rcsbuf;
|
||||
{
|
||||
return rcsbuf->pos + (rcsbuf->ptr - rcsbuf_buffer);
|
||||
return rcsbuf->pos + rcsbuf->ptr - rcsbuf_buffer;
|
||||
}
|
||||
|
||||
/* Return a pointer to any data buffered for RCSBUF, along with the
|
||||
@ -1880,9 +1979,9 @@ rcsbuf_cache_close ()
|
||||
{
|
||||
if (cached_rcs != NULL)
|
||||
{
|
||||
rcsbuf_close (&cached_rcsbuf);
|
||||
if (fclose (cached_rcsbuf.fp) != 0)
|
||||
error (0, errno, "cannot close %s", cached_rcsbuf.filename);
|
||||
rcsbuf_close (&cached_rcsbuf);
|
||||
freercsnode (&cached_rcs);
|
||||
cached_rcs = NULL;
|
||||
}
|
||||
@ -1899,6 +1998,7 @@ rcsbuf_cache_open (rcs, pos, pfp, prcsbuf)
|
||||
FILE **pfp;
|
||||
struct rcsbuffer *prcsbuf;
|
||||
{
|
||||
#ifndef HAVE_MMAP
|
||||
if (cached_rcs == rcs)
|
||||
{
|
||||
if (rcsbuf_ftell (&cached_rcsbuf) != pos)
|
||||
@ -1929,19 +2029,32 @@ rcsbuf_cache_open (rcs, pos, pfp, prcsbuf)
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif /* ifndef HAVE_MMAP */
|
||||
/* FIXME: If these routines can be rewritten to not write to the
|
||||
* rcs file buffer, there would be a considerably larger memory savings
|
||||
* from using mmap since the shared file would never need be copied to
|
||||
* process memory.
|
||||
*
|
||||
* If this happens, cached mmapped buffers would be usable, but don't
|
||||
* forget to make sure rcs->pos < pos here...
|
||||
*/
|
||||
if (cached_rcs != NULL)
|
||||
rcsbuf_cache_close ();
|
||||
|
||||
*pfp = CVS_FOPEN (rcs->path, FOPEN_BINARY_READ);
|
||||
if (*pfp == NULL)
|
||||
error (1, 0, "unable to reopen `%s'", rcs->path);
|
||||
#ifndef HAVE_MMAP
|
||||
if (pos != 0)
|
||||
{
|
||||
if (fseek (*pfp, pos, SEEK_SET) != 0)
|
||||
error (1, 0, "cannot fseek RCS file %s", rcs->path);
|
||||
}
|
||||
#endif /* ifndef HAVE_MMAP */
|
||||
rcsbuf_open (prcsbuf, *pfp, rcs->path, pos);
|
||||
#ifndef HAVE_MMAP
|
||||
}
|
||||
#endif /* ifndef HAVE_MMAP */
|
||||
}
|
||||
|
||||
|
||||
@ -2239,7 +2352,7 @@ RCS_gettag (rcs, symtag, force_tag_match, simple_tag)
|
||||
RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
|
||||
|
||||
/* If tag is "HEAD", special case to get head RCS revision */
|
||||
if (tag && (STREQ (tag, TAG_HEAD) || *tag == '\0'))
|
||||
if (tag && STREQ (tag, TAG_HEAD))
|
||||
#if 0 /* This #if 0 is only in the Cygnus code. Why? Death support? */
|
||||
if (force_tag_match && (rcs->flags & VALID) && (rcs->flags & INATTIC))
|
||||
return ((char *) NULL); /* head request for removed file */
|
||||
@ -2848,16 +2961,21 @@ RCS_getdate (rcs, date, force_tag_match)
|
||||
|
||||
/* if the head is on a branch, try the branch first */
|
||||
if (rcs->branch != NULL)
|
||||
{
|
||||
retval = RCS_getdatebranch (rcs, date, rcs->branch);
|
||||
|
||||
/* if we found a match, we are done */
|
||||
if (retval != NULL)
|
||||
return (retval);
|
||||
if (retval != NULL)
|
||||
return (retval);
|
||||
}
|
||||
|
||||
/* otherwise if we have a trunk, try it */
|
||||
if (rcs->head)
|
||||
{
|
||||
p = findnode (rcs->versions, rcs->head);
|
||||
if (p == NULL)
|
||||
{
|
||||
error (0, 0, "%s: head revision %s doesn't exist", rcs->path,
|
||||
rcs->head);
|
||||
}
|
||||
while (p != NULL)
|
||||
{
|
||||
/* if the date of this one is before date, take it */
|
||||
@ -2875,10 +2993,13 @@ RCS_getdate (rcs, date, force_tag_match)
|
||||
p = (Node *) NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
error (0, 0, "%s: no head revision", rcs->path);
|
||||
|
||||
/*
|
||||
* at this point, either we have the revision we want, or we have the
|
||||
* first revision on the trunk (1.1?) in our hands
|
||||
* first revision on the trunk (1.1?) in our hands, or we've come up
|
||||
* completely empty
|
||||
*/
|
||||
|
||||
/* if we found what we're looking for, and it's not 1.1 return it */
|
||||
@ -2913,7 +3034,8 @@ RCS_getdate (rcs, date, force_tag_match)
|
||||
if (retval != NULL)
|
||||
return (retval);
|
||||
|
||||
if (!force_tag_match || RCS_datecmp (vers->date, date) <= 0)
|
||||
if (!force_tag_match ||
|
||||
(vers != NULL && RCS_datecmp (vers->date, date) <= 0))
|
||||
return (xstrdup (vers->version));
|
||||
else
|
||||
return (NULL);
|
||||
@ -3186,6 +3308,8 @@ translate_symtag (rcs, tag)
|
||||
|
||||
while (! whitespace (*cp) && *cp != '\0')
|
||||
++cp;
|
||||
if (*cp == '\0')
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4267,7 +4391,7 @@ RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat)
|
||||
/* If the size of `devtype' changes, fix the sscanf call also */
|
||||
char devtype[16];
|
||||
|
||||
if (sscanf (info->data, "%16s %lu",
|
||||
if (sscanf (info->data, "%15s %lu",
|
||||
devtype, &devnum_long) < 2)
|
||||
error (1, 0, "%s:%s has bad `special' newphrase %s",
|
||||
workfile, vers->version, info->data);
|
||||
@ -4332,7 +4456,7 @@ RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat)
|
||||
#ifdef PRESERVE_PERMISSIONS_SUPPORT
|
||||
else if (special_file)
|
||||
{
|
||||
#ifdef HAVE_MKNOD
|
||||
# ifdef HAVE_MKNOD
|
||||
char *dest;
|
||||
|
||||
/* Can send either to WORKFILE or to SOUT, as long as SOUT is
|
||||
@ -4353,11 +4477,11 @@ RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat)
|
||||
if (mknod (dest, special_file, devnum) < 0)
|
||||
error (1, errno, "could not create special file %s",
|
||||
dest);
|
||||
#else
|
||||
# else
|
||||
error (1, 0,
|
||||
"cannot create %s: unable to create special files on this system",
|
||||
workfile);
|
||||
#endif
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
else
|
||||
@ -4960,7 +5084,7 @@ RCS_checkin (rcs, workfile, message, rev, flags)
|
||||
case S_IFREG: break;
|
||||
case S_IFCHR:
|
||||
case S_IFBLK:
|
||||
#ifdef HAVE_ST_RDEV
|
||||
# ifdef HAVE_ST_RDEV
|
||||
np = getnode();
|
||||
np->type = RCSFIELD;
|
||||
np->key = xstrdup ("special");
|
||||
@ -4970,11 +5094,11 @@ RCS_checkin (rcs, workfile, message, rev, flags)
|
||||
(unsigned long) sb.st_rdev);
|
||||
np->data = xstrdup (buf);
|
||||
addnode (delta->other_delta, np);
|
||||
#else
|
||||
# else
|
||||
error (0, 0,
|
||||
"can't preserve %s: unable to save device files on this system",
|
||||
workfile);
|
||||
#endif
|
||||
# endif
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -5825,7 +5949,9 @@ RCS_unlock (rcs, rev, unlock_quiet)
|
||||
if (rcs->flags & PARTIAL)
|
||||
RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
|
||||
|
||||
/* If rev is NULL, unlock the latest revision (first in
|
||||
/* If rev is NULL, unlock the revision held by the caller; if more
|
||||
than one, make the user specify the revision explicitly. This
|
||||
differs from RCS which unlocks the latest revision (first in
|
||||
rcs->locks) held by the caller. */
|
||||
if (rev == NULL)
|
||||
{
|
||||
@ -5850,17 +5976,24 @@ RCS_unlock (rcs, rev, unlock_quiet)
|
||||
lock = NULL;
|
||||
for (p = locks->list->next; p != locks->list; p = p->next)
|
||||
{
|
||||
if (lock != NULL)
|
||||
if (STREQ (p->data, user))
|
||||
{
|
||||
if (!unlock_quiet)
|
||||
error (0, 0, "\
|
||||
if (lock != NULL)
|
||||
{
|
||||
if (!unlock_quiet)
|
||||
error (0, 0, "\
|
||||
%s: multiple revisions locked by %s; please specify one", rcs->path, user);
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
lock = p;
|
||||
}
|
||||
lock = p;
|
||||
}
|
||||
if (lock == NULL)
|
||||
{
|
||||
if (!unlock_quiet)
|
||||
error (0, 0, "No locks are set for %s.\n", user);
|
||||
return 0; /* no lock found, ergo nothing to do */
|
||||
}
|
||||
xrev = xstrdup (lock->key);
|
||||
}
|
||||
else
|
||||
@ -5888,6 +6021,9 @@ RCS_unlock (rcs, rev, unlock_quiet)
|
||||
is called with a NULL revision, since that means "whatever
|
||||
revision is currently locked by the caller." */
|
||||
char *repos, *workfile;
|
||||
if (!unlock_quiet)
|
||||
error (0, 0, "\
|
||||
%s: revision %s locked by %s; breaking lock", rcs->path, xrev, lock->data);
|
||||
repos = xstrdup (rcs->path);
|
||||
workfile = strrchr (repos, '/');
|
||||
*workfile++ = '\0';
|
||||
@ -7109,8 +7245,8 @@ RCS_deltas (rcs, fp, rcsbuf, version, op, text, len, log, loglen)
|
||||
node = findnode (rcs->versions, key);
|
||||
if (node == NULL)
|
||||
error (1, 0,
|
||||
"mismatch in rcs file %s between deltas and deltatexts",
|
||||
rcs->path);
|
||||
"mismatch in rcs file %s between deltas and deltatexts (%s)",
|
||||
rcs->path, key);
|
||||
|
||||
/* Stash the previous version. */
|
||||
prev_vers = vers;
|
||||
@ -7602,8 +7738,8 @@ RCS_getdeltatext (rcs, fp, rcsbuf)
|
||||
|
||||
p = findnode (rcs->versions, num);
|
||||
if (p == NULL)
|
||||
error (1, 0, "mismatch in rcs file %s between deltas and deltatexts",
|
||||
rcs->path);
|
||||
error (1, 0, "mismatch in rcs file %s between deltas and deltatexts (%s)",
|
||||
rcs->path, num);
|
||||
|
||||
d = (Deltatext *) xmalloc (sizeof (Deltatext));
|
||||
d->version = xstrdup (num);
|
||||
@ -7963,8 +8099,10 @@ RCS_copydeltas (rcs, fin, rcsbufin, fout, newdtext, insertpt)
|
||||
char *bufrest;
|
||||
int nls;
|
||||
size_t buflen;
|
||||
#ifndef HAVE_MMAP
|
||||
char buf[8192];
|
||||
int got;
|
||||
#endif
|
||||
|
||||
/* Count the number of versions for which we have to do some
|
||||
special operation. */
|
||||
@ -8073,7 +8211,12 @@ RCS_copydeltas (rcs, fin, rcsbufin, fout, newdtext, insertpt)
|
||||
|
||||
fwrite (bufrest, 1, buflen, fout);
|
||||
}
|
||||
|
||||
#ifndef HAVE_MMAP
|
||||
/* This bit isn't necessary when using mmap since the entire file
|
||||
* will already be available via the RCS buffer. Besides, the
|
||||
* mmap code doesn't always keep the file pointer up to date, so
|
||||
* this adds some data twice.
|
||||
*/
|
||||
while ((got = fread (buf, 1, sizeof buf, fin)) != 0)
|
||||
{
|
||||
if (nls > 0
|
||||
@ -8090,6 +8233,7 @@ RCS_copydeltas (rcs, fin, rcsbufin, fout, newdtext, insertpt)
|
||||
|
||||
nls = 0;
|
||||
}
|
||||
#endif /* HAVE_MMAP */
|
||||
}
|
||||
|
||||
/* A helper procedure for RCS_copydeltas. This is called via walklist
|
||||
@ -8351,7 +8495,8 @@ RCS_rewrite (rcs, newdtext, insertpt)
|
||||
/* Update delta_pos to the current position in the output file.
|
||||
Do NOT move these statements: they must be done after fin has
|
||||
been positioned at the old delta_pos, but before any delta
|
||||
texts have been written to fout. */
|
||||
texts have been written to fout.
|
||||
*/
|
||||
rcs->delta_pos = ftell (fout);
|
||||
if (rcs->delta_pos == -1)
|
||||
error (1, errno, "cannot ftell in RCS file %s", rcs->path);
|
||||
@ -8368,7 +8513,7 @@ RCS_rewrite (rcs, newdtext, insertpt)
|
||||
fragile even if it happens to sometimes be true. The real
|
||||
solution is to make sure that all the code which reads
|
||||
from fin checks for errors itself (some does, some doesn't). */
|
||||
error (0, 0, "warning: when closing RCS file `%s'", rcs->path);
|
||||
error (0, 0, "warning: ferror set while rewriting RCS file `%s'", rcs->path);
|
||||
if (fclose (fin) < 0)
|
||||
error (0, errno, "warning: closing RCS file `%s'", rcs->path);
|
||||
|
||||
|
@ -248,7 +248,10 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc, callerdat,
|
||||
directories. */
|
||||
|
||||
if (!wrap_name_has (argv[i], WRAP_TOCVS) && isdir (argv[i]))
|
||||
{
|
||||
strip_trailing_slashes (argv[i]);
|
||||
addlist (&dirlist, argv[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* otherwise, split argument into directory and component names. */
|
||||
|
@ -63,7 +63,10 @@ int cvs_gssapi_encrypt;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYSLOG_H
|
||||
#include <syslog.h>
|
||||
# include <syslog.h>
|
||||
# ifndef LOG_DAEMON /* for ancient syslogs */
|
||||
# define LOG_DAEMON 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_KERBEROS
|
||||
@ -163,7 +166,7 @@ static int fd_buffer_input PROTO((void *, char *, int, int, int *));
|
||||
static int fd_buffer_output PROTO((void *, const char *, int, int *));
|
||||
static int fd_buffer_flush PROTO((void *));
|
||||
static int fd_buffer_block PROTO((void *, int));
|
||||
static int fd_buffer_shutdown PROTO((void *));
|
||||
static int fd_buffer_shutdown PROTO((struct buffer *));
|
||||
|
||||
/* Initialize a buffer built on a file descriptor. FD is the file
|
||||
descriptor. INPUT is nonzero if this is for input, zero if this is
|
||||
@ -325,10 +328,10 @@ fd_buffer_block (closure, block)
|
||||
/* The buffer shutdown function for a buffer built on a file descriptor. */
|
||||
|
||||
static int
|
||||
fd_buffer_shutdown (closure)
|
||||
void *closure;
|
||||
fd_buffer_shutdown (buf)
|
||||
struct buffer *buf;
|
||||
{
|
||||
free (closure);
|
||||
free (buf->closure);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -364,7 +367,7 @@ create_adm_p (base_dir, dir)
|
||||
if (tmp == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
|
||||
|
||||
/* We make several passes through this loop. On the first pass,
|
||||
we simply create the CVSADM directory in the deepest directory.
|
||||
For each subsequent pass, we try to remove the last path
|
||||
@ -427,8 +430,7 @@ create_adm_p (base_dir, dir)
|
||||
}
|
||||
(void) umask (omask);
|
||||
}
|
||||
|
||||
|
||||
|
||||
f = CVS_FOPEN (tmp, "w");
|
||||
if (f == NULL)
|
||||
{
|
||||
@ -735,7 +737,7 @@ serve_root (arg)
|
||||
{
|
||||
char *env;
|
||||
char *path;
|
||||
|
||||
|
||||
if (error_pending()) return;
|
||||
|
||||
if (!isabsolute (arg))
|
||||
@ -773,12 +775,11 @@ serve_root (arg)
|
||||
sprintf (pending_error_text, "\
|
||||
E Protocol error: Root says \"%s\" but pserver says \"%s\"",
|
||||
arg, Pserver_Repos);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (current_parsed_root != NULL)
|
||||
free_cvsroot_t (current_parsed_root);
|
||||
current_parsed_root = local_cvsroot (arg);
|
||||
|
||||
/* For pserver, this will already have happened, and the call will do
|
||||
@ -919,7 +920,7 @@ E protocol error: directory '%s' not within current directory",
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Add as many directories to the temp directory as the client tells us it
|
||||
* will use "..", so we never try to access something outside the temp
|
||||
@ -1008,7 +1009,7 @@ dirswitch (dir, repos)
|
||||
pending_error = ENOMEM;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
strcpy (dir_name, server_temp_dir);
|
||||
strcat (dir_name, "/");
|
||||
strcat (dir_name, dir);
|
||||
@ -2125,9 +2126,9 @@ serve_argument (arg)
|
||||
char *arg;
|
||||
{
|
||||
char *p;
|
||||
|
||||
|
||||
if (error_pending()) return;
|
||||
|
||||
|
||||
if (argument_vector_size <= argument_count)
|
||||
{
|
||||
argument_vector_size *= 2;
|
||||
@ -2155,9 +2156,9 @@ serve_argumentx (arg)
|
||||
char *arg;
|
||||
{
|
||||
char *p;
|
||||
|
||||
|
||||
if (error_pending()) return;
|
||||
|
||||
|
||||
p = argument_vector[argument_count - 1];
|
||||
p = realloc (p, strlen (p) + 1 + strlen (arg) + 1);
|
||||
if (p == NULL)
|
||||
@ -2479,7 +2480,7 @@ check_command_legal_p (cmd_name)
|
||||
size_t flen;
|
||||
FILE *fp;
|
||||
int found_it = 0;
|
||||
|
||||
|
||||
/* else */
|
||||
flen = strlen (current_parsed_root->directory)
|
||||
+ strlen (CVSROOTADM)
|
||||
@ -2571,7 +2572,7 @@ check_command_legal_p (cmd_name)
|
||||
/* Chop newline by hand, for strcmp()'s sake. */
|
||||
if (linebuf[num_red - 1] == '\n')
|
||||
linebuf[num_red - 1] = '\0';
|
||||
|
||||
|
||||
if (strcmp (linebuf, CVS_Username) == 0)
|
||||
{
|
||||
found_it = 1;
|
||||
@ -2638,7 +2639,7 @@ do_cvs_command (cmd_name, command)
|
||||
* interleaved with data from stdout_pipe or stderr_pipe).
|
||||
*/
|
||||
int protocol_pipe[2];
|
||||
|
||||
|
||||
int dev_null_fd = -1;
|
||||
|
||||
int errs;
|
||||
@ -3017,7 +3018,7 @@ error \n");
|
||||
{
|
||||
int status;
|
||||
int count_read;
|
||||
|
||||
|
||||
status = buf_input_data (protocol_inbuf, &count_read);
|
||||
|
||||
if (status == -1)
|
||||
@ -3175,7 +3176,7 @@ error \n");
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (WIFEXITED (status))
|
||||
errs += WEXITSTATUS (status);
|
||||
else
|
||||
@ -3302,7 +3303,7 @@ server_pause_check()
|
||||
FD_ZERO (&fds);
|
||||
FD_SET (flowcontrol_pipe[0], &fds);
|
||||
numtocheck = flowcontrol_pipe[0] + 1;
|
||||
|
||||
|
||||
do {
|
||||
numfds = select (numtocheck, &fds, (fd_set *)0,
|
||||
(fd_set *)0, (struct timeval *)NULL);
|
||||
@ -3314,7 +3315,7 @@ server_pause_check()
|
||||
return;
|
||||
}
|
||||
} while (numfds < 0);
|
||||
|
||||
|
||||
if (FD_ISSET (flowcontrol_pipe[0], &fds))
|
||||
{
|
||||
int got;
|
||||
@ -3437,7 +3438,7 @@ server_register (name, version, timestamp, options, tag, date, conflict)
|
||||
len += strlen (tag);
|
||||
if (date)
|
||||
len += strlen (date);
|
||||
|
||||
|
||||
entries_line = xmalloc (len);
|
||||
sprintf (entries_line, "/%s/%s/", name, version);
|
||||
if (conflict != NULL)
|
||||
@ -3672,7 +3673,7 @@ static void
|
||||
serve_tag (arg)
|
||||
char *arg;
|
||||
{
|
||||
do_cvs_command ("cvstag", cvstag);
|
||||
do_cvs_command ("tag", cvstag);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -3797,20 +3798,38 @@ static void
|
||||
serve_init (arg)
|
||||
char *arg;
|
||||
{
|
||||
cvsroot_t *saved_parsed_root;
|
||||
|
||||
if (!isabsolute (arg))
|
||||
{
|
||||
if (alloc_pending (80 + strlen (arg)))
|
||||
sprintf (pending_error_text,
|
||||
"E Root %s must be an absolute pathname", arg);
|
||||
/* Fall through to do_cvs_command which will return the
|
||||
actual error. */
|
||||
"E init %s must be an absolute pathname", arg);
|
||||
}
|
||||
#ifdef AUTH_SERVER_SUPPORT
|
||||
else if (Pserver_Repos != NULL)
|
||||
{
|
||||
if (strcmp (Pserver_Repos, arg) != 0)
|
||||
{
|
||||
if (alloc_pending (80 + strlen (Pserver_Repos) + strlen (arg)))
|
||||
/* The explicitness is to aid people who are writing clients.
|
||||
I don't see how this information could help an
|
||||
attacker. */
|
||||
sprintf (pending_error_text, "\
|
||||
E Protocol error: init says \"%s\" but pserver says \"%s\"",
|
||||
arg, Pserver_Repos);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (current_parsed_root != NULL)
|
||||
free_cvsroot_t (current_parsed_root);
|
||||
if (print_pending_error ())
|
||||
return;
|
||||
|
||||
saved_parsed_root = current_parsed_root;
|
||||
current_parsed_root = local_cvsroot (arg);
|
||||
|
||||
do_cvs_command ("init", init);
|
||||
free_cvsroot_t (current_parsed_root);
|
||||
current_parsed_root = saved_parsed_root;
|
||||
}
|
||||
|
||||
static void serve_annotate PROTO ((char *));
|
||||
@ -4574,7 +4593,6 @@ serve_expand_modules (arg)
|
||||
DBM *db;
|
||||
err = 0;
|
||||
|
||||
server_expanding = 1;
|
||||
db = open_module ();
|
||||
for (i = 1; i < argument_count; i++)
|
||||
err += do_module (db, argument_vector[i],
|
||||
@ -4582,7 +4600,6 @@ serve_expand_modules (arg)
|
||||
NULL, 0, 0, 0, 0,
|
||||
(char *) NULL);
|
||||
close_module (db);
|
||||
server_expanding = 0;
|
||||
{
|
||||
/* argument_vector[0] is a dummy argument, we don't mess with it. */
|
||||
char **cp;
|
||||
@ -4612,23 +4629,24 @@ server_prog (dir, name, which)
|
||||
{
|
||||
if (!supported_response ("Set-checkin-prog"))
|
||||
{
|
||||
buf_output0 (buf_to_net, "E \
|
||||
buf_output0 (protocol, "E \
|
||||
warning: this client does not support -i or -u flags in the modules file.\n");
|
||||
return;
|
||||
}
|
||||
switch (which)
|
||||
{
|
||||
case PROG_CHECKIN:
|
||||
buf_output0 (buf_to_net, "Set-checkin-prog ");
|
||||
buf_output0 (protocol, "Set-checkin-prog ");
|
||||
break;
|
||||
case PROG_UPDATE:
|
||||
buf_output0 (buf_to_net, "Set-update-prog ");
|
||||
buf_output0 (protocol, "Set-update-prog ");
|
||||
break;
|
||||
}
|
||||
buf_output0 (buf_to_net, dir);
|
||||
buf_append_char (buf_to_net, '\n');
|
||||
buf_output0 (buf_to_net, name);
|
||||
buf_append_char (buf_to_net, '\n');
|
||||
buf_output0 (protocol, dir);
|
||||
buf_append_char (protocol, '\n');
|
||||
buf_output0 (protocol, name);
|
||||
buf_append_char (protocol, '\n');
|
||||
buf_send_counted (protocol);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -4862,32 +4880,33 @@ server_cleanup (sig)
|
||||
|
||||
if (buf_to_net != NULL)
|
||||
{
|
||||
/* FIXME: If this is not the final call from server, this
|
||||
could deadlock, because the client might be blocked writing
|
||||
to us. This should not be a problem in practice, because
|
||||
we do not generate much output when the client is not
|
||||
waiting for it. */
|
||||
/* Since we're done, go ahead and put BUF_TO_NET back into blocking
|
||||
* mode and send any pending output. In the usual case there won't
|
||||
* won't be any, but there might be if an error occured.
|
||||
*/
|
||||
|
||||
set_block (buf_to_net);
|
||||
buf_flush (buf_to_net, 1);
|
||||
|
||||
/* The calls to buf_shutdown are currently only meaningful
|
||||
when we are using compression. First we shut down
|
||||
BUF_FROM_NET. That will pick up the checksum generated
|
||||
when the client shuts down its buffer. Then, after we have
|
||||
generated any final output, we shut down BUF_TO_NET. */
|
||||
/* Next we shut down BUF_FROM_NET. That will pick up the checksum
|
||||
* generated when the client shuts down its buffer. Then, after we
|
||||
* have generated any final output, we shut down BUF_TO_NET.
|
||||
*/
|
||||
|
||||
status = buf_shutdown (buf_from_net);
|
||||
if (status != 0)
|
||||
{
|
||||
error (0, status, "shutting down buffer from client");
|
||||
buf_flush (buf_to_net, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (dont_delete_temp)
|
||||
{
|
||||
if (buf_to_net != NULL)
|
||||
{
|
||||
(void) buf_flush (buf_to_net, 1);
|
||||
(void) buf_shutdown (buf_to_net);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -4985,11 +5004,13 @@ server_cleanup (sig)
|
||||
noexec = save_noexec;
|
||||
|
||||
if (buf_to_net != NULL)
|
||||
{
|
||||
(void) buf_flush (buf_to_net, 1);
|
||||
(void) buf_shutdown (buf_to_net);
|
||||
}
|
||||
}
|
||||
|
||||
int server_active = 0;
|
||||
int server_expanding = 0;
|
||||
|
||||
int
|
||||
server (argc, argv)
|
||||
@ -5010,7 +5031,7 @@ server (argc, argv)
|
||||
|
||||
buf_to_net = fd_buffer_initialize (STDOUT_FILENO, 0,
|
||||
outbuf_memory_error);
|
||||
buf_from_net = stdio_buffer_initialize (stdin, 1, outbuf_memory_error);
|
||||
buf_from_net = stdio_buffer_initialize (stdin, 0, 1, outbuf_memory_error);
|
||||
|
||||
saved_output = buf_nonio_initialize (outbuf_memory_error);
|
||||
saved_outerr = buf_nonio_initialize (outbuf_memory_error);
|
||||
@ -5190,7 +5211,7 @@ error ENOMEM Virtual memory exhausted.\n");
|
||||
char *cmd, *orig_cmd;
|
||||
struct request *rq;
|
||||
int status;
|
||||
|
||||
|
||||
status = buf_read_line (buf_from_net, &cmd, (int *) NULL);
|
||||
if (status == -2)
|
||||
{
|
||||
@ -5327,7 +5348,7 @@ error 0 %s: no such user\n", username);
|
||||
error_exit ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (setuid (pw->pw_uid) < 0)
|
||||
{
|
||||
/* Note that this means that if run as a non-root user,
|
||||
@ -5351,12 +5372,12 @@ error 0 %s: no such user\n", username);
|
||||
if (CVS_Username == NULL)
|
||||
CVS_Username = xstrdup (username);
|
||||
#endif
|
||||
|
||||
|
||||
#if HAVE_PUTENV
|
||||
/* Set LOGNAME, USER and CVS_USER in the environment, in case they
|
||||
are already set to something else. */
|
||||
{
|
||||
char *env, *cvs_user;
|
||||
char *env;
|
||||
|
||||
env = xmalloc (sizeof "LOGNAME=" + strlen (username));
|
||||
(void) sprintf (env, "LOGNAME=%s", username);
|
||||
@ -5366,10 +5387,11 @@ error 0 %s: no such user\n", username);
|
||||
(void) sprintf (env, "USER=%s", username);
|
||||
(void) putenv (env);
|
||||
|
||||
cvs_user = NULL != CVS_Username ? CVS_Username : "";
|
||||
env = xmalloc (sizeof "CVS_USER=" + strlen (cvs_user));
|
||||
(void) sprintf (env, "CVS_USER=%s", cvs_user);
|
||||
#ifdef AUTH_SERVER_SUPPORT
|
||||
env = xmalloc (sizeof "CVS_USER=" + strlen (CVS_Username));
|
||||
(void) sprintf (env, "CVS_USER=%s", CVS_Username);
|
||||
(void) putenv (env);
|
||||
#endif
|
||||
}
|
||||
#endif /* HAVE_PUTENV */
|
||||
}
|
||||
@ -5380,7 +5402,7 @@ error 0 %s: no such user\n", username);
|
||||
extern char *crypt PROTO((const char *, const char *));
|
||||
|
||||
|
||||
/*
|
||||
/*
|
||||
* 0 means no entry found for this user.
|
||||
* 1 means entry found and password matches (or found password is empty)
|
||||
* 2 means entry found, but password does not match.
|
||||
@ -5449,7 +5471,7 @@ check_repository_password (username, password, repository, host_user_ptr)
|
||||
char *found_password, *host_user_tmp;
|
||||
char *non_cvsuser_portion;
|
||||
|
||||
/* We need to make sure lines such as
|
||||
/* We need to make sure lines such as
|
||||
*
|
||||
* "username::sysuser\n"
|
||||
* "username:\n"
|
||||
@ -5582,7 +5604,7 @@ check_password (username, password, repository)
|
||||
{
|
||||
found_passwd = pw->pw_passwd;
|
||||
}
|
||||
|
||||
|
||||
if (found_passwd == NULL)
|
||||
{
|
||||
printf ("E Fatal error, aborting.\n\
|
||||
@ -5600,7 +5622,7 @@ error 0 %s: no such user\n", username);
|
||||
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
if (*found_passwd)
|
||||
{
|
||||
/* user exists and has a password */
|
||||
@ -5655,7 +5677,7 @@ error 0 %s: no such user\n", username);
|
||||
handle_return:
|
||||
if (host_user)
|
||||
{
|
||||
/* Set CVS_Username here, in allocated space.
|
||||
/* Set CVS_Username here, in allocated space.
|
||||
It might or might not be the same as host_user. */
|
||||
CVS_Username = xmalloc (strlen (username) + 1);
|
||||
strcpy (CVS_Username, username);
|
||||
@ -5749,10 +5771,12 @@ pserver_authenticate_connection ()
|
||||
|
||||
/* Make sure the protocol starts off on the right foot... */
|
||||
if (getline_safe (&tmp, &tmp_allocated, stdin, PATH_MAX) < 0)
|
||||
/* FIXME: what? We could try writing error/eof, but chances
|
||||
are the network connection is dead bidirectionally. log it
|
||||
somewhere? */
|
||||
;
|
||||
{
|
||||
#ifdef HAVE_SYSLOG_H
|
||||
syslog (LOG_DAEMON | LOG_NOTICE, "bad auth protocol start: EOF");
|
||||
#endif
|
||||
error (1, 0, "bad auth protocol start: EOF");
|
||||
}
|
||||
|
||||
if (strcmp (tmp, "BEGIN VERIFICATION REQUEST\n") == 0)
|
||||
verify_and_exit = 1;
|
||||
@ -5783,7 +5807,7 @@ pserver_authenticate_connection ()
|
||||
getline_safe (&username, &username_allocated, stdin, PATH_MAX);
|
||||
getline_safe (&password, &password_allocated, stdin, PATH_MAX);
|
||||
|
||||
/* Make them pure. */
|
||||
/* Make them pure. */
|
||||
strip_trailing_newlines (repository);
|
||||
strip_trailing_newlines (username);
|
||||
strip_trailing_newlines (password);
|
||||
@ -5817,8 +5841,6 @@ pserver_authenticate_connection ()
|
||||
/* We need the real cleartext before we hash it. */
|
||||
descrambled_password = descramble (password);
|
||||
host_user = check_password (username, descrambled_password, repository);
|
||||
memset (descrambled_password, 0, strlen (descrambled_password));
|
||||
free (descrambled_password);
|
||||
if (host_user == NULL)
|
||||
{
|
||||
#ifdef HAVE_SYSLOG_H
|
||||
@ -5828,6 +5850,8 @@ pserver_authenticate_connection ()
|
||||
username, descrambled_password, repository);
|
||||
#endif
|
||||
#endif
|
||||
memset (descrambled_password, 0, strlen (descrambled_password));
|
||||
free (descrambled_password);
|
||||
i_hate_you:
|
||||
printf ("I HATE YOU\n");
|
||||
fflush (stdout);
|
||||
@ -5836,6 +5860,8 @@ pserver_authenticate_connection ()
|
||||
yet. */
|
||||
error_exit ();
|
||||
}
|
||||
memset (descrambled_password, 0, strlen (descrambled_password));
|
||||
free (descrambled_password);
|
||||
|
||||
/* Don't go any farther if we're just responding to "cvs login". */
|
||||
if (verify_and_exit)
|
||||
@ -6521,7 +6547,7 @@ cvs_flusherr ()
|
||||
{
|
||||
/* make sure stderr is flushed before we send the flush count on the
|
||||
* protocol pipe
|
||||
*/
|
||||
*/
|
||||
fflush (stderr);
|
||||
/* Send a special count to tell the parent to flush. */
|
||||
buf_send_special_count (protocol, -2);
|
||||
@ -6551,7 +6577,7 @@ cvs_flushout ()
|
||||
main.c, didn't get called in the server child process. But
|
||||
in the future it is quite plausible that we'll want to make
|
||||
this case work analogously to cvs_flusherr.
|
||||
|
||||
|
||||
FIXME - DRP - I tried to implement this and triggered the following
|
||||
error: "Protocol error: uncounted data discarded". I don't need
|
||||
this feature right now, so I'm not going to bother with it yet.
|
||||
|
@ -38,7 +38,7 @@
|
||||
#include "cvs.h"
|
||||
#include "savecwd.h"
|
||||
#ifdef SERVER_SUPPORT
|
||||
#include "md5.h"
|
||||
# include "md5.h"
|
||||
#endif
|
||||
#include "watch.h"
|
||||
#include "fileattr.h"
|
||||
@ -1793,7 +1793,7 @@ patch_file (finfo, vers_ts, docheckout, file_info, checksum)
|
||||
}
|
||||
else
|
||||
{
|
||||
#define BINARY "Binary"
|
||||
# define BINARY "Binary"
|
||||
char buf[sizeof BINARY];
|
||||
unsigned int c;
|
||||
|
||||
@ -2689,7 +2689,7 @@ special_file_mismatch (finfo, rev1, rev2)
|
||||
rev1_symlink = xreadlink (finfo->file);
|
||||
else
|
||||
{
|
||||
#ifdef HAVE_ST_RDEV
|
||||
# ifdef HAVE_ST_RDEV
|
||||
if (CVS_LSTAT (finfo->file, &sb) < 0)
|
||||
error (1, errno, "could not get file information for %s",
|
||||
finfo->file);
|
||||
@ -2698,10 +2698,10 @@ special_file_mismatch (finfo, rev1, rev2)
|
||||
rev1_mode = sb.st_mode;
|
||||
if (S_ISBLK (rev1_mode) || S_ISCHR (rev1_mode))
|
||||
rev1_dev = sb.st_rdev;
|
||||
#else
|
||||
# else
|
||||
error (1, 0, "cannot handle device files on this system (%s)",
|
||||
finfo->file);
|
||||
#endif
|
||||
# endif
|
||||
}
|
||||
rev1_hardlinks = list_linked_files_on_disk (finfo->file);
|
||||
}
|
||||
@ -2740,7 +2740,7 @@ special_file_mismatch (finfo, rev1, rev2)
|
||||
{
|
||||
/* If the size of `ftype' changes, fix the sscanf call also */
|
||||
char ftype[16];
|
||||
if (sscanf (n->data, "%16s %lu", ftype,
|
||||
if (sscanf (n->data, "%15s %lu", ftype,
|
||||
&dev_long) < 2)
|
||||
error (1, 0, "%s:%s has bad `special' newphrase %s",
|
||||
finfo->file, rev1, n->data);
|
||||
@ -2767,7 +2767,7 @@ special_file_mismatch (finfo, rev1, rev2)
|
||||
rev2_symlink = xreadlink (finfo->file);
|
||||
else
|
||||
{
|
||||
#ifdef HAVE_ST_RDEV
|
||||
# ifdef HAVE_ST_RDEV
|
||||
if (CVS_LSTAT (finfo->file, &sb) < 0)
|
||||
error (1, errno, "could not get file information for %s",
|
||||
finfo->file);
|
||||
@ -2776,10 +2776,10 @@ special_file_mismatch (finfo, rev1, rev2)
|
||||
rev2_mode = sb.st_mode;
|
||||
if (S_ISBLK (rev2_mode) || S_ISCHR (rev2_mode))
|
||||
rev2_dev = sb.st_rdev;
|
||||
#else
|
||||
# else
|
||||
error (1, 0, "cannot handle device files on this system (%s)",
|
||||
finfo->file);
|
||||
#endif
|
||||
# endif
|
||||
}
|
||||
rev2_hardlinks = list_linked_files_on_disk (finfo->file);
|
||||
}
|
||||
@ -2818,7 +2818,7 @@ special_file_mismatch (finfo, rev1, rev2)
|
||||
{
|
||||
/* If the size of `ftype' changes, fix the sscanf call also */
|
||||
char ftype[16];
|
||||
if (sscanf (n->data, "%16s %lu", ftype,
|
||||
if (sscanf (n->data, "%15s %lu", ftype,
|
||||
&dev_long) < 2)
|
||||
error (1, 0, "%s:%s has bad `special' newphrase %s",
|
||||
finfo->file, rev2, n->data);
|
||||
|
Loading…
Reference in New Issue
Block a user