* FIX: netatalk: fix a crash on Solaris when registering with mDNS
* FIX: netatalk: SIGHUP would kill the process instead of being resent
to the other Netatalk processes, bug #579
+* FIX: afpd: Solaris locking problem, bug #559
Changes in 3.1.6
================
int size = 0;
int toUTF8 = 0;
- LOG(log_maxdebug, logtype_afpd, "came('%s'): {start}", cfrombstr(dir->d_fullpath));
+ LOG(log_maxdebug, logtype_afpd, "cname('%s'): {start}", cfrombstr(dir->d_fullpath));
data = *cpath;
afp_errno = AFPERR_NOOBJ;
ret.d_dir = dir;
}
- LOG(log_debug, logtype_afpd, "came('%s') {end: curdir:'%s', path:'%s'}",
+ LOG(log_debug, logtype_afpd, "cname('%s') {end: curdir:'%s', path:'%s'}",
cfrombstr(dir->d_fullpath),
cfrombstr(curdir->d_fullpath),
ret.u_name);
*/
int afp_listextattr(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
{
- int ret, oflag = 0, adflags = 0;
+ int ret, oflag = 0, adflags = 0, fd = -1;
uint16_t vid, bitmap, uint16;
uint32_t did, maxreply, tmpattr;
struct vol *vol;
struct path *s_path;
struct stat *st;
struct adouble ad, *adp = NULL;
+ struct ofork *opened = NULL;
char *uname, *FinderInfo;
char emptyFinderInfo[32] = { 0 };
via FPGetExtAttr !
*/
- if (S_ISDIR(st->st_mode))
- adflags = ADFLAGS_DIR;
-
adp = &ad;
ad_init(adp, vol);
+
+ if (path_isadir(s_path)) {
+ LOG(log_debug, logtype_afpd, "afp_listextattr(%s): is a dir", uname);
+ adflags = ADFLAGS_DIR;
+ } else {
+ LOG(log_debug, logtype_afpd, "afp_listextattr(%s): is a file", uname);
+ opened = of_findname(vol, s_path);
+ if (opened) {
+ adp = opened->of_ad;
+ fd = ad_meta_fileno(adp);
+ }
+ }
+
if (ad_metadata(uname, adflags, adp) != 0 ) {
switch (errno) {
case ENOENT:
attrbuflen += strlen(ea_resourcefork) + 1;
}
}
-
- ret = vol->vfs->vfs_ea_list(vol, attrnamebuf, &attrbuflen, uname, oflag);
+
+ ret = vol->vfs->vfs_ea_list(vol, attrnamebuf, &attrbuflen, uname, oflag, fd);
switch (ret) {
case AFPERR_BADTYPE:
int afp_getextattr(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
{
- int ret, oflag = 0;
+ int ret, oflag = 0, fd = -1;
uint16_t vid, bitmap, attrnamelen;
uint32_t did, maxreply;
char attruname[256];
struct vol *vol;
struct dir *dir;
struct path *s_path;
+ struct adouble ad, *adp = NULL;
+ struct ofork *opened = NULL;
*rbuflen = 0;
rbuf += sizeof(bitmap);
*rbuflen += sizeof(bitmap);
+ if (path_isadir(s_path)) {
+ LOG(log_debug, logtype_afpd, "afp_getextattr(%s): is a dir", s_path->u_name);
+ } else {
+ LOG(log_debug, logtype_afpd, "afp_getextattr(%s): is a file", s_path->u_name);
+ opened = of_findname(vol, s_path);
+ if (opened) {
+ adp = opened->of_ad;
+ fd = ad_meta_fileno(adp);
+ }
+ }
+
/*
Switch on maxreply:
if its 0 we must return the size of the requested attribute,
if its non 0 we must return the attribute.
*/
if (maxreply == 0)
- ret = vol->vfs->vfs_ea_getsize(vol, rbuf, rbuflen, s_path->u_name, oflag, attruname);
+ ret = vol->vfs->vfs_ea_getsize(vol, rbuf, rbuflen, s_path->u_name, oflag, attruname, fd);
else
- ret = vol->vfs->vfs_ea_getcontent(vol, rbuf, rbuflen, s_path->u_name, oflag, attruname, maxreply);
+ ret = vol->vfs->vfs_ea_getcontent(vol, rbuf, rbuflen, s_path->u_name, oflag, attruname, maxreply, fd);
return ret;
}
int afp_setextattr(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
{
- int oflag = 0, ret;
+ int oflag = 0, ret, fd = -1;
uint16_t vid, bitmap, attrnamelen;
uint32_t did, attrsize;
char attruname[256];
struct vol *vol;
struct dir *dir;
struct path *s_path;
+ struct adouble ad, *adp = NULL;
+ struct ofork *opened = NULL;
*rbuflen = 0;
ibuf += 2;
return AFPERR_NOOBJ;
}
+ if (path_isadir(s_path)) {
+ LOG(log_debug, logtype_afpd, "afp_setextattr(%s): is a dir", s_path->u_name);
+ } else {
+ LOG(log_debug, logtype_afpd, "afp_setextattr(%s): is a file", s_path->u_name);
+ opened = of_findname(vol, s_path);
+ if (opened) {
+ adp = opened->of_ad;
+ fd = ad_meta_fileno(adp);
+ }
+ }
+
+
if ((unsigned long)ibuf & 1)
ibuf++;
LOG(log_debug, logtype_afpd, "afp_setextattr(%s): EA: %s, size: %u", s_path->u_name, to_stringz(attrmname, attrnamelen), attrsize);
- ret = vol->vfs->vfs_ea_set(vol, s_path->u_name, attruname, ibuf, attrsize, oflag);
+ ret = vol->vfs->vfs_ea_set(vol, s_path->u_name, attruname, ibuf, attrsize, oflag, fd);
return ret;
}
int afp_remextattr(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
{
- int oflag = 0, ret;
+ int oflag = 0, ret, fd = -1;
uint16_t vid, bitmap, attrnamelen;
uint32_t did;
char attruname[256];
struct vol *vol;
struct dir *dir;
struct path *s_path;
+ struct adouble ad, *adp = NULL;
+ struct ofork *opened = NULL;
*rbuflen = 0;
ibuf += 2;
/* get name */
if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
- LOG(log_debug, logtype_afpd, "afp_setextattr: cname error: %s", strerror(errno));
+ LOG(log_debug, logtype_afpd, "afp_remextattr: cname error: %s", strerror(errno));
return AFPERR_NOOBJ;
}
+ if (path_isadir(s_path)) {
+ LOG(log_debug, logtype_afpd, "afp_remextattr(%s): is a dir", s_path->u_name);
+ } else {
+ LOG(log_debug, logtype_afpd, "afp_remextattr(%s): is a file", s_path->u_name);
+ opened = of_findname(vol, s_path);
+ if (opened) {
+ adp = opened->of_ad;
+ fd = ad_meta_fileno(adp);
+ }
+ }
+
if ((unsigned long)ibuf & 1)
ibuf++;
LOG(log_debug, logtype_afpd, "afp_remextattr(%s): EA: %s", s_path->u_name, to_stringz(ibuf, attrnamelen));
- ret = vol->vfs->vfs_ea_remove(vol, s_path->u_name, attruname, oflag);
+ ret = vol->vfs->vfs_ea_remove(vol, s_path->u_name, attruname, oflag, fd);
return ret;
}
ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size);
ssize_t sys_listxattr (const char *path, char *list, size_t size);
ssize_t sys_llistxattr (const char *path, char *list, size_t size);
-ssize_t sys_flistxattr (int filedes, char *list, size_t size);
+/* ssize_t sys_flistxattr (int filedes, char *list, size_t size); */
+ssize_t sys_flistxattr (int filedes, const char *path, char *list, size_t size);
int sys_removexattr (const char *path, const char *name);
int sys_lremovexattr (const char *path, const char *name);
-int sys_fremovexattr (int filedes, const char *name);
+/* int sys_fremovexattr (int filedes, const char *name); */
+int sys_fremovexattr (int filedes, const char *path, const char *name);
int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags);
int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags);
int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags);
#define VFS_FUNC_ARGS_REMOVE_ACL const struct vol *vol, const char *path, int dir
#define VFS_FUNC_VARS_REMOVE_ACL vol, path, dir
-#define VFS_FUNC_ARGS_EA_GETSIZE const struct vol * restrict vol, char * restrict rbuf, size_t * restrict rbuflen, const char * restrict uname, int oflag, const char * restrict attruname
-#define VFS_FUNC_VARS_EA_GETSIZE vol, rbuf, rbuflen, uname, oflag, attruname
+#define VFS_FUNC_ARGS_EA_GETSIZE const struct vol * restrict vol, char * restrict rbuf, size_t * restrict rbuflen, const char * restrict uname, int oflag, const char * restrict attruname, int fd
+#define VFS_FUNC_VARS_EA_GETSIZE vol, rbuf, rbuflen, uname, oflag, attruname, fd
-#define VFS_FUNC_ARGS_EA_GETCONTENT const struct vol * restrict vol, char * restrict rbuf, size_t * restrict rbuflen, const char * restrict uname, int oflag, const char * restrict attruname, int maxreply
-#define VFS_FUNC_VARS_EA_GETCONTENT vol, rbuf, rbuflen, uname, oflag, attruname, maxreply
+#define VFS_FUNC_ARGS_EA_GETCONTENT const struct vol * restrict vol, char * restrict rbuf, size_t * restrict rbuflen, const char * restrict uname, int oflag, const char * restrict attruname, int maxreply, int fd
+#define VFS_FUNC_VARS_EA_GETCONTENT vol, rbuf, rbuflen, uname, oflag, attruname, maxreply, fd
-#define VFS_FUNC_ARGS_EA_LIST const struct vol * restrict vol, char * restrict attrnamebuf, size_t * restrict buflen, const char * restrict uname, int oflag
-#define VFS_FUNC_VARS_EA_LIST vol, attrnamebuf, buflen, uname, oflag
+#define VFS_FUNC_ARGS_EA_LIST const struct vol * restrict vol, char * restrict attrnamebuf, size_t * restrict buflen, const char * restrict uname, int oflag, int fd
+#define VFS_FUNC_VARS_EA_LIST vol, attrnamebuf, buflen, uname, oflag, fd
-#define VFS_FUNC_ARGS_EA_SET const struct vol * restrict vol, const char * restrict uname, const char * restrict attruname, const char * restrict ibuf, size_t attrsize, int oflag
-#define VFS_FUNC_VARS_EA_SET vol, uname, attruname, ibuf, attrsize, oflag
+#define VFS_FUNC_ARGS_EA_SET const struct vol * restrict vol, const char * restrict uname, const char * restrict attruname, const char * restrict ibuf, size_t attrsize, int oflag, int fd
+#define VFS_FUNC_VARS_EA_SET vol, uname, attruname, ibuf, attrsize, oflag, fd
-#define VFS_FUNC_ARGS_EA_REMOVE const struct vol * restrict vol, const char * restrict uname, const char * restrict attruname, int oflag
-#define VFS_FUNC_VARS_EA_REMOVE vol, uname, attruname, oflag
+#define VFS_FUNC_ARGS_EA_REMOVE const struct vol * restrict vol, const char * restrict uname, const char * restrict attruname, int oflag, int fd
+#define VFS_FUNC_VARS_EA_REMOVE vol, uname, attruname, oflag, fd
/*
* Forward declaration. We need it because of the circular inclusion of
*/
int get_eacontent(VFS_FUNC_ARGS_EA_GETCONTENT)
{
- int ret = AFPERR_MISC, fd = -1;
+ int ret = AFPERR_MISC;
unsigned int count = 0;
uint32_t uint32;
size_t toread;
LOG(log_debug7, logtype_afpd, "sys_getextattr_size(%s): attribute: \"%s\"", uname, attruname);
- if ((oflag & O_NOFOLLOW) ) {
- ret = sys_lgetxattr(uname, attruname, rbuf +4, 0);
- }
- else {
- ret = sys_getxattr(uname, attruname, rbuf +4, 0);
+ /* PBaranski fix */
+ if (fd != -1) {
+ LOG(log_debug, logtype_afpd, "sys_get_easize(%s): file is already opened", uname);
+ ret = sys_fgetxattr(fd, attruname, rbuf +4, 0);
+ } else {
+ if ((oflag & O_NOFOLLOW) ) {
+ ret = sys_lgetxattr(uname, attruname, rbuf +4, 0);
+ }
+ else {
+ ret = sys_getxattr(uname, attruname, rbuf +4, 0);
+ }
}
+ /* PBaranski fix */
+
if (ret == -1) {
memset(rbuf, 0, 4);
* oflag (r) link and create flag
* attruname (r) name of attribute
* maxreply (r) maximum EA size as of current specs/real-life
- *
+ * fd (r) file descriptor
* Returns: AFP code: AFP_OK on success or appropiate AFP error code
*
* Effects:
LOG(log_debug7, logtype_afpd, "sys_getextattr_content(%s): attribute: \"%s\", size: %u", uname, attruname, maxreply);
- if ((oflag & O_NOFOLLOW) ) {
- ret = sys_lgetxattr(uname, attruname, rbuf +4, maxreply);
- }
- else {
- ret = sys_getxattr(uname, attruname, rbuf +4, maxreply);
+ /* PBaranski fix */
+ if (fd != -1) {
+ LOG(log_debug, logtype_afpd, "sys_get_eacontent(%s): file is already opened", uname);
+ ret = sys_fgetxattr(fd, attruname, rbuf +4, maxreply);
+ } else {
+ if ((oflag & O_NOFOLLOW) ) {
+ ret = sys_lgetxattr(uname, attruname, rbuf +4, maxreply);
+ }
+ else {
+ ret = sys_getxattr(uname, attruname, rbuf +4, maxreply);
+ }
}
-
+ /* PBaranski fix */
+
if (ret == -1) {
memset(rbuf, 0, 4);
*rbuflen += 4;
int ret, len, nlen;
char *buf;
char *ptr;
-
+ struct adouble ad, *adp;
+
buf = malloc(ATTRNAMEBUFSIZ);
if (!buf)
return AFPERR_MISC;
- if ((oflag & O_NOFOLLOW)) {
- ret = sys_llistxattr(uname, buf, ATTRNAMEBUFSIZ);
- }
- else {
- ret = sys_listxattr(uname, buf, ATTRNAMEBUFSIZ);
+ /* PBaranski fix */
+ if ( fd != -1) {
+ LOG(log_debug, logtype_afpd, "sys_list_eas(%s): file is already opened", uname);
+ ret = sys_flistxattr(fd, uname, buf, ATTRNAMEBUFSIZ);
+ } else {
+ if ((oflag & O_NOFOLLOW)) {
+ ret = sys_llistxattr(uname, buf, ATTRNAMEBUFSIZ);
+ }
+ else {
+ ret = sys_listxattr(uname, buf, ATTRNAMEBUFSIZ);
+ }
}
+ /* PBaranski fix */
if (ret == -1) switch(errno) {
case OPEN_NOFOLLOW_ERRNO:
else if ((oflag & O_TRUNC) )
attr_flag |= XATTR_REPLACE;
- if ((oflag & O_NOFOLLOW) ) {
- ret = sys_lsetxattr(uname, attruname, ibuf, attrsize,attr_flag);
- }
- else {
- ret = sys_setxattr(uname, attruname, ibuf, attrsize, attr_flag);
+ /* PBaranski fix */
+ if ( fd != -1) {
+ LOG(log_debug, logtype_afpd, "sys_set_ea(%s): file is already opened", uname);
+ ret = sys_fsetxattr(fd, attruname, ibuf, attrsize, attr_flag);
+ } else {
+ if ((oflag & O_NOFOLLOW) ) {
+ ret = sys_lsetxattr(uname, attruname, ibuf, attrsize,attr_flag);
+ }
+ else {
+ ret = sys_setxattr(uname, attruname, ibuf, attrsize, attr_flag);
+ }
}
+ /* PBaranski fix */
if (ret == -1) {
switch(errno) {
* uname (r) filename
* attruname (r) EA name
* oflag (r) link and create flag
+ * fd (r) file descriptor
*
* Returns: AFP code: AFP_OK on success or appropiate AFP error code
*
{
int ret;
- if ((oflag & O_NOFOLLOW) ) {
- ret = sys_lremovexattr(uname, attruname);
- }
- else {
- ret = sys_removexattr(uname, attruname);
+ /* PBaranski fix */
+ if ( fd != -1) {
+ LOG(log_debug, logtype_afpd, "sys_remove_ea(%s): file is already opened", uname);
+ ret = sys_fremovexattr(fd, uname, attruname);
+ } else {
+ if ((oflag & O_NOFOLLOW) ) {
+ ret = sys_lremovexattr(uname, attruname);
+ }
+ else {
+ ret = sys_removexattr(uname, attruname);
+ }
}
+ /* PBaranski fix */
if (ret == -1) {
switch(errno) {
static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
static int solaris_unlinkat(int attrdirfd, const char *name);
static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
+static int solaris_attropenat(int filedes, const char *path, const char *attrpath, int oflag, mode_t mode);
static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
#endif
#endif
}
+ssize_t sys_flistxattr (int filedes, const char *path, char *list, size_t size)
+{
+#if defined(HAVE_LISTXATTR)
+ ssize_t ret;
+
+#ifndef XATTR_ADD_OPT
+ ret = listxattr(path, list, size);
+#else
+ int options = 0;
+ ret = listxattr(path, list, size, options);
+#endif
+ return remove_user(ret, list, size);
+
+#elif defined(HAVE_LISTEA)
+ return listea(path, list, size);
+#elif defined(HAVE_EXTATTR_LIST_FILE)
+ extattr_arg arg;
+ arg.path = path;
+ 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_attropenat(filedes, path, ".", O_RDONLY, 0);
+ if (attrdirfd >= 0) {
+ ret = solaris_list_xattr(attrdirfd, list, size);
+ close(attrdirfd);
+ }
+ return ret;
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
ssize_t sys_llistxattr (const char *path, char *list, size_t size)
{
#if defined(HAVE_LLISTXATTR)
#endif
}
+int sys_fremovexattr (int filedes, const char *path, const char *uname)
+{
+ const char *name = prefix(uname);
+#if defined(HAVE_REMOVEXATTR)
+#ifndef XATTR_ADD_OPT
+ return removexattr(path, name);
+#else
+ int options = 0;
+ return removexattr(path, name, options);
+#endif
+#elif defined(HAVE_REMOVEEA)
+ return removeea(path, name);
+#elif defined(HAVE_EXTATTR_DELETE_FILE)
+ return extattr_delete_file(path, EXTATTR_NAMESPACE_USER, uname);
+#elif defined(HAVE_ATTR_REMOVE)
+ int flags = 0;
+ char *attrname = strchr(name,'.') + 1;
+
+ 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_attropenat(filedes, path, ".", O_RDONLY, 0);
+ if (attrdirfd >= 0) {
+ ret = solaris_unlinkat(attrdirfd, name);
+ close(attrdirfd);
+ }
+ return ret;
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
int sys_lremovexattr (const char *path, const char *uname)
{
const char *name = prefix(uname);
return eafd;
}
+static int solaris_attropenat(int filedes, const char *path, const char *attrpath, int oflag, mode_t mode)
+{
+ EC_INIT;
+ int eafd = -1;
+
+ if ((eafd = openat(filedes, attrpath, oflag | O_XATTR, mode)) == -1) {
+ switch (errno) {
+ case ENOENT:
+ case EEXIST:
+ EC_FAIL;
+ default:
+ LOG(log_debug, logtype_default, "openat(\"%s\"): %s", fullpathname(path), strerror(errno));
+ EC_FAIL;
+ }
+ }
+
+EC_CLEANUP:
+ if (ret != 0) {
+ if (eafd != -1)
+ close(eafd);
+ eafd = -1;
+ }
+ return eafd;
+}
+
+
static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
{
int filedes;