summaryrefslogtreecommitdiffstats
path: root/support
diff options
context:
space:
mode:
Diffstat (limited to 'support')
-rwxr-xr-xsupport/cvs2includes85
-rwxr-xr-xsupport/files-to-excludes58
-rwxr-xr-xsupport/idmap45
-rwxr-xr-xsupport/json-rsync-version2
-rwxr-xr-xsupport/mapfrom15
-rwxr-xr-xsupport/mapto15
-rwxr-xr-xsupport/mnt-excl48
-rwxr-xr-xsupport/rrsync4
-rw-r--r--support/rrsync.1.md7
9 files changed, 172 insertions, 107 deletions
diff --git a/support/cvs2includes b/support/cvs2includes
index fc7f78f..4a0d1d8 100755
--- a/support/cvs2includes
+++ b/support/cvs2includes
@@ -1,42 +1,63 @@
-#!/usr/bin/env perl
-#
+#!/usr/bin/env python3
# This script finds all CVS/Entries files in the current directory and below
# and creates a local .cvsinclude file with non-inherited rules including each
# checked-in file. Then, use this option whenever using --cvs-exclude (-C):
#
-# -f ': .cvsinclude'
+# -f ': .cvsinclude'
#
# That ensures that all checked-in files/dirs are included in the transfer.
# (You could alternately put ": .cvsinclude" into an .rsync-filter file and
# use the -F option, which is easier to type.)
#
# The downside is that you need to remember to re-run cvs2includes whenever
-# you add a new file to the project.
-use strict;
-
-open(FIND, 'find . -name CVS -type d |') or die $!;
-while (<FIND>) {
- chomp;
- s#^\./##;
-
- my $entries = "$_/Entries";
- s/CVS$/.cvsinclude/;
- my $filter = $_;
-
- open(ENTRIES, $entries) or die "Unable to open $entries: $!\n";
- my @includes;
- while (<ENTRIES>) {
- push(@includes, $1) if m#/(.+?)/#;
- }
- close ENTRIES;
- if (@includes) {
- open(FILTER, ">$filter") or die "Unable to write $filter: $!\n";
- print FILTER map "+ /$_\n", @includes;
- close FILTER;
- print "Updated $filter\n";
- } elsif (-f $filter) {
- unlink($filter);
- print "Removed $filter\n";
- }
-}
-close FIND;
+# CVS gets an added or removed file. Maybe just run it before every copy.
+
+import os, argparse
+
+INC_NAME = '.cvsinclude'
+
+def main():
+ if args.dir:
+ os.chdir(args.dir)
+
+ cvs_includes = set()
+ for root, dirs, files in os.walk('.'):
+ if INC_NAME in files:
+ cvs_includes.add((root + '/' + INC_NAME)[2:])
+ if root.endswith('/CVS') and 'Entries' in files:
+ entries = root[2:] + '/Entries'
+ includes = [ ]
+ with open(entries) as fh:
+ for line in fh:
+ if line.startswith(('/', 'D/')):
+ includes.append(line.split('/', 2)[1])
+ if includes:
+ inc = root[2:-3] + INC_NAME
+ cvs_includes.discard(inc)
+ try:
+ with open(inc) as fh:
+ old_txt = fh.read()
+ except OSError:
+ old_txt = ''
+ txt = ''.join(f"+ /{x}\n" for x in includes)
+ if txt == old_txt:
+ print("Unchanged", inc)
+ else:
+ print("Updating", inc)
+ with open(inc, 'w') as fh:
+ fh.write(txt)
+ dirs.sort()
+
+ for inc in sorted(cvs_includes):
+ print("Removing", inc)
+ os.unlink(inc)
+
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser(description=f"Transform CVS/Entries into {INC_NAME} files.", add_help=False)
+ parser.add_argument("--help", "-h", action="help", help="Output this help message and exit.")
+ parser.add_argument("dir", nargs='?', help="The top CVS dir. Defaults to the current directory.")
+ args = parser.parse_args()
+ main()
+
+# vim: sw=4 et
diff --git a/support/files-to-excludes b/support/files-to-excludes
index a28955c..a47d7f8 100755
--- a/support/files-to-excludes
+++ b/support/files-to-excludes
@@ -1,27 +1,37 @@
-#!/usr/bin/env perl
-# This script takes an input of filenames and outputs a set of
-# include/exclude directives that can be used by rsync to copy
-# just the indicated files using an --exclude-from=FILE option.
-use strict;
+#!/usr/bin/env python3
+# This script takes an input of filenames and outputs a set of include/exclude
+# directives that can be used by rsync to copy just the indicated files using
+# an --exclude-from=FILE or -f'. FILE' option. To be able to delete files on
+# the receiving side, either use --delete-excluded or change the exclude (-)
+# rules to hide filter rules (H) that only affect the sending side.
-my %hash;
+import os, fileinput, argparse
-while (<>) {
- chomp;
- s#^/+##;
- my $path = '/';
- while (m#([^/]+/)/*#g) {
- $path .= $1;
- print "+ $path\n" unless $hash{$path}++;
- }
- if (m#([^/]+)$#) {
- print "+ $path$1\n";
- } else {
- delete $hash{$path};
- }
-}
+def main():
+ paths = set()
+ for line in fileinput.input(args.files):
+ dirs = line.strip().lstrip('/').split('/')
+ if not dirs:
+ continue
+ for j in range(1, len(dirs)):
+ if dirs[j] == '':
+ continue
+ path = '/' + '/'.join(dirs[:j]) + '/'
+ if path not in paths:
+ print('+', path)
+ paths.add(path)
+ print('+', '/' + '/'.join(dirs))
-foreach (sort keys %hash) {
- print "- $_*\n";
-}
-print "- /*\n";
+ for path in sorted(paths):
+ print('-', path + '*')
+ print('-', '/*')
+
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser(description="Transform a list of files into a set of include/exclude rules.", add_help=False)
+ parser.add_argument("--help", "-h", action="help", help="Output this help message and exit.")
+ parser.add_argument("files", metavar="FILE", default='-', nargs='*', help="The file(s) that hold the pathnames to translate. Defaults to stdin.")
+ args = parser.parse_args()
+ main()
+
+# vim: sw=4 et
diff --git a/support/idmap b/support/idmap
new file mode 100755
index 0000000..b212aaf
--- /dev/null
+++ b/support/idmap
@@ -0,0 +1,45 @@
+#!/usr/bin/env python3
+# This helper script makes it easy to use a passwd or group file to map values
+# in a LOCAL transfer. For instance, if you mount a backup that does not have
+# the same passwd setup as the local machine, you can do a copy to/from the
+# backup area as follows and get the differing ID values mapped just like a
+# remote transfer to/from the backed-up machine would do:
+#
+# rsync -av --usermap=`idmap --to /mnt/backup/etc/passwd` \
+# --groupmap=`idmap --to /mnt/backup/etc/group` \
+# /some/src/ /mnt/backup/some/dest/
+#
+# rsync -av --usermap=`idmap --from /mnt/backup/etc/passwd` \
+# --groupmap=`idmap --from /mnt/backup/etc/group` \
+# /mnt/backup/some/src/ /some/dest/
+
+import re, fileinput, argparse
+
+NAME_ID_RE = re.compile(r'^(\w+):[^:]+:(\d+)')
+
+def main():
+ maps = [ ]
+ for line in fileinput.input(args.files):
+ m = NAME_ID_RE.match(line)
+ if not m:
+ continue
+ if args.to:
+ pair = (m[1], m[2])
+ else:
+ pair = (m[2], m[1])
+ maps.append(':'.join(pair))
+ print(','.join(maps))
+
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser(description="Output usermap or groupmap args for rsync.", add_help=False)
+ action = parser.add_argument_group()
+ action = parser.add_mutually_exclusive_group(required=True)
+ action.add_argument("--from", action="store_true", help="Output the map for use on the sending side.")
+ action.add_argument("--to", action="store_true", help="Output the map for use on the receiving side.")
+ parser.add_argument("--help", "-h", action="help", help="Output this help message and exit.")
+ parser.add_argument("files", metavar="FILE", default='-', nargs='*', help="The file(s) that hold the name & id pairs. Defaults to stdin.")
+ args = parser.parse_args()
+ main()
+
+# vim: sw=4 et
diff --git a/support/json-rsync-version b/support/json-rsync-version
index 31fed7f..b01e1e4 100755
--- a/support/json-rsync-version
+++ b/support/json-rsync-version
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
import sys, argparse, subprocess, json
diff --git a/support/mapfrom b/support/mapfrom
deleted file mode 100755
index 88946bc..0000000
--- a/support/mapfrom
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env perl
-# This helper script makes it easy to use a passwd or group file to map
-# values in a LOCAL transfer. For instance, if you mount a backup that
-# does not have the same passwd setup as the local machine, you can do
-# a copy FROM the backup area as follows and get the differing ID values
-# mapped just like a remote transfer FROM the backed-up machine would do:
-#
-# rsync -av --usermap=`mapfrom /mnt/backup/etc/passwd` \
-# --groupmap=`mapfrom /mnt/backup/etc/group` \
-# /mnt/backup/some/src/ /some/dest/
-
-while (<>) {
- push @_, "$2:$1" if /^(\w+):[^:]+:(\d+)/;
-}
-print join(',', @_), "\n";
diff --git a/support/mapto b/support/mapto
deleted file mode 100755
index 9588752..0000000
--- a/support/mapto
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env perl
-# This helper script makes it easy to use a passwd or group file to map
-# values in a LOCAL transfer. For instance, if you mount a backup that
-# does not have the same passwd setup as the local machine, you can do
-# a copy TO the backup area as follows and get the differing ID values
-# mapped just like a remote transfer TO the backed-up machine would do:
-#
-# rsync -av --usermap=`mapto /mnt/backup/etc/passwd` \
-# --groupmap=`mapto /mnt/backup/etc/group` \
-# /some/src/ /mnt/backup/some/dest/
-
-while (<>) {
- push @_, "$1:$2" if /^(\w+):[^:]+:(\d+)/;
-}
-print join(',', @_), "\n";
diff --git a/support/mnt-excl b/support/mnt-excl
index ed7b49b..bc8b5bc 100755
--- a/support/mnt-excl
+++ b/support/mnt-excl
@@ -1,4 +1,4 @@
-#!/usr/bin/env perl
+#!/usr/bin/env python3
# This script takes a command-line arg of a source directory
# that will be passed to rsync, and generates a set of excludes
# that will exclude all mount points from the list. This is
@@ -27,23 +27,33 @@
# awk '{print $2}' /proc/mounts | grep -v '^/$' | \
# rsync -avf 'merge,/- -' /dir host:/dest/
-use strict;
-use warnings;
-use Cwd 'abs_path';
+import os, argparse
-my $file = '/proc/mounts';
-my $dir = shift || '/';
-my $trailing_slash = $dir =~ m{./$} ? '/' : '';
-$dir = abs_path($dir) . $trailing_slash;
-$dir =~ s{([^/]*)$}{};
-my $trailing = $1;
-$trailing = '' if $trailing eq '.' || !-d "$dir$trailing";
-$trailing .= '/' if $trailing ne '';
+MNT_FILE = '/proc/mounts';
-open(IN, $file) or die "Unable to open $file: $!\n";
-while (<IN>) {
- $_ = (split)[1];
- next unless s{^\Q$dir$trailing\E}{}o && $_ ne '';
- print "- /$trailing$_\n";
-}
-close IN;
+def main():
+ trailing_slash = '/' if args.path.endswith(('/', '/.')) and args.path != '/' else ''
+ args.path = os.path.realpath(args.path) + trailing_slash
+ parent_dir = os.path.dirname(args.path)
+ trailing = os.path.basename(args.path)
+ if not os.path.isdir(args.path):
+ trailing = ''
+ elif trailing != '':
+ trailing += '/'
+ want_path = os.path.join(parent_dir, trailing)
+ wp_len = len(want_path)
+
+ with open(MNT_FILE) as fh:
+ for line in fh:
+ mnt_path = line.split()[1]
+ if mnt_path.startswith(want_path) and mnt_path != want_path:
+ print(f"- /{trailing}{mnt_path[wp_len:]}")
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser(description="Output mount points as rsync excludes.", add_help=False)
+ parser.add_argument("--help", "-h", action="help", help="Output this help message and exit.")
+ parser.add_argument('path', metavar='PATH', nargs='?', default='/', help="Limit output to those within the PATH hierarchy.")
+ args = parser.parse_args()
+ main()
+
+# vim: sw=4 et
diff --git a/support/rrsync b/support/rrsync
index 94c85f5..4b4b87c 100755
--- a/support/rrsync
+++ b/support/rrsync
@@ -258,6 +258,9 @@ def main():
if args.munge:
rsync_opts.append('--munge-links')
+
+ if args.no_overwrite:
+ rsync_opts.append('--ignore-existing')
if not rsync_args:
rsync_args = [ '.' ]
@@ -364,6 +367,7 @@ if __name__ == '__main__':
arg_parser.add_argument('-munge', action='store_true', help="Enable rsync's --munge-links on the server side.")
arg_parser.add_argument('-no-del', action='store_true', help="Disable rsync's --delete* and --remove* options.")
arg_parser.add_argument('-no-lock', action='store_true', help="Avoid the single-run (per-user) lock check.")
+ arg_parser.add_argument('-no-overwrite', action='store_true', help="Prevent overwriting existing files by enforcing --ignore-existing")
arg_parser.add_argument('-help', '-h', action='help', help="Output this help message and exit.")
arg_parser.add_argument('dir', metavar='DIR', help="The restricted directory to use.")
args = arg_parser.parse_args()
diff --git a/support/rrsync.1.md b/support/rrsync.1.md
index 98f2cab..2489290 100644
--- a/support/rrsync.1.md
+++ b/support/rrsync.1.md
@@ -5,7 +5,7 @@ rrsync - a script to setup restricted rsync users via ssh logins
## SYNOPSIS
```
-rrsync [-ro|-rw] [-munge] [-no-del] [-no-lock] DIR
+rrsync [-ro|-rw] [-munge] [-no-del] [-no-lock] [-no-overwrite] DIR
```
The single non-option argument specifies the restricted _DIR_ to use. It can be
@@ -85,6 +85,11 @@ The remainder of this manpage is dedicated to using the rrsync script.
Avoid the single-run (per-user) lock check. Useful with [`-munge`](#opt).
+0. `-no-overwrite`
+
+ Enforce `--ignore-existing` on the server. Prevents overwriting existing
+ files when the server is the receiver.
+
0. `-help`, `-h`
Output this help message and exit.