Hints and documentation for developers

Detailed Description

Some description of data structures, and similar.

Dear developers/debuggers,

thank you for your interest in fsvs.

I highly appreciate any help, tips and tricks, and even if it's just a bug report I want to know that.

I'm also looking forward to documentation updates, and notifying me about mistakes will be politely answered, too.


 What to do in case of errors
 First, please read the documentation to rule out the possibility that it's just a badly written sentence that caused misunderstanding.
 The internal design
 Entry data storage.
 The basic data structure for entries; an entry can be a file, directory, or special node (symlink or device).
 Debugging and error checking.
 Depending on configure options (--enable-debug, --enable-release) and system state (valgrind found) various debug and error check functions are compiled out.
 Global options.
 A list of variables that can be set by commandline parameters or environment variables; these are used in nearly every action.


apr_hash_t * ign___groups = NULL
 All groups, addressed by name.

Variable Documentation

apr_hash_t* ign___groups = NULL

All groups, addressed by name.

Specification of groups and patterns

While an ignore pattern just needs the pattern itself (in one of the formats below), there are some modifiers that can be additionally specified:
These are listed in the section Modifiers below.

These kinds of ignore patterns are available:

Shell-like patterns

These must start with ./, just like a base-directory-relative path. ? , * as well as character classes [a-z] have their usual meaning, and ** is a wildcard for directory levels.

You can use a backslash \ outside of character classes to match usually special characters literally, eg. \* within a pattern will match a literal asterisk character within a file or directory name. Within character classes all characters except ] are treated literally. If a literal ] should be included in a character class, it can be placed as the first character or also be escaped using a backslash.

Example for / as the base-directory


This would ignore files and directories called apt or opt in the root directory (and files below, in the case of a directory), the directory /sys and everything below, the contents of /proc (but take the directory itself, so that upon restore it gets created as a mountpoint), and all entries matching *~ in and below /home .

The patterns are anchored at the beginning and the end. So a pattern ./sys will match only a file or directory named sys. If you want to exclude a directories' files, but not the directory itself, use something like ./dir/* or ./dir/**
If you're deep within your working copy and you'd like to ignore some files with a WC-relative ignore pattern, you might like to use the rign command.

Absolute shell patterns

There's another way to specify shell patterns - using absolute paths. The syntax is similar to normal shell patterns; but instead of the ./ prefix the full path, starting with /, is used.


The advantage of using full paths is that a later dump and load in another working copy (eg. when moving from versioning /etc to /) does simply work; the patterns don't have to be modified.

Internally this simply tries to remove the working copy base directory at the start of the patterns; then they are processed as usually.

If a pattern does not match the wc base, and neither has the wild-wildcard prefix /**, a warning is issued; this can be handled as usual.


PCRE stands for Perl Compatible Regular Expressions; you can read about them with man pcre (if the manpages are installed), and/or perldoc perlre (if perldoc is installed)

These patterns have the form PCRE:{pattern} (with PCRE in uppercase, to distinguish from modifiers).

An example:

This one achieves exactly the same as ./home/**~ .

Another example:


This would match /home/anthony , /home/guest , /home/somebody and so on, but would not match /home/theodore .

Note that the pathnames start with ./ , just like above, and that the patterns are anchored at the beginning. To additionally anchor at the end you could use a $ at the end.

Ignoring all files on a device

Another form to discern what is needed and what not is possible with DEVICE:[<|<=|>|>=]major[:minor].

This takes advantage of the major and minor numbers of inodes (see man 1 stat and man 2 stat).

The rule is as follows:

  • Directories have their parent matched against the given string
  • All other entries have their own device matched.

This is because the mount-point (ie. the directory, where the other filesystem gets attached) should be versioned (as it's needed after restore), but all entries (and all binding mounts) should not.

The possible options <= or >= define a less-or-equal-than respective bigger-or-equal-than relationship, to ignore a set of device classes.


This patterns would define that all filesystems on IDE-devices (with major number 3) are taken , and all other files are ignored.

This would ignore all filesystems with major number 0 - in linux these are the virtual filesystems ( proc , sysfs , devpts , etc.; see /proc/filesystems , the lines with nodev ).

Mind NFS and smb-mounts, check if you're using md , lvm and/or device-mapper !

Note: The values are parsed with strtoul() , so you can use decimal, hexadecimal (with 0x prepended) and octal (with 0 prepended) notation.

Ignoring a single file, by inode

At last, another form to ignore entries is to specify them via the device their on and their inode:
This can be used if a file can be hardlinked to many places, but only one copy should be stored. Then one path can be marked as to take , and other instances are ignored.
That's probably a bad example. There should be a better mechanism for handling hardlinks, but that needs some help from subversion.


All of these patterns can have one or more of these modifiers before them, with (currently) optional "," as separators; not all combinations make sense.

"take": Take pattern

This modifier is just a short-hand for assigning the group take.

"insens" or "nocase": Case insensitive

By using this you can force the match to be case-insensitive; this can be useful if other machines use eg. samba to access files.

"dironly": Match only directories

Match directories only. This is useful if you have a directory tree in which only certain files should be taken; see below.

"mode": Match entries' mode

This expects a specification of two octal values in the form m:and_value:compare_value, like m:04:00; the following examples give only the numbers.

As an example: the file has mode 0750; a specification of

  • 0700:0700 matches, and
  • 0007:0007 doesn't match.

A real-world example: 0007:0000 would match all entries that have no right bits set for "others", and could be used to exclude private files (like /etc/shadow). (Alternatively, the others-read bit could be used: 0004:0000.

FSVS will give an error for invalid specifications, ie. ones that can never match; an example would be 0700:0007.

For patterns with the m (mode match) and d (dironly) modifiers the filename pattern gets optional; so you don't have to give an all-match wildcard pattern (./**) for these cases.


This would take all ".*.sieve" files (or directories) below /var/vmail, in all depths, and all directories there; but no other files.

If your files are at a certain depth, and you don't want all other directories taken, too, you can specify that exactly:


This would take all files from /etc, but ignoring the files that are not world-readable (other-read bit cleared).


Some thoughts about groups in FSVS.

Groups have to be considered as follows:

  • On commit the auto-props must be used
  • if an entry was added manually, they should apply as usual
  • unless they're overridden by prop-set or prop-del

The easiest way seems to be to write the properties in the filesystem when the entries are allocated for being stored in the entry list, ie. at add, prop-set or commit time. The simplest way to do that would be in waa__output_tree() - we see that an entry is newly allocated, and push all (not already set) properties there. But that wouldn't work with the prop-del command, as an automatically assigned property wouldn't get removed.

So there's the function ops__apply_group(), which is called in the appropriate places.

Definition at line 604 of file ignore.c.

Referenced by ign___new_group().

Generated for fsvs by  doxygen 1.5.6