#include "usage.h" #include #include #include void print_usage(void) { printf("Usage:\n"); printf(" fastsync [options] \n"); printf(" fastsync [options] --source-dir --dest-dir \n"); printf("\n"); printf("Destination formats:\n"); printf(" user@host:/path SSH transport (rsync-style)\n"); printf(" host:/path SSH transport (current user)\n"); printf(" /local/path TCP transport (requires server on localhost:8080)\n"); printf("\n"); printf("Options:\n"); printf(" -c [level] Enable compression (level 1-22, default 5)\n"); printf(" -z [level] Alias for -c\n"); printf(" -a, --archive Archive mode (-c -m -M)\n"); printf(" -n, --dry-run Show what would be transferred\n"); printf(" --remove-source-files Remove regular source files after successful transfer\n"); printf(" -p SSH port (default: 22)\n"); printf(" -e, --rsh Remote shell to launch on the client for the SSH\n"); printf(" transport (default: ssh). The command may include\n"); printf(" arguments, e.g. -e \"ssh -p 2222\"\n"); printf(" --rsync-path Alias for --fastsync-server-path (path to the\n"); printf(" fastsync server binary on the remote side)\n"); printf(" --blocking-io Leave the SSH transport socket without read/write\n"); printf(" timeouts so it blocks naturally\n"); printf(" --outbuf=MODE stdout/stderr buffering: N (none/unbuffered),\n"); printf(" L (line-buffered), or B (block-buffered, default)\n"); printf(" --progress Show transfer progress\n"); printf(" -P Partial mode with progress (retention incomplete)\n"); printf(" -8, --8-bit-output Leave high-bit characters unescaped in output\n"); printf(" --delete Delete files on receiver not in source\n"); printf(" (default timing: delete only after the whole\n"); printf(" transfer has succeeded)\n"); printf(" --delete-before Delete extras before the transfer starts\n"); printf(" (implies --delete)\n"); printf(" --delete-during Delete extras once the keep-set manifest is known,\n"); printf(" before the data is applied (implies --delete)\n"); printf(" --del Alias for --delete-during\n"); printf(" --delete-delay Delete extras only after a successful transfer\n"); printf(" (implies --delete)\n"); printf(" --delete-after Delete only after the whole transfer succeeded\n"); printf(" (the default --delete timing; implies --delete)\n"); printf(" --delete-excluded Also delete destination files that were excluded on\n"); printf(" the source (default protects them, matching rsync)\n"); printf(" --max-delete=NUM Never delete more than NUM destination entries per run;\n"); printf(" if the extras would exceed NUM, nothing is deleted and\n"); printf(" the run fails with a clear error (implies --delete only\n"); printf(" when used with it)\n"); printf(" --ignore-errors Continue (and still delete) when a source directory is\n"); printf(" unreadable during the scan, instead of aborting with no\n"); printf(" deletion\n"); printf(" --force A file may replace a destination directory by removing\n"); printf(" that (non-empty) directory first\n"); printf(" --ignore-missing-args A --files-from entry that does not exist under the\n"); printf(" source is silently skipped instead of failing the run\n"); printf(" --delete-missing-args Implies --ignore-missing-args; also deletes each missing\n"); printf(" entry's destination mirror receiver-side. Independent of\n"); printf(" --delete (it does not imply --delete; a non-empty directory\n"); printf(" mirror is removed only with --force or --delete)\n"); printf(" --prune-empty-dirs Do not transfer empty directory entries (--dirs mode);\n"); printf(" recursive transfers never send empty dirs. rsync's -m\n"); printf(" short form stays FastSync multithreading\n"); printf(" Note: each timing flag implies --delete. Combining a timing flag with\n"); printf(" --no-delete (in either order) is rejected as a config error.\n"); printf(" --ignore-existing Skip files that already exist on receiver\n"); printf(" --delay-updates Put updated files into place only at the end of transfer\n"); printf(" --dirs, -d, --old-dirs, --old-d Transfer the named directory entries without\n"); printf(" recursing into their contents (-d mirrors the source\n"); printf(" directory empty; with --files-from listed dirs are created\n"); printf(" empty and listed files are transferred)\n"); printf(" -R, --relative With --files-from, preserve each listed entry's relative path\n"); printf(" below the destination root instead of mirroring the full\n"); printf(" source path (no effect without --files-from)\n"); printf(" --no-implied-dirs With -R --files-from, refuse to place a listed file whose\n"); printf(" parent directory is not itself listed\n"); printf(" --mkpath Create the destination root directory on the server when it\n"); printf(" does not exist yet\n"); printf(" --exclude Exclude files matching pattern\n"); printf(" --include Only include files matching pattern\n"); printf(" --exclude-from Read exclude patterns from file\n"); printf(" --include-from Read include patterns from file\n"); printf(" --files-from Read the source file list from FILE (paths relative to the " "source root)\n"); printf(" -0, --from0 Entries in --files-from are NUL-delimited\n"); printf(" --filter=RULE rsync-style filter rule (+/- include/exclude; repeatable; the\n"); printf(" rsync -f short form conflicts with FastSync sendfile -f)\n"); printf(" -C, --cvs-exclude Auto-ignore common CVS/SCM files (.git/, .svn/, *.o, *~, ...)\n"); printf(" -F Apply per-directory .rsync-filter files during the scan\n"); printf(" --max-size Skip files larger than n bytes\n"); printf(" --min-size Skip files smaller than n bytes\n"); printf(" --max-alloc Maximum single allocation (default: 1G)\n"); printf(" --incremental Skip files unchanged since last transfer\n"); printf(" --size-only Skip incremental files matching in size, ignoring mtime\n"); printf(" -I, --ignore-times Transfer files even when size and mtime match\n"); printf(" -@, --modify-window Modification time tolerance\n"); printf(" -u, --update Skip files newer than the source on receiver\n"); printf(" --existing Skip files not already present at destination\n"); printf(" --compare-dest Treat DIR (relative to destination root) as an extra\n"); printf(" comparison basis: unchanged files are not transferred\n"); printf(" (requires --incremental, which is implied)\n"); printf(" --copy-dest Like --compare-dest, but copies the unchanged file from DIR\n"); printf(" into the destination instead of transferring its data\n"); printf(" --link-dest Like --copy-dest, but hard-links the unchanged file from DIR\n"); printf(" into the destination (repeatable; earlier DIRs win)\n"); printf(" --checksum-choice, --cc Whole-file checksum algorithm for --incremental/\n"); printf(" --checksum compares (xxh64/xxhash or md5; default xxh64 with\n"); printf(" seed 0). The seed comes from --checksum-seed\n"); printf(" --checksum-seed Seed for the whole-file xxHash64 digest (and the delta\n"); printf(" block strong hash, low 32 bits); md5 ignores the seed. The\n"); printf(" digest algorithm and seed must match on sender and receiver\n"); printf(" --delta Delta transfer for changed files (requires --incremental)\n"); printf(" -W, --whole-file Transfer changed files without delta processing\n"); printf(" -y, --fuzzy Use a similar-named file already in the destination\n"); printf(" directory as the delta basis when the destination has no\n"); printf(" usable file at the exact path (saves bandwidth; implies\n"); printf(" --incremental and --delta; inert with --whole-file,\n"); printf(" --no-delta, or --no-incremental)\n"); printf(" --no-fuzzy Disable --fuzzy\n"); printf(" --delta-block Delta block size in bytes (default: %d)\n", DELTA_BLOCK_SIZE_DEFAULT); printf(" --delta-max Max file size for delta transfer (default: %llu)\n", DELTA_MAX_FILE_SIZE); printf(" -m Enable multithreading\n"); printf(" -s Enable chunk serialization\n"); printf(" --secluded-args Accept rsync compatibility option (no effect)\n"); printf(" -f Enable sendfile (TCP only, not with -c or -s)\n"); printf(" --compress-choice Compression algorithm (default: zstd)\n"); printf(" --zc Alias for --compress-choice\n"); printf(" -v, --verbose Enable debug logging\n"); printf(" -q, --quiet Suppress non-error output\n"); printf(" --debug=FLAGS Fine-grained debug logging (use --debug=help for flags)\n"); printf(" --info=FLAGS Fine-grained info: copy,misc,skip,stats,all,none\n"); printf(" none suppresses info even with --verbose\n"); printf(" -M, --preserve Preserve file metadata\n"); printf(" -E, --executability Preserve executable permission bits\n"); printf(" -X, --xattrs Preserve user extended attributes (user.* only;\n"); printf(" privileged security.*/trusted.* namespaces are\n"); printf(" never captured or applied)\n"); printf(" -A, --acls Preserve POSIX ACLs (the system.posix_acl_* xattrs;\n"); printf(" setting an ACL the receiver is not permitted to\n"); printf(" set is warned and skipped, never fatal)\n"); printf(" --fake-super Store the source uid/gid/mode/mtime in a reserved\n"); printf(" user.fastsync.stat xattr on each written file instead\n"); printf(" of applying ownership (for a later privileged restore);\n"); printf(" partial: full rsync fake-super replay is out of scope\n"); printf(" --chmod Modify transferred permissions (rsync syntax)\n"); printf(" --numeric-ids Do not map uid/gid by name: use the source numeric\n"); printf(" ids directly when applying ownership\n"); printf(" --usermap=MAP Map usernames when applying ownership: comma-separated\n"); printf(" FROM:TO rules, first match wins. FROM/TO are names\n"); printf(" (resolved on the source machine), * (match any /\n"); printf(" current user), or @N numeric ids. e.g. *:nobody\n"); printf(" --groupmap=MAP Map group names when applying ownership (same syntax)\n"); printf(" --chown=USER:GROUP Override the ownership of transferred files. Forms:\n"); printf(" USER:GROUP, USER (owner only), :GROUP (group only); a\n"); printf(" value of * means the current/root user as appropriate.\n"); printf(" Names resolve on the source machine; @N for numerics.\n"); printf(" Note: -M is already FastSync's preserve flag; these use\n"); printf(" long forms only.\n"); printf(" --chunk-size Chunk size in bytes (default: %d)\n", DEFAULT_CHUNK_SIZE); printf(" --source-dir Source directory\n"); printf(" --dest-dir Destination directory\n"); printf(" --save-to-disk Write received files to disk\n"); printf(" --server-host Server IP address (default: 127.0.0.1)\n"); printf(" --server-port Server port (default: 8080)\n"); printf(" --bwlimit Bandwidth limit in kilobytes per second\n"); printf(" --tls Enable TLS encryption\n"); printf(" --cert TLS certificate file (PEM)\n"); printf(" --key TLS private key file (PEM)\n"); printf(" --ca TLS CA certificate file (PEM)\n"); printf(" --timeout I/O timeout in seconds (default: 30)\n"); printf(" -T Alias for --timeout\n"); printf(" --contimeout Connection timeout in seconds (default: 10)\n"); printf(" --backup Backup existing files before overwriting\n"); printf(" --backup-dir Directory for backups (requires --backup)\n"); printf(" --suffix Backup suffix (default: ~)\n"); printf(" --stats Print transfer statistics at end\n"); printf(" -i, --itemize-changes Print an rsync-style per-file change line\n"); printf(" --out-format=FORMAT Output format for changed files (%%f %%n %%l %%b %%M %%%%)\n"); printf(" --list-only List source files instead of transferring\n"); printf(" --log-file-format=FORMAT Per-file log line format (needs --log-file)\n"); printf(" -h, --human-readable Print byte sizes in human-readable form\n"); printf(" --max-depth Maximum directory depth (0=unlimited)\n"); printf(" -x, --one-file-system Do not cross filesystem boundaries\n"); printf(" --log-file Write log messages to file\n"); printf(" --stderr=MODE Route logging to stderr: errors or all\n"); printf(" --partial Keep partial files on interrupted transfer\n"); printf(" --partial-dir Directory for partial files\n"); printf(" --temp-dir Scratch dir for temp files before atomic install\n"); printf(" --fastsync-server-path \n"); printf(" Path to fastsync-server on remote (default: fastsync-server)\n"); printf( " --old-args Disable safe SSH command argument quoting (legacy compatibility)\n"); printf(" -l, --links Copy symlinks as symlinks\n"); printf(" --copy-links Transform symlinks into referent files\n"); printf(" --safe-links Skip symlinks that point outside transfer tree\n"); printf(" --copy-unsafe-links Only transform unsafe symlinks into referent files\n"); printf(" -k, --copy-dirlinks Transform symlinks to directories into real dirs\n"); printf(" -K, --keep-dirlinks Keep an existing symlink-to-dir as that dir\n"); printf(" --munge-links Munge symlink targets on the wire (sender)\n"); printf(" -H, --hard-links Preserve hard-link relationships across the transfer\n"); printf(" -S, --sparse Handle sparse files efficiently\n"); printf( " -D Preserve device and special files (implies --devices --specials)\n"); printf( " --devices Recreate device nodes on the destination (privileged; skipped when\n"); printf(" the receiver lacks CAP_MKNOD)\n"); printf(" --specials Recreate special files (FIFOs) on the destination (sockets " "skipped)\n"); printf(" --copy-devices Copy a source device's content as a regular file instead\n"); printf(" --write-devices Write received data into an existing destination device node\n"); printf(" --inplace Update files in-place (no temp+rename)\n"); printf( " --preallocate Allocate destination file space up front (fail-fast on full disk)\n"); printf(" --append Resume a shorter destination by appending only its tail\n"); printf(" (prefix is not verified; requires --incremental)\n"); printf(" --append-verify Like --append, but verifies the retained prefix checksum\n"); printf(" before appending (falls back to a full transfer on mismatch)\n"); printf(" --fsync Fsync every written file before publication\n"); printf(" --compress-level Compression level (default: 5)\n"); printf(" --zl Alias for --compress-level\n"); printf(" --skip-compress=LIST Skip compression for comma-separated suffixes\n"); printf(" --compress-threads Compression worker threads (requires zstd threaded support)\n"); printf(" --no-OPTION Disable a supported boolean option\n"); printf(" --help Show this help\n"); printf(" -V, --version Show version\n"); } void print_debug_usage(void) { printf("Supported debug flags: IO,PROTO,PACK,UTIL,ALL,NONE\n"); printf("Flags may be comma-separated, for example: --debug=io,proto\n"); printf("Other rsync debug flags are unsupported and rejected.\n"); }