summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Ippolito <bob@redivi.com>2010-01-02 23:11:35 +0000
committerBob Ippolito <bob@redivi.com>2010-01-02 23:11:35 +0000
commit2219053938529df211440e2b5758bc6ecaf17062 (patch)
tree762782b4c4c460c91f743f922fa18d570c955120
parenta4dd71da148892930905d5ffbfe46b33c7daaba1 (diff)
downloadxattr-2219053938529df211440e2b5758bc6ecaf17062.tar.gz
experimental solaris support, test suite
-rw-r--r--Modules/xattr/_xattr.c193
-rw-r--r--setup.py5
2 files changed, 195 insertions, 3 deletions
diff --git a/Modules/xattr/_xattr.c b/Modules/xattr/_xattr.c
index 5c2b3ba..59ee0b1 100644
--- a/Modules/xattr/_xattr.c
+++ b/Modules/xattr/_xattr.c
@@ -1,6 +1,12 @@
#include "Python.h"
#ifdef __FreeBSD__
#include <sys/extattr.h>
+#elif defined(__SUN__) || defined(__sun__)
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <dirent.h>
#else
#include <sys/xattr.h>
#endif
@@ -226,6 +232,191 @@ static ssize_t xattr_flistxattr(int fd, char *namebuf, size_t size, int options)
return rv;
}
+#elif defined(__SUN__) || defined(__sun__)
+
+/* Solaris 9 and later compatibility API */
+#define XATTR_XATTR_NOFOLLOW 0x0001
+#define XATTR_XATTR_CREATE 0x0002
+#define XATTR_XATTR_REPLACE 0x0004
+#define XATTR_XATTR_NOSECURITY 0x0008
+
+#define u_int32_t unsigned int
+
+static ssize_t xattr_fgetxattr(int fd, const char *name, void *value,
+ ssize_t size, u_int32_t position, int options)
+{
+ int xfd;
+ ssize_t bytes;
+ struct stat statbuf;
+
+ /* XXX should check that name does not have / characters in it */
+ xfd = openat(fd, name, O_RDONLY | O_XATTR);
+ close(fd);
+ if (xfd == -1) {
+ return -1;
+ }
+ if (lseek(xfd, position, SEEK_SET) == -1) {
+ close(xfd);
+ return -1;
+ }
+ if (value == NULL) {
+ if (fstat(xfd, &statbuf) == -1) {
+ close(xfd);
+ return -1;
+ }
+ close(xfd);
+ return statbuf.st_size;
+ }
+ /* XXX should keep reading until the buffer is exhausted or EOF */
+ bytes = read(xfd, value, size);
+ close(xfd);
+ return bytes;
+}
+
+static ssize_t xattr_getxattr(const char *path, const char *name,
+ void *value, ssize_t size, u_int32_t position,
+ int options)
+{
+ int fd;
+ ssize_t bytes;
+
+ if (position != 0 ||
+ !(options == 0 || options == XATTR_XATTR_NOFOLLOW)) {
+ return -1;
+ }
+
+ fd = open(path,
+ O_RDONLY |
+ ((options & XATTR_XATTR_NOFOLLOW) ? O_NOFOLLOW : 0));
+ if (fd == -1) {
+ return -1;
+ }
+ bytes = xattr_fgetxattr(fd, name, value, size, position, options);
+ close(fd);
+ return bytes;
+}
+
+static ssize_t xattr_fsetxattr(int fd, const char *name, void *value,
+ ssize_t size, u_int32_t position, int options)
+{
+ int xfd;
+ ssize_t bytes = 0;
+
+ /* XXX should check that name does not have / characters in it */
+ xfd = openat(fd, name, O_XATTR | O_TRUNC |
+ ((options & XATTR_XATTR_CREATE) ? O_EXCL : 0) |
+ ((options & XATTR_XATTR_NOFOLLOW) ? O_NOFOLLOW : 0) |
+ ((options & XATTR_XATTR_REPLACE) ? O_RDWR : O_WRONLY|O_CREAT),
+ 0644);
+ if (xfd == -1) {
+ return -1;
+ }
+ while (size > 0) {
+ bytes = write(xfd, value, size);
+ if (bytes == -1) {
+ close(xfd);
+ return -1;
+ }
+ size -= bytes;
+ value += bytes;
+ }
+ close(xfd);
+ return 0;
+}
+
+static ssize_t xattr_setxattr(const char *path, const char *name,
+ void *value, ssize_t size, u_int32_t position,
+ int options)
+{
+ int fd;
+ ssize_t bytes;
+
+ if (position != 0) {
+ return -1;
+ }
+
+ fd = open(path,
+ O_RDONLY | (options & XATTR_XATTR_NOFOLLOW) ? O_NOFOLLOW : 0);
+ if (fd == -1) {
+ return -1;
+ }
+ bytes = xattr_fsetxattr(fd, name, value, size, position, options);
+ close(fd);
+ return bytes;
+}
+
+static ssize_t xattr_fremovexattr(int fd, const char *name, int options)
+{
+ int xfd, status;
+ /* XXX should check that name does not have / characters in it */
+ if (!(options == 0 || options == XATTR_XATTR_NOFOLLOW)) {
+ return -1;
+ }
+ if (options & XATTR_XATTR_NOFOLLOW) {
+ return -1;
+ }
+ xfd = openat(fd, ".", O_XATTR, 0644);
+ if (xfd == -1) {
+ return -1;
+ }
+ status = unlinkat(xfd, name, 0);
+ close(xfd);
+ return status;
+}
+
+static ssize_t xattr_removexattr(const char *path, const char *name,
+ int options)
+{
+ int fd;
+ ssize_t status;
+
+ fd = open(path,
+ O_RDONLY | ((options & XATTR_XATTR_NOFOLLOW) ? O_NOFOLLOW : 0));
+ if (fd == -1) {
+ return -1;
+ }
+ status = xattr_fremovexattr(fd, name, options);
+ close(fd);
+ return status;
+}
+
+static ssize_t xattr_xflistxattr(int xfd, char *namebuf, size_t size, int options)
+{
+ int esize;
+ DIR *dirp;
+ struct dirent *entry;
+ ssize_t nsize = 0;
+
+ dirp = fdopendir(xfd);
+ while (entry = readdir(dirp)) {
+ esize = strlen(entry->d_name);
+ if (nsize + esize + 1 < size) {
+ strcat(namebuf + nsize, entry->d_name);
+ nsize += esize + 1; /* +1 for \0 */
+ } else {
+ break;
+ }
+ }
+ closedir(dirp);
+ return nsize;
+}
+static ssize_t xattr_flistxattr(int fd, char *namebuf, size_t size, int options)
+{
+ int xfd;
+
+ xfd = openat(fd, ".", O_RDONLY);
+ return xattr_xflistxattr(xfd, namebuf, size, options);
+}
+
+static ssize_t xattr_listxattr(const char *path, char *namebuf,
+ size_t size, int options)
+{
+ int xfd;
+
+ xfd = attropen(path, ".", O_RDONLY);
+ return xattr_xflistxattr(xfd, namebuf, size, options);
+}
+
#elif !defined(XATTR_NOFOLLOW)
/* Linux compatibility API */
#define XATTR_XATTR_NOFOLLOW 0x0001
@@ -342,7 +533,7 @@ static ssize_t xattr_flistxattr(int fd, char *namebuf, size_t size, int options)
}
}
-#else
+#else /* Mac OS X assumed */
#define xattr_getxattr getxattr
#define xattr_fgetxattr fgetxattr
#define xattr_removexattr removexattr
diff --git a/setup.py b/setup.py
index 4ba4f02..a0bffec 100644
--- a/setup.py
+++ b/setup.py
@@ -12,8 +12,8 @@ Extended attributes extend the basic attributes of files and directories
in the file system. They are stored as name:data pairs associated with
file system objects (files, directories, symlinks, etc).
-Extended attributes are currently only available on Darwin 8.0+ (Max OS X 10.4)
-and Linux 2.6+.
+Extended attributes are currently only available on Darwin 8.0+ (Mac OS X 10.4)
+and Linux 2.6+. Experimental support is included for Solaris and FreeBSD.
"""
CLASSIFIERS = filter(None, map(str.strip,
@@ -50,5 +50,6 @@ setup(
"xattr = xattr.tool:main",
],
},
+ test_suite="xattr.tests.all_tests_suite",
zip_safe=False,
)