FSC(1) FSC(1)
FSC
fsc - personal source control utility
SYNOPSIS
fsc [ moduleName ... ] [options]
DESCRIPTION
Fsc is a source control utility which keeps track of the successive
versions of one or more files. Using this program, you can remember
all of your changes to your files, and get back any of the old
versions of the files. The versions of the files can be given names
so that you can easily extract sets of files which were consistent
with each other at some point in time.
Fsc does not perform any locking of files, and for this reason it is
most useful as a personal source control utility. It provides a
simple way to make backups of changes to files you are editing without
you having to worry about read-only verses write-enabled files, or
having to remember to check-out files before you edit them.
Fsc only can only be used for text files. Binary files cannot be used
since null characters will prematurely terminate input lines.
Because some of the options of fsc accept a variable number of
arguments, module names cannot be specified immediately after these
options. In order to avoid any confusion, it is best to always
specify module names first, followed by the options for the command.
MODULES
Fsc manipulates entities called modules. A module is simply the name
of a text file that you are interested in keeping versions of. For
example, a source file "doit.c" is a module, and so is a documentation
file "howto.txt". The module name includes the suffix of the file (as
in the above examples).
A module name can also include leading directory components, as in
"src/bar.c". The use of absolute module names (those starting with a
slash) is not recommended since the absoluteness of the path is not
preserved by fsc.
Modules are stored in a directory called the module storage directory.
The default module storage directory is "FSC_EDITS" in your current
directory. This default is convenient when you are in a directory
containing many modules, and you want a local storage directory to
contain just those modules. If you give the -p option, then you can
locate the storage directory anywhere you choose. This is useful if
you choose to have a common storage directory for all of your files,
independent of where they actually are used.
The term module is used here instead of file because while they can
usually be considered as the same thing, there can be differences.
- 1 - Formatted: October 26, 2025
FSC(1) FSC(1)
The module name is the string used by fsc to refer to the whole set of
versions of a file stored in the storage module directory. Using the
appropriate options, it is possible to insert the contents of an
arbitrary file as a version of a module, or to extract a version of a
module into an arbitrary file. Only by default does the file name to
be inserted or extracted match the module name.
CREATING MODULES
To use fsc for the first time, you need to create your storage
directory. Therefore, cd to the directory where you want it to be,
which is probably the directory containing the modules you want to
save the versions of. Then create the directory "FSC_EDITS".
To start using a module under fsc, you must first use the -create
option. This creates the initial edit for that module in the storage
directory, with the contents of the specified module as the initial
edit. Thus, if you have a source file "prog.c", then the command:
fsc prog.c -create
creates the initial edit of the module.
You can then delete the file "prog.c" if desired and fsc would be able
to recreate it later. Alternatively, you can leave it there as the
working copy of the module.
UPDATING MODULES
To save another version of the module, you use the -u option. This
updates the files in the storage directory to include the latest
changes. Thus, to continue the example, after editing "prog.c", the
command:
fsc prog.c -u
will save the changes as a new edit. This command compares the newest
version of the module to the previous version, and saves the new
version and the differences in the module storage directory. At this
point, you can once again delete the "prog.c" file if desired, and
later get back either of the two versions of the program.
In either the -create or -u options, the file containing the new
version of the module defaults to the same name as the module. In the
example, the module "prog.c" was created and updated from the data in
the file "prog.c". When you wish the data to come from some other
file, you can use the -i option, which specifies the input file to use
for the data. For example, if you wanted to update "prog.c", but from
a filename called "newprog.c", then the command:
fsc prog.c -u -i newprog.c
would save a new version of "prog.c", but with the data that was in
- 2 - Formatted: October 26, 2025
FSC(1) FSC(1)
the file "newprog.c". In this case, the file "prog.c" does not have
to exist, and isn't referenced even if it did exist. Again, once the
update is complete, you could delete "newprog.c" if desired and then
later you can retrieve its contents.
The -i option can also be a directory name, in which case the input
file is contained in the specified directory having the same name as
the module name.
The -cu option conditionally updates a module. That is, it will only
do an update if there are any differences between a file and the
latest version of a module. This is convenient when related changes
are made to many modules in a directory, and one command using wild-
cards or the -all option can update just those modules that were
changed.
The -du option combines the effects of the -d and -u options. It
displays the differences between a file and the latest version of a
module. If there are any differences, it then proceeds to perform an
update of the module with that file, possibly asking for remarks.
This option is very useful when used with wild-carded module names and
the -r option. Then you can update just those modules which were
changed by an edit session, and see the changes for each module before
typing the appropriate remark for each module.
EXTRACTING A VERSION OF A MODULE
To extract a previous version of a module, you specify the name of the
module and use the -e option to specify the edit number you want
extracted. Edit numbers are assigned sequentially starting with 1.
Thus the initial version of the module has edit number 1, the first
version has edit number 2, and so on until the latest version. If the
-e option is not used, or if no edit number is supplied for it, then
the latest edit number is extracted. Therefore, this is the default
action if no options at all are specified.
Edit numbers can also be zero, negative, or be a name with an optional
offset. The number zero represents the latest edit number, and
negative numbers indicate edit numbers backwards from the latest edit
number. Edit names represent edit numbers whose name had been set by
using the -name option. For example, if edit number 10 was associated
with the name "foo", then the edit name "foo" represents 10, "foo-4"
represents 6, and "foo+2" represents 12. The special reserved names
"oldest" and "newest" refer to the oldest and newest versions of the
module in the edit history.
As an example of extractions, assume that you have saved ten versions
of the module "prog.c". The following commands will then extract the
versions of the file with the specified edit numbers:
fsc prog.c ;version 10 (the latest)
fsc prog.c -e 9 ;version 9 (the version just prior)
- 3 - Formatted: October 26, 2025
FSC(1) FSC(1)
fsc prog.c -e oldest ;version 1 (the oldest version)
fsc prog.c -e -2 ;version 8 (latest version - 2).
The output filename is again defaulted to the module name. So when
the module "prog.c" is extracted, the specified version of the module
is written to the file "prog.c". You can change the output filename
using the -o option. Thus, the command:
fsc prog.c -o newprog.c
will extract the latest version of the module "prog.c", and put it
into the file "newprog.c". Once again, the file "prog.c" is ignored,
whether or not it existed.
A directory name can be used for the -o option, in which case the
output file will be placed in the specified directory with the same
name as the module name.
In order to prevent accidental overwriting of a file, fsc will by
default ask you if overwriting is permitted if that would occur. A
common mistake might be to edit "prog.c", and then try to update the
module, but forget to specify the -u option. Then fsc would try to
extract the newest version of the module, and thus overwrite the file
with the new changes. Asking the question allows you to notice your
mistake, and prevent the overwriting.
The -fw option will force overwriting of the file, thus never asking
you if overwriting is permitted. This might be useful in a script, or
when you are SURE that you want to overwrite any existing file. The
-nw option is the no-overwrite option, and will cause any existing
files to NOT be overwritten, again without asking you. This is useful
if you already have some of the modules in your directory, and you
want to extract the rest of the modules without overwriting the ones
you already have. Specifying both -fw and -nw is an error.
The -t option is used to output an extracted module to the terminal
(stdout), instead of writing it to a file. This is useful in order to
view the beginning of a version of the file. This can be interrupted
if you do not want to see the whole file.
ASSIGNING EDIT NAMES FOR A VERSION
The -name option is used to associate a name for the newest version of
a module. It can be given along with the -create, -u, -cu, or -du
options, to specify a name for the new version of the module. It can
also be given by itself in order to specify a name for the newest
version of a module.
Each edit number can have many names associated with it, so this will
not remove any previously defined name for the edit. This option is
useful to correlate many modules together. For example, when a new
version of a program is ready to be released, you could give each
- 4 - Formatted: October 26, 2025
FSC(1) FSC(1)
module of the program the same name "release1". Then in the future,
you can recreate the sources making up that release by extracting the
edits with the name "release1" for every module.
Edit names must contain at least one non-digit character, and must
contain at least one non-digit character following the last plus or
minus sign in the name. These rules prevent ambiguous parsing of edit
numbers for the -e, -t, -d, and -l options.
DISPLAYING DIFFERENCES BETWEEN VERSIONS
The -d option is used to display the differences between two versions
of a module, or a file and a version of a module. There are three
modes for this action, depending on how many edit numbers are
supplied. These modes are illustrated by the following examples:
fsc foo.c -d Compare latest version against "foo.c"
fsc foo.c -d 3 Compare version 3 against "foo.c"
fsc foo.c -d 3 4 Compare version 3 against version 4
This option accepts the -i option to specify the file to be compared.
When using the -d option, the output defaults to stdout. Therefore,
you must use -o (or redirection) if you wish the differences saved to
a file. Using -q with -d will only output a quick summary of the
changes, instead of the detailed changes. This summary only supplies
the number of lines inserted, deleted, and unchanged between the
files. Using -w with -d will display all of both files, showing in
detail what the differences are using change bars.
The -d option may need to write one or two temporary files in order to
extract old versions of a module to be compared. They are deleted
again just before differences are output, so that stopping the output
before it is complete will not leave these files around. The
temporary files are usually written to the /tmp directory. If this is
not possible because of permission or disk full problems, then you can
specify the directory for writing the temporary files into. This is
done by defining the "TMPDIR" environment variable to be the path of
the directory.
SPECIFYING MULTIPLE MODULES
More than one module can be acted on by a single fsc command. The
effect is as if each module was acted on using separate invocations of
fsc. Multiple modules can be specified in one of three methods.
These are to explicitly specify a list of module names on the command
line, to act on every module in the module storage directory by using
-all, or to act on a list of module names read from standard input
using -stdin. Only one of these methods can be used in one command.
The -all option can be used with any of the action options. It means
perform the operation for all modules in the module storage directory.
Subdirectories within the module storage directory are also scanned.
- 5 - Formatted: October 26, 2025
FSC(1) FSC(1)
The -stdin option is used to read module names from standard input.
Module names are read one per line and operated on until end of file
is reached. Blank lines are ignored. This option is useful in
conjunction with find to operate on all of the modules within a
directory hierarchy. When -stdin is used, confirmation for
overwriting of files is not possible, and so one of the -fw or -nw
options must also be specified.
If -all or -input are not specified then you can specify multiple
module names on the command line, and the actions will be performed
with those modules.
When using multiple explicit modules, the -all option, or the -stdin
option, the -i and the -o options have a slightly different meaning.
In these cases, the -i and -o arguments must be directory names which
contains filenames with the same name as the module names. If the
argument is not a directory, then an error is given. This feature is
used for example, to extract all the modules and place them into some
remote directory, as in:
fsc -all -e -o tempdir
You should be careful when specifying numeric edit numbers for
multiple modules. Most probably, a particular edit number is not
appropriate for multiple modules, since changes to two files
corresponding to a particular edit number are not usually related.
Using edit names avoids these problems. As an example, if you wanted
to extract every module which had an edit that was named "rev3", then
you could use the command:
fsc -all -e rev3
Some other useful examples of commands which use multiple modules are:
fsc *.c -create
fsc -check
fsc -cu -all
fsc -clean -all
fsc -all -name release2
ENTERING REMARKS FOR AN EDIT
Whenever a module is created or updated, you can optionally ask to
include some remarks describing why that edit was created which will
be saved in the edit history. The remarks consist of one or more
lines of text. Remarks are saved only when the -r option is used as
part of the command.
If the -r option is followed by an argument, then the argument is a
filename which contains the remarks for the update. This is useful if
you are updating many modules at once, and want the same remarks for
each module.
- 6 - Formatted: October 26, 2025
FSC(1) FSC(1)
If no argument follows the -r option, then the remarks are entered
from the terminal. Fsc prompts you for each line of the remarks.
When you have entered all of the lines of the remarks, a single blank
line is used to terminate the input.
Some simple editing commands can be used while entering remarks. This
commands are used at the beginning of a line, and start with an
exclaimation mark. The following commands are available:
!b Backs up to the previous line so that you can retype it.
!c Clears all of the remarks entered so far so that you can reenter
them.
!r Redisplays all of the remarks entered so far.
!q Aborts updating of the current module.
As an example of using remarks, to update "prog.c" and supply some
remarks for the update from the terminal, you can use the command:
fsc prog.c -u -r
OTHER OPTIONS
The -clean option is used to remove files which match the newest
versions of modules. If a file exists which matches the newest
version of a module, then the file is deleted, otherwise it is kept.
This option is used to clean up a work directory after building a new
version of a product. This option is especially useful when used with
the -all option. It will also accept the -i option to specify a
directory containing the files to be cleaned.
The -check option is used to find out if a file does not match the
latest version of a module. If so, a message is given. If the file
does match, no output occurs. This option is thus useful to determine
which files have been modified and in need of updating. The -all
option is defaulted for this option, since it is usually used for all
modules. For example,
fsc -check
will report on all files which are different than the latest modules.
If -q is specified, then the output will consist of the module names
with no other output. This is useful for the back-quote operator in
shell commands for referencing the modules which are out of date. The
-check option will also accept the -i option.
The -l option prints a list of edits for the module, giving the user
name, date, user remarks, and names specified for the edits. If no
edit number is supplied, then all edits are printed in reverse order.
If a single edit number is supplied, then only that edit number is
- 7 - Formatted: October 26, 2025
FSC(1) FSC(1)
printed. If two edit numbers are supplied, then all edits in the
specified range are printed. The output from this option defaults to
stdout. You can use the -o option to save the results to a file.
The -prune option is used to permanently remove early edits from an
edit history. This is useful if you wish to cut down on the amount of
disk space taken by an edit history file, or when you want to start
another release of a file, and want a copy of the edit history file
for that new release. The option takes an edit number to preserve,
and all edits in the edit history file before that edit are deleted,
and can no longer be referenced. For example, to keep only the
current edit plus the previous 10 edits of the module "file", you
could use the command:
fsc file -prune -10
Since the -prune option is unrecoverable (unless backup files are
available), fsc asks the user to verify that the prune is really
wanted. The -fu option can be used to bypass this verification.
The -v option can be specified with any other action, and outputs
status information about the progress of the action. This is useful
for debugging of problems, or just for amusement when the system is
slow or a large file is being processed. It accepts a numeric
argument to indicate the verbosity for output. The levels are as
follows:
0 No output at all (except for errors).
1 Single-line output describing action (default).
2 Detailed status as action proceeds.
Finally, fsc has an -h option, which will briefly list the possible
options.
SPECIAL CHARACTER SEQUENCES
When extracting a file, fsc looks for and updates special character
sequences in the first few lines of the file. These special sequences
are used for documentation purposes, such as describing the edit
number the file is from. For speed of extraction and updating, these
sequences are usually limited to the first 25 lines of the file, since
fsc then does not have to examine each line of the file. The -m
option can be used to change the number of lines to be modified from
the default value of 25. Specifying zero totally disables the special
character sequences, whereas specifying a very large number will cause
the sequences to be checked for each line of the file (and thus
slightly slow fsc down).
Each special sequence is of the form:
[# keyword value, keyword value, ..., keyword value #]
- 8 - Formatted: October 26, 2025
FSC(1) FSC(1)
where each keyword describes an item, and each value is the value for
the preceding keyword. The keywords can be in upper or lower case, or
both. The single space following the "[#", following each comma, and
preceding the "#]" must be present. If the sequence is wrong, an
unknown keyword is used, the line is longer than 200 characters, or
more than four keywords are used, then the whole line will not be
changed. The current keywords which can be used are the following:
edit The edit number
date The date that the edit was created
user The user name who created the edit
module The module name
In order to use this special character sequence, you simply insert it
into your module inside of a comment (within the first few lines).
When this is done, the value parts of the sequence can be null. For
example, if you want to put a special sequence into a program called
"delete.c", then you could edit the first few lines as follows:
/*
* Delete - program to delete files
* [# Edit, Date #]
*/
When an extract is done, the proper edit number and date are
automatically inserted as the new values. Thus, if you extract edit
23 of the module "delete.c" which had been created on 8 January 2000,
then the resulting file would begin:
/*
* Delete - program to delete files
* [# Edit 23, Date 8-Jan-2000 #]
*/
When updating a module, it is never necessary to edit these sequences,
as any old values will be removed and replaced with the new ones.
Also, when using the -d or -du options, lines with these sequences
compare as if the values were null, and thus will not cause spurious
differences.
During an update, the special character sequences are read and any
edit value found is compared against the current edit number of the
module. If they differ, then the update fails. This provides a
simple interlock check for the case of two users extracting the same
version of a file, editing it, and then both updating it without
knowledge of each other. In this case, the second user would fail,
and then he can merge his edits with the previous user's edit and then
retry the update. This checking is disabled if there is no special
character sequence containing the edit keyword, the edit number value
is null, or if the -fu option is used to indicate that the check is
- 9 - Formatted: October 26, 2025
FSC(1) FSC(1)
not needed.
MODULE STORAGE DIRECTORY DETAILS
Each module in a storage directory is stored as two files in the
directory. The two files have the same name as the module's file name
except for the addition of a suffix. The file with the ".s" suffix is
a copy of the latest version of the module, with one extra line at the
beginning. The file with the ".e" suffix is the edit history of the
module, and contains information needed to extract previous versions
of the module.
For module names which contain directory components, the directory
paths are reflected in the structure of the module storage directory.
For example, the module "src/bar.c" would be stored in the directory
"FSC_EDITS/src" as the two files "bar.c.s" and "bar.c.e".
Subdirectories in the module storage directory are automatically
created when new modules require them.
If the edit history for a module becomes corrupted (which hopefully
should never happen), you will at least have the most recent version
of the module. All you have to do is remove the first line from the
file with the ".s" extension.
The edit history file contains file offsets to lines in the lastest
version of the module, along with lines of text that has been deleted
from older versions of the module. If you modify the files in the
module storage directory outside of the fsc program, you will probably
corrupt your edit history, causing errors when you extract old
versions of the module.
One safe operation that you can do is to change the name of a module
by renaming both the ".s" and ".e" files to the new module name (with
the same suffixes). For example, the module "fred.c" can be changed
to "barney.c" by renaming "fred.c.s" to "barney.c.s" and "fred.c.e" to
"barney.c.e". You can also move the files within a module storage
directory to a different subdirectory, which will change the directory
component of the moved module names.
ERROR HANDLING
Fsc handles disk full problems during a create or update operation
without any damage occurring to the edit history files. If an edit
cannot be completed because of such problems, the edit is backed out
completely, and you will get an error message about the disk problem.
There is no need for any error recovery in this case, other than
retrying the update when more disk space is available.
Fsc also disables signals during the critical file operations, so you
do not have to worry about damaging the edit history files because of
attempts to quit out of the program.
- 10 - Formatted: October 26, 2025
FSC(1) FSC(1)
As an additional safeguard, the new latest version of a module does
not overwrite the old version. The new version is written with a ".n"
extension, the old version is then renamed to a ".o" extension, and
only then is the ".n" extension renamed to the ".s" extension and the
".o" file deleted. In this way, a valid copy of the latest version of
a module should always be present.
FILES
FSC_EDITS Default module storage directory
file.s Latest edit of file
file.e Edit history of file
AUTHOR
David I. Bell
dbell@canb.auug.org.au
- 11 - Formatted: October 26, 2025