133 lines
7.2 KiB
C
133 lines
7.2 KiB
C
#ifndef SCANNER_INTERNAL_H
|
|
#define SCANNER_INTERNAL_H
|
|
|
|
/* Internal declarations shared between the scanner translation units
|
|
* (scanner_filter.c, scanner.c, scanner_parallel.c). Nothing here is part of
|
|
* the public scanner façade (scanner.h); every symbol stays internal to the
|
|
* client module. */
|
|
|
|
#include "array_list.h"
|
|
#include "file.h"
|
|
#include "scanner.h"
|
|
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
#include <sys/stat.h>
|
|
|
|
typedef struct {
|
|
char* path;
|
|
int depth;
|
|
FilterNode* context; /* inherited per-directory filter context */
|
|
} DirEntry;
|
|
|
|
/* How rsync's readlink_stat()/generator resolves one source symlink. */
|
|
typedef enum {
|
|
LINK_ACTION_SKIP, /* not transferred (no link option) */
|
|
LINK_ACTION_SKIP_PROTECTED, /* ignored as unsafe by --safe-links; rsync keeps
|
|
it in the transfer, so its destination mirror
|
|
must be protected from --delete */
|
|
LINK_ACTION_DEREF, /* follow the referent (--copy-links, an unsafe
|
|
target under --copy-unsafe-links, or -k dir) */
|
|
LINK_ACTION_CARRY, /* transmit the link itself (-l) */
|
|
} LinkAction;
|
|
|
|
typedef struct {
|
|
char* path;
|
|
struct stat stats;
|
|
bool is_directory;
|
|
/* True when the entry should be carried through as a SYMLINK (is_symlink)
|
|
rather than a dereferenced file/directory. When true, `link_target` holds
|
|
the owned target string to transmit (sender-munged under --munge-links);
|
|
ownership transfers to the File built from this entry. */
|
|
bool is_symlink;
|
|
char* link_target;
|
|
/* True when the entry was pruned by a user selection rule (--filter/-C/per-dir
|
|
rules or the --exclude/--include layer) rather than skipped for another
|
|
reason (unreadable, symlink policy, not applicable). */
|
|
bool excluded;
|
|
/* True when the entry was skipped specifically by --max-size/--min-size.
|
|
Size pruning protects the destination mirror even under --delete-excluded,
|
|
so it is recorded into a separate sink from `excluded`. */
|
|
bool size_excluded;
|
|
/* True when a symlink selected for dereferencing (-L/--copy-links or an
|
|
unsafe target under --copy-unsafe-links) had no usable referent (a broken
|
|
link or a stat() failure). rsync still reports this as a partial transfer
|
|
(exit 23) even though the entry is skipped, so the scanner records it as a
|
|
non-fatal I/O error. */
|
|
bool referent_error;
|
|
} ScannerEntry;
|
|
|
|
typedef enum {
|
|
SCANNER_SPECIAL_REGULAR, /* ordinary file: transfer content */
|
|
SCANNER_SPECIAL_RECREATE, /* is_special node to recreate on the receiver */
|
|
SCANNER_SPECIAL_SKIP, /* non-regular entry not requested: skip */
|
|
} ScannerSpecial;
|
|
|
|
/* Result of scanner_build_file_entry(). The two failure variants preserve the
|
|
* sequential scanner's historical distinction between a failure before the
|
|
* File existed (which kept walking the directory) and one afterwards (which cut
|
|
* the chunk short); both mark the scan failed. */
|
|
typedef enum {
|
|
SCANNER_BUILD_OK, /* File built; caller owns it */
|
|
SCANNER_BUILD_SKIP, /* non-regular entry not preserved; no File */
|
|
SCANNER_BUILD_FAIL_CONTINUE, /* failed before the File existed */
|
|
SCANNER_BUILD_FAIL_BREAK, /* failed after the File existed */
|
|
} ScannerBuildStatus;
|
|
|
|
/* scanner_filter.c */
|
|
void filter_node_destroy(void* item);
|
|
FilterNode* filter_node_alloc(FilterNode* parent, FilterRuleList* own);
|
|
void dir_entry_destroy(void* item);
|
|
DirEntry* dir_entry_create(const char* path, int depth, FilterNode* context);
|
|
LinkAction scanner_link_action(const ScannerOptions* options, const char* path,
|
|
const char* link_rel, char* target, size_t target_size);
|
|
File* scanner_build_dir_file(const char* path, const struct stat* stats,
|
|
const ScannerOptions* options);
|
|
char* child_rel_path(const char* parent_rel, const char* name);
|
|
char* scanner_prefix_send_path(const char* prefix, const char* rel);
|
|
char* scanner_dest_rel_path(const ScannerOptions* options, const char* fs_path, const char* rel,
|
|
bool relative_mode);
|
|
bool entry_passes_selection(const FileListSet* file_list, const FilterRuleList* base,
|
|
const FilterNode* node, const char* rel, const char* leaf, bool is_dir,
|
|
bool per_dir_filters, bool exclude_filter_files, bool* protect_out);
|
|
void scanner_capture_xattrs(const DirectoryScanner* scanner, File* file);
|
|
void scanner_capture_xattrs_opts(const ScannerOptions* options, File* file);
|
|
bool scanner_assign_hardlink(HardLinkTable* table, File* file, const struct stat* stats);
|
|
ScannerSpecial scanner_prepare_special(bool preserve_devices, bool preserve_specials,
|
|
bool copy_devices, File* file, const struct stat* stats);
|
|
/* Build one non-directory transfer File from an inspected entry. `rel` is the
|
|
* entry's transfer-root-relative path (used for the -R wire path); `inspected`
|
|
* supplies the on-disk path, stats and (for a carried symlink) the target whose
|
|
* ownership transfers to the File. Populates data size, send_path, special-node
|
|
* state, hardlink group, metadata and xattrs. On SCANNER_BUILD_OK the caller
|
|
* owns *out_file; on SCANNER_BUILD_SKIP it is NULL and the entry is dropped; on
|
|
* either failure it is NULL and the caller must mark the scan failed. `*failed`
|
|
* additionally reports a non-fatal hardlink-table allocation failure, in which
|
|
* case a usable File is still returned. */
|
|
ScannerBuildStatus scanner_build_file_entry(const ScannerOptions* options, ScannerEntry* inspected,
|
|
const char* rel, File** out_file, bool* failed);
|
|
bool excluded_sink_append(ArrayList* list, mtx_t* mtx, const char* rel);
|
|
void scanner_note_nonreg(const ScannerOptions* options, const char* fs_path);
|
|
void scanner_note_mount(const ScannerOptions* options, const char* fs_path);
|
|
void scanner_note_filter(const ScannerOptions* options, const char* name);
|
|
void scanner_dir_count_count(const ScannerOptions* options);
|
|
void scanner_dir_count_uncount(const ScannerOptions* options);
|
|
void scanner_record_excluded(DirectoryScanner* scanner, const char* fs_path);
|
|
void scanner_record_size_skipped(DirectoryScanner* scanner, const char* fs_path);
|
|
bool scanner_record_synced_dir(const ScannerOptions* options, const char* fs_path, const char* rel,
|
|
bool relative_mode);
|
|
FilterRuleList* read_dir_filters(const ScannerOptions* options, const char* dir_path,
|
|
const char* rel, bool relative_mode, bool* any_exists, char* err,
|
|
size_t err_size);
|
|
int open_directory_filter_context(DirectoryScanner* scanner, const FilterNode* inherited);
|
|
int scanner_inspect_entry(const ScannerOptions* options, const char* containing_dir,
|
|
const char* link_rel, const char* name, ScannerEntry* entry);
|
|
|
|
/* scanner.c */
|
|
bool scanner_capture_dir_time(ArrayList* dir_entries, mtx_t* mutex, const char* root_path,
|
|
const char* fs_path, bool relative_mode, const char* relative_prefix,
|
|
bool preserve_atimes, bool preserve_crtimes, bool preserve_xattrs,
|
|
bool preserve_acls, bool no_implied_dirs,
|
|
const FileListSet* file_list);
|
|
|
|
#endif
|