/* * Ceph - scalable distributed file system * * Copyright (C) 2011 Stanislav Sedov * * 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 #include #include #include #include #include #elif defined(__linux__) #include #include #elif defined(DARWIN) #include #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); }