initial code repo
[stor4nfv.git] / src / ceph / src / common / xattr.c
diff --git a/src/ceph/src/common/xattr.c b/src/ceph/src/common/xattr.c
new file mode 100644 (file)
index 0000000..080bebc
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2011 Stanislav Sedov <stas@FreeBSD.org>
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation.  See file COPYING.
+ */
+
+#if defined(__FreeBSD__)
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <sys/types.h>
+#include <sys/extattr.h>
+#elif defined(__linux__)
+#include <sys/types.h>
+#include <sys/xattr.h>
+#elif defined(DARWIN)
+#include <sys/xattr.h>
+#else
+#error "Your system is not supported!"
+#endif
+
+#include "common/xattr.h"
+
+/*
+ * Sets extended attribute on a file.
+ * Returns 0 on success, -1 on failure.
+ */
+int
+ceph_os_setxattr(const char *path, const char *name,
+    const void *value, size_t size)
+{
+       int error = -1;
+
+#if defined(__FreeBSD__)
+       error = extattr_set_file(path, EXTATTR_NAMESPACE_USER, name, value,
+           size);
+       if (error > 0)
+               error = 0;
+#elif defined(__linux__) 
+       error = setxattr(path, name, value, size, 0);
+#elif defined(DARWIN)
+       error = setxattr(path, name, value, size, 0 /* position */, 0);
+#endif
+
+       return (error);
+}
+
+int
+ceph_os_fsetxattr(int fd, const char *name, const void *value,
+    size_t size)
+{
+       int error = -1;
+
+#if defined(__FreeBSD__)
+       error = extattr_set_fd(fd, EXTATTR_NAMESPACE_USER, name, value, size);
+       if (error > 0)
+               error = 0;
+#elif defined(__linux__)
+       error = fsetxattr(fd, name, value, size, 0);
+#elif defined(DARWIN)
+       error = fsetxattr(fd, name, value, size, 0, 0 /* no options should be indentical to Linux */ );
+#endif
+
+       return (error);
+}
+
+ssize_t
+ceph_os_getxattr(const char *path, const char *name,
+void *value, size_t size)
+{
+       ssize_t error = -1;
+
+#if defined(__FreeBSD__)
+       if (value == NULL || size == 0) {
+               error = extattr_get_file(path, EXTATTR_NAMESPACE_USER, name, value,
+                   size);
+       } else {
+               error = extattr_get_file(path, EXTATTR_NAMESPACE_USER, name, NULL,
+                   0);
+               if (error > 0) {
+                       if (error > size) {
+                               errno = ERANGE;
+                               error = -1;
+                       } else  {
+                               error = extattr_get_file(path, EXTATTR_NAMESPACE_USER,
+                                   name, value, size);
+                       }
+               }
+       }
+#elif defined(__linux__)
+       error = getxattr(path, name, value, size);
+#elif defined(DARWIN)
+       error = getxattr(path, name, value, size, 0 /* position  */, 0);
+       /* ENOATTR and ENODATA have different values */
+       if (error < 0 && errno == ENOATTR)
+               errno = ENODATA;
+#endif
+
+       return (error);
+}
+
+ssize_t
+ceph_os_fgetxattr(int fd, const char *name, void *value,
+    size_t size)
+{
+       ssize_t error = -1;
+
+#if defined(__FreeBSD__)
+       if (value == NULL || size == 0) {
+               error = extattr_get_fd(fd, EXTATTR_NAMESPACE_USER, name, value,
+                   size);
+       } else {
+               error = extattr_get_fd(fd, EXTATTR_NAMESPACE_USER, name, NULL,
+                   0);
+               if (error > 0) {
+                       if (error > size) {
+                               errno = ERANGE;
+                               error = -1;
+                       } else  {
+                               error = extattr_get_fd(fd, EXTATTR_NAMESPACE_USER,
+                                   name, value, size);
+                       }
+               }
+       }
+#elif defined(__linux__)
+       error = fgetxattr(fd, name, value, size);
+#elif defined(DARWIN)
+       error = fgetxattr(fd, name, value, size, 0, 0 /* no options */);
+       /* ENOATTR and ENODATA have different values */
+       if (error < 0 && errno == ENOATTR)
+               errno = ENODATA;
+#endif
+
+       return (error);
+}
+
+ssize_t
+ceph_os_listxattr(const char *path, char *list, size_t size)
+{
+       ssize_t error = -1;
+
+#if defined(__FreeBSD__)
+       /*
+        * XXX. The format of the list FreeBSD returns differs
+        * from the Linux ones.  We have to perform the conversion. :-(
+        */
+       char *newlist, *p, *p1;
+
+       if (size != 0) {
+               newlist = malloc(size);
+               if (newlist != NULL) {
+                       error = extattr_list_file(path, EXTATTR_NAMESPACE_USER,
+                           newlist, size);
+                       if (error > 0) {
+                               p = newlist;
+                               p1 = list;
+                               while ((p - newlist) < error) {
+                                       uint8_t len = *(uint8_t *)p;
+                                       p++;
+                                       if ((p + len - newlist) > error)
+                                               break;
+                                       if (len > 0) {
+                                               bcopy(p, p1, len);
+                                               p += len;
+                                               p1 += len;
+                                               *p1++ = '\0';
+                                       }
+                               }
+                               error = p1 - list;
+                       }
+                       free(newlist);
+               }
+       } else {
+               error = extattr_list_file(path, EXTATTR_NAMESPACE_USER,
+                   list, size);
+       }
+#elif defined(__linux__)
+       error = listxattr(path, list, size);
+#elif defined(DARWIN)
+       error = listxattr(path, list, size, 0);
+#endif
+
+       return (error);
+}
+
+ssize_t
+ceph_os_flistxattr(int fd, char *list, size_t size)
+{
+       ssize_t error = -1;
+
+#if defined(__FreeBSD__)
+       /*
+        * XXX. The format of the list FreeBSD returns differs
+        * from the Linux ones.  We have to perform the conversion. :-(
+        */
+       char *newlist, *p, *p1;
+
+       if (size != 0) {
+               newlist = malloc(size);
+               if (newlist != NULL) {
+                       error = extattr_list_fd(fd, EXTATTR_NAMESPACE_USER,
+                           newlist, size);
+                       if (error > 0) {
+                               p = newlist;
+                               p1 = list;
+                               while ((p - newlist) < error) {
+                                       uint8_t len = *(uint8_t *)p;
+                                       p++;
+                                       if ((p + len - newlist) > error)
+                                               break;
+                                       if (len > 0) {
+                                               bcopy(p, p1, len);
+                                               p += len;
+                                               p1 += len;
+                                               *p1++ = '\0';
+                                       }
+                               }
+                               error = p1 - list;
+                       }
+                       free(newlist);
+               }
+       } else {
+               error = extattr_list_fd(fd, EXTATTR_NAMESPACE_USER,
+                   list, size);
+       }
+#elif defined(__linux__)
+       error = flistxattr(fd, list, size);
+#elif defined(DARWIN)
+       error = flistxattr(fd, list, size, 0);
+#endif
+
+       return (error);
+}
+
+int
+ceph_os_removexattr(const char *path, const char *name)
+{
+       int error = -1;
+
+#if defined(__FreeBSD__)
+       error = extattr_delete_file(path, EXTATTR_NAMESPACE_USER, name);
+#elif defined(__linux__)
+       error = removexattr(path, name);
+#elif defined(DARWIN)
+       error = removexattr(path, name, 0);
+       /* ENOATTR and ENODATA have different values */
+       if (error < 0 && errno == ENOATTR)
+               errno = ENODATA;
+#endif
+
+       return (error);
+}
+
+int
+ceph_os_fremovexattr(int fd, const char *name)
+{
+       int error = -1;
+
+#if defined(__FreeBSD__)
+       error = extattr_delete_fd(fd, EXTATTR_NAMESPACE_USER, name);
+#elif defined(__linux__)
+       error = fremovexattr(fd, name);
+#elif defined(DARWIN)
+       error = fremovexattr(fd, name, 0);
+       /* ENOATTR and ENODATA have different values */
+       if (error < 0 && errno == ENOATTR)
+               errno = ENODATA;
+#endif
+
+       return (error);
+}