From b3c08670f56d7c5ee85dffa1a2faa5e03d2df5a1 Mon Sep 17 00:00:00 2001 From: Adam Spragg Date: Tue, 17 May 2022 12:47:32 +0100 Subject: Add ability to write Format 1 metadata files --- src/metaentry.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ src/metastore.h | 1 + src/utils.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ src/utils.h | 9 +++++++++ 4 files changed, 106 insertions(+) diff --git a/src/metaentry.c b/src/metaentry.c index 1eeed5b..6e27f11 100644 --- a/src/metaentry.c +++ b/src/metaentry.c @@ -432,6 +432,52 @@ mentries_tofile_v0(const struct metahash *mhash, FILE * to) } } +/* Stores metaentries to a Format 1 file */ +static void +mentries_tofile_v1(const struct metahash *mhash, FILE * to) +{ + const struct metaentry *mentry; + int key; + struct tm tm; + char tmbuf[20]; + unsigned i; + + fputc('\n', to); + + for (key = 0; key < HASH_INDEXES; key++) { + for (mentry = mhash->bucket[key]; mentry; mentry = mentry->next) { + write_string_url(mentry->path, to); + + fputc('\t', to); + write_string_url(mentry->owner, to); + + fputc('\t', to); + write_string_url(mentry->group, to); + + fputc('\t', to); + fprintf(to, "%.6o", mentry->mode); + + fputc('\t', to); + gmtime_r(&mentry->mtime, &tm); + strftime(tmbuf, sizeof(tmbuf), "%Y-%m-%dT%H:%M:%S", &tm); + fputs(tmbuf, to); + + fputc('.', to); + fprintf(to, "%.9ldZ", mentry->mtimensec); + + for (i = 0; i < mentry->xattrs; i++) { + fputc('\t', to); + write_string_url(mentry->xattr_names[i], to); + fputc('\t', to); + write_binary_url(mentry->xattr_values[i], + mentry->xattr_lvalues[i], to); + } + + fputc('\n', to); + } + } +} + /* Stores metaentries to a file */ void mentries_tofile(const struct metahash *mhash, const char *path, int format) @@ -442,6 +488,7 @@ mentries_tofile(const struct metahash *mhash, const char *path, int format) switch (format) { case 0: formatstr = VERSION_0; tofile = mentries_tofile_v0; break; + case 1: formatstr = VERSION_1; tofile = mentries_tofile_v1; break; default: msg(MSG_CRITICAL, "Unknown format %d\n", format); exit(EXIT_FAILURE); diff --git a/src/metastore.h b/src/metastore.h index 612b55b..bd79416 100644 --- a/src/metastore.h +++ b/src/metastore.h @@ -25,6 +25,7 @@ #define SIGNATURE "MeTaSt00r3" #define SIGNATURELEN 10 #define VERSION_0 "\0\0\0\0\0\0\0\0" +#define VERSION_1 "00000001" #define VERSIONLEN 8 /* Default filename */ diff --git a/src/utils.c b/src/utils.c index 87292e3..5cdef6b 100644 --- a/src/utils.c +++ b/src/utils.c @@ -143,6 +143,55 @@ write_string(const char *string, FILE *to) xfwrite(string, strlen(string) + 1, to); } +/* Check if a character being put into a URL must be encoded */ +static int +char_url_mustencode(int c) +{ + return (c >= 0 && c <= 0x20) + || c == '%' + || c == '\x7F'; +} + +/* Writes a single character to a file, URL-encoding if necessary */ +void +write_char_url(int c, FILE *to) +{ + int ok; + + if (c < -127 || c > 255) + ok = 0; + else if (char_url_mustencode(c)) + ok = fprintf(to, "%%%.2X", (unsigned char) c) == 3; + else + ok = fputc(c, to) != EOF; + + if (!ok) { + msg(MSG_CRITICAL, "Failed to write to file: %s\n", + strerror(errno)); + exit(EXIT_FAILURE); + } +} + +/* Writes binary data to a file, URL-encoding any bytes if necessary */ +void +write_binary_url(const char *string, size_t len, FILE *to) +{ + size_t i; + + for (i = 0; i < len; ++i) + write_char_url(string[i], to); +} + +/* Writes a normal C string to a file, URL-encoding any chars if necessary */ +void +write_string_url(const char *string, FILE *to) +{ + int c; + + while ((c = *string++) != '\0') + write_char_url(c, to); +} + /* Reads an int from a file, using len bytes, in little-endian order */ uint64_t read_int(const char **from, size_t len, const char *max) diff --git a/src/utils.h b/src/utils.h index 35209d1..ef21b22 100644 --- a/src/utils.h +++ b/src/utils.h @@ -68,6 +68,15 @@ void write_binary_string(const char *string, size_t len, FILE *to); /* Writes a normal C string to a file */ void write_string(const char *string, FILE *to); +/* Writes a single character to a file, URL-encoding if necessary */ +void write_char_url(int c, FILE *to); + +/* Writes binary data to a file, URL-encoding any bytes if necessary */ +void write_binary_url(const char *string, size_t len, FILE *to); + +/* Writes a normal C string to a file, URL-encoding any chars if necessary */ +void write_string_url(const char *string, FILE *to); + /* Reads an int from a file, using len bytes, in little-endian order */ uint64_t read_int(const char **from, size_t len, const char *max); -- cgit v1.2.1