summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2012-01-27 14:32:19 +0300
committerIgor Pashev <pashev.igor@gmail.com>2012-01-27 14:32:19 +0300
commit74a46085bbffdfc3d69681bb951c45b85c03ddf7 (patch)
tree09ed643235ca1f564ade0e2a815e2a86ae861fc7
parent6f2c706e5158ceffc2065148fc2d00ee57a324b9 (diff)
downloadattr-74a46085bbffdfc3d69681bb951c45b85c03ddf7.tar.gz
Added Solaris support (not sure about namespaces: user., trusted., etc). Symlinks are not supported
-rw-r--r--libattr/Makefile5
-rw-r--r--libattr/solaris.c319
2 files changed, 324 insertions, 0 deletions
diff --git a/libattr/Makefile b/libattr/Makefile
index c084130..c314474 100644
--- a/libattr/Makefile
+++ b/libattr/Makefile
@@ -33,6 +33,11 @@ ifeq ($(PKG_PLATFORM),linux)
CFILES += syscalls.c
else
LSRCFILES = syscalls.c
+ifeq ($(PKG_PLATFORM),sunos)
+CFILES += solaris.c
+else
+LSRCFILES += solaris.c
+endif
endif
LCFLAGS = -include libattr.h
diff --git a/libattr/solaris.c b/libattr/solaris.c
new file mode 100644
index 0000000..966a977
--- /dev/null
+++ b/libattr/solaris.c
@@ -0,0 +1,319 @@
+/*
+ * Copyright (c) 2012 Igor Pashev <pashev.igor@gmail.com>
+ * All Rights Reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#ifndef __EXTENSIONS__
+# define __EXTENSIONS__
+#endif
+#include <string.h>
+
+#include <xattr.h>
+
+ssize_t
+fgetxattr (int filedes, const char *name,
+ void *value, size_t size)
+{
+ int xfd;
+ ssize_t rv;
+ struct stat sb;
+
+ xfd = openat(filedes, name, O_RDONLY | O_XATTR);
+ if (xfd == -1) {
+ if (errno == ENOENT)
+ errno = ENOATTR;
+ return (-1);
+ }
+
+ if (fstat(xfd, &sb) == -1) {
+ rv = -1;
+ } else if (sb.st_size > SSIZE_MAX) {
+ errno = ERANGE;
+ rv = -1;
+ } else if (value == NULL || size == 0) {
+ rv = sb.st_size;
+ } else if (sb.st_size > size) {
+ errno = ERANGE;
+ rv = -1;
+ } else {
+ rv = read(xfd, value, size);
+ }
+
+ (void) close(xfd);
+ return (rv);
+}
+
+ssize_t
+getxattr (const char *path, const char *name,
+ void *value, size_t size)
+{
+ int fd;
+ ssize_t rv;
+
+ fd = open(path, O_RDONLY);
+ if (fd == -1) {
+ return (-1);
+ }
+
+ rv = fgetxattr(fd, name, value, size);
+
+ (void) close(fd);
+ return (rv);
+}
+
+static
+ssize_t
+__fflistxattr (int xfd, char *list, size_t size)
+{
+ ssize_t rv;
+ DIR *d;
+ struct dirent *de;
+ size_t l;
+
+ d = fdopendir(xfd);
+ if (d == NULL) {
+ return (-1);
+ }
+
+ rv = 0;
+ while ((de = readdir(d)) != NULL) {
+ if (
+ !strcmp(de->d_name, ".") ||
+ !strcmp(de->d_name, "..") ||
+ !strcmp(de->d_name, "SUNWattr_rw") ||
+ !strcmp(de->d_name, "SUNWattr_ro")
+ )
+ {
+ continue;
+ }
+
+ /* Define __EXTENSIONS__ for strlcpy() */
+ /* http://www.gratisoft.us/todd/papers/strlcpy.html */
+ l = strlcpy(list, de->d_name, size);
+ if (l >= size) {
+ errno = ERANGE;
+ rv = -1;
+ break;
+ }
+
+ rv += l + 1;
+ size -= l + 1;
+ list += l + 1;
+ }
+
+ (void) closedir(d);
+ return (rv);
+}
+
+ssize_t
+flistxattr (int fd, char *list, size_t size)
+{
+ int xfd;
+ ssize_t rv;
+
+ xfd = openat(fd, ".", O_RDONLY);
+ if (xfd == -1) {
+ return (-1);
+ }
+
+ rv = __fflistxattr(xfd, list, size);
+
+ (void) close(xfd);
+ return (rv);
+}
+
+ssize_t
+listxattr (const char * path, char *list, size_t size)
+{
+ int xfd;
+ ssize_t rv;
+
+ xfd = attropen(path, ".", O_RDONLY);
+ if (xfd == -1) {
+ return (-1);
+ }
+
+ rv = __fflistxattr(xfd, list, size);
+
+ (void) close(xfd);
+ return (rv);
+}
+
+int
+fremovexattr (int filedes, const char *name)
+{
+ int xfd;
+ int rv;
+
+ xfd = openat(filedes, ".", O_XATTR, 0644);
+ if (xfd == -1) {
+ return (-1);
+ }
+
+ rv = unlinkat(xfd, name, 0);
+ (void) close(xfd);
+
+ if (rv == -1) {
+ if (errno == ENOENT)
+ errno = ENOATTR;
+ }
+ return (rv);
+}
+
+int
+removexattr (const char *path, const char *name)
+{
+ int fd;
+ int rv;
+
+ fd = open(path, O_RDONLY);
+ if (fd == -1) {
+ return (-1);
+ }
+
+ rv = fremovexattr(fd, name);
+
+ (void) close(fd);
+ return (rv);
+}
+
+int
+fsetxattr (int filedes, const char *name,
+ const void *value, size_t size, int flags)
+{
+ int xfd;
+ ssize_t w;
+
+ xfd = openat(filedes, name,
+ O_XATTR | O_TRUNC |
+ ((flags & XATTR_CREATE) ? O_EXCL : 0) |
+ ((flags & XATTR_REPLACE) ? O_RDWR : O_WRONLY | O_CREAT),
+ 0644);
+
+ if (xfd == -1) {
+ return (-1);
+ }
+
+ while (size > 0) {
+ w = write(xfd, value, size);
+ if (w == -1) {
+ break;
+ }
+ size -= w;
+ value += w;
+ }
+
+ (void) close(xfd);
+ return ((w == -1) ? -1 : 0);
+}
+
+int
+setxattr (const char *path, const char *name,
+ const void *value, size_t size, int flags)
+{
+ int fd;
+ int rv;
+
+ fd = open(path, O_RDONLY);
+ if (fd == -1) {
+ return (-1);
+ }
+
+ rv = fsetxattr(fd, name, value, size, flags);
+
+ (void) close(fd);
+ return (rv);
+}
+
+
+
+
+/*
+ * Extended attributes for symlinks are not supported
+ *
+ */
+
+
+ssize_t
+lgetxattr (const char *path, const char *name,
+ void *value, size_t size)
+{
+ struct stat s;
+ if (lstat(path, &s) == -1) {
+ return (-1);
+ }
+ if (S_ISLNK(s.st_mode)) {
+ errno = ENOTSUP;
+ return (-1);
+ }
+
+ return getxattr(path, name, value, size);
+}
+
+int
+lsetxattr (const char *path, const char *name,
+ const void *value, size_t size, int flags)
+{
+ struct stat s;
+ if (lstat(path, &s) == -1) {
+ return (-1);
+ }
+ if (S_ISLNK(s.st_mode)) {
+ errno = ENOTSUP;
+ return (-1);
+ }
+
+ return setxattr(path, name, value, size, flags);
+}
+
+int
+lremovexattr (const char *path, const char *name)
+{
+ struct stat s;
+ if (lstat(path, &s) == -1) {
+ return (-1);
+ }
+ if (S_ISLNK(s.st_mode)) {
+ errno = ENOTSUP;
+ return (-1);
+ }
+
+ return removexattr(path, name);
+}
+
+ssize_t
+llistxattr (const char *path, char *list, size_t size)
+{
+ struct stat s;
+ if (lstat(path, &s) == -1) {
+ return (-1);
+ }
+ if (S_ISLNK(s.st_mode)) {
+ errno = ENOTSUP;
+ return (-1);
+ }
+
+ return listxattr(path, list, size);
+}