summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Härdeman <david@hardeman.nu>2007-05-18 23:48:55 +0200
committerDavid Härdeman <david@hardeman.nu>2007-05-18 23:48:55 +0200
commit3cb9d64b9b2ace1463f274c8554bffbfa4979e0d (patch)
tree79b570d8ed8ba30e619921d079ea8fd9b362f3fd
parent3b9fa8b3619f0ef0ddd47efa6ab285682b686af1 (diff)
Split meta entry functions into a separate file
-rw-r--r--Makefile2
-rw-r--r--metaentry.c533
-rw-r--r--metaentry.h18
-rw-r--r--metastore.c554
-rw-r--r--metastore.h15
-rw-r--r--utils.c19
-rw-r--r--utils.h9
7 files changed, 589 insertions, 561 deletions
diff --git a/Makefile b/Makefile
index 43783e8..91bb1ce 100644
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@ INCLUDES =
COMPILE = $(CC) $(INCLUDES) $(CFLAGS)
LINK = $(CC) $(CFLAGS) $(LDFLAGS)
-objects = utils.o metastore.o
+objects = utils.o metastore.o metaentry.o
%.o: %.c
$(COMPILE) -o $@ -c $<
diff --git a/metaentry.c b/metaentry.c
new file mode 100644
index 0000000..3af4a6c
--- /dev/null
+++ b/metaentry.c
@@ -0,0 +1,533 @@
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+#include <attr/xattr.h>
+#include <limits.h>
+#include <dirent.h>
+#include <sys/mman.h>
+#include <utime.h>
+#include <fcntl.h>
+#include <stdint.h>
+
+#include "metastore.h"
+#include "metaentry.h"
+#include "utils.h"
+
+static void
+mentry_free(struct metaentry *m)
+{
+ int i;
+
+ if (!m)
+ return;
+
+ free(m->path);
+ free(m->owner);
+ free(m->group);
+
+ for (i = 0; i < m->xattrs; i++) {
+ free(m->xattr_names[i]);
+ free(m->xattr_values[i]);
+ }
+
+ free(m->xattr_names);
+ free(m->xattr_values);
+ free(m->xattr_lvalues);
+
+ free(m);
+}
+
+static struct metaentry *
+mentry_alloc()
+{
+ struct metaentry *mentry;
+ mentry = xmalloc(sizeof(struct metaentry));
+ memset(mentry, 0, sizeof(struct metaentry));
+ return mentry;
+}
+
+static void
+mentry_insert(struct metaentry *mentry, struct metaentry **mhead)
+{
+ struct metaentry *prev;
+ struct metaentry *curr;
+ int comp;
+
+ if (!(*mhead)) {
+ *mhead = mentry;
+ return;
+ }
+
+ if (strcmp(mentry->path, (*mhead)->path) < 0) {
+ mentry->next = *mhead;
+ *mhead = mentry;
+ return;
+ }
+
+ prev = *mhead;
+ for (curr = prev->next; curr; curr = curr->next) {
+ comp = strcmp(mentry->path, curr->path);
+ if (!comp)
+ /* Two matching paths */
+ return;
+ if (comp < 0)
+ break;
+ prev = curr;
+ }
+
+ if (curr)
+ mentry->next = curr;
+ prev->next = mentry;
+}
+
+static void
+mentry_print(const struct metaentry *mentry)
+{
+ int i;
+
+ if (!mentry || !mentry->path) {
+ fprintf(stderr, "Incorrect meta entry passed to printmetaentry\n");
+ return;
+ }
+
+ printf("===========================\n");
+ printf("Dump of metaentry %p\n", mentry);
+ printf("===========================\n");
+
+ printf("path\t\t: %s\n", mentry->path);
+ printf("owner\t\t: %s\n", mentry->owner);
+ printf("group\t\t: %s\n", mentry->group);
+ printf("mtime\t\t: %ld\n", (unsigned long)mentry->mtime);
+ printf("mtimensec\t: %ld\n", (unsigned long)mentry->mtimensec);
+ printf("mode\t\t: %ld\n", (unsigned long)mentry->mode);
+ for (i = 0; i < mentry->xattrs; i++) {
+ printf("xattr[%i]\t: %s=\"", i, mentry->xattr_names[i]);
+ binary_print(mentry->xattr_values[i], mentry->xattr_lvalues[i]);
+ printf("\"\n");
+ }
+
+ printf("===========================\n\n");
+}
+
+static void
+mentries_print(const struct metaentry *mhead)
+{
+ const struct metaentry *mentry;
+ int i;
+
+ for (mentry = mhead; mentry; mentry = mentry->next) {
+ i++;
+ mentry_print(mentry);
+ }
+
+ printf("%i entries in total\n", i);
+}
+
+static struct metaentry *
+mentry_create(const char *path)
+{
+ ssize_t lsize, vsize;
+ char *list, *attr;
+ struct stat sbuf;
+ struct passwd *pbuf;
+ struct group *gbuf;
+ int i;
+ struct metaentry *mentry;
+
+ if (lstat(path, &sbuf)) {
+ perror("lstat");
+ return NULL;
+ }
+
+ pbuf = getpwuid(sbuf.st_uid);
+ if (!pbuf) {
+ perror("getpwuid");
+ return NULL;
+ }
+
+ gbuf = getgrgid(sbuf.st_gid);
+ if (!gbuf) {
+ perror("getgrgid");
+ return NULL;
+ }
+
+ mentry = mentry_alloc();
+ mentry->path = xstrdup(path);
+ mentry->owner = xstrdup(pbuf->pw_name);
+ mentry->group = xstrdup(gbuf->gr_name);
+ mentry->mode = sbuf.st_mode & 0177777;
+ mentry->mtime = sbuf.st_mtim.tv_sec;
+ mentry->mtimensec = sbuf.st_mtim.tv_nsec;
+
+ /* symlinks have no xattrs */
+ if (S_ISLNK(mentry->mode))
+ return mentry;
+
+ lsize = listxattr(path, NULL, 0);
+ if (lsize < 0) {
+ perror("listxattr");
+ return NULL;
+ }
+
+ list = xmalloc(lsize);
+ lsize = listxattr(path, list, lsize);
+ if (lsize < 0) {
+ perror("listxattr");
+ return NULL;
+ }
+
+ i = 0;
+ for (attr = list; attr < list + lsize; attr = strchr(attr, '\0') + 1) {
+ if (*attr == '\0')
+ continue;
+ i++;
+ }
+
+ if (i == 0)
+ return mentry;
+
+ mentry->xattrs = i;
+ mentry->xattr_names = xmalloc(i * sizeof(char *));
+ mentry->xattr_values = xmalloc(i * sizeof(char *));
+ mentry->xattr_lvalues = xmalloc(i * sizeof(ssize_t));
+
+ i = 0;
+ for (attr = list; attr < list + lsize; attr = strchr(attr, '\0') + 1) {
+ if (*attr == '\0')
+ continue;
+
+ mentry->xattr_names[i] = xstrdup(attr);
+ vsize = getxattr(path, attr, NULL, 0);
+ if (vsize < 0) {
+ perror("getxattr");
+ return NULL;
+ }
+
+ mentry->xattr_lvalues[i] = vsize;
+ mentry->xattr_values[i] = xmalloc(vsize);
+
+ vsize = getxattr(path, attr, mentry->xattr_values[i], vsize);
+ if (vsize < 0) {
+ perror("getxattr");
+ return NULL;
+ }
+ i++;
+ }
+
+ return mentry;
+}
+
+static char *
+normalize_path(const char *orig)
+{
+ char *real = canonicalize_file_name(orig);
+ char cwd[PATH_MAX];
+ char *result;
+
+ getcwd(cwd, PATH_MAX);
+ if (!real)
+ return NULL;
+
+ if (!strncmp(real, cwd, strlen(cwd))) {
+ result = xmalloc(strlen(real) - strlen(cwd) + 1 + 1);
+ result[0] = '\0';
+ strcat(result, ".");
+ strcat(result, real + strlen(cwd));
+ } else {
+ result = xstrdup(real);
+ }
+
+ free(real);
+ return result;
+}
+
+static void
+mentries_recurse(const char *path, struct metaentry **mhead)
+{
+ struct stat sbuf;
+ struct metaentry *mentry;
+ char tpath[PATH_MAX];
+ DIR *dir;
+ struct dirent *dent;
+
+ if (!path)
+ return;
+
+ if (lstat(path, &sbuf)) {
+ printf("Failed to stat %s\n", path);
+ return;
+ }
+
+ mentry = mentry_create(path);
+ if (!mentry) {
+ printf("Failed to get metadata for %s\n", path);
+ return;
+ }
+
+ mentry_insert(mentry, mhead);
+
+ if (S_ISDIR(sbuf.st_mode)) {
+ dir = opendir(path);
+ if (!dir) {
+ printf("Failed to open dir %s\n", path);
+ return;
+ }
+
+ while ((dent = readdir(dir))) {
+ if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..") || !strcmp(dent->d_name, ".git"))
+ continue;
+ snprintf(tpath, PATH_MAX, "%s/%s", path, dent->d_name);
+ tpath[PATH_MAX - 1] = '\0';
+ mentries_recurse(tpath, mhead);
+ }
+
+ closedir(dir);
+ }
+}
+
+void
+mentries_recurse_path(const char *opath, struct metaentry **mhead)
+{
+ char *path = normalize_path(opath);
+ mentries_recurse(path, mhead);
+ free(path);
+}
+
+void
+mentries_tofile(const struct metaentry *mhead, const char *path)
+{
+ FILE *to;
+ const struct metaentry *mentry;
+ int i;
+
+ to = fopen(path, "w");
+ if (!to) {
+ perror("fopen");
+ exit(EXIT_FAILURE);
+ }
+
+ write_binary_string(SIGNATURE, SIGNATURELEN, to);
+ write_binary_string(VERSION, VERSIONLEN, to);
+
+ for (mentry = mhead; mentry; mentry = mentry->next) {
+ write_string(mentry->path, to);
+ write_string(mentry->owner, to);
+ write_string(mentry->group, to);
+ write_int((uint64_t)mentry->mtime, 8, to);
+ write_int((uint64_t)mentry->mtimensec, 8, to);
+ write_int((uint64_t)mentry->mode, 2, to);
+ write_int(mentry->xattrs, 4, to);
+ for (i = 0; i < mentry->xattrs; i++) {
+ write_string(mentry->xattr_names[i], to);
+ write_int(mentry->xattr_lvalues[i], 4, to);
+ write_binary_string(mentry->xattr_values[i], mentry->xattr_lvalues[i], to);
+ }
+ }
+
+ fclose(to);
+}
+
+void
+mentries_fromfile(struct metaentry **mhead, const char *path)
+{
+ struct metaentry *mentry;
+ char *mmapstart;
+ char *ptr;
+ char *max;
+ int fd;
+ struct stat sbuf;
+ int i;
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0) {
+ perror("open");
+ exit(EXIT_FAILURE);
+ }
+
+ if (fstat(fd, &sbuf)) {
+ perror("fstat");
+ exit(EXIT_FAILURE);
+ }
+
+ if (sbuf.st_size < (SIGNATURELEN + VERSIONLEN)) {
+ fprintf(stderr, "Invalid size for file %s\n", path);
+ exit(EXIT_FAILURE);
+ }
+
+ mmapstart = mmap(NULL, (size_t)sbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
+ if (mmapstart == MAP_FAILED) {
+ perror("mmap");
+ exit(EXIT_FAILURE);
+ }
+ ptr = mmapstart;
+ max = mmapstart + sbuf.st_size;
+
+ if (strncmp(ptr, SIGNATURE, SIGNATURELEN)) {
+ printf("Invalid signature for file %s\n", path);
+ goto out;
+ }
+ ptr += SIGNATURELEN;
+
+ if (strncmp(ptr, VERSION, VERSIONLEN)) {
+ printf("Invalid version for file %s\n", path);
+ goto out;
+ }
+ ptr += VERSIONLEN;
+
+ while (ptr < mmapstart + sbuf.st_size) {
+ if (*ptr == '\0') {
+ fprintf(stderr, "Invalid characters in file %s\n", path);
+ goto out;
+ }
+
+ mentry = mentry_alloc();
+ mentry->path = read_string(&ptr, max);
+ mentry->owner = read_string(&ptr, max);
+ mentry->group = read_string(&ptr, max);
+ mentry->mtime = (time_t)read_int(&ptr, 8, max);
+ mentry->mtimensec = (time_t)read_int(&ptr, 8, max);
+ mentry->mode = (mode_t)read_int(&ptr, 2, max);
+ mentry->xattrs = (unsigned int)read_int(&ptr, 4, max);
+
+ if (mentry->xattrs > 0) {
+ mentry->xattr_names = xmalloc(mentry->xattrs * sizeof(char *));
+ mentry->xattr_lvalues = xmalloc(mentry->xattrs * sizeof(int));
+ mentry->xattr_values = xmalloc(mentry->xattrs * sizeof(char *));
+
+ for (i = 0; i < mentry->xattrs; i++) {
+ mentry->xattr_names[i] = read_string(&ptr, max);
+ mentry->xattr_lvalues[i] = (int)read_int(&ptr, 4, max);
+ mentry->xattr_values[i] = read_binary_string(&ptr, mentry->xattr_lvalues[i], max);
+ }
+ }
+ mentry_insert(mentry, mhead);
+ }
+
+out:
+ munmap(mmapstart, sbuf.st_size);
+ close(fd);
+}
+
+static struct metaentry *
+mentry_find(const char *path, struct metaentry *mhead)
+{
+ struct metaentry *m;
+
+ /* FIXME - We can do a bisect search here instead */
+ for (m = mhead; m; m = m->next) {
+ if (!strcmp(path, m->path))
+ return m;
+ }
+ return NULL;
+}
+
+/* Returns xattr index in haystack which corresponds to xattr n in needle */
+int
+mentry_find_xattr(struct metaentry *haystack, struct metaentry *needle, int n)
+{
+ int i;
+
+ for (i = 0; i < haystack->xattrs; i++) {
+ if (strcmp(haystack->xattr_names[i], needle->xattr_names[n]))
+ continue;
+ if (haystack->xattr_lvalues[i] != needle->xattr_lvalues[n])
+ return -1;
+ if (bcmp(haystack->xattr_values[i], needle->xattr_values[n], needle->xattr_lvalues[n]))
+ return -1;
+ return i;
+ }
+ return -1;
+}
+
+/* Returns zero if all xattrs in left and right match */
+static int
+mentry_compare_xattr(struct metaentry *left, struct metaentry *right)
+{
+ int i;
+
+ if (left->xattrs != right->xattrs)
+ return 1;
+
+ /* Make sure all xattrs in left are found in right and vice versa */
+ for (i = 0; i < left->xattrs; i++) {
+ if (mentry_find_xattr(right, left, i) < 0 ||
+ mentry_find_xattr(left, right, i) < 0) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+mentry_compare(struct metaentry *left, struct metaentry *right)
+{
+ int retval = DIFF_NONE;
+
+ if (!left || !right) {
+ fprintf(stderr, "mentry_compare called with empty arguments\n");
+ return -1;
+ }
+
+ if (strcmp(left->path, right->path))
+ return -1;
+
+ if (strcmp(left->owner, right->owner))
+ retval |= DIFF_OWNER;
+
+ if (strcmp(left->group, right->group))
+ retval |= DIFF_GROUP;
+
+ if ((left->mode & 07777) != (right->mode & 07777))
+ retval |= DIFF_MODE;
+
+ if ((left->mode & S_IFMT) != (right->mode & S_IFMT))
+ retval |= DIFF_TYPE;
+
+ if (do_mtime && strcmp(left->path, METAFILE) &&
+ (left->mtime != right->mtime || left->mtimensec != right->mtimensec))
+ retval |= DIFF_MTIME;
+
+ if (mentry_compare_xattr(left, right)) {
+ retval |= DIFF_XATTR;
+ return retval;
+ }
+
+ return retval;
+}
+
+void
+mentries_compare(struct metaentry *mheadleft,
+ struct metaentry *mheadright,
+ void (*printfunc)(struct metaentry *, struct metaentry *, int))
+{
+ struct metaentry *left, *right;
+ int cmp;
+
+ if (!mheadleft || !mheadright) {
+ fprintf(stderr, "mentries_compare called with empty list\n");
+ return;
+ }
+
+ for (left = mheadleft; left; left = left->next) {
+ right = mentry_find(left->path, mheadright);
+ if (!right)
+ cmp = DIFF_ADDED;
+ else
+ cmp = mentry_compare(left, right);
+ printfunc(left, right, cmp);
+ }
+
+ for (right = mheadright; right; right = right->next) {
+ left = mentry_find(right->path, mheadleft);
+ if (!left)
+ printfunc(left, right, DIFF_DELE);
+ }
+}
+
diff --git a/metaentry.h b/metaentry.h
new file mode 100644
index 0000000..dfc43cb
--- /dev/null
+++ b/metaentry.h
@@ -0,0 +1,18 @@
+void mentries_recurse_path(const char *, struct metaentry **);
+void mentries_tofile(const struct metaentry *, const char *);
+void mentries_fromfile(struct metaentry **, const char *);
+int mentry_find_xattr(struct metaentry *, struct metaentry *, int);
+
+#define DIFF_NONE 0x00
+#define DIFF_OWNER 0x01
+#define DIFF_GROUP 0x02
+#define DIFF_MODE 0x04
+#define DIFF_TYPE 0x08
+#define DIFF_MTIME 0x10
+#define DIFF_XATTR 0x20
+#define DIFF_ADDED 0x40
+#define DIFF_DELE 0x80
+void mentries_compare(struct metaentry *, struct metaentry *,
+ void (*printfunc)(struct metaentry *, struct metaentry *, int));
+
+
diff --git a/metastore.c b/metastore.c
index 0948dbd..ec28c38 100644
--- a/metastore.c
+++ b/metastore.c
@@ -1,527 +1,22 @@
-#define _GNU_SOURCE
#include <stdio.h>
-#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <unistd.h>
-#include <attr/xattr.h>
-#include <string.h>
#include <pwd.h>
#include <grp.h>
-#include <limits.h>
-#include <dirent.h>
-#include <sys/mman.h>
-#include <fcntl.h>
-#include <stdint.h>
#include <getopt.h>
-#include <stdarg.h>
#include <utime.h>
+#include <attr/xattr.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
#include "metastore.h"
#include "utils.h"
+#include "metaentry.h"
-int verbosity = 0;
int do_mtime = 0;
-int
-msg(int level, const char *fmt, ...)
-{
- int ret;
- va_list ap;
-
- if (level > verbosity)
- return 0;
-
- va_start(ap, fmt);
- ret = vfprintf(stderr, fmt, ap);
- va_end(ap);
- return ret;
-}
-
-void
-mentry_free(struct metaentry *m)
-{
- int i;
-
- if (!m)
- return;
-
- free(m->path);
- free(m->owner);
- free(m->group);
-
- for (i = 0; i < m->xattrs; i++) {
- free(m->xattr_names[i]);
- free(m->xattr_values[i]);
- }
-
- free(m->xattr_names);
- free(m->xattr_values);
- free(m->xattr_lvalues);
-
- free(m);
-}
-
-struct metaentry *
-mentry_alloc()
-{
- struct metaentry *mentry;
- mentry = xmalloc(sizeof(struct metaentry));
- memset(mentry, 0, sizeof(struct metaentry));
- return mentry;
-}
-
-void
-mentry_insert(struct metaentry *mentry, struct metaentry **mhead)
-{
- struct metaentry *prev;
- struct metaentry *curr;
- int comp;
-
- if (!(*mhead)) {
- *mhead = mentry;
- return;
- }
-
- if (strcmp(mentry->path, (*mhead)->path) < 0) {
- mentry->next = *mhead;
- *mhead = mentry;
- return;
- }
-
- prev = *mhead;
- for (curr = prev->next; curr; curr = curr->next) {
- comp = strcmp(mentry->path, curr->path);
- if (!comp)
- /* Two matching paths */
- return;
- if (comp < 0)
- break;
- prev = curr;
- }
-
- if (curr)
- mentry->next = curr;
- prev->next = mentry;
-}
-
-void
-mentry_print(const struct metaentry *mentry)
-{
- int i;
-
- if (!mentry || !mentry->path) {
- fprintf(stderr, "Incorrect meta entry passed to printmetaentry\n");
- return;
- }
-
- printf("===========================\n");
- printf("Dump of metaentry %p\n", mentry);
- printf("===========================\n");
-
- printf("path\t\t: %s\n", mentry->path);
- printf("owner\t\t: %s\n", mentry->owner);
- printf("group\t\t: %s\n", mentry->group);
- printf("mtime\t\t: %ld\n", (unsigned long)mentry->mtime);
- printf("mtimensec\t: %ld\n", (unsigned long)mentry->mtimensec);
- printf("mode\t\t: %ld\n", (unsigned long)mentry->mode);
- for (i = 0; i < mentry->xattrs; i++) {
- printf("xattr[%i]\t: %s=\"", i, mentry->xattr_names[i]);
- binary_print(mentry->xattr_values[i], mentry->xattr_lvalues[i]);
- printf("\"\n");
- }
-
- printf("===========================\n\n");
-}
-
-void
-mentries_print(const struct metaentry *mhead)
-{
- const struct metaentry *mentry;
- int i;
-
- for (mentry = mhead; mentry; mentry = mentry->next) {
- i++;
- mentry_print(mentry);
- }
-
- printf("%i entries in total\n", i);
-}
-
-struct metaentry *
-mentry_create(const char *path)
-{
- ssize_t lsize, vsize;
- char *list, *attr;
- struct stat sbuf;
- struct passwd *pbuf;
- struct group *gbuf;
- int i;
- struct metaentry *mentry;
-
- if (lstat(path, &sbuf)) {
- perror("lstat");
- return NULL;
- }
-
- pbuf = getpwuid(sbuf.st_uid);
- if (!pbuf) {
- perror("getpwuid");
- return NULL;
- }
-
- gbuf = getgrgid(sbuf.st_gid);
- if (!gbuf) {
- perror("getgrgid");
- return NULL;
- }
-
- mentry = mentry_alloc();
- mentry->path = xstrdup(path);
- mentry->owner = xstrdup(pbuf->pw_name);
- mentry->group = xstrdup(gbuf->gr_name);
- mentry->mode = sbuf.st_mode & 0177777;
- mentry->mtime = sbuf.st_mtim.tv_sec;
- mentry->mtimensec = sbuf.st_mtim.tv_nsec;
-
- /* symlinks have no xattrs */
- if (S_ISLNK(mentry->mode))
- return mentry;
-
- lsize = listxattr(path, NULL, 0);
- if (lsize < 0) {
- perror("listxattr");
- return NULL;
- }
-
- list = xmalloc(lsize);
- lsize = listxattr(path, list, lsize);
- if (lsize < 0) {
- perror("listxattr");
- return NULL;
- }
-
- i = 0;
- for (attr = list; attr < list + lsize; attr = strchr(attr, '\0') + 1) {
- if (*attr == '\0')
- continue;
- i++;
- }
-
- if (i == 0)
- return mentry;
-
- mentry->xattrs = i;
- mentry->xattr_names = xmalloc(i * sizeof(char *));
- mentry->xattr_values = xmalloc(i * sizeof(char *));
- mentry->xattr_lvalues = xmalloc(i * sizeof(ssize_t));
-
- i = 0;
- for (attr = list; attr < list + lsize; attr = strchr(attr, '\0') + 1) {
- if (*attr == '\0')
- continue;
-
- mentry->xattr_names[i] = xstrdup(attr);
- vsize = getxattr(path, attr, NULL, 0);
- if (vsize < 0) {
- perror("getxattr");
- return NULL;
- }
-
- mentry->xattr_lvalues[i] = vsize;
- mentry->xattr_values[i] = xmalloc(vsize);
-
- vsize = getxattr(path, attr, mentry->xattr_values[i], vsize);
- if (vsize < 0) {
- perror("getxattr");
- return NULL;
- }
- i++;
- }
-
- return mentry;
-}
-
-char *
-normalize_path(const char *orig)
-{
- char *real = canonicalize_file_name(orig);
- char cwd[PATH_MAX];
- char *result;
-
- getcwd(cwd, PATH_MAX);
- if (!real)
- return NULL;
-
- if (!strncmp(real, cwd, strlen(cwd))) {
- result = xmalloc(strlen(real) - strlen(cwd) + 1 + 1);
- result[0] = '\0';
- strcat(result, ".");
- strcat(result, real + strlen(cwd));
- } else {
- result = xstrdup(real);
- }
-
- free(real);
- return result;
-}
-
-void
-mentries_recurse(const char *path, struct metaentry **mhead)
-{
- struct stat sbuf;
- struct metaentry *mentry;
- char tpath[PATH_MAX];
- DIR *dir;
- struct dirent *dent;
-
- if (!path)
- return;
-
- if (lstat(path, &sbuf)) {
- printf("Failed to stat %s\n", path);
- return;
- }
-
- mentry = mentry_create(path);
- if (!mentry) {
- printf("Failed to get metadata for %s\n", path);
- return;
- }
-
- mentry_insert(mentry, mhead);
-
- if (S_ISDIR(sbuf.st_mode)) {
- dir = opendir(path);
- if (!dir) {
- printf("Failed to open dir %s\n", path);
- return;
- }
-
- while ((dent = readdir(dir))) {
- if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..") || !strcmp(dent->d_name, ".git"))
- continue;
- snprintf(tpath, PATH_MAX, "%s/%s", path, dent->d_name);
- tpath[PATH_MAX - 1] = '\0';
- mentries_recurse(tpath, mhead);
- }
-
- closedir(dir);
- }
-}
-
-void
-mentries_recurse_path(const char *opath, struct metaentry **mhead)
-{
- char *path = normalize_path(opath);
- mentries_recurse(path, mhead);
- free(path);
-}
-
-void
-mentries_tofile(const struct metaentry *mhead, const char *path)
-{
- FILE *to;
- const struct metaentry *mentry;
- int i;
-
- to = fopen(path, "w");
- if (!to) {
- perror("fopen");
- exit(EXIT_FAILURE);
- }
-
- write_binary_string(SIGNATURE, SIGNATURELEN, to);
- write_binary_string(VERSION, VERSIONLEN, to);
-
- for (mentry = mhead; mentry; mentry = mentry->next) {
- write_string(mentry->path, to);
- write_string(mentry->owner, to);
- write_string(mentry->group, to);
- write_int((uint64_t)mentry->mtime, 8, to);
- write_int((uint64_t)mentry->mtimensec, 8, to);
- write_int((uint64_t)mentry->mode, 2, to);
- write_int(mentry->xattrs, 4, to);
- for (i = 0; i < mentry->xattrs; i++) {
- write_string(mentry->xattr_names[i], to);
- write_int(mentry->xattr_lvalues[i], 4, to);
- write_binary_string(mentry->xattr_values[i], mentry->xattr_lvalues[i], to);
- }
- }
-
- fclose(to);
-}
-
-void
-mentries_fromfile(struct metaentry **mhead, const char *path)
-{
- struct metaentry *mentry;
- char *mmapstart;
- char *ptr;
- char *max;
- int fd;
- struct stat sbuf;
- int i;
-
- fd = open(path, O_RDONLY);
- if (fd < 0) {
- perror("open");
- exit(EXIT_FAILURE);
- }
-
- if (fstat(fd, &sbuf)) {
- perror("fstat");
- exit(EXIT_FAILURE);
- }
-
- if (sbuf.st_size < (SIGNATURELEN + VERSIONLEN)) {
- fprintf(stderr, "Invalid size for file %s\n", path);
- exit(EXIT_FAILURE);
- }
-
- mmapstart = mmap(NULL, (size_t)sbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
- if (mmapstart == MAP_FAILED) {
- perror("mmap");
- exit(EXIT_FAILURE);
- }
- ptr = mmapstart;
- max = mmapstart + sbuf.st_size;
-
- if (strncmp(ptr, SIGNATURE, SIGNATURELEN)) {
- printf("Invalid signature for file %s\n", path);
- goto out;
- }
- ptr += SIGNATURELEN;
-
- if (strncmp(ptr, VERSION, VERSIONLEN)) {
- printf("Invalid version for file %s\n", path);
- goto out;
- }
- ptr += VERSIONLEN;
-
- while (ptr < mmapstart + sbuf.st_size) {
- if (*ptr == '\0') {
- fprintf(stderr, "Invalid characters in file %s\n", path);
- goto out;
- }
-
- mentry = mentry_alloc();
- mentry->path = read_string(&ptr, max);
- mentry->owner = read_string(&ptr, max);
- mentry->group = read_string(&ptr, max);
- mentry->mtime = (time_t)read_int(&ptr, 8, max);
- mentry->mtimensec = (time_t)read_int(&ptr, 8, max);
- mentry->mode = (mode_t)read_int(&ptr, 2, max);
- mentry->xattrs = (unsigned int)read_int(&ptr, 4, max);
-
- if (mentry->xattrs > 0) {
- mentry->xattr_names = xmalloc(mentry->xattrs * sizeof(char *));
- mentry->xattr_lvalues = xmalloc(mentry->xattrs * sizeof(int));
- mentry->xattr_values = xmalloc(mentry->xattrs * sizeof(char *));
-
- for (i = 0; i < mentry->xattrs; i++) {
- mentry->xattr_names[i] = read_string(&ptr, max);
- mentry->xattr_lvalues[i] = (int)read_int(&ptr, 4, max);
- mentry->xattr_values[i] = read_binary_string(&ptr, mentry->xattr_lvalues[i], max);
- }
- }
- mentry_insert(mentry, mhead);
- }
-
-out:
- munmap(mmapstart, sbuf.st_size);
- close(fd);
-}
-
-struct metaentry *
-mentry_find(const char *path, struct metaentry *mhead)
-{
- struct metaentry *m;
-
- /* FIXME - We can do a bisect search here instead */
- for (m = mhead; m; m = m->next) {
- if (!strcmp(path, m->path))
- return m;
- }
- return NULL;
-}
-
-/* Returns xattr index in haystack which corresponds to xattr n in needle */
-int
-mentry_find_xattr(struct metaentry *haystack, struct metaentry *needle, int n)
-{
- int i;
-
- for (i = 0; i < haystack->xattrs; i++) {
- if (strcmp(haystack->xattr_names[i], needle->xattr_names[n]))
- continue;
- if (haystack->xattr_lvalues[i] != needle->xattr_lvalues[n])
- return -1;
- if (bcmp(haystack->xattr_values[i], needle->xattr_values[n], needle->xattr_lvalues[n]))
- return -1;
- return i;
- }
- return -1;
-}
-
-/* Returns zero if all xattrs in left and right match */
-int
-mentry_compare_xattr(struct metaentry *left, struct metaentry *right)
-{
- int i;
-
- if (left->xattrs != right->xattrs)
- return 1;
-
- /* Make sure all xattrs in left are found in right and vice versa */
- for (i = 0; i < left->xattrs; i++) {
- if (mentry_find_xattr(right, left, i) < 0 ||
- mentry_find_xattr(left, right, i) < 0) {
- return 1;
- }
- }
-
- return 0;
-}
-
-int
-mentry_compare(struct metaentry *left, struct metaentry *right)
-{
- int retval = DIFF_NONE;
-
- if (!left || !right) {
- fprintf(stderr, "mentry_compare called with empty arguments\n");
- return -1;
- }
-
- if (strcmp(left->path, right->path))
- return -1;
-
- if (strcmp(left->owner, right->owner))
- retval |= DIFF_OWNER;
-
- if (strcmp(left->group, right->group))
- retval |= DIFF_GROUP;
-
- if ((left->mode & 07777) != (right->mode & 07777))
- retval |= DIFF_MODE;
-
- if ((left->mode & S_IFMT) != (right->mode & S_IFMT))
- retval |= DIFF_TYPE;
-
- if (do_mtime && strcmp(left->path, METAFILE) &&
- (left->mtime != right->mtime || left->mtimensec != right->mtimensec))
- retval |= DIFF_MTIME;
-
- if (mentry_compare_xattr(left, right)) {
- retval |= DIFF_XATTR;
- return retval;
- }
-
- return retval;
-}
-
-void
+static void
compare_print(struct metaentry *left, struct metaentry *right, int cmp)
{
if (!left) {
@@ -555,7 +50,7 @@ compare_print(struct metaentry *left, struct metaentry *right, int cmp)
printf("\n");
}
-void
+static void
compare_fix(struct metaentry *left, struct metaentry *right, int cmp)
{
struct group *group;
@@ -663,36 +158,7 @@ compare_fix(struct metaentry *left, struct metaentry *right, int cmp)
}
}
-void
-mentries_compare(struct metaentry *mheadleft,
- struct metaentry *mheadright,
- void (*printfunc)(struct metaentry *, struct metaentry *, int))
-{
- struct metaentry *left, *right;
- int cmp;
-
- if (!mheadleft || !mheadright) {
- fprintf(stderr, "mentries_compare called with empty list\n");
- return;
- }
-
- for (left = mheadleft; left; left = left->next) {
- right = mentry_find(left->path, mheadright);
- if (!right)
- cmp = DIFF_ADDED;
- else
- cmp = mentry_compare(left, right);
- printfunc(left, right, cmp);
- }
-
- for (right = mheadright; right; right = right->next) {
- left = mentry_find(right->path, mheadleft);
- if (!left)
- printfunc(left, right, DIFF_DELE);
- }
-}
-
-void
+static void
usage(const char *arg0, const char *msg)
{
if (msg)
@@ -707,9 +173,7 @@ usage(const char *arg0, const char *msg)
" -v, --verbose\tPrint more verbose messages\n"
" -q, --quiet\tPrint less verbose messages\n");
- if (msg)
- exit(EXIT_FAILURE);
- exit(EXIT_SUCCESS);
+ exit(msg ? EXIT_FAILURE : EXIT_SUCCESS);
}
static struct option long_options[] = {
diff --git a/metastore.h b/metastore.h
index 1ccdb54..e8f52bb 100644
--- a/metastore.h
+++ b/metastore.h
@@ -4,25 +4,12 @@
#define VERSIONLEN 8
#define METAFILE "./.metadata"
-#define MSG_NORMAL 0
-#define MSG_DEBUG 1
-#define MSG_QUIET -1
-#define MSG_CRITICAL -2
-
#define ACTION_DIFF 0x01
#define ACTION_SAVE 0x02
#define ACTION_APPLY 0x04
#define ACTION_HELP 0x08
-#define DIFF_NONE 0x00
-#define DIFF_OWNER 0x01
-#define DIFF_GROUP 0x02
-#define DIFF_MODE 0x04
-#define DIFF_TYPE 0x08
-#define DIFF_MTIME 0x10
-#define DIFF_XATTR 0x20
-#define DIFF_ADDED 0x40
-#define DIFF_DELE 0x80
+extern int do_mtime;
struct metaentry {
struct metaentry *next;
diff --git a/utils.c b/utils.c
index f7eb194..91cb1ed 100644
--- a/utils.c
+++ b/utils.c
@@ -3,9 +3,26 @@
#include <ctype.h>
#include <string.h>
#include <stdint.h>
+#include <stdarg.h>
#include "utils.h"
-#include "metastore.h"
+
+int verbosity = 0;
+
+int
+msg(int level, const char *fmt, ...)
+{
+ int ret;
+ va_list ap;
+
+ if (level > verbosity)
+ return 0;
+
+ va_start(ap, fmt);
+ ret = vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ return ret;
+}
void *
xmalloc(size_t size)
diff --git a/utils.h b/utils.h
index 2f39611..d9989a4 100644
--- a/utils.h
+++ b/utils.h
@@ -1,3 +1,12 @@
+#include <stdint.h>
+
+extern int verbosity;
+#define MSG_NORMAL 0
+#define MSG_DEBUG 1
+#define MSG_QUIET -1
+#define MSG_CRITICAL -2
+int msg(int level, const char *fmt, ...);
+
void *xmalloc(size_t size);
char *xstrdup(const char *s);
void binary_print(const char *s, ssize_t len);