summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Maw <richard.maw@codethink.co.uk>2011-10-19 16:40:34 +0100
committerRichard Maw <richard.maw@codethink.co.uk>2011-10-19 16:40:34 +0100
commit0065d7d5f9440b725aa969a1ef8edcfe02c184f7 (patch)
tree2a30fc9ccbb1fcf619a0f84d8ef8c7b9da8cc2c0
parentfa85a17045e56479c0ec69a40a177c013f487291 (diff)
downloadtbdiff-0065d7d5f9440b725aa969a1ef8edcfe02c184f7.tar.gz
Forgot some files
-rw-r--r--libtbd_xattrs.c226
-rw-r--r--libtbd_xattrs.h59
2 files changed, 285 insertions, 0 deletions
diff --git a/libtbd_xattrs.c b/libtbd_xattrs.c
new file mode 100644
index 0000000..8f0886b
--- /dev/null
+++ b/libtbd_xattrs.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2011 Codethink Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "libtbd_xattrs.h"
+#include "tbdiff.h"
+#include <string.h>
+#include <stdlib.h>
+
+#include <attr/xattr.h>
+#include <errno.h>
+
+int tbd_xattrs_names(char const *path, tbd_xattrs_names_t *names)
+{
+ char *attrnames = NULL;
+ /* get size of names list */
+ ssize_t size = llistxattr(path, NULL, 0);
+ if (size < 0) {
+ if (errno == ENOSYS || errno == ENOTSUP) {
+ return TBD_ERROR(TBD_ERROR_XATTRS_NOT_SUPPORTED);
+ } else {
+ return TBD_ERROR(TBD_ERROR_FAILURE);
+ }
+ }
+
+ if (size == 0) {
+ names->begin = NULL;
+ names->end = NULL;
+ return TBD_ERROR_SUCCESS;
+ }
+
+ while (1) {
+ { /* allocate memory for list */
+ /* allocate 1 more for NUL terminator */
+ char *allocres = realloc(attrnames, size + 1);
+ if (allocres == NULL) {
+ free(attrnames);
+ return TBD_ERROR(TBD_ERROR_OUT_OF_MEMORY);
+ }
+ attrnames = allocres;
+ }
+
+ { /* try to read names list */
+ ssize_t listres = llistxattr(path, attrnames, size);
+ if (listres >= 0) {
+ /* succeeded, save size */
+ size = listres;
+ break;
+ }
+ if (errno != ERANGE) {
+ /* other error, can't fix */
+ free(attrnames);
+ return TBD_ERROR(TBD_ERROR_FAILURE);
+ }
+ /* not big enough, enlarge and try again */
+ size *= 2;
+ errno = 0;
+ }
+ }
+ /* ensure NUL terminated */
+ attrnames[size] = '\0';
+ names->begin = attrnames;
+ names->end = attrnames + size;
+ return TBD_ERROR_SUCCESS;
+}
+
+void tbd_xattrs_names_free(tbd_xattrs_names_t *names)
+{
+ free((void *)names->begin);
+}
+
+int tbd_xattrs_names_each(tbd_xattrs_names_t const *names,
+ int (*f)(char const *name, void *ud), void *ud)
+{
+ char const *name;
+ int err = TBD_ERROR_SUCCESS;
+ for (name = names->begin; name != names->end;
+ name = strchr(name, '\0') + 1) {
+ if ((err = f(name, ud)) != TBD_ERROR_SUCCESS) {
+ return err;
+ }
+ }
+ return err;
+}
+
+static int names_sum(char const *name, void *ud) {
+ if (name == NULL || ud == NULL)
+ return TBD_ERROR(TBD_ERROR_NULL_POINTER);
+ (*((uint16_t*)ud))++;
+ return TBD_ERROR_SUCCESS;
+}
+int tbd_xattrs_names_count(tbd_xattrs_names_t const *names, int *count) {
+ int _count = 0;
+ int err;
+ if ((err = tbd_xattrs_names_each(names, &names_sum, &_count)) ==
+ TBD_ERROR_SUCCESS) {
+ *count = _count;
+ }
+ return err;
+}
+
+static int name_remove(char const *name, void *ud) {
+ char const *path = ud;
+ if (lremovexattr(path, name) < 0) {
+ switch (errno) {
+ case ENOATTR:
+ return TBD_ERROR(TBD_ERROR_XATTRS_MISSING_ATTR);
+ case ENOTSUP:
+ return TBD_ERROR(TBD_ERROR_XATTRS_NOT_SUPPORTED);
+ default:
+ return TBD_ERROR(TBD_ERROR_FAILURE);
+ }
+ }
+ return TBD_ERROR_SUCCESS;
+}
+int tbd_xattrs_removeall(char const *path)
+{
+ int err = TBD_ERROR_SUCCESS;
+ tbd_xattrs_names_t list;
+
+ /* get the list of attributes */
+ if ((err = tbd_xattrs_names(path, &list)) != TBD_ERROR_SUCCESS) {
+ return err;
+ }
+
+ err = tbd_xattrs_names_each(&list, &name_remove, (void*)path);
+
+ tbd_xattrs_names_free(&list);
+ return err;
+}
+
+int tbd_xattrs_get(char const *path, char const* name, void **buf,
+ size_t *bufsize, size_t *valsize)
+{
+ ssize_t toalloc = *bufsize;
+ if (toalloc == 0 || *buf == NULL) {
+ toalloc = lgetxattr(path, name, NULL, 0);
+ if (toalloc < 0) {
+ if (errno == ENOSYS || errno == ENOTSUP) {
+ return TBD_ERROR(TBD_ERROR_XATTRS_NOT_SUPPORTED);
+ } else {
+ return TBD_ERROR(TBD_ERROR_FAILURE);
+ }
+ }
+ {
+ void *allocres = malloc(toalloc);
+ if (allocres == NULL) {
+ return TBD_ERROR(TBD_ERROR_OUT_OF_MEMORY);
+ }
+ *buf = allocres;
+ *bufsize = toalloc;
+ }
+
+ }
+ while (1) {
+ { /* try to get value */
+ ssize_t getres = lgetxattr(path, name, *buf, *bufsize);
+ if (getres >= 0) {
+ /* succeeded, save size */
+ *valsize = getres;
+ break;
+ }
+ if (errno != ERANGE) {
+ /* other error, can't fix */
+ return TBD_ERROR(TBD_ERROR_FAILURE);
+ }
+ /* not big enough, enlarge and try again */
+ toalloc *= 2;
+ errno = 0;
+ }
+
+ { /* allocate memory for list */
+ void *allocres = realloc(*buf, toalloc);
+ if (allocres == NULL) {
+ return TBD_ERROR(TBD_ERROR_OUT_OF_MEMORY);
+ }
+ *buf = allocres;
+ *bufsize = toalloc;
+ }
+ }
+ return TBD_ERROR_SUCCESS;
+}
+
+typedef struct {
+ char const *path;
+ tbd_xattrs_pairs_callback_t f;
+ void *pairs_ud;
+ void *data;
+ size_t data_size;
+} tbd_xattrs_pairs_params_t;
+static int call_with_data(char const *name, void *ud)
+{
+ tbd_xattrs_pairs_params_t *params;
+ params = ud;
+ size_t value_size;
+ int err;
+ if ((err = tbd_xattrs_get(params->path, name, &(params->data),
+ &(params->data_size), &value_size)) !=
+ TBD_ERROR_SUCCESS) {
+ return err;
+ }
+ return params->f(name, params->data, value_size, params->pairs_ud);
+}
+int tbd_xattrs_pairs(tbd_xattrs_names_t const *names, char const *path,
+ tbd_xattrs_pairs_callback_t f, void *ud)
+{
+ tbd_xattrs_pairs_params_t params = {
+ path, f, ud, NULL, 0,
+ };
+ int err = tbd_xattrs_names_each(names, &call_with_data, &params);
+ free(params.data);
+ return err;
+}
diff --git a/libtbd_xattrs.h b/libtbd_xattrs.h
new file mode 100644
index 0000000..7a1399c
--- /dev/null
+++ b/libtbd_xattrs.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2011 Codethink Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _LIBTBD_XATTRS_H
+#define _LIBTBD_XATTRS_H
+
+#include <stddef.h>
+
+/* structure for names data */
+typedef struct tbd_xattrs_names {
+ char const *begin;
+ char const *end;
+} tbd_xattrs_names_t;
+
+/* gets a list of the names of the file referenced by path */
+extern int tbd_xattrs_names(char const *path, tbd_xattrs_names_t *names_out);
+
+/* frees up the INTERNAL resources of the list, doesn't free the list itself */
+extern void tbd_xattrs_names_free(tbd_xattrs_names_t *names);
+
+/* calls f with every name in the list */
+extern int tbd_xattrs_names_each(tbd_xattrs_names_t const *names,
+ int (*f)(char const *name, void *ud),
+ void *ud);
+
+/* gets how many different attributes there are in the list */
+extern int tbd_xattrs_names_count(tbd_xattrs_names_t const *names, int *count);
+
+/* puts the value of the attribute called name into *buf with size *bufsize
+ * if *buf is NULL or *bufsize is 0 then memory will be allocated for it
+ * if *buf was too small it will be reallocated
+ * if it is successful, *buf will contain *valsize bytes of data
+ */
+extern int tbd_xattrs_get(char const *path, char const* name, void **buf,
+ size_t *bufsize, size_t *valsize);
+
+/* removes all attributes of the file referenced by path */
+extern int tbd_xattrs_removeall(char const *path);
+
+/* calls f for every attribute:value pair in the list */
+typedef int (*tbd_xattrs_pairs_callback_t)(char const *name, void const *data,
+ size_t size, void *ud);
+extern int tbd_xattrs_pairs(tbd_xattrs_names_t const *names, char const *path,
+ tbd_xattrs_pairs_callback_t f, void *ud);
+#endif