Go to the previous, next section.
Figure 3 below shows a typical setup of a repository. Only directories are shown below.
/usr | +--local | | | +--cvsroot | | | | | +--CVSROOT | (administrative files) | +--gnu | | | +--diff | | (source code to GNU diff) | | | +--rcs | | (source code to RCS) | | | +--cvs | (source code to CVS) | +--yoyodyne | +--tc | | | +--man | | | +--testing | +--(other Yoyodyne software)
There are a couple of different ways to tell CVS
where to find the repository. You can name the
repository on the command line explicitly, with the
-d (for "directory") option:
cvs -d /usr/local/cvsroot checkout yoyodyne/tc
Or you can set the
variable to an absolute path to the root of the
repository, `/usr/local/cvsroot' in this example.
users should have this line in their `.cshrc' or
setenv CVSROOT /usr/local/cvsroot
bash users should instead have these lines in their
`.profile' or `.bashrc':
CVSROOT=/usr/local/cvsroot export CVSROOT
A repository specified with
$CVSROOT environment variable.
Once you've checked a working copy out from the
repository, it will remember where its repository is
(the information is recorded in the
`CVS/Root' file in the working copy).
-d option and the `CVS/Root' file both
$CVSROOT environment variable. If
-d option differs from `CVS/Root', the
former is used (and specifying
-d will cause
`CVS/Root' to be updated). Of course, for proper
operation they should be two ways of referring to the
There is nothing magical about the name `/usr/local/cvsroot'. You can choose to place the repository anywhere you like. See section Remote repositories to learn how the repository can be on a different machine than your working copy of the sources.
Note: For compatibility with older versions, CVS will treat any repository name that contains a colon as an indication of a remote repository (See section Remote repositories). If the name of your local repository contains a colon, you should prepend the string `:local:' to the pathname to tell CVS that it is, indeed, a local repository. For example, you might use this command line under Windows NT:
cvs -d :local:c:\src\cvsroot checkout yoyodyne/tc
The repository is split in two parts. `$CVSROOT/CVSROOT' contains administrative files for CVS. The other directories contain the actual user-defined modules.
$CVSROOT| +--yoyodyne | | | +--tc | | | +--Makefile,v +--backend.c,v +--driver.c,v +--frontend.c,v +--parser.c,v +--man | | | +--tc.1,v | +--testing | +--testpgm.t,v +--test2.t,v
The figure above shows the contents of the `tc'
module inside the repository. As you can see all file
names end in `,v'. The files are history
files. They contain, among other things, enough
information to recreate any revision of the file, a log
of all commit messages and the user-name of the person
who committed the revision. CVS uses the
facilities of RCS, a simpler version control
system, to maintain these files. For a full
description of the file format, see the
This means that you can only control access to files on a per-directory basis.
CVS tries to set up reasonable file permissions for new directories that are added inside the tree, but you must fix the permissions manually when a new directory should have different permissions than its parent directory.
Since CVS was not written to be run setuid, it is unsafe to try to run it setuid. You cannot use the setuid features of RCS together with CVS.
The directory `$CVSROOT/CVSROOT' contains some administrative files. See section Reference manual for the Administrative files, for a complete description. You can use CVS without any of these files, but some commands work better when at least the `modules' file is properly set up.
The most important of these files is the `modules' file. It defines all modules in the repository. This is a sample `modules' file.
CVSROOT CVSROOT modules CVSROOT modules cvs gnu/cvs rcs gnu/rcs diff gnu/diff tc yoyodyne/tc
The `modules' file is line oriented. In its
simplest form each line contains the name of the
module, whitespace, and the directory where the module
resides. The directory is a path relative to
$CVSROOT. The last four lines in the example
above are examples of such lines.
The line that defines the module called `modules' uses features that are not explained here. See section The modules file, for a full explanation of all the available features.
You edit the administrative files in the same way that you would edit any other module. Use `cvs checkout CVSROOT' to get a working copy, edit it, and commit your changes in the normal way.
It is possible to commit an erroneous administrative file. You can often fix the error and check in a new revision, but sometimes a particularly bad error in the administrative file makes it impossible to commit new revisions.
In some situations it is a good idea to have more than
one repository, for instance if you have two
development groups that work on separate projects
without sharing any code. All you have to do to have
several repositories is to specify the appropriate
repository, using the
variable, the `-d' option to CVS, or (once
you have checked out a working directory) by simply
allowing CVS to use the repository that was used
to check out the working directory
(see section The Repository).
Notwithstanding, it can be confusing to have two or more repositories.
None of the examples in this manual show multiple repositories.
To set up a CVS repository, choose a directory with ample disk space available for the revision history of the source files. It should be accessable (directly or via a networked file system) from all machines which want to use CVS in server or local mode; the client machines need not have any access to it other than via the CVS protocol.
To create a repository, run the
command. It will set up an empty repository in the
CVS root specified in the usual way
(see section The Repository). For example,
cvs -d /usr/local/cvsroot init
cvs init is careful to never overwrite any
existing files in the repository, so no harm is done if
cvs init on an already set-up
cvs init will enable history logging; if you
don't want that, remove the history file after running
cvs init. See section The history file.
Your working copy of the sources can be on a different machine than the repository. Generally, using a remote repository is just like using a local one, except that the format of the repository name is:
The details of exactly what needs to be set up depend on how you are connecting to the server.
CVS uses the `rsh' protocol to perform these operations, so the remote user host needs to have a `.rhosts' file which grants access to the local user.
For example, suppose you are the user `mozart' on the local machine `anklet.grunge.com', and the server machine is `chainsaw.brickyard.com'. On chainsaw, put the following line into the file `.rhosts' in `bach''s home directory:
Then test that
rsh is working with
rsh -l bach chainsaw.brickyard.com echo $PATH
Next you have to make sure that
rsh will be able
to find the server. Make sure that the path which
rsh printed in the above example includes the
directory containing a program named
is the server. You need to set the path in
`.bashrc', `.cshrc', etc., not `.login'
or `.profile'. Alternately, you can set the
CVS_SERVER on the client
machine to the filename of the server you want to use,
for example `/usr/local/bin/cvs-1.6'.
There is no need to edit
inetd.conf or start a
CVS server daemon.
Continuing our example, supposing you want to access the module `foo' in the repository `/usr/local/cvsroot/', on machine `chainsaw.brickyard.com', you are ready to go:
cvs -d :server:email@example.com:/usr/local/cvsroot checkout foo
(The `bach@' can be omitted if the username is the same on both the local and remote hosts.)
The CVS client can also connect to the server
using a password protocol. This is particularly useful
rsh is not feasible (for example,
the server is behind a firewall), and Kerberos also is
To use this method, it is necessary to make some adjustments on both the server and client sides.
On the server side, the file `/etc/inetd.conf'
needs to be edited so
inetd knows to run the
cvs pserver when it receives a
connection on the right port. By default, the port
number is 2401; it would be different if your client
were compiled with
CVS_AUTH_PORT defined to
something else, though.
inetd allows raw port numbers in
`/etc/inetd.conf', then the following (all on a
single line in `inetd.conf') should be sufficient:
2401 stream tcp nowait root /usr/local/bin/cvs cvs -b /usr/local/bin pserver
The `-b' option specifies the directory which contains the RCS binaries on the server.
inetd wants a symbolic service
name instead of a raw port number, then put this in
cvspserver instead of
2401 in `inetd.conf'.
Once the above is taken care of, restart your
inetd, or do whatever is necessary to force it
to reread its initialization files.
Because the client stores and transmits passwords in cleartext (almost--see section Security considerations with password authentication for details), a separate CVS password file may be used, so people don't compromise their regular passwords when they access the repository. This file is `$CVSROOT/CVSROOT/passwd' (see section The administrative files). Its format is similar to `/etc/passwd', except that it only has two fields, username and password. For example:
The password is encrypted according to the standard
crypt() function, so it is possible to
paste in passwords directly from regular Unix
When authenticating a password, the server first checks for the user in the CVS `passwd' file. If it finds the user, it compares against that password. If it does not find the user, or if the CVS `passwd' file does not exist, then the server tries to match the password using the system's user-lookup routine. When using the CVS `passwd' file, the server runs under as the username specified in the the third argument in the entry, or as the first argument if there is no third argument (in this way CVS allows imaginary usernames provided the CVS `passwd' file indicates corresponding valid system usernames). In any case, CVS will have no privileges which the (valid) user would not have.
Right now, the only way to put a password in the
CVS `passwd' file is to paste it there from
somewhere else. Someday, there may be a
cvs login. Logging in verifies a password with the server, and also records the password for later transactions with the server. The
cvs logincommand needs to know the username, server hostname, and full repository path, and it gets this information from the repository argument or the
cvs login is interactive -- it prompts for a
cvs -d :pserver:firstname.lastname@example.org:/usr/local/cvsroot login CVS password:
The password is checked with the server; if it is
login succeeds, else it fails,
complaining that the password was incorrect.
Once you have logged in, you can force CVS to connect directly to the server and authenticate with the stored password:
cvs -d :pserver:email@example.com:/usr/local/cvsroot checkout foo
The `:pserver:' is necessary because without it,
CVS will assume it should use
connect with the server (see section Connecting with rsh).
(Once you have a working copy checked out and are
running CVS commands from within it, there is no
longer any need to specify the repository explicitly,
because CVS records it in the working copy's
Passwords are stored by default in the file `$HOME/.cvspass'. Its format is human-readable, but don't edit it unless you know what you are doing. The passwords are not stored in cleartext, but are trivially encoded to protect them from "innocent" compromise (i.e., inadvertently being seen by a system administrator who happens to look at that file).
CVS_PASSFILE environment variable overrides
this default. If you use this variable, make sure you
set it before
cvs login is run. If you
were to set it after running
cvs login, then
later CVS commands would be unable to look up the
password for transmission to the server.
CVS_PASSWORD environment variable overrides
all stored passwords. If it is set, CVS
will use it for all password-authenticated
The passwords are stored on the client side in a trivial encoding of the cleartext, and transmitted in the same encoding. The encoding is done only to prevent inadvertent password compromises (i.e., a system administrator accidentally looking at the file), and will not prevent even a naive attacker from gaining the password.
The separate CVS password file (see section Setting up the server for password authentication) allows people to use a different password for repository access than for login access. On the other hand, once a user has access to the repository, she can execute programs on the server system through a variety of means. Thus, repository access implies fairly broad system access as well. It might be possible to modify CVS to prevent that, but no one has done so as of this writing. Furthermore, there may be other ways in which having access to CVS allows people to gain more general access to the system; noone has done a careful audit.
In summary, anyone who gets the password gets repository access, and some measure of general system access as well. The password is available to anyone who can sniff network packets or read a protected (i.e., user read-only) file. If you want real security, get Kerberos.
The main disadvantage of using rsh is that all the data needs to pass through additional programs, so it may be slower. So if you have kerberos installed you can connect via a direct TCP connection, authenticating with kerberos (note that the data transmitted is not encrypted).
To do this, CVS needs to be compiled with kerberos support; when configuring CVS it tries to detect whether kerberos is present or you can use the `--with-krb4' flag to configure.
You need to edit
inetd.conf on the server
machine to run
cvs kserver. The client uses
port 1999 by default; if you want to use another port
specify it in the
variable on the client.
When you want to use CVS, get a ticket in the
usual way (generally
kinit); it must be a ticket
which allows you to log into the server machine. Then
you are ready to go:
cvs -d :kserver:chainsaw.brickyard.com:/user/local/cvsroot checkout foo
Previous versions of CVS would fall back to a connection via rsh; this version will not do so.
Go to the previous, next section.