##
##  lsync.pod -- Access Layer Synchronization Tool (Manual Page)
##  Copyright (c) 2000-2002 Ralf S. Engelschall <rse@engelschall.com> 
##
##  Permission to use, copy, modify, and distribute this software for
##  any purpose with or without fee is hereby granted, provided that
##  the above copyright notice and this permission notice appear in all
##  copies.
##
##  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
##  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
##  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
##  IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
##  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
##  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
##  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
##  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
##  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
##  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
##  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
##  SUCH DAMAGE.
##

=pod

=head1 NAME

B<lsync> - Access Layer Synchronization Tool

=head1 SYNOPSIS

B<lsync>
[B<--version>|B<-v>]
[B<--help>|B<-h>]
[B<--init>|B<-i>]
[B<--nop>|B<-n>]
[B<--quiet>|B<-q>]
[B<--trace>|B<-t>]
[B<--local>|B<-l>]
[B<--uninstall>|B<-u>]
[B<--root=>I<root>]
[B<--pkgdir=>I<pkgdir>]
[B<--subdirs=>I<subdir>[,I<subdir>,...]]

=head1 DESCRIPTION

This program activates software packages which were locally
installed in a sub-directory of a package hierarchy (located under
I<root>/I<pkgdir>/) by managing symbolic links in an access layer
(located under I<root>/) corresponding to package installation
files (found in I<root>/I<pkgdir>/pkgname/subdir/) which need to be
collected in global directories (located under I<root>/subdir/). 

The purpose of this is that individual packages can be installed and
deinstalled seperately without interfering with other packages while
all packages as a whole still can be treated like a single package
(installed into the access layer).

The
actual creation of symbolic links is as following ("foo" indicating an
arbitrary file; "bar" indicating an arbitrary package name):

=over 4

=item I<root>B</bin/>foo -> B<../>I<pkgdir>B</>barB</bin/>foo

This activates the user executeable
I<root>B</>I<pkgdir>B</>barB</bin>/foo as I<root>B</bin/>foo. It can
be found by the shell by placing I<root>B</bin> into the environment
variable C<PATH> (B<PATH="..:>I<root>B</bin:..">).

=item I<root>B</sbin/>foo -> B<../>I<pkgdir>B</>barB</sbin/>foo

This activates the system executeable
I<root>B</>I<pkgdir>B</>barB</sbin>/foo as I<root>B</sbin/>foo. It can
be found by the shell by placing I<root>B</sbin> into the environment
variable C<PATH> (B<PATH="..:>I<root>B</sbin:..">).

=item I<root>B</man/man>I<N>B</>foo -> B<../>I<pkgdir>B</>barB</man/man>I<N>B</>foo

This activates the Unix manual page
I<root>B</>I<pkgdir>B</>barB</man/man>I<N>B</>foo as
I<root>B</man/man>I<N>B</>foo. It can be found by the man(1) tool
by placing I<root>B</man> into the environment variable C<MANPATH>
(B<MANPATH="..:>I<root>B</man:..">). Keep in mind that lsync(1)
activates any files found in the B<man/manI<N>> sub-directory of the
package, but the man(1) tool usually requires the filename scheme
fooB<.>I<N> before it can find the file.

=item I<root>B</info/>foo -> B<../>I<pkgdir>B</>barB</info/>foo

This activates the GNU info page I<root>B</>I<pkgdir>B</>barB</info/>foo
as I<root>B</info/>foo. It can be found by the info(1) and pinfo(1)
tools by placing I<root>B</info> into the environment variable
C<INFOPATH> (B<INFOPATH="..:>I<root>B</info:..">). Keep in mind that
lsync(1) activates any files found in the B<info/> sub-directory of the
package, but the info(1) and pinfo(1) tools usually require the filename
scheme fooB<.info> before it can find the file.

=item I<root>B</include/>foo -> B<../>I<pkgdir>B</>barB</include/>foo

This activates the C header I<root>B</>I<pkgdir>B</>barB</include>/foo
as I<root>B</include/>foo. It can be found by the C/C++ compilers
by adding I<root>B</include> to their include search path (B<cc ..
-I>I<root>B</include> B<...>). Keep in mind that lsync(1) activates any
files found in the B<include/> sub-directory of the package, but the
C/C++ compiler usually by convention use the filename scheme fooB<.h>.

=item I<root>B</lib/>foo -> B<../>I<pkgdir>B</>barB</lib/>foo

This activates the C library I<root>B</>I<pkgdir>B</>barB</lib>/foo
as I<root>B</lib/>foo. It can be found by the C/C++ compilers (and
the linker they use) by adding I<root>B</lib> to their library search
path (B<cc .. -L>I<root>B</lib> B<...>). It can be found by the Unix
Dynamic Loader by adding I<root>B</lib> to the environment variable
C<LD_LIBRARY_PATH> (B<LD_LIBRARY_PATH="..:>I<root>B</lib:..">).
Keep in mind that lsync(1) activates any files found in the B<lib/>
sub-directory of the package, but the C/C++ compiler usually require the
filename scheme B<lib>fooB<.a> and the Unix Dynamic Loader the filename
scheme B<lib>fooB<.so> before they actually can use the file.

