Published on (
 See this if you're having trouble printing code examples

Big Scary Daemons

BSD Tricks: CVS


Also in Big Scary Daemons:

Running Commercial Linux Software on FreeBSD

Building Detailed Network Reports with Netflow

Visualizing Network Traffic with Netflow and FlowScan

Monitoring Network Traffic with Netflow

Information Security with Colin Percival

Earlier, we looked at RCS. I highly recommend RCS on any file where incorrect changes can cause havoc or pain. RCS also has a network-aware big brother: CVS, or Concurrent Versions System. If you've been around the BSD world for any length of time, chances are you've heard of CVS. The term for developers, "committers," comes from CVS.

Many curious users have checked it out and been put off by a man page that's over nine thousand words long and describes hundreds of possible combinations of operations. Most people only need a small subset of CVS' abilities, however.

The basic idea of CVS is quite simple: revision control from a repository server somewhere on the Net. As a user, though, you don't need to check things into the repository. All you have to do is check them out. Since CVS is network-aware, you're essentially downloading files from the central server. Unlike other server protocols, but much like RCS, CVS keeps a complete history of what's happened to each file. You can download particular versions of files, branches of source code trees, or even source code as it existed on a particular date.

Before you can do anything, you need to tell your system where to find the repository. You do this with the CVSROOT environment variable. Choose the appropriate CVSROOT for your project. Although many projects use CVS, we'll look at the BSD CVS servers. Each BSD has several CVS mirrors, but here's one of each to play with.

Once you've set CVSROOT, connect to the server with

cvs login

If the CVS server's anonymous account has no password, it will let you right in. Otherwise, it'll prompt you for a password. Most projects (including non-BSD ones) use the password anoncvs.

Once you've successfully logged in, you'll get your local shell prompt back. Unlike FTP's obvious client, CVS lurks in the background. You can do whatever you like in the foreground, and CVS will just wait for any command beginning with cvs.

CVS organizes information in modules. A module is generally a directory in the source tree. In FreeBSD, for example, a module is most commonly a program name (e.g., more) or a port name (e.g., ports/security/strobe is the module "strobe"). NetBSD has large modules; for example, the kernel sources are the srcsys modules. OpenBSD is somewhere in between, with smaller modules for large chunks of the operating system.

To see the modules available in a particular repository, just do:

cvs checkout CVSROOT/modules

This will create a directory, CVSROOT, that contains a file, modules. This file lists every module you can check out of that repository.

You can easily download a module with the "cvs checkout" command. For example, if you want the latest version of FreeBSD's make, you do:

cvs checkout make

Similarly, if you want the latest version of the FreeBSD port snort, you can use:

cvs checkout snort

This is convenient if you want the latest version of a port, but don't want to upgrade your whole source tree or bother to FTP out for it.

Some modules contain other modules. For example, FreeBSD's usr.sbin module includes the modules for everything in /usr/sbin. You can grab the whole usr.sbin tree, or just one part, with proper selection of module names.

CVS also allows you to access arbitrary chunks of a project's source tree. All you need is the path to the portion of the source tree you want. For example, various developers are working on integrating portions of the BSD make system. If one of these folks wants to download the latest version of OpenBSD's make to see how they handle something, he can log into an OpenBSD CVS server and do:

cvs checkout src/usr.bin/make

FreeBSD's multiplicity of module names is convenient, but not necessary.

When reading a BSD mailing list, one common solution is "grab this revision of this file and see if your problem goes away." You can specify revisions with the -r flag.

cvs checkout -r1.15 sys/netinet/ip_log.c

You can also specify branches. Most people don't want the latest version of a file; by definition, that's -current. To get the latest version of FreeBSD's 4.0-STABLE kernel source, use the RELENG_4 revision.

cvs checkout -rRELENG_4 sys

There are many other uses for downloading pieces of source code. If you think you've fried something in your /etc directory, you can grab the latest version. If you think a particular file in your system might be breaking something, use CVS to check out the previous revision. Or, if you want to try backporting a feature from -current or from another BSD, CVS allows you to easily fetch the relevant sources.

The cvs command takes a variety of useful options. Options to cvs must appear between cvs and checkout. A good one is -z3, which compresses the source code before sending it across the network. This can vastly reduce bandwidth. The -q option makes CVS run almost silently, checking out the code without listing every file. Finally, the -d option lets you set an alternate CVSROOT without changing your environment. For example, to quietly download the latest version of the core nessus utility without changing my environment, I could use:

cvs -q -z3 checkout nessus-core

What's more, the checkout command takes a variety of flags. The -l flag tells CVS to not recurse down the source tree. If you just wanted the files under /etc, not in its subdirectories, you would use:

cvs checkout -l etc

One of the more interesting features is the ability to check out code as of a particular date. Suppose your system ran fine a month ago, but "ls" started failing when you upgraded a few days ago. You can narrow down the problem by getting the last source code you know is good. The -D flag allows you to specify a date in a variety of formats.

cvs checkout -D "1 month ago" ls

You can confirm that the code worked then, and successively bring the code closer to the current date.

cvs checkout -D "1 fortnight ago" ls

(Somehow, I never thought the word "fortnight" would be useful to a sysadmin.)

By building successive versions of ls, you can learn when the problem started. You can even fall back to older versions of kernel and world this way.

When you're finished, tell CVS you're done:

cvs logout

Combined with RCS, CVS gives you the ability to grab arbitrary versions of almost any file -- both those you maintain, and those supported by a BSD project. This gives you unlimited control over your system, and greatly enhances your abilities.

Michael W. Lucas

Read more Big Scary Daemons columns.

Return to the BSD DevCenter.

Copyright © 2009 O'Reilly Media, Inc.