A web page containing 4 files: manual, notes, mirror (sh script)
and Params (sh script), the separations of which should be failry
obvious. This is a script program which mirrors any set of directories
recursively, and any set of files from one machine to others by updating
the remote files if a change has been made to them.
It is assumed that the machines have uucp connection.
The existence of certain mathematical C programs 'plus', in particular
is also assumed. See the web pages on C programs (in the future).
'plus' is being revised to handle integers of arbitrary size.
In the mean time:
The locution
k = `plus -i 1 $k`
can be replaced with the morr conventional expression
k=`expr 1 + $k`
Various alterations may have to be made to accommodate uxix type sytems
other than the now semidefunct Xenix System V systems.
MIRROR(LOCAL) XENIX System V (Lambda) MIRROR(LOCAL)
NAME
mirror - uucp file and directory update/backup system
SYNOPSIS
mirror -[S | M | m | U | A] [-D] mirror -[S | M | m | U ]
[-P] [-R ] [-D] mirror -[M | m | U ] [-P] [-N] [-R
] [-D]
DESCRIPTION
The mirror system automatically updates remote system files
by uucp from local system files and allows local files to be
updated by remote systems, by providing the remote system
with an available database of checksums.
INDICATIONS
A network of uucp nodes each of which generates different
files and for which it is desirable that every node in the
net work maintain updated mirrors of some subset of the
totality of files created in the network.
A mirror system (topology file) is a node of an arbitrary
uucp network with any number of nodes, but a mirror node
communicates only with its nearest neighbors in the network.
The transmissions are not directed through nodes, but only
with a node directly: there is no node hopping. Each node
must know, through its configuration files, its place in the
network. The coordination of all the configuration files
will depend on which node generates what, and what is being
mirrored at each node.
Every mirror node must have:
the mirror script and associated utilities
the directory setup in /usr/lib
the correctly topologizing files
/usr/lib/mirror/systems/slaves
/usr/lib/mirror/systems/masters
crontab entries for the running of
mirror -S and mirror -M
or
mirror -S and mirror -m, and mirror -U
that may have to be coordinated with the crontab entries
on the relative slave and master systems of nearest
neighbor nodes.
The system centered in the shell script
/usr/lib/mirror/mirror which should be scheduled to run
periodically as above by cron.
Page 1 (printed 11/11/97)
MIRROR(LOCAL) XENIX System V (Lambda) MIRROR(LOCAL)
It requires the compiled utilities:
gtln, gtfield, chmog, chmogdir, plus
the utility:
creat,
the topologizing database files:
/usr/lib/mirror/systems/slaves - list of systems that we update,
one system per line.
/usr/lib/mirror/systems/masters - list of systems that update us
one system per line.
(The lists are not necessarily mutually exclusive:
the direction of the slave - master relationship depends
on which files are mirrored node A to node B, and which
files are mirrored node B to node A.)
The update priority of systems by master mode is the order
of their listing in the file /usr/lib/mirror/systems/slaves.
Not as significant, but the order in which the sum files
constructed for remote master systems is the order in
which the the master systems are listed in the file
/usr/lib/mirror/systems/masters.
NB Care should be taken, in the coordinated file setup,
with regard to any single file F, that the following
is avoided:
Node A uses its F to update the F of node B
and
Node B uses its F to update the F of node A
This can happen surreptitiously by passage through
various nodes of the network.
For any F, a path can be drawn through the complete graph
associated with all the nodes of the network.
THE LAW is then that for every F the graph that is its
path must have no self-intersections.
Notice that, in general, the path of F can, and most
probably will bifurcate.
Therefore every F dissemination path MUST be
"a connected tree graph".
and directories:
Page 2 (printed 11/11/97)
MIRROR(LOCAL) XENIX System V (Lambda) MIRROR(LOCAL)
/usr/lib/mirror/systems/
containing files "slave" and "master"
/usr/lib/mirror/slaves/
containing subdirectories named for each slave system
/usr/lib/mirror/masters/
containing subdirectories named for each master system
In each of the the last two system subdirectories
there are two files
files, dirs
which list the full pathnames of the files and directories
that are to be updated remotely if under the slave
hierarchy, or that update our files if under the master
hierarchy. [NOTE that the directory entries in the 'dirs'
files will be treated recursively down through
subdirectories; all files in the named directory AND in any
subdirectories and subdirectories of those subdirectories
etc., are files to be mirrored.] Also the file,
sums
which is a file requested from a remote slave system, if
under the slave hierarchy and contains the slave's checksum
information, or is the local checksum file put in place for
retrieval by a remote master system. Every system produces
locally in each of the slave system subdirectories a file
named
lsums
These contain the checksums for the files that are used to
update a remote slave system's files. When mirror running
in master mode sees that the sums file requested from the
slave system has a checksum for a given file that does not
match the local version, the slave system's file updated
with the local version. That is, it is queued for uucp
transmission. The actual sending is left to local uucp
scheduler.
FILE STRUCTURE
In the systems directory, the files slaves and masters list,
one per line, the uucp names of the systems that are slave
and master to the local system. A given remote system may
be master with respect to one set of files and directories
and slave with respect to another necessarily distinct and
different set of files and directories. Thus a given system
name may appear in either or both of these files. A line
beginning with '#' followed by a space or tab is considered
to be a comment line.
Page 3 (printed 11/11/97)
MIRROR(LOCAL) XENIX System V (Lambda) MIRROR(LOCAL)
The 'files' and 'dirs' files may be commented similarly.
Both of these files list the files and directories that are
to be mirrored. There are two columns. The first column
contains the full local pathname, while the second separated
from the second by TABS, contains the full remote pathname.
PERMISSIONS
All files and directories should be readable and writable by
owner and group (chmod 664) with owner 'uucp' and group
'root'.
OPTIONS
-D Turn on the debugging flag. Compatible
with all options. The output is quite
voluminous and should probably take and
option to determine a debugging level.
-A Run in interactive administrative mode
to add systems, remove systems and edit
the topology file as well as the 'files'
and 'dir' files for the slave or master
aspect of any system.
-R Takes as argument the name of a mirror
system. When mirror is run with any of
the options M, m, U, or S, that mode
operation is confined to only the
specified system. This option is not
compatible with the A option.
-S Run in slave mode.
-U Run in local update mode. turned on.
The default is off.
-m Run in master (distributing) mode.
-M Run in complete master mode: do the work
specified in both the -U and -m options.
-N Do not actually queue files for
transfer. Useful with The -M, -m modes
together with the -D mode to get an
output of what mirror would do if it
were actually run. do the work
specified in both the -U and -m options.
-P Set the canonical permissions running in
any of the modes M, m, S, U, other wise
they are not set. The modes that are
set are defined in the Params file.
Inactive in -A mode.
Page 4 (printed 11/11/97)
MIRROR(LOCAL) XENIX System V (Lambda) MIRROR(LOCAL)
SEE ALSO
uucp(C), cron(C), rm(C), uuname(C), uuinstall(AD)
gtfield(LOCAL), gtln(LOCAL)
FILES
/usr/lib/mirror/mirror
the shell script
/usr/lib/mirror/Params
parameters for the mirror script.
/usr/lib/mirror/systems/slaves
list of slave systems
/usr/lib/mirror/systems/masters
list of master systems
/usr/lib/mirror/slaves/*/files
list of files mirrored to remote systems
/usr/lib/mirror/slaves/*/dirs
list of directories mirrored to remote systems
/usr/lib/mirror/masters/*/files
list of files mirrored from remote systems
/usr/lib/mirror/masters/*/dirs
list of directories mirrored from remote systems
/usr/lib/mirror/slaves/*/sums
transferred remote checksums from remote slaves
/usr/lib/mirror/slaves/*/lsums
local checksums of files that we mirror to remote slaves
/usr/lib/mirror/masters/*/sums
checksum files available for remote masters
/usr/lib/mirror/work
for temporary files
NOTES
The variables LOCALSYSTEM, SUMPROG, RMFPROG, UUDEMON and
UUINSTALL of the 'mirror' shell script are system and unix
flavor dependent and may have to be set by the System
Administrator.
Notes on mirrored network configuration:
Reference: "Data Networks" - Gallagher & Bertsekas
A given node should not have too many connections. This
will swamp the node causing network failure. The maximum
Page 5 (printed 11/11/97)
MIRROR(LOCAL) XENIX System V (Lambda) MIRROR(LOCAL)
number of connections should be determined by the power or
capacity of the node which should depend on:
machine speed
available RAM
available disk storage
local activity
An additional consideration is the mirror demands placed on
the node. What is the expected throughput for each
connection? This will be dependent on the centrality (if it
can be defined) of the node in the network. A peripheral
network node will presumably have fewer demands placed on
it.
For a star network, the central machine should have the
maximal possible power, since it is exactly central and
singularly so.
Efficiency and manageability of a network is inversely
proportional to the dimension of its topologizing graph.
Page 6 (printed 11/11/97)
File: /usr/lib/mirror/Notes
-----------------------------------------------------------------------------
For Improvements and extensions or generalizations.
-----------------------------------------------------------------------------
It is currently possible that in directory mirroring, a file may exist
on the remote system that we do not have.
This is treated as an error. The master system should be able to ignore
such a file.
For adding a system allow within the menu, modifications and intallation
of the system to the uucp network files. - DONE
Enable runs for a particular remote system: -R . - DONE
Local and remote files to have different pathnames. - DONE
SLAVE SYSTEM:
Manufactures a 'sums' file for its master.
(Uses its own path name)
MASTER SYSTEM:
Sends for slave's 'sums' file.
Manufactures its own 'lsums' file for its slave.
(Uses its own path name)
Compares checksums of mirrored files by taking its own files
one by one (line by line in 'lsums').
--------
To match pathnames, i.e., to find the correct checksum in the
slave's sums file it needs to use the 'files' and 'dirs' files
associated to the slave:
Search 'files' first to find the line with its own pathname.
If found, it will be the first field and the slave's
pathname will be the second field.
Quit search.
Next, create two strings which are: (1. the local directory pathname of
the file) and (2. the local filename) listed in the 'lsums file'.
Search the 'dirs' file for the matching line. It should be found.
Second field on that line is the pathname for the slave system.
Get it.
concat: (slave pathname) and (local file name)
---------
Use the resulting full pathname to grep the slave's 'sums'
file. Master may be adding a newfile to slave'sa directory
and so if it is not found we queue for transmission.
Otherwise do the checksum comparison. With no match, we
queue for transmission.
Replace queue for transmission by a direct uucp invocation:
uucp $localpthname $system!$slavepath/$filename
Add number of files transferred to each remote system to a log file.
Send Timing to a log file.
Operation warnings should still be captured by administrator's mail.
:
#
# mirror
#
# UUCP network file and database mirroring system
#
# Runs in MASTER MODE - Update remote systems (local checksum update)
# in master MODE - Update remote systems (without local checksum update)
# in UPDATE MODE - (Only local checksum update)
# in SLAVE MODE - Supplier to Master Systems that request
# checksum files.
#
# and in interactive ADMINISTRATIVE MODE - Edit system files
#
# Run by cron in appropriate mode (other than administrative) at appropriate
# times, on all mirror systems.
#
# Version 1.2
#
# Bill Hammel - September 18, 1996
# October 7, 1996 - Added mirror administrative functions
# + uucp administration.
# October 8, 1996 - Option parsing & -R option,
# & -D option.
# October 9, 1996 - Split off of Params file.
# - Files and directories to have different
# paths on remote systems.
# - uuq & uureq -> uucp directly.
# October 10, 1996 - [-P] option
# October 14, 1996 - [-N] Don't actually queue
#
#--------------------------------------------------------------------------#
#
trap "rm -f $SUMFILE $TMP/$$; exit 1"
USAGE="Usage:\t$0 -[M | m | S | U] [-P] [-R ] [-D]\n\t$0 -N -[M | m] -[R ] [-D]\n\t$0 -A [-D]"
#
# Root of mirror system directories and files
# exported to 'Params' when it is read.
# See Params file for setting of parameters, constants, initializing,
# pathnames, permission, owner and group defaults, etc.
#
MIRROOT="/usr/lib/mirror"
#--------------------- ADMINISTRATION FUNCTIONS ---------------------------#
# Editing of the system files:
# systems/slaves, systems/masters
# slaves/*/files, masters/*/files
# slaves/*/dirs, masters/*/dirs
# topology
#
admin_menu0() {
clear
echo "\n\n\n"
echo "\t\t\tMIRROR ADMINISTRATION\n\n\n"
echo "\t\t\ta. ADD A SYSTEM\n"
echo "\t\t\tr. REMOVE A SYSTEM FROM MIRROR\n"
echo "\t\t\tu. UPDATE A SYSTEM'S FILES\n"
echo "\t\t\tt. SYSTEMS TOPOLOGY FILE\n"
echo "\t\t\tc. CONVERT LOCAL FILE PATH TO REMOTE FILE PATH - check\n"
echo "\t\t\tU. ADD and DELETE FROM, UPDATE UUCP FILES\n"
echo "\t\t\te. EXIT\n\n"
echo "\t\t\tENTER> \c"
}
admin_menu1() {
clear
echo "\n\n\n\n\n"
echo "\t\t\tUPDATE MIRROR SYSTEM FILES\n\n\n"
case $mode in
s|S)
echo "\t\t\tf. FILES MIRRORED TO SYSTEM: $system\n"
echo "\t\t\td. DIRECTORIES MIRRORED TO SYSTEM: $system\n"
;;
m|M)
echo "\t\t\tf. FILES MIRRORED FROM SYSTEM: $system\n"
echo "\t\t\td. DIRECTORIES MIRRORED FROM SYSTEM: $system\n"
;;
esac
echo "\t\t\te. EXIT\n\n"
echo "\t\t\tENTER> \c"
}
fd_files() {
# Enter here with the variables $system and $mode set
case $mode in
s|S)
UPDIR=$S_RSYSD/$system
;;
m|M)
UPDIR=$M_RSYSD/$system
;;
esac
while true
do
admin_menu1
read ans junk
case $ans in
f)
vi $UPDIR/files
;;
d)
vi $UPDIR/dirs
;;
e)
return
;;
*)
echo "\n\t\tUnrecognized response: $ans"
sleep 5
continue
;;
esac
done
}
rm_sys() {
clear
echo "\n\n\n\n\n\n"
echo "\t\tENTER NAME OF SYSTEM TO REMOVE> \c"
read oldsys junk
grep $oldsys $MASTER_LIST $SLAVE_LIST
exstat=$?
if [ $exstat -ne 0 ]; then
echo "\n\t\tSystem: $oldsys is unknown"
sleep 5
return
fi
#
# edit to remove from slaves and masters lists use grep -v
# rm -rf the oldsys subdirectories of the slave and master
# directories.
#
cat $MASTER_LIST | grep -v $oldsys > $TMPD/$$
mv $TMPD/$$ $MASTER_LIST
chmod 644 uucp root $MASTER_LIST
cat $SLAVE_LIST | grep -v $oldsys > $TMPD/$$
mv $TMPD/$$ $SLAVE_LIST
chmod 644 uucp root $SLAVE_LIST
if [ ! -d $M_RSYSD/$oldsys ]; then
rm -rf $M_RSYSD/$oldsys
fi
if [ ! -d $S_RSYSD/$oldsys ]; then
rm -rf $S_RSYSD/$oldsys
fi
# NB We should display and check with user to remove.
echo "\t\tSYSTEM $oldsys REMOVED FROM MIRROR"
sleep 5
}
add_sys() {
clear
echo "\n\n\n\n"
echo "\t\tENTER NEW SYSTEM\'S NAME> \c"
read newsys junk
grep $newsys $MASTER_LIST $SLAVE_LIST
exstat=$?
if [ $exstat -eq 0 ]; then
echo "\n\t\tSystem: $newsys is already known"
sleep 5
return
fi
echo "\t\tSYSTEMS CAN BE BOTH MASTER AND SLAVE\n"
echo "\n\t\tIS NEW SYSTEM A SLAVE (y/n)> \c"
read s_ans junk
echo "\n\t\tIS NEW SYSTEM A MASTER (y/n)> \c"
read m_ans junk
if [ "$s_ans" = "y" -o "$s_ans" = "Y" ]; then
grep $newsys $SLAVE_LIST
exstat=$?
if [ $exstat -eq 0 ]; then
echo "\n\t\tSystem: $newsys is already slave system"
sleep 5
else
echo "\n\t\tINSTALLING $newsys AS A SLAVE SYSTEM\n"
echo $newsys >> $SLAVE_LIST
if [ ! -d $S_RSYSD/$newsys ]; then
mkdir $S_RSYSD/$newsys
chmod 664 uucp root $S_RSYSD/$newsys
fi
fi
fi
if [ "$m_ans" = "y" -o "$m_ans" = "Y" ]; then
grep $newsys $MASTER_LIST
exstat=$?
if [ $exstat -eq 0 ]; then
echo "\t\tSystem: $newsys is already slave system"
sleep 5
else
echo "\n\t\tINSTALLING $newsys AS A MASTER SYSTEM\n"
echo $newsys >> $MASTER_LIST
if [ ! -d $M_RSYSD/$newsys ]; then
mkdir $M_RSYSD/$newsys
chmod 664 uucp root $M_RSYSD/$newsys
fi
fi
fi
}
update_sys() {
clear
echo "\n\n\n"
echo "\t\tENTER SYSTEM NAME AND MODE (name s|m)> \c"
read system mode
echo "\n\t\tChecking System: $system Current Mode\n"
grep $system $MASTER_LIST $SLAVE_LIST
exstat=$?
if [ $exstat != 0 ]; then
echo "\t\tUnknown system: $system"
sleep 5
return
else
sleep 2
fi
case $mode in
s|S)
grep $system $SLAVE_LIST
exstat=$?
if [ $exstat != 0 ]; then
while true
do
echo "\t\tNot slave system: $system"
echo "\t\tMake it one? (y/n) ENTER> \c"
read ans junk
case $ans in
y|Y)
echo $system >> $SLAVE_LIST
if [ ! -d $S_RSYSD/$system ]; then
mkdir $S_RSYSD/$system
chmod 664 uucp root $S_RSYSD/$system
fi
echo "\n\n\t\t\t\tOK - DONE"
sleep 5
;;
n|N)
echo "\n\n\t\t\t\tOK"
sleep 5
return
;;
*)
echo "\n\t\tUnrecognized response: $ans"
sleep 5
continue
;;
esac
done
else
sleep 2
fi
;;
m|M)
grep $system $MASTER_LIST
exstat=$?
if [ $exstat != 0 ]; then
while true
do
echo "\n\t\tNot master system: $system"
echo "\n\t\tMake it one? (y/n) ENTER> \c"
read ans junk
case $ans in
y|Y)
echo $system >> $MASTER_LIST
if [ ! -d $M_RSYSD/$system ]; then
mkdir $M_RSYSD/$system
chmod 664 uucp root $M_RSYSD/$system
fi
echo "\n\t\t\t\tOK - DONE"
sleep 5
;;
n|N)
echo "\n\t\t\t\tOK"
sleep 5
return
;;
*)
echo "\n\t\tUnrecognized response: $ans"
continue
;;
esac
done
else
sleep 2
fi
;;
*)
echo "\n\t\tUnrecognized mode: $mode"
sleep 5
return
;;
esac
# Updating a system with $system name and with slave or master $mode
fd_files
}
# Administrative mode entry point
#
admin_mirror() {
while true
do
admin_menu0
read ans junk
case $ans in
a)
add_sys
continue
;;
r)
rm_sys
continue
;;
u)
update_sys
continue
;;
t)
vi $TOPOLOGY
continue
;;
c)
echo "LOCAL FILE PATH> \c"
read l_path
echo "REMOTE SYSTEM> \c"
read system
path_conv
echo "REMOTE FILE: $system!$r_path"
echo "RETURN> \c"
read system
continue
;;
U)
clear
$UUINSTALL
continue
;;
E|e|Q|q)
clear
exit 0
;;
*)
echo "\n\t\tUnrecognized Response $ans"
sleep 5
continue
;;
esac
done
# Switch below does exiting after dropout - if it happens
}
#---------------- END ADMINISTRATION FUNCTIONS ---------------------------#
# Sets and maintains permissions
# Files
Fchmog() {
if [ $DOPERMS -eq 0 ]; then
return
fi
if [ $MODE -eq $SLAVE ]; then
chmog $S_F_MODE $S_F_OWNER $S_F_GROUP $l_path
else
chmog $M_F_MODE $M_F_OWNER $M_F_GROUP $l_path
fi
}
# Sets and maintains permissions
# Directories and their file and directory contents
Dchmog() {
if [ $DOPERMS -eq 0 ]; then
return
fi
if [ $MODE -eq $SLAVE ]; then
chmog $S_D_MODE $S_D_OWNER $S_D_GROUP $l_dir
find $l_dir -type d -exec chmog $S_D_MODE $S_D_OWNER $S_D_GROUP {} \;
find $l_dir -type f -exec chmog $S_F_MODE $S_F_OWNER $S_F_GROUP {} \;
# NB This is really incomplete below one level
else
chmog $M_D_MODE $M_D_OWNER $M_D_GROUP $l_dir
find $l_dir -type d -exec chmog $M_D_MODE $M_D_OWNER $M_D_GROUP {} \;
find $l_dir -type f -exec chmog $M_F_MODE $M_F_OWNER $M_F_GROUP {} \;
fi
}
#------------ FUNCTIONS THAT CHECK INTEGRITY OF CHECK FILES ---------------#
# SUMFILE is externally set in the main process.
# Function sets external flag depending on integrity check outcome.
chk_sumfile() {
# Extract checksum line for this 'sums' file
rchksum=`gtln 1 $SUMFILE`
if [ $DEBUG -eq 1 ]; then
echo "$SUMFILE:\c"
wc $SUMFILE
echo "Editing"
fi
# Edit out the checksum line
ed $SUMFILE <<- EOF > /dev/null
1d
w
q
EOF
if [ $DEBUG -eq 1 ]; then
echo "Edited"
echo "$SUMFILE:\c"
wc $SUMFILE
fi
# Calculate the actual checksum output of the received file
cchksum=`$SUMPROG $SUMFILE`
# Get the actual checksum numbers from each line
rsum=`gtfield -c 1 $rchksum`
csum=`gtfield -c 1 $cchksum`
if [ $DEBUG -eq 1 ]; then
echo "\nReceived checksum: $rsum"
echo "Computed checksum: $csum"
fi
# Compare checksums for file sent and file received and set
# the GOODFILE flag accordingly
if [ $rsum -eq $csum ]; then
GOODFILE=1
else
GOODFILE=0
fi
if [ $DEBUG -eq 1 ]; then
echo "chk_sumfile returning"
fi
}
# Modify the simple list of checksums to include its own checksum
mk_sumfile() {
# Get checksum output for 'sums' file that is to be sent to a
# master system
cchksum=`$SUMPROG $SUMFILE`
# Edit to add this line as the first line in the file
ed $SUMFILE <<- EOF > /dev/null
0a
$cchksum
.
w
q
EOF
if [ $DEBUG -eq 1 ]; then
echo "mk_sumfile returning"
fi
}
#---------------------- FUNCTIONS THAT CREATE CHECKSUMS ----------------------#
# Must be called before premakedsums
# Called by S_mk_sums and M_mk_lsums.
#
premakefsums() {
if [ $DEBUG -eq 1 ]; then
echo "premakefsums begin"
fi
# Set loop parameters
# Find number of lines (= number of files) in 'files' file.
flns=`cat $RF_FILE | wc -l`
flno=1
# Loop creating checksum lines in 'sums' file for the current file
# master system for each file indicated in 'files' file.
while [ $flno -le $flns ]
do
line=`gtln $flno $RF_FILE`
l_path=`gtfield -c 1 $line`
if [ "$l_path" = "#" ]; then
# A comment line
flno=`plus -i $flno 1`
continue
fi
# Set proper m o g for current file
# Function performs setting on $l_file
Fchmog
if [ $MODE -eq $SLAVE ]; then
if [ -f $l_path ]; then
echo "`$SUMPROG $l_path` $l_path" >> $R_SUMFILE
else
# File is not there; put in a parseable entry
echo "0 0 $l_path" >> $R_SUMFILE
fi
else
if [ -f $l_path ]; then
echo "`$SUMPROG $l_path` $l_path" >> $R_SUMFILE
else
# File is not there; put in a parseable entry
echo "WARNING: file $l_path does not exist for us to mirror to $system"
flno=`plus -i $flno 1`
continue
fi
fi
flno=`plus -i $flno 1`
done
if [ $DEBUG -eq 1 ]; then
echo "premakefsums returning"
fi
}
# Must be called after premakefsums
# Called by S_mk_sums and M_mk_lsums.
#
premakedsums() {
if [ $DEBUG -eq 1 ]; then
echo "premakedsums begin"
fi
# Set loop paprameters
dlns=`cat $RD_FILE | wc -l`
dlno=1
# Loop creating checksum lines in 'sums' file for the current system
# for each file of each directory indicated.
# Outer loop is loop on directories in the 'dirs' file for the
# current remote master system.
while [ $dlno -le $dlns ]
do
line=`gtln $dlno $RD_FILE`
l_dir=`gtfield -c 1 $line`
if [ "$l_dir" = "#" ]; then
# A comment line
dlno=`plus -i $dlno 1`
continue
fi
if [ $DEBUG -eq 1 ]; then
echo "Creating list of files in: $l_dir"
fi
# Set proper m o g for current directories
# and files.
# Function performs setting on $l_dir
Dchmog
# List all files of the current directory in a workfile.
if [ $MODE -eq $SLAVE ]; then
if [ -d $l_dir ]; then
find $l_dir -type f -print > $TMPD/$$F
else
# Can't make entries; master system will
# understand to send anyhow.
# Increment loop counter
dlno=`plus -i $dlno 1`
continue
fi
else
# A master mode
if [ -d $l_dir ]; then
find $l_dir -type f -print > $TMPD/$$F
else
# Can't make entries; master system will
# understand to send anyhow.
# Increment loop counter
echo "WARNING: directory $l_dir does not exist to mirror to $system"
dlno=`plus -i $dlno 1`
continue
fi
fi
if [ $DEBUG -eq 1 ]; then
echo "Converting workfile list to Shell script"
fi
# Edit created list of files: transforming it into
# an sh script that will generate the checksum lines
# for all files listed.
ed $TMPD/$$F <<- END > /dev/null
1,\$s/.*/echo \"\`$SUMPROG &\` &\"/
w
q
END
if [ $DEBUG -eq 1 ]; then
echo "Shell Script adding sums to lsums file"
fi
# Run created sh script appending output to the 'sums' file
# being created.
sh $TMPD/$$F >> $R_SUMFILE
# Increment loop counter
dlno=`plus -i $dlno 1`
done
rm -f $TMPD/$$F
if [ $DEBUG -eq 1 ]; then
echo "Clean up work directory"
echo "premakedsums returning"
fi
}
M_mk_lsums() {
if [ $DEBUG -eq 1 ]; then
echo "M_mk_lsums begin"
fi
# Reset the R_SYSS file to Remote System list of our slaves
R_SYSS="$MIRROOT/systems/slaves"
# Loop on the systems that our slaves.
slns=`cat $R_SYSS | wc -l`
slno=1
while [ $slno -le $slns ]
do
rsys=`gtln $slno $R_SYSS`
if [ "$ONLYSYSTEM" != "" ]; then
# The -R option has been used
if [ "$ONLYSYSTEM" != "$rsys" ]; then
slno=`plus -i $slno 1`
continue
fi
fi
R_SUMFILE="$S_RSYSD/$rsys/lsums"
creat $R_SUMFILE
# For the slave system's files
RF_FILE="$S_RSYSD/$rsys/files"
premakefsums
# For the slave system's directories
RD_FILE="$S_RSYSD/$rsys/dirs"
premakedsums
# We do not have to put a file checksum in since these
# files aren't going anywhere.
chmog $M_F_MODE $M_F_OWNER $M_F_GROUP $R_SUMFILE
slno=`plus -i $slno 1`
done
if [ $DEBUG -eq 1 ]; then
echo "M_mk_lsums returning"
fi
}
S_mk_sums() {
if [ $DEBUG -eq 1 ]; then
echo "S_mk_sums begin"
fi
# Init loop parameters
slns=`cat $R_SYSS | wc -l`
slno=1
if [ $DEBUG -eq 1 ]; then
echo "Entering master systems loop"
fi
# Loop on the systems that our masters.
while [ $slno -le $slns ]
do
rsys=`gtln $slno $R_SYSS`
if [ "$ONLYSYSTEM" != "" ]; then
# The -R option has been used
if [ "$ONLYSYSTEM" != "$rsys" ]; then
slno=`plus -i $slno 1`
continue
fi
fi
R_SUMFILE="$M_RSYSD/$rsys/sums"
if [ $DEBUG -eq 1 ]; then
echo "Recreating: $R_SUMFILE"
fi
# This zeros out any old sum file contents
creat $R_SUMFILE
# For the master system's files
RF_FILE="$M_RSYSD/$rsys/files"
if [ $DEBUG -eq 1 ]; then
echo "Checksum for entries in: $RF_FILE"
fi
premakefsums
# For the master system's directories
RD_FILE="$M_RSYSD/$rsys/dirs"
if [ $DEBUG -eq 1 ]; then
echo "Checksum for entries in: $RD_FILE"
fi
premakedsums
# Put in the checksum of checksums.
# (function mk_sumfile uses value of SUMFILE)
SUMFILE=$R_SUMFILE
mk_sumfile
if [ $DEBUG -eq 1 ]; then
echo "Checksum added to: $SUMFILE"
echo "Adjusting Transmission Permissions"
fi
# Set proper permissions for transmission
chmog $S_F_MODE $S_F_OWNER $S_F_GROUP $R_SUMFILE
# Increment counter of master systems
slno=`plus -i $slno 1`
if [ $DEBUG -eq 1 ]; then
echo "Next Master System: prepare sums file for request"
fi
done
if [ $DEBUG -eq 1 ]; then
echo "S_mk_sums returning"
fi
}
# Convert the full pathaname of the local file to the
# full pathname of the remote file that we are mirroring.
# Given: l_path = local pathname of file to mirror out.
# Set the variables: r_file = l_file = local file name
# l_dir = local directory of file in question.
# r_path = remote full pathname of file
# r_dir = remote directory of file in question.
#
# Called only in -m and -M noninteractive mode
# and in -A mode as a check
#
path_conv() {
RSFILES="$S_RSYSD/$system/files"
RSDIRS="$S_RSYSD/$system/dirs"
l_dir=`dirname $l_path`
l_file=`basename $l_path`
if [ $DEBUG -eq 1 ]; then
echo "path_conv begin"
echo "l_path = $l_path"
echo "l_file = $l_file"
echo "l_dir = $l_dir"
echo "\tConversion files:"
echo "$RSFILES : $RSDIRS"
fi
# Assume first the pathname is a file
t_r_line=`grep "$l_path " $RSFILES`
grstat=$?
if [ $DEBUG -eq 1 ]; then
echo "path_conv: (files) t_r_line = $t_r_line"
fi
if [ $grstat -eq 0 ]; then
# It is a file and we are finished
r_path=`gtfield -c 2 $t_r_line`
r_dir=`dirname $r_path`
r_file=`basename $r_path`
if [ $DEBUG -eq 1 ]; then
echo "path_conv - files returning with conversion"
fi
return
fi
if [ $DEBUG -eq 1 ]; then
echo "path_conv: Remote file not converted as file,"
echo " Searching dirs file."
fi
# ----------------------------------------------------- #
while [ "$l_dir" != "." ]
do
# If here the pathanme is not a file and we look for
# the pathname that is that of a mirrored directory.
if [ $DEBUG -eq 1 ]; then
echo "path_conv: dirs l_dir = $l_dir"
fi
t_r_line=`grep "$l_dir " $RSDIRS`
grstat=$?
if [ $grstat -eq 0 ]; then
# We have the line with the remote pathname
r_dir=`gtfield -c 2 $t_r_line`
r_file=$l_file
r_path=$r_dir/$r_file
if [ $DEBUG -eq 1 ]; then
echo "r_path = $r_path"
echo "r_file = $r_file"
echo "r_dir = $r_dir"
echo "path_conv - dirs returning"
fi
return
else
# This event seems like a logical inconsistency; it is
# the result 'find' working recursively and find files
# in a subdirectory of the directory named in the 'dirs'
# file. Transfer the subdirectory name to the file
# name and search again for the directory.
t_dir=$l_dir
t_file=$l_file
l_dir=`dirname $t_dir`
subd_name=`basename $t_dir`
r_file=$subd_name/$t_file
l_file=$subd_name/$t_file
if [ $DEBUG -eq 1 ]; then
echo "SUBDIRECTORY"
echo "l_dir = $l_dir"
echo "l_file = $l_file"
fi
continue
fi
done
}
#---------------------- REREQUEST ABBERANT sums FILE ---------------------#
rereqsums() {
# Request immediate transfer of prepared checksum files
# from our remote master directory to the local
# slave's directory of the remote system.
if [ $DEBUG -eq 1 ]; then
echo "uucp -d -c -r $system!$M_RSYSD/$LOCALSYSTEM/sums $S_RSYSD/$system/sums"
sleep 2
fi
uucp -d -c -r $system!$M_RSYSD/$LOCALSYSTEM/sums $S_RSYSD/$system/sums
# Increment counter of reqrequests for this file
REREQS=`plus -i $REREQS 1`
# Wait for new copy of remote sums file
until [ -f $SUMFILE ]
do
sleep $CHECKTIME
done
}
#--------------------- END FUNCTION DEFINITIONS --------------------------#
#---------------- PARAMETERS, SWITCHES, VARIABLE INITITIALIZATIONS -------#
#---------------- STRINGS, PATHNAMES, PROGRAMS, FILENAMES ----------------#
# Params sets all other paramters
. $MIRROOT/Params
#------------------------ NONINTERACTIVE MODE OPTIONS ------------------------#
# The MODE token values - Should never be any reason to change.
NOTSET=-1
SLAVE=0
MASTER=1
UPDATE=2
master=3
ADMIN=4
MODE=$NOTSET
# Same format as that for getopt in C
OPTSTRING="R:ADMmNSU"
#
#------------ INTERACTIVE MODE or NONINTERACTIVE MODE OPTION SETUPS ----------#
# First and only command line argument is the option determining MODE.
# Don't need a default case since syntax check has already eliminated
# all options that are not syntactically acceptable.
#-------------------------- Option Syntax Check ---------------------------#
if [ $# -eq 0 ]; then
echo $USAGE
exit 0
fi
if [ $# -gt 4 ]; then
echo "Too many options/paramters"
echo $USAGE
exit 1
fi
set -- `getopt $OPTSTRING $*`
if [ $? != 0 ]; then
echo Options: $*
echo Optstring: $OPTSTRING
echo $USAGE
exit 1
fi
#
for i in $*
do
case $i in
-N)
QUEUE=0
shift
;;
-R)
# Option takes systen name as argument
# Cannot be used in Aministrative Mode.
ONLYSYSTEM=$2
shift; shift
;;
-P)
# Option takes no argument
DOPERMS=1
shift
;;
-A)
# Option takes no argument
if [ $MODE -eq $NOTSET ]; then
MODE=$ADMIN
fi
shift
;;
-D)
# Turn on the debugging flag
DEBUG=1
shift
;;
-M)
if [ $MODE -eq $NOTSET ]; then
# Set Mode switch
MODE=$MASTER
# Remote System list of our slaves
R_SYSS="$MIRROOT/systems/slaves"
fi
shift
;;
-m)
if [ $MODE -eq $NOTSET ]; then
# Set Mode switch
MODE=$master
# Remote System list of our slaves
R_SYSS="$MIRROOT/systems/slaves"
fi
shift
;;
-S)
if [ $MODE -eq $NOTSET ]; then
# Set Mode switch
MODE=$SLAVE
# Remote System list of our masters
R_SYSS="$MIRROOT/systems/masters"
fi
shift
;;
-U)
if [ $MODE -eq $NOTSET ]; then
# Set Mode switch
MODE=$UPDATE
# Remote System list of our masters
R_SYSS="$MIRROOT/systems/slaves"
fi
shift
;;
--)
shift
break
;;
*)
echo "Unknown Option: $1"
echo $USAGE
exit 1
;;
esac
done
if [ $MODE -eq $NOTSET ]; then
echo "Improper Syntax"
echo "One of options: -[AMmUS] must be set"
echo $USAGE
exit 1
fi
if [ $DEBUG -eq 1 ]; then
echo "End function definitions, constants, parameters and options"
echo "Mode: $MODE"
echo "Local system: $LOCALSYSTEM"
echo "Remote System directories: $R_SYSS"
sleep 2
fi
if [ $MODE -eq $ADMIN ]; then
# Only do administrative stuff.
admin_mirror
exit 0
fi
#-------------------------- END SETUP SECTIONS ---------------------------#
# This message will go to administrator's mail
echo "$0 $1: Begin \c"
date
#------------------- BEGIN MAIN NONINTERACTIVE PROCESS -------------------#
#-------------------------- Slave Mode Process ---------------------------#
# Slave mode simply prepares the checksum files for retrieval by all
# the master systems.
if [ $MODE -eq $SLAVE ]; then
S_mk_sums
# This message will go to administrator's mail
echo "$0 $1: local update run Complete: \c"
date
fi
#-------------------------- Master Mode Process ---------------------------#
# Examine by SUMPROG, the remote mirrored images of all the files
# in 'files', and all the directories of 'dirs'
# to see if they are conformed to the the cognate files on the
# local system.
# If the are not, update them by queueing for uucp transfer to the
# specified systems.
if [ $MODE -eq $MASTER -o $MODE -eq $master ]; then
#
# Remote system has presumably constructed its checksum files by running
# in Slave Mode.
# Request them from all remote slave systems that we mirror to.
#
mlns=`cat $R_SYSS | wc -l`
mlno=1
while [ $mlno -le $mlns ]
do
system=`gtln $mlno $R_SYSS`
if [ "$ONLYSYSTEM" != "" ]; then
# The -R option has been used
if [ "$ONLYSYSTEM" != "$system" ]; then
mlno=`plus -i $mlno 1`
continue
fi
fi
# Remove the old sums file that may be present
$RMFPROG $S_RSYSD/$system/sums
# Request immediate transfer of prepared checksum files
# from our remote master directory to the local
# slave's directory on our local system.
if [ $DEBUG -eq 1 ]; then
echo "uucp -d -c -r $system!$M_RSYSD/$LOCALSYSTEM/sums $S_RSYSD/$system/sums"
sleep 2
fi
uucp -d -c -r $system!$M_RSYSD/$LOCALSYSTEM/sums $S_RSYSD/$system/sums
# Increment counter of remote slave systems
mlno=`plus -i $mlno 1`
done
# Start demon to send out queued requests for all sums files.
$UUDEMON
fi
if [ $MODE -eq $MASTER -o $MODE -eq $UPDATE ]; then
#
# While we are waiting for the remote checksum files to arrive,
# recreate the sums files for the local system files 'lsums' that
# are to be distributed to all remote slave systems. We will need
# them for the checksum comparisons. We initiate remote file
# update if the remote checksum is not equal to our local checksum.
#
M_mk_lsums
# This message will go to administrator's mail
echo "$0 $1: Local Update Complete \c"
date
fi
if [ $MODE -eq $MASTER -o $MODE -eq $master ]; then
# Reset the R_SYSS file
R_SYSS="$MIRROOT/systems/slaves" # Remote System list of our slaves
# MASTER MODE
# We must now await the arrival of all the 'sums' files from the remote
# systems to which we mirror.
# NB Do we really have to wait for ALL the checksum files to arrive?
# I don't think so. Perhaps change the below!
#
# The number of remote slave systems
slns=`cat $R_SYSS | wc -l`
# The number of remote files that have arrived
rfiles=0
# Unused arrival_list except in debugging
arrival_list=""
# The "waiting loop" for the arrival of the correct number of
# sums files from the slave systems.
while [ $rfiles -lt $slns ]
do
# Check periodically to see if all files are here
# The "check on all arrivals" loop
rfiles=0
slno=1
while [ $slno -le $slns ]
do
system=`gtln $slno $R_SYSS`
if [ "$ONLYSYSTEM" != "" ]; then
# The -R option has been used
if [ "$ONLYSYSTEM" != "$system" ]; then
# Don't actually check
slno=`plus -i $slno 1`
rfiles=`plus -i $rfiles 1`
continue
fi
fi
if [ -f $S_RSYSD/$system/sums ]; then
arrival_list="$arrival_list $system"
rfiles=`plus -i $rfiles 1`
fi
if [ $DEBUG -eq 1 ]; then
echo "Arrivals: $arrival_list"
echo "# of Systems: $slns"
echo "# of Arrivals: $rfiles"
echo "Checked system #: $slno"
fi
slno=`plus -i $slno 1`
if [ $slno -ge $slns ]; then
break
fi
done
if [ $DEBUG -eq 1 ]; then
echo "Out of system loop on sums files"
fi
if [ $rfiles -eq $slns ]; then
if [ $DEBUG -eq 1 ]; then
echo "All system sums files here."
echo "Break waiting loop."
fi
break
fi
if [ $DEBUG -eq 1 ]; then
echo "Waiting $CHECKTIME seconds."
date
fi
sleep $CHECKTIME
done
#
# All remote files are here and we begin the loop on each system
# with the checksum comparisons of the sums and lsums files
# themselves.
#
# Loop on all slave systems
rsyss=`cat $R_SYSS | wc -l`
rsysno=1
if [ $DEBUG -eq 1 ]; then
echo "Entering slave system processing loop."
fi
while [ $rsysno -le $rsyss ]
do
system=`gtln $rsysno $R_SYSS`
if [ "$ONLYSYSTEM" != "" ]; then
# The -R option has been used
if [ "$ONLYSYSTEM" != "$system" ]; then
# Don't actually check
rsysno=`plus -i $rsysno 1`
continue
fi
fi
SUMFILE="$S_RSYSD/$system/sums"
chk_sumfile
chmog $M_F_MODE $M_F_OWNER $M_F_GROUP $SUMFILE
if [ $DEBUG -eq 1 ]; then
echo "Checksum done of $SUMFILE"
fi
if [ $GOODFILE -eq 0 ]; then
echo "Bad checksum ($0): $SUMFILE"
echo "Saving remote file as: $SUMFILE.bad"
echo "Rerequesting $SUMFILE"
mv $SUMFILE $SUMFILE.bad
if [ $REREQS -gt $MAXREREQS ]; then
echo "The Number of Requests for our $SUMFILE"
echo "due to bad xmission now exceeds"
echo "($MAXREREQS), this is the set maximum."
echo "$0 of system: $system will not be done."
echo "$0 proceding to next system."
echo "Admin should check transmission setup."
# Set for next system
rsysno=`plus -i $rsysno 1`
# Reset the REREQS counter for the next system
REREQS=0
# Increment number of systems skipped
# Not Used.
N_SYSSKIPPED=`plus -i $N_SYSSKIPPED 1`
SYSSKIPPED="$SYSSKIPPED $system"
fi
# Implied else:
# Do NOT go to the next system.
# The requesting process will continue until we
# get a copy that checks out, or MAXREREQS is
# exceeded.
# The function rereqsums has done the waiting
# for the file to arrive.
# Rerequest the sums file that is bad.
# This function will use the currently set value
# of the 'system' variable.
rereqsums
continue
fi
if [ $DEBUG -eq 1 ]; then
echo "Good Checksum on $SUMFILE"
fi
#
# If here:
# Good checksum on received sum file and its own checksum
# line has been removed.
# We compare the sums and lsums files, assuming that the
# we being the master of this process, know what files to
# transfer.
#
LSUMFILE="$S_RSYSD/$system/lsums"
rlns=`cat $SUMFILE | wc -l`
llns=`cat $LSUMFILE | wc -l`
if [ $rlns -ne $llns ]; then
echo "Warning ($0):"
echo "\twc -l $SUMFILE: $rlns"
echo "\twc -l $LSUMFILE: $llns"
fi
#
# Start reading our lsums file line by line, and searching
# the sums file of the current remote system for the
# pathename on our line. We already have 'llns' value.
#
if [ $DEBUG -eq 1 ]; then
echo "System: $system -"
echo " Entering main sums-lsums comparison loop"
fi
llno=1
while [ $llno -le $llns ]
do
# Sums File Line format: (checksum) (blocks) (pathname)
l_line=`gtln $llno $LSUMFILE`
l_chksum=`gtfield -c 1 $l_line`
# Get full pathname of the file we mirror from
l_path=`gtfield -c 3 $l_line`
#
# NB For a remote file to have a different pathname
# we use our 'files' & 'dirs' to convert to the
# correct remote pathname 'r_line' before grepping
# the 'sums' arrived from the remote system.
# The remote system will use its own pathname.
#
# Convert: l_path -> r_path,
# Set variables: r_path, r_file, r_dir
path_conv
# Look for matching line with converted full path name
# in sums file from remote system.
r_line=`grep "$r_path\$" $SUMFILE`
grepstatus=$?
if [ $DEBUG -eq 1 ]; then
echo "greped r_line: $r_line"
fi
if [ $grepstatus -ne 0 -o "$r_line" = "" ]; then
# grep has failed to find a match in sums.
# Assume this is starting a new file on the
# remote system.
if [ $DEBUG -eq 1 ]; then
echo "$r_path not present on $system"
fi
r_chksum=0
else
# Otherwise we have a matching line; get its
# checksum field.
r_chksum=`gtfield -c 1 $r_line`
fi
if [ $DEBUG -eq 1 ]; then
echo "r_chksum: $r_chksum l_chksum: $l_chksum"
fi
if [ $r_chksum -ne $l_chksum ]; then
# Update of the remote system file is necessary.
# Queue the update do not let system do the
# scheduling since this process is part of
# the system scheduling
# The list of the slave systems is the
# order of priority.
if [ $DEBUG -eq 1 ]; then
echo "\t\t\tSENDING -"
echo "uucp -d -c -r $l_path $system!$r_path"
echo "Remote System: $system"
echo "Local - File: $l_path\tDirectory: $l_dir"
echo "Remote - File: $r_file\tDirectory: $r_dir"
sleep 2
fi
if [ $QUEUE -eq 1 ]; then
uucp -d -c -r $l_path $system!$r_path
else
echo "\t\t\t\tNOT QUEUED"
fi
else
if [ $DEBUG -eq 1 ]; then
echo "\t\t\t\tCHECKSUMS MATCH\n"
fi
fi
# Increment counter of lsums line
llno=`plus -i $llno 1`
done # End loop on system checksum comparisons
rsysno=`plus -i $rsysno 1`
# Reset the REREQS counter for the next system
REREQS=0
rm -f $SUMFILE
if [ $DEBUG -eq 1 ]; then
echo "Remote $system 'sums' file removed - Next system"
fi
done # End loop on slave systems
# Start Uucp Scheduler as background process.
$UUDEMON &
if [ $DEBUG -eq 1 ]; then
echo "All slave system files queued for remote mirroring."
echo "Uucp Scheduler started as background process."
fi
# This message will go to Administrator's mail
echo "$0 $1: run Complete \c"
date
fi
if [ $DEBUG -eq 1 ]; then
echo "mirror - EXITING WITH SUCCESS."
fi
exit 0
:
# /usr/lib/mirror/Params
#
# '.' read by mirror
#
# The value of MIRROOT is exported from mirror
#
#---------------- PARAMETERS, SWITCHES, VARIABLE INITITIALIZATIONS -------#
#---------------- STRINGS, PATHNAMES, PROGRAMS, FILENAMES ----------------#
# Switch for debugging output.
# Normal setting should be 0; set to 1 for debug runs at the command line.
# Option -D turns this switch on.
DEBUG=0
# Set on: actually do the uucp queueing, off just show what you would do.
# Option -N turns this switch off.
QUEUE=1
# UNIX FLAVOR DEPENDENT - Change by unix masters only
SUMPROG=sum
UUDEMON=/usr/lib/uucp/uudemon.hour
UUINSTALL="/etc/uuinstall 2"
# UNIX FLAVOR DEPENDENT - Change by unix masters only
# Check local manual - This should "remove forcefully"
RMFPROG="rm -f"
# UNIX FLAVOR DEPENDENT - Change by unix masters only
# Check local manual - This should retrieve the local uucp system name
# in /etc/systemid or a file of similar name and same use.
LOCALSYSTEM=`uuname -l`
# Time interval in seconds between checks for arrival of the sent for
# remote system sums files.
# Changeable with caution.
CHECKTIME=150
# The number of requests allowed before a complaint is registered.
# This number is adjustable.
MAXREREQS=5
# Counter for the number of times a remote sums file is rerequested.
# This is an initialization - DO NOT CHANGE.
REREQS=0
# Counter for the number of systems skipped due to intolerable transmission,
# as defined by MAXREREQS.
# This is an initialization - DO NOT CHANGE.
N_SYSSKIPPED=0
# List of the systems skipped due to intolerable transmission,
# as defined by MAXREREQS.
# This is an initialization - DO NOT CHANGE.
SYSSKIPPED=""
# For -R option in -M -S -U -m modes
# This is an initialization - DO NOT CHANGE
ONLYSYSTEM=""
# Topology file of Mirror nodes
TOPOLOGY=$MIRROOT/topology
# System files of master and slave remote systems
# Should never be changed.
MASTER_LIST="$MIRROOT/systems/masters"
SLAVE_LIST="$MIRROOT/systems/slaves"
# Master system and Slave system Directories
# Should never be changed.
M_RSYSD="$MIRROOT/masters"
S_RSYSD="$MIRROOT/slaves"
# What it says it is.
# Should never need to be changed.
TMPD="$MIRROOT/work"
# Without the -P option do not set the canonical permissions below
DOPERMS=0
# Permissions, owner and group for files mirrored
# Cf mirror: Fchmog(), Dchmog()
# SLAVE Files
S_F_MODE="+rw"
S_F_OWNER=uucp
S_F_GROUP=root
# SLAVE Directories
S_D_MODE=777
S_D_OWNER=uucp
S_D_GROUP=root
# MASTER Files
M_F_MODE="+rw"
M_F_OWNER=uucp
M_F_GROUP=root
# MASTER Directories
M_F_MODE=777
M_F_OWNER=uucp
M_F_GROUP=root
# End Params
Return to Home Page
Return to Metayoga Page
Return to shell Page
The URL for this document is:
http://graham.main.nc.us/~bhammel/graham/SHELL/mirror.html
Created: 1997
Last Updated: May 28, 2000
Email me, Bill Hammel at
bhammel@graham.main.nc.us
READ WARNING BEFORE SENDING E-MAIL