=back

It is obvious that more sub-directories in a package installation
might exist -- for instance B<share/>, B<var/>, B<libexec/>, etc. But
lsync(1) intentionally does not link files in those directories into
corresponding directories of the access layer, because those files do
not require that they are located in a global area in order to be used.
So lsync(1) only creates the access layer for files where a common area
is required for (easy) use.

=head1 SPECIAL FEATURES

There are two special features supported by lsync(1):

=over 4

=item B<Run-Command Files>

lsync(1) on startup implicitly reads command line options from
C<.lsyncrc> files. They are searched in all parent directories and in
the callers home directory. Their contents is prepended to the list of
given command line options.

=item B<Multiple Package Versions>

lsync(1) skips all directories under I<root>/I<pkgdir>/ which contain
the pattern "-[0-9]" in their directory name. On the other hand,
lsync(1) follows also symbolic links under I<root>/I<pkgdir>/.
This can be used for installing multiple versions of a package and
switching between them. For instance, if version 1.0 of package
"foo" is installed into directory I<root>/I<pkgdir>/foo-1.0,
version 1.1 into I<root>/I<pkgdir>/foo-1.1 and version 1.2 into
I<root>/I<pkgdir>/foo-1.2, lsync(1) does skip all three. To enable
version 1.1 one just creates a symbolic link I<root>/I<pkgdir>/foo
pointing to foo-1.1. Then lsync(1) picks up the files in
I<root>/I<pkgdir>/foo-1.1. If you want to temporarily upgrade to
foo-1.2, all you have to do is to change the symlink pointing from
foo-1.1 to foo-1.2.

=item B<Temporarily Deactivated Package>

One can deactivate a package "foo" by going to I<root>/I<pkgdir>/foo/
and running "lsync --local --uninstall", of course. Alternatively
one can set the sticky bit on the directory I<root>/I<pkgdir>/foo.
Then lsync(1) also skips the package. Alternatively, assume
package "foo" as a whole should not be deactivated, but its
I<root>/I<pkgdir>/foo/lib directory (usually because this directory
unfortunately contains non-library files), one just sets the sticky bit
on I<root>/I<pkgdir>/foo/lib.

=back

=head1 OPTIONS

=over 4

=item B<--version>, B<-v>

Display program version information only.

=item B<--help>, B<-h>

Display program usage information only.

=item B<--init>, B<-i>

Create an initial access layer hierarchy under I<root>.

=item B<--nop>, B<-n>

No Operation -- causes lsync(1) to not perform any filesystem
operations. In conjunction with B<--trace> you can at least see what
would be executed.

=item B<--quiet>, B<-q>

Forces lsync(1) to perform the operations quietly, i.e., without any
verbose messages.

=item B<--trace>, B<-t>

Forces lsync(1) to show what filesystem operations are performed.

=item B<--local>, B<-l>

This restricts the operations to a local package area. This option can
only be used if you are physically staying below a package sub-directory
under I<root>/I<pkgdir>/. For instance, when you are staying in
I<root>/I<pkgdir>/bar or I<root>/I<pkgdir>/bar/bin and use B<--local>,
all operations are restricted to the package "bar".

=item B<--uninstall>, B<-u>

This performs only package uninstallation operations, i.e., only
symbolic links are removed. This can be used to completely empty the
access layer. Additionally it is very useful in combination with
B<--local> in order to uninstall a particular package without having to
remove its files.

=item B<--root=>I<root>

Sets the root directory where the access layer and package subdirectory
is located. The default can be determined by running C<lsync --help>
(see section "Current configuration").

=item B<--pkgdir=>I<pkgdir>

Sets the sub-directory under the root directory where packages are
located. The default can be determined by running C<lsync --help> (see
section "Current configuration").

=item B<--subdirs=>I<subdirs>[,I<subdir>,...]

Sets one or more sub-directories of the access layer on which lsync(1)
should act. The default can be determined by running C<lsync --help>
(see section "Current configuration").

=back

=head1 RESULTS

This program uses the following return codes on exit: 0 (operation
successful), 1 (system error), 2 (command line error) and 3 (other user
error).

=head1 HISTORY

The idea of filesystem access layers consisting of symbolic links
pointing to actual package installation areas is a rather old one. It
dates back to the early days of Unix and was implemented many times over
the last decades. One of many implementation was B<GenOPT>, written by
Ralf S. Engelschall for sd&m GmbH & Co KG, Munich in 1992. The name
indicates the programs purpose: to generate symbolic links in an access
layer which was located under C</opt>. B<GenOPT> was very flexible, but
hence also very complex. Because of lack of documentation it was never
released and so only used at sd&m and on all machines which were under
control of Ralf S. Engelschall.

For Cable & Wireless Deutschland GmbH, Munich, the old B<GenOPT>
principle was again needed to manage the C</cw/local> area on their
servers. For this in November 2000 the functionality of B<GenOPT> was
revised, heavily stripped down and finally implemented from scratch. The
result is the current B<LSync>.

=head1 AUTHOR

 Ralf S. Engelschall
 rse@engelschall.com
 www.engelschall.com

=cut

