From 9342df70273f7c52ba1c6015c7e4addff7f78a4f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 10 Aug 2007 09:44:13 +0000 Subject: r24304: patch from Bjoern JAcke : attached patches add EA support for Solaris. If no one disagrees, can someone check this in please? metze (This used to be commit 81e5afc363e1f0bdc4768c0f5c696f4152fe5b44) --- source3/lib/system.c | 242 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 242 insertions(+) (limited to 'source3/lib/system.c') diff --git a/source3/lib/system.c b/source3/lib/system.c index 9bca41d978..33633d93ed 100644 --- a/source3/lib/system.c +++ b/source3/lib/system.c @@ -4,6 +4,7 @@ Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Jeremy Allison 1998-2005 Copyright (C) Timur Bakeyev 2005 + Copyright (C) Bjoern Jacke 2006-2007 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1682,6 +1683,17 @@ int sys_dup2(int oldfd, int newfd) SAFE_FREE(msgbuf); } +/******** Solaris EA helper function prototypes ********/ +#ifdef HAVE_ATTROPEN +#define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP +int solaris_write_xattr(int attrfd, const char *value, size_t size); +ssize_t solaris_read_xattr(int attrfd, void *value, size_t size); +ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size); +int solaris_unlinkat(int attrdirfd, const char *name); +int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode); +int solaris_openat(int fildes, const char *path, int oflag, mode_t mode); +#endif + /************************************************************************** Wrappers for extented attribute calls. Based on the Linux package with support for IRIX and (Net|Free)BSD also. Expand as other systems have them. @@ -1730,6 +1742,14 @@ ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t si retval = attr_get(path, attrname, (char *)value, &valuelength, flags); return retval ? retval : valuelength; +#elif defined(HAVE_ATTROPEN) + ssize_t ret = -1; + int attrfd = solaris_attropen(path, name, O_RDONLY, 0); + if (attrfd >= 0) { + ret = solaris_read_xattr(attrfd, value, size); + close(attrfd); + } + return ret; #else errno = ENOSYS; return -1; @@ -1773,6 +1793,14 @@ ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t s retval = attr_get(path, attrname, (char *)value, &valuelength, flags); return retval ? retval : valuelength; +#elif defined(HAVE_ATTROPEN) + ssize_t ret = -1; + int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0); + if (attrfd >= 0) { + ret = solaris_read_xattr(attrfd, value, size); + close(attrfd); + } + return ret; #else errno = ENOSYS; return -1; @@ -1818,6 +1846,14 @@ ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size) retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags); return retval ? retval : valuelength; +#elif defined(HAVE_ATTROPEN) + ssize_t ret = -1; + int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0); + if (attrfd >= 0) { + ret = solaris_read_xattr(attrfd, value, size); + close(attrfd); + } + return ret; #else errno = ENOSYS; return -1; @@ -2002,6 +2038,14 @@ ssize_t sys_listxattr (const char *path, char *list, size_t size) return bsd_attr_list(0, arg, list, size); #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H) return irix_attr_list(path, 0, list, size, 0); +#elif defined(HAVE_ATTROPEN) + ssize_t ret = -1; + int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0); + if (attrdirfd >= 0) { + ret = solaris_list_xattr(attrdirfd, list, size); + close(attrdirfd); + } + return ret; #else errno = ENOSYS; return -1; @@ -2023,6 +2067,14 @@ ssize_t sys_llistxattr (const char *path, char *list, size_t size) return bsd_attr_list(1, arg, list, size); #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H) return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW); +#elif defined(HAVE_ATTROPEN) + ssize_t ret = -1; + int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0); + if (attrdirfd >= 0) { + ret = solaris_list_xattr(attrdirfd, list, size); + close(attrdirfd); + } + return ret; #else errno = ENOSYS; return -1; @@ -2046,6 +2098,14 @@ ssize_t sys_flistxattr (int filedes, char *list, size_t size) return bsd_attr_list(2, arg, list, size); #elif defined(HAVE_ATTR_LISTF) return irix_attr_list(NULL, filedes, list, size, 0); +#elif defined(HAVE_ATTROPEN) + ssize_t ret = -1; + int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0); + if (attrdirfd >= 0) { + ret = solaris_list_xattr(attrdirfd, list, size); + close(attrdirfd); + } + return ret; #else errno = ENOSYS; return -1; @@ -2077,6 +2137,14 @@ int sys_removexattr (const char *path, const char *name) if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; return attr_remove(path, attrname, flags); +#elif defined(HAVE_ATTROPEN) + int ret = -1; + int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0); + if (attrdirfd >= 0) { + ret = solaris_unlinkat(attrdirfd, name); + close(attrdirfd); + } + return ret; #else errno = ENOSYS; return -1; @@ -2106,6 +2174,14 @@ int sys_lremovexattr (const char *path, const char *name) if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; return attr_remove(path, attrname, flags); +#elif defined(HAVE_ATTROPEN) + int ret = -1; + int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0); + if (attrdirfd >= 0) { + ret = solaris_unlinkat(attrdirfd, name); + close(attrdirfd); + } + return ret; #else errno = ENOSYS; return -1; @@ -2137,6 +2213,14 @@ int sys_fremovexattr (int filedes, const char *name) if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; return attr_removef(filedes, attrname, flags); +#elif defined(HAVE_ATTROPEN) + int ret = -1; + int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0); + if (attrdirfd >= 0) { + ret = solaris_unlinkat(attrdirfd, name); + close(attrdirfd); + } + return ret; #else errno = ENOSYS; return -1; @@ -2195,6 +2279,17 @@ int sys_setxattr (const char *path, const char *name, const void *value, size_t if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE; return attr_set(path, attrname, (const char *)value, size, myflags); +#elif defined(HAVE_ATTROPEN) + int ret = -1; + int myflags = O_RDWR; + if (flags & XATTR_CREATE) myflags |= O_EXCL; + if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT; + int attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE); + if (attrfd >= 0) { + ret = solaris_write_xattr(attrfd, value, size); + close(attrfd); + } + return ret; #else errno = ENOSYS; return -1; @@ -2247,6 +2342,17 @@ int sys_lsetxattr (const char *path, const char *name, const void *value, size_t if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE; return attr_set(path, attrname, (const char *)value, size, myflags); +#elif defined(HAVE_ATTROPEN) + int ret = -1; + int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW; + if (flags & XATTR_CREATE) myflags |= O_EXCL; + if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT; + int attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE); + if (attrfd >= 0) { + ret = solaris_write_xattr(attrfd, value, size); + close(attrfd); + } + return ret; #else errno = ENOSYS; return -1; @@ -2300,12 +2406,148 @@ int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE; return attr_setf(filedes, attrname, (const char *)value, size, myflags); +#elif defined(HAVE_ATTROPEN) + int ret = -1; + int myflags = O_RDWR | O_XATTR; + if (flags & XATTR_CREATE) myflags |= O_EXCL; + if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT; + int attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE); + if (attrfd >= 0) { + ret = solaris_write_xattr(attrfd, value, size); + close(attrfd); + } + return ret; #else errno = ENOSYS; return -1; #endif } +/************************************************************************** + helper functions for Solaris' EA support +****************************************************************************/ +#ifdef HAVE_ATTROPEN +static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size) +{ + struct stat sbuf; + + if (fstat(attrfd, &sbuf) == -1) { + errno = ENOATTR; + return -1; + } + + /* This is to return the current size of the named extended attribute */ + if (size == 0) { + return sbuf.st_size; + } + + /* check size and read xattr */ + if (sbuf.st_size > size) { + errno = ERANGE; + return -1; + } + + return read(attrfd, value, sbuf.st_size); +} + +static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size) +{ + ssize_t len = 0; + int stop = 0; + DIR *dirp; + struct dirent *de; + int newfd = dup(attrdirfd); + /* CAUTION: The originating file descriptor should not be + used again following the call to fdopendir(). + For that reason we dup() the file descriptor + here to make things more clear. */ + dirp = fdopendir(newfd); + + while ((de = readdir(dirp))) { + size_t listlen = strlen(de->d_name); + if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) { + /* we don't want "." and ".." here: */ + DEBUG(10,("skipped EA %s\n",de->d_name)); + continue; + } + + if (size == 0) { + /* return the current size of the list of extended attribute names*/ + len += listlen + 1; + } else { + /* check size and copy entrieѕ + nul into list. */ + if ((len + listlen + 1) > size) { + errno = ERANGE; + len = -1; + break; + } else { + safe_strcpy(list + len, de->d_name, listlen); + pstrcpy(list + len, de->d_name); + len += listlen; + list[len] = '\0'; + ++len; + } + } + } + + if (closedir(dirp) == -1) { + DEBUG(0,("closedir dirp failed: %s\n",strerror(errno))); + return -1; + } + return len; +} + +static int solaris_unlinkat(int attrdirfd, const char *name) +{ + if (unlinkat(attrdirfd, name, 0) == -1) { + if (errno == ENOENT) { + errno = ENOATTR; + } + return -1; + } + return 0; +} + +static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode) +{ + int filedes = attropen(path, attrpath, oflag, mode); + if (filedes == -1) { + DEBUG(10,("attropen FAILED: path: %s, name: %s, errno: %s\n",path,attrpath,strerror(errno))); + if (errno == EINVAL) { + errno = ENOTSUP; + } else { + errno = ENOATTR; + } + } + return filedes; +} + +static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode) +{ + int filedes = openat(fildes, path, oflag, mode); + if (filedes == -1) { + DEBUG(10,("openat FAILED: fd: %s, path: %s, errno: %s\n",filedes,path,strerror(errno))); + if (errno == EINVAL) { + errno = ENOTSUP; + } else { + errno = ENOATTR; + } + } + return filedes; +} + +static int solaris_write_xattr(int attrfd, const char *value, size_t size) +{ + if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) { + return 0; + } else { + DEBUG(10,("solaris_write_xattr FAILED!\n")); + return -1; + } +} +#endif /*HAVE_ATTROPEN*/ + + /**************************************************************************** Return the major devicenumber for UNIX extensions. ****************************************************************************/ -- cgit