71 lines
3.5 KiB
C
71 lines
3.5 KiB
C
#ifndef METADATA_H
|
|
#define METADATA_H
|
|
|
|
#include "file.h"
|
|
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <sys/stat.h>
|
|
#include <time.h>
|
|
|
|
/*
|
|
* Wire format (introduced in protocol version 2.0.0):
|
|
* int32_t present
|
|
* int32_t mode (was mode_t, platform-dependent)
|
|
* int32_t uid (was uid_t, platform-dependent)
|
|
* int32_t gid (was gid_t, platform-dependent)
|
|
* int64_t mtime_sec (was time_t, platform-dependent)
|
|
* int64_t mtime_nsec (was long, platform-dependent)
|
|
* int32_t atime_valid (-U/--atimes; protocol 2.12.0)
|
|
* int64_t atime_sec
|
|
* int64_t atime_nsec
|
|
* int32_t crtime_valid (-N/--crtimes; protocol 2.12.0)
|
|
* int64_t crtime_sec
|
|
* int64_t crtime_nsec
|
|
*
|
|
* Prior to 2.0.0 the wire format used the raw platform-dependent types,
|
|
* which broke compatiblity across different systems. All fields are now
|
|
* serialized as fixed-width integers.
|
|
*/
|
|
|
|
/* Size of metadata fields on wire, excluding the int32_t `present` field that
|
|
* is always sent first. The total wire size for present metadata is
|
|
* sizeof(int32_t) + FILE_METADATA_WIRE_SIZE (68 bytes on most platforms).
|
|
*
|
|
* metadata_send()/metadata_receive() (protocol 2.20.0) frame the metadata as a
|
|
* single packed record: one int32 present flag (0 = absent) followed, when
|
|
* present, by exactly FILE_METADATA_WIRE_SIZE bytes of field data. This is the
|
|
* same present+fields byte layout metadata_to_buf()/metadata_from_buf() use, so
|
|
* the wire metadata is now one frame instead of one frame per field. */
|
|
#define FILE_METADATA_WIRE_SIZE (sizeof(int32_t) * 5 + sizeof(int64_t) * 6)
|
|
|
|
void metadata_to_buf(char** buf, const FileMetadata* m);
|
|
/* Decode one packed metadata record (an int32 present flag followed, when
|
|
* present, by FILE_METADATA_WIRE_SIZE field bytes) from `buf`, which has `len`
|
|
* readable bytes. Every read is bounds-checked against `len`, so the function
|
|
* can never over-read the caller's buffer: a too-short record, an absent
|
|
* (present == 0) record and a malformed record all return NULL. A successful
|
|
* decode returns a heap-allocated FileMetadata owned by the caller. */
|
|
FileMetadata* metadata_from_buf(const uint8_t* buf, size_t len);
|
|
bool metadata_send(int file_descriptor, const FileMetadata* m);
|
|
FileMetadata* metadata_receive(int file_descriptor, int* ok);
|
|
void file_restore_metadata(const char* path, const FileMetadata* metadata,
|
|
bool preserve_executability);
|
|
bool file_restore_metadata_fd(int fd, const FileMetadata* metadata, bool preserve_executability);
|
|
/* P7 Wave D: apply a SYMLINK's own metadata using no-follow primitives only
|
|
* (utimensat/lchown/fchmodat with AT_SYMLINK_NOFOLLOW), confined fd-relative
|
|
* under the authorized root. `omit_link_times` (-J/--omit-link-times)
|
|
* suppresses the timestamps; the link's mode/ownership are still attempted
|
|
* (ownership stays gated by the identity policy and by default is not applied).
|
|
* A null metadata or an unfollowable parent is a harmless no-op. Returns false
|
|
* only when a REQUIRED --copy-as ownership application failed, so the caller can
|
|
* report the entry as failed instead of claiming a wrong-owner success. */
|
|
bool file_restore_symlink_metadata(const char* path, const FileMetadata* metadata,
|
|
bool omit_link_times);
|
|
|
|
/* Compare timestamps using rsync's whole-second modification window. */
|
|
bool metadata_mtime_matches(time_t left_sec, long left_nsec, time_t right_sec, long right_nsec,
|
|
int modify_window);
|
|
|
|
#endif
|