summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/metaentry.c47
-rw-r--r--src/metastore.h1
-rw-r--r--src/utils.c49
-rw-r--r--src/utils.h9
4 files changed, 106 insertions, 0 deletions
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);