From 7c7eabdfc213636fa1f5a7fe7e457b20a8d7defd Mon Sep 17 00:00:00 2001 From: Przemyslaw Pawelczyk Date: Tue, 8 Sep 2015 01:08:32 +0200 Subject: [PATCH] Add action to dump metadata in human-readable form: -d / --dump. metastore depends now on libbsd, because of strmode() function. This commit fixes issue #28. --- Makefile | 2 +- NEWS | 6 ++++++ metaentry.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ metaentry.h | 2 ++ metastore.1 | 9 +++++++++ metastore.c | 15 +++++++++++---- metastore.h | 1 + 7 files changed, 79 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 4ee6fb7..7eaa7c2 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ # CC = gcc CFLAGS += -g -Wall -pedantic -std=c99 -D_FILE_OFFSET_BITS=64 -O2 -LDFLAGS += +LDFLAGS += -lbsd INCLUDES = INSTALL = install -c INSTALL_PROGRAM = ${INSTALL} diff --git a/NEWS b/NEWS index 4dbd0f5..7cf7a77 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,10 @@ Latest stuff (planned release date: 2015-09-??) * Empty directories not present in metadata can be now removed when applying stored metadata if -E / --remove-empty-dirs option is used. + * Stored metadata (in .metadata file by default) and real metadata + (from filesystem) can be now dumped in human-readable form using new + action: -d / --dump. Please do not rely on its current format! + * Scripts in example/ directory do not require bash anymore and there is a new example for post checkout hook. @@ -14,6 +18,8 @@ Latest stuff (planned release date: 2015-09-??) As long as your libc provides sys/xattr.h (glibc does it since v2.3), everything should be fine. + * Dependency on libbsd has been added. It's used by dump action. + Old times (2007-2014) ------------------------------------------------------------------------ diff --git a/metaentry.c b/metaentry.c index 2064f29..f3ba692 100644 --- a/metaentry.c +++ b/metaentry.c @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include "metastore.h" #include "metaentry.h" @@ -626,3 +628,50 @@ mentries_compare(struct metahash *mhashreal, } } +/* Dumps given metadata */ +void +mentries_dump(struct metahash *mhash) +{ + const struct metaentry *mentry; + char mode[11 + 1] = ""; + char date[12 + 2 + 2 + 2*1 + 1 + 2 + 2 + 2 + 2*1 + 1] = ""; + char zone[5 + 1] = ""; + struct tm cal; + + for (int key = 0; key < HASH_INDEXES; key++) { + for (mentry = mhash->bucket[key]; mentry; mentry = mentry->next) { + strmode(mentry->mode, mode); + localtime_r(&mentry->mtime, &cal); + strftime(date, sizeof(date), "%F %T", &cal); + strftime(zone, sizeof(zone), "%z", &cal); + printf("%s\t%s\t%s\t%s.%09ld %s\t%s%s\n", + mode, + mentry->owner, mentry->group, + date, mentry->mtimensec, zone, + mentry->path, S_ISDIR(mentry->mode) ? "/" : ""); + for (int i = 0; i < mentry->xattrs; i++) { + printf("\t\t\t\t%s%s\t%s=", + mentry->path, S_ISDIR(mentry->mode) ? "/" : "", + mentry->xattr_names[i]); + ssize_t p = 0; + for (; p < mentry->xattr_lvalues[i]; p++) { + const char ch = mentry->xattr_values[i][p]; + if ((unsigned)(ch - 32) > 126 - 32) { + p = -1; + break; + } + } + if (p >= 0) + printf("\"%.*s\"\n", + (int)mentry->xattr_lvalues[i], + mentry->xattr_values[i]); + else { + printf("0x"); + for (p = 0; p < mentry->xattr_lvalues[i]; p++) + printf("%02hhx", (char)mentry->xattr_values[i][p]); + printf("\n"); + } + } + } + } +} diff --git a/metaentry.h b/metaentry.h index f402bc7..666c5af 100644 --- a/metaentry.h +++ b/metaentry.h @@ -92,4 +92,6 @@ void mentries_compare(struct metahash *mhashreal, int cmp), msettings *st); +void mentries_dump(struct metahash *mhash); + #endif /* METAENTRY_H */ diff --git a/metastore.1 b/metastore.1 index d6c561e..7651b91 100644 --- a/metastore.1 +++ b/metastore.1 @@ -26,6 +26,15 @@ Saves the current metadata to ./.metadata or to the specified file .B \-a, \-\-apply Attempts to apply the stored metadata to the file system. .TP +.B \-d, \-\-dump +Dumps stored (if no \fIPATH\fR is given) or real metadata (if \fIPATH\fR is +present, e.g. \fB./\fR) in human-readable form. + +This action is meant only as a helpful debugging facility or merge conflict +helper. Do not ever compare its output generated using different metastore +version. Do not rely on current output format (especially in batch scripts), +because it may change in future without prior notice. +.TP .B \-h, \-\-help Prints a help message and exits. .\" diff --git a/metastore.c b/metastore.c index ec3083f..2956cab 100644 --- a/metastore.c +++ b/metastore.c @@ -407,6 +407,8 @@ usage(const char *arg0, const char *message) " -c, --compare Show differences between stored and real metadata\n" " -s, --save Save current metadata\n" " -a, --apply Apply stored metadata\n" +" -d, --dump Dump stored (if no PATH is given) or real metadata\n" +" (if PATH is present, e.g. ./) in human-readable form\n" " -h, --help Help message (this text)\n" "\n" "Valid OPTIONS are:\n" @@ -427,6 +429,7 @@ static struct option long_options[] = { { "compare", no_argument, NULL, 'c' }, { "save", no_argument, NULL, 's' }, { "apply", no_argument, NULL, 'a' }, + { "dump", no_argument, NULL, 'd' }, { "help", no_argument, NULL, 'h' }, { "verbose", no_argument, NULL, 'v' }, { "quiet", no_argument, NULL, 'q' }, @@ -451,7 +454,7 @@ main(int argc, char **argv) i = 0; while (1) { int option_index = 0; - c = getopt_long(argc, argv, "csahvqmeEgf:", + c = getopt_long(argc, argv, "csadhvqmeEgf:", long_options, &option_index); if (c == -1) break; @@ -459,6 +462,7 @@ main(int argc, char **argv) case 'c': /* compare */ action |= ACTION_DIFF; i++; break; case 's': /* save */ action |= ACTION_SAVE; i++; break; case 'a': /* apply */ action |= ACTION_APPLY; i++; break; + case 'd': /* dump */ action |= ACTION_DUMP; i++; break; case 'h': /* help */ action |= ACTION_HELP; i++; break; case 'v': /* verbose */ adjust_verbosity(1); break; case 'q': /* quiet */ adjust_verbosity(-1); break; @@ -489,7 +493,7 @@ main(int argc, char **argv) usage(argv[0], NULL); /* Perform action */ - if (action & ACTIONS_READING) { + if (action & ACTIONS_READING && !(action == ACTION_DUMP && optind < argc)) { mentries_fromfile(&stored, settings.metafile); if (!stored) { msg(MSG_CRITICAL, "Failed to load metadata from %s\n", @@ -501,11 +505,11 @@ main(int argc, char **argv) if (optind < argc) { while (optind < argc) mentries_recurse_path(argv[optind++], &real, &settings); - } else { + } else if (action != ACTION_DUMP) { mentries_recurse_path(".", &real, &settings); } - if (!real) { + if (!real && (action != ACTION_DUMP || optind < argc)) { msg(MSG_CRITICAL, "Failed to load metadata from file system\n"); exit(EXIT_FAILURE); @@ -525,6 +529,9 @@ main(int argc, char **argv) if (settings.do_removeemptydirs) fixup_newemptydirs(); break; + case ACTION_DUMP: + mentries_dump(real ? real : stored); + break; } exit(EXIT_SUCCESS); diff --git a/metastore.h b/metastore.h index 9dbd19e..384808d 100644 --- a/metastore.h +++ b/metastore.h @@ -32,6 +32,7 @@ /* Utility defines for the action to take */ #define ACTION_APPLY 0x01 #define ACTION_DIFF 0x02 +#define ACTION_DUMP 0x04 #define ACTION_SAVE 0x10 #define ACTION_HELP 0x80 -- 2.11.4.GIT