diff options
author | Wayne Davison <wayne@opencoder.net> | 2021-12-27 17:44:32 -0800 |
---|---|---|
committer | Wayne Davison <wayne@opencoder.net> | 2021-12-27 17:57:53 -0800 |
commit | e07f8fb86329d9370edb47d5c057def16108892e (patch) | |
tree | 618e36972fe531987548dd7b6d9f26bb431fc8f9 /support/rrsync | |
parent | 8cf9dbb742ce4c89c649cd4f4a14ed9bd254a075 (diff) | |
download | rsync-e07f8fb86329d9370edb47d5c057def16108892e.tar.gz |
Add a default single-access lock.
Diffstat (limited to 'support/rrsync')
-rwxr-xr-x | support/rrsync | 35 |
1 files changed, 30 insertions, 5 deletions
diff --git a/support/rrsync b/support/rrsync index 5b43a819..469288b9 100755 --- a/support/rrsync +++ b/support/rrsync @@ -24,8 +24,12 @@ LOGFILE = 'rrsync.log' # NOTE: the file must exist for a line to be appended! ### START of options data produced by the cull_options script. ### # To disable a short-named option, add its letter to this string: -short_disabled = 'Ls' +short_disabled = 's' +# These are also disabled when the restricted dir is not "/": +short_disabled_subdir = 'KLk' + +# These are all possible short options that we will accept (when not disabled above): short_no_arg = 'ACDEHIJKLNORSUWXbcdgklmnopqrstuvxyz' # DO NOT REMOVE ANY short_with_num = '@B' # DO NOT REMOVE ANY @@ -125,7 +129,7 @@ long_opts = { ### END of options data produced by the cull_options script. ### -import os, sys, re, argparse, glob, socket, time +import os, sys, re, argparse, glob, socket, time, subprocess from argparse import RawTextHelpFormatter try: @@ -174,6 +178,10 @@ def main(): if args.ro: long_opts['log-file'] = -1 + if args.dir != '/': + global short_disabled + short_disabled += short_disabled_subdir + short_no_arg_re = short_no_arg short_with_num_re = short_with_num if short_disabled: @@ -268,8 +276,12 @@ def main(): log_fh.close() # NOTE: This assumes that the rsync protocol will not be maliciously hijacked. - os.execlp(RSYNC, *cmd) - die("execlp(", RSYNC, *cmd, ') failed') + if args.no_lock: + os.execlp(RSYNC, *cmd) + die("execlp(", RSYNC, *cmd, ') failed') + child = subprocess.run(cmd) + if child.returncode != 0: + sys.exit(child.returncode) def validated_arg(opt, arg, typ=3, wild=False): @@ -319,6 +331,16 @@ def validated_arg(opt, arg, typ=3, wild=False): return ret if wild else ret[0] +def lock_or_die(dirname): + import fcntl + global lock_handle + lock_handle = os.open(dirname, os.O_RDONLY) + try: + fcntl.flock(lock_handle, fcntl.LOCK_EX | fcntl.LOCK_NB) + except: + die('Another instance of rrsync is already accessing this directory.') + + def die(*msg): print(sys.argv[0], 'error:', *msg, file=sys.stderr) if sys.stdin.isatty(): @@ -336,9 +358,10 @@ if __name__ == '__main__': our_desc = """Use "man rrsync" to learn how to restrict ssh users to using a restricted rsync command.""" arg_parser = OurArgParser(description=our_desc, add_help=False) only_group = arg_parser.add_mutually_exclusive_group() - only_group.add_argument('-ro', action='store_true', help="Allow only reading from the DIR. Implies -no-del.") + only_group.add_argument('-ro', action='store_true', help="Allow only reading from the DIR. Implies -no-del and -no-lock.") only_group.add_argument('-wo', action='store_true', help="Allow only writing to the DIR.") 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('-munge', action='store_true', help="Enable rsync's --munge-links on the server side.") 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.") @@ -348,6 +371,8 @@ if __name__ == '__main__': args.dir_slash_len = len(args.dir) if args.ro: args.no_del = True + elif not args.no_lock: + lock_or_die(args.dir) main() # vim: sw=4 et |