CI / lint (pull_request) Successful in 26s
CI / sanitizers (address) (pull_request) Failing after 41s
CI / sanitizers (undefined) (pull_request) Successful in 40s
CI / fuzz-build (pull_request) Successful in 18s
CI / coverage (pull_request) Successful in 35s
CI / valgrind (pull_request) Failing after 37s
CI / build-and-test (pull_request) Failing after 2m35s
RSYNC_COMPAT Phase-2 row M: path-list construction and destination directory creation while preserving traversal safety. - -R/--relative with --files-from: transmit each listed entry under its bare relative destination path (no source-root mirror). Files keep an absolute local read path plus a separate wire/dest path (File.send_path); manifest, incremental quick-check and change output follow the wire path, so --delete and --remove-source-files stay consistent. -R without --files-from is unchanged (full mirror). - --no-implied-dirs: client-only, only meaningful with -R + --files-from. A listed file whose parent dir is not itself (or via an ancestor) explicitly listed cannot be placed; the run fails up front with a clear error. No effect otherwise. - --dirs/-d + --old-dirs/--old-d aliases: -d <dir> transmits the source root as an explicit empty directory entry (STATUS_MKDIR frame); with --files-from listed dirs are created empty and listed files transferred, never descending. Works single-threaded, -m (sequential scanner in the -m scan thread) and chunk-serialization (per-file type marker). Directory entries appear in the delete manifest. - --mkpath: new wire bool; server creates the destination root (and missing leading components under its authorized root) at connection start. A missing destination root is now rejected by default. - Protocol bumped to 2.7.0 (mkpath wire field + STATUS_MKDIR + chunk type marker). All receive paths funnel through file_save_to_disk_full which creates directories via the secure confined mkdir engine; dir entries are excluded from --remove-source-files outcome acknowledgements on both ends. - Unit coverage: CLI parse (relative/dirs aliases/mkpath/no-implied-dirs), config round-trip (relative + mkpath), scanner --dirs non-recursion and -R send_path (sequential + parallel), receiver dir-entry save. - Integration coverage: TestRelativeFilesFrom, TestNoImpliedDirs, TestDirs, TestMkpath (single and -m). - RSYNC_COMPAT: 4 rows move to Implemented (Summary 67/3/5/1/71 = 147).
79 lines
3.5 KiB
C
79 lines
3.5 KiB
C
#ifndef CHANGE_LIST_H
|
|
#define CHANGE_LIST_H
|
|
|
|
#include "config.h"
|
|
#include "file_types.h"
|
|
#include <stdbool.h>
|
|
#include <sys/stat.h>
|
|
#include <time.h>
|
|
|
|
/*
|
|
* Shared per-file change-event / output model (rsync --itemize-changes,
|
|
* --out-format, --log-file-format, and --list-only all render from here).
|
|
*
|
|
* FastSync is a push-style tool: the client sends files from the source tree
|
|
* to a server that writes them under the destination root. Events are
|
|
* emitted by whichever code path decides a file's fate (the single-threaded
|
|
* send loop and the `-m` sender thread both call the same per-file sender), so
|
|
* all change events are emitted by exactly one thread and itemize/out-format
|
|
* lines never interleave with each other. They may still interleave with
|
|
* legacy log messages (log.c) that share the same stdout/log-file stream.
|
|
*/
|
|
|
|
typedef enum {
|
|
CHANGE_SENT, /* file data (full or delta) was transmitted */
|
|
CHANGE_UP_TO_DATE, /* receiver already had an identical file; skipped */
|
|
} ChangeDecision;
|
|
|
|
typedef struct {
|
|
const char* path; /* full source path */
|
|
ChangeDecision decision;
|
|
bool is_directory;
|
|
unsigned long long size; /* source file length in bytes */
|
|
/* The number of bytes reported for a sent file. FastSync has no wire-byte
|
|
* counter, so this is always the source length (== size / %l); actual
|
|
* post-compression/delta bytes on the wire are not counted. */
|
|
unsigned long long bytes_sent;
|
|
time_t mtime_sec; /* 0 when unknown */
|
|
} ChangeEvent;
|
|
|
|
/* True when any output mode is active and per-file events matter. */
|
|
bool change_list_enabled(const Config* config);
|
|
|
|
/* Render the rsync-style itemize line for a transferred file:
|
|
* `>f+++++++++ <path>`
|
|
* The 11-char code is `>f` (regular file transferred to the remote host)
|
|
* followed by c/s/t/p/o/g/u/a/x markers that are all `+` (value will be set
|
|
* / differs) because FastSync does not separately compare checksums, size,
|
|
* mtime, perms, owner, group, uid, acl, or xattr on the receiving side, so a
|
|
* sent file is reported as fully updated. Up-to-date files print no line
|
|
* (rsync single `-i` only shows changes). Caller frees the result. */
|
|
char* change_render_itemize(const ChangeEvent* event);
|
|
|
|
/* Expand an --out-format/--log-file-format template. Tokens:
|
|
* %f full source path %b "bytes sent" == the source length (%l);
|
|
* %n leaf (base) name actual post-compression/delta wire bytes
|
|
* %l file length in bytes are not counted
|
|
* %M mtime in whole seconds %% a literal percent sign
|
|
* Unknown %X sequences are preserved verbatim. Caller frees the result. */
|
|
char* change_render_format(const char* format, const ChangeEvent* event);
|
|
|
|
/* Render one --list-only long-listing entry:
|
|
* `-rw-r--r-- 12 2026/09/06 10:00:00 <path>`
|
|
* (ls -l style columns; mtime in the local time zone). Caller frees it. */
|
|
char* change_render_list_line(mode_t mode, unsigned long long size, time_t mtime, const char* path);
|
|
|
|
/* Emit an event to every active destination:
|
|
* stdout: --itemize-changes line, or the --out-format expansion when set;
|
|
* log file: the --log-file-format expansion (requires --log-file).
|
|
* CHANGE_UP_TO_DATE events produce no output. */
|
|
void change_emit(const Config* config, const ChangeEvent* event);
|
|
|
|
/* Build and emit a CHANGE_SENT event for a file the client just sent. */
|
|
void change_emit_file_sent(const Config* config, const File* file);
|
|
|
|
/* Build and emit a CHANGE_SENT event for an explicit directory entry (-d). */
|
|
void change_emit_dir_sent(const Config* config, const File* file);
|
|
|
|
#endif
|