diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2012-01-27 14:32:19 +0300 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2012-01-27 14:32:19 +0300 |
commit | 74a46085bbffdfc3d69681bb951c45b85c03ddf7 (patch) | |
tree | 09ed643235ca1f564ade0e2a815e2a86ae861fc7 | |
parent | 6f2c706e5158ceffc2065148fc2d00ee57a324b9 (diff) | |
download | attr-74a46085bbffdfc3d69681bb951c45b85c03ddf7.tar.gz |
Added Solaris support (not sure about namespaces: user., trusted., etc). Symlinks are not supported
-rw-r--r-- | libattr/Makefile | 5 | ||||
-rw-r--r-- | libattr/solaris.c | 319 |
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); +} |