Makefile
Makefile.in
afpd-mtab.pl
+apple_cleanup
apple_cp
apple_mv
apple_rm
/*
- * $Id: directory.c,v 1.106 2009-10-13 22:55:36 didg Exp $
+ * $Id: directory.c,v 1.107 2009-10-14 15:04:00 franklahm Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
return NULL;
}
if ((size_t)-1 == convert_string_allocate((utf8_encoding())?CH_UTF8_MAC:vol->v_maccharset, CH_UCS2, path->m_name, strlen(path->m_name), &cdir->d_m_name_ucs2)) {
- LOG(log_error, logtype_afpd, "Couldn't set UCS2 name for %s", name);
- cdir->d_m_name_ucs2 = NULL;
+ LOG(log_error, logtype_afpd, "Couldn't set UCS2 name for %s", name);
+ cdir->d_m_name_ucs2 = NULL;
}
cdir->d_did = id;
}
}
- vol->vfs->rf_renamedir(vol, src, dst);
+ vol->vfs->vfs_renamedir(vol, src, dst);
len = strlen( newname );
/* rename() succeeded so we need to update our tree even if we can't open
return AFPERR_OLOCK;
}
}
- err = vol->vfs->rf_deletecurdir(vol);
+ err = vol->vfs->vfs_deletecurdir(vol);
if (err) {
return err;
}
/*
- * $Id: enumerate.c,v 1.45 2009-10-13 22:55:36 didg Exp $
+ * $Id: enumerate.c,v 1.46 2009-10-14 15:04:00 franklahm Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
*/
char *check_dirent(const struct vol *vol, char *name)
{
-
if (!strcmp(name, "..") || !strcmp(name, "."))
return NULL;
- if (!vol->vfs->validupath(vol, name))
+ if (!vol->vfs->vfs_validupath(vol, name))
return NULL;
/* check for vetoed filenames */
if (veto_file(vol->v_veto, name))
return NULL;
+
#if 0
char *m_name = NULL;
/*
- $Id: extattrs.c,v 1.4 2009-10-02 09:32:40 franklahm Exp $
+ $Id: extattrs.c,v 1.5 2009-10-14 15:04:00 franklahm Exp $
Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
This program is free software; you can redistribute it and/or modify
attrbuflen += strlen(ea_resourcefork) + 1;
}
- ret = vol->vfs->list_eas(vol, attrnamebuf, &attrbuflen, uname, oflag);
+ ret = vol->vfs->vfs_ea_list(vol, attrnamebuf, &attrbuflen, uname, oflag);
switch (ret) {
case AFPERR_BADTYPE:
if its non 0 we must return the attribute.
*/
if (maxreply == 0)
- ret = vol->vfs->get_easize(vol, rbuf, rbuflen, s_path->u_name, oflag, attruname);
+ ret = vol->vfs->vfs_ea_getsize(vol, rbuf, rbuflen, s_path->u_name, oflag, attruname);
else
- ret = vol->vfs->get_eacontent(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);
return ret;
}
LOG(log_debug, logtype_afpd, "afp_setextattr(%s): EA: %s, size: %u", s_path->u_name, attrmname, attrsize);
- ret = vol->vfs->set_ea(vol, s_path->u_name, attruname, ibuf, attrsize, oflag);
+ ret = vol->vfs->vfs_ea_set(vol, s_path->u_name, attruname, ibuf, attrsize, oflag);
return ret;
}
LOG(log_debug, logtype_afpd, "afp_remextattr(%s): EA: %s", s_path->u_name, attrmname);
- ret = vol->vfs->remove_ea(vol, s_path->u_name, attruname, oflag);
+ ret = vol->vfs->vfs_ea_remove(vol, s_path->u_name, attruname, oflag);
return ret;
}
/*
- * $Id: file.c,v 1.112 2009-10-13 22:55:36 didg Exp $
+ * $Id: file.c,v 1.113 2009-10-14 15:04:00 franklahm Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
}
}
- if (vol->vfs->rf_renamefile(vol, src, dst) < 0 ) {
+ if (vol->vfs->vfs_renamefile(vol, src, dst) < 0 ) {
int err;
err = errno;
if (adp && ad_tmplock( &ad, ADEID_DFORK, ADLOCK_WR, 0, 0, 0 ) < 0) {
err = AFPERR_BUSY;
}
- else if (!(err = vol->vfs->rf_deletefile(vol, file)) && !(err = netatalk_unlink( file )) ) {
+ else if (!(err = vol->vfs->vfs_deletefile(vol, file)) && !(err = netatalk_unlink( file )) ) {
cnid_t id;
if (checkAttrib && (id = cnid_get(vol->v_cdb, curdir->d_did, file, strlen(file))))
{
/*
- * $Id: filedir.c,v 1.56 2009-10-13 22:55:37 didg Exp $
+ * $Id: filedir.c,v 1.57 2009-10-14 15:04:01 franklahm Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
if ((vol->v_flags & AFPVOL_NOHEX) && strchr(name, '/'))
return AFPERR_PARAM;
- if (!vol->vfs->validupath(vol, name)) {
+ if (!vol->vfs->vfs_validupath(vol, name)) {
LOG(log_info, logtype_afpd, "check_name: illegal name: '%s'", name);
return AFPERR_EXIST;
}
int admode = ad_mode("", 0777) | vol->v_fperm;
setfilmode(upath, admode, NULL, vol->v_umask);
- vol->vfs->rf_setfilmode(vol, upath, admode, NULL);
+ vol->vfs->vfs_setfilmode(vol, upath, admode, NULL);
}
setvoltime(obj, vol );
}
/*
- * $Id: unix.c,v 1.54 2009-10-13 22:55:37 didg Exp $
+ * $Id: unix.c,v 1.55 2009-10-14 15:04:01 franklahm Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
if (setfilmode( path->u_name, mode, &path->st, vol->v_umask) < 0)
return -1;
/* we need to set write perm if read set for resource fork */
- return vol->vfs->rf_setfilmode(vol, path->u_name, mode, &path->st);
+ return vol->vfs->vfs_setfilmode(vol, path->u_name, mode, &path->st);
}
if ( stickydirmode(name, DIRBITS | mode, dropbox, vol->v_umask) < 0 )
return -1;
}
- if (vol->vfs->rf_setdirunixmode(vol, name, mode, NULL) < 0 && !vol_noadouble(vol)) {
+ if (vol->vfs->vfs_setdirunixmode(vol, name, mode, NULL) < 0 && !vol_noadouble(vol)) {
return -1 ;
}
if (!dir_rx_set(mode)) {
}
closedir( dir );
- if (vol->vfs->rf_setdirmode(vol, name, mode, NULL) < 0 && !vol_noadouble(vol)) {
+ if (vol->vfs->vfs_setdirmode(vol, name, mode, NULL) < 0 && !vol_noadouble(vol)) {
return -1 ;
}
return -1;
}
- if (vol->vfs->rf_chown(vol, path->u_name, uid, gid ) < 0 && errno != EPERM) {
+ if (vol->vfs->vfs_chown(vol, path->u_name, uid, gid ) < 0 && errno != EPERM) {
LOG(log_debug, logtype_afpd, "setfilowner: rf_chown %d/%d %s: %s",
uid, gid, path->u_name, strerror(errno) );
return -1;
}
closedir( dir );
- if (vol->vfs->rf_setdirowner(vol, name, uid, gid) < 0) {
+ if (vol->vfs->vfs_setdirowner(vol, name, uid, gid) < 0) {
return -1;
}
cnid.h compat.h ddp.h dsi.h ldapconfig.h list.h logger.h \
nbp.h netddp.h pap.h paths.h rtmp.h server_child.h \
server_ipc.h tdb.h uam.h unicode.h util.h uuid.h volinfo.h \
- zip.h ea.h
+ zip.h ea.h acl.h
noinst_HEADERS = cnid_dbd_private.h
--- /dev/null
+/*
+ $Id: acl.h,v 1.1 2009-10-14 15:04:01 franklahm Exp $
+ Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
+
+ 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
+ the Free Software Foundation; either version 2 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 General Public License for more details.
+*/
+
+#ifndef ATALK_ACL_H
+#define ATALK_ACL_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#ifdef HAVE_NFSv4_ACLS
+#include <sys/acl.h>
+#endif /* HAVE_NFSv4_ACLS */
+
+/* Solaris NFSv4 ACL stuff */
+#ifdef HAVE_NFSv4_ACLS
+extern int get_nfsv4_acl(const char *name, ace_t **retAces);
+extern int remove_acl(const char *name);
+#endif /* HAVE_NFSv4_ACLS */
+
+
+#endif /* ATALK_ACL_H */
/*
- $Id: ea.h,v 1.1 2009-10-02 09:32:40 franklahm Exp $
+ $Id: ea.h,v 1.2 2009-10-14 15:04:01 franklahm Exp $
Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
This program is free software; you can redistribute it and/or modify
#include <config.h>
#endif
+#ifdef HAVE_NFSv4_ACLS
+#include <sys/acl.h>
+#endif
+
+#include <atalk/vfs.h>
+
/*
* This seems to be the current limit fo HFS+, we arbitrarily force that
* which also safes us from buffer overflows
kXAttrReplace = 0x4
};
-
+#define EA_INITED 0xea494e54 /* ea"INT", for interfacing ea_open w. ea_close */
#define EA_MAGIC 0x61644541 /* "adEA" */
#define EA_VERSION1 0x01
#define EA_VERSION EA_VERSION1
/* We read the on-disk data into *ea_data and parse it into this*/
struct ea {
+ uint32_t ea_inited; /* needed for interfacing ea_open w. ea_close */
const struct vol *vol; /* vol handle, ea_close needs it */
char *filename; /* name of file, needed by ea_close too */
unsigned int ea_count; /* number of EAs in ea_entries array */
};
#endif /* 0 */
+/* VFS inderected funcs ... : */
+
+/* Default adouble EAs */
+extern int get_easize(VFS_FUNC_ARGS_EA_GETSIZE);
+extern int get_eacontent(VFS_FUNC_ARGS_EA_GETCONTENT);
+extern int list_eas(VFS_FUNC_ARGS_EA_LIST);
+extern int set_ea(VFS_FUNC_ARGS_EA_SET);
+extern int remove_ea(VFS_FUNC_ARGS_EA_REMOVE);
+/* ... EA VFS funcs that deal with file/dir cp/mv/rm */
+extern int ea_deletefile(VFS_FUNC_ARGS_DELETEFILE);
+extern int ea_renamefile(VFS_FUNC_ARGS_RENAMEFILE);
+
+/* Solaris native EAs */
+#ifdef HAVE_SOLARIS_EAS
+extern int sol_get_easize(VFS_FUNC_ARGS_EA_GETSIZE);
+extern int sol_get_eacontent(VFS_FUNC_ARGS_EA_GETCONTENT);
+extern int sol_list_eas(VFS_FUNC_ARGS_EA_LIST);
+extern int sol_set_ea(VFS_FUNC_ARGS_EA_SET);
+extern int sol_remove_ea(VFS_FUNC_ARGS_EA_REMOVE);
+#endif /* HAVE_SOLARIS_EAS */
+
#endif /* ATALK_EA_H */
#include "config.h"
#endif /* HAVE_CONFIG_H */
-#ifdef HAVE_NFSv4_ACLS
-#include <sys/acl.h>
-#endif
-
#include <atalk/adouble.h>
#include <atalk/volume.h>
+#define VFS_FUNC_ARGS_VALIDUPATH const struct vol *vol, const char *name
+#define VFS_FUNC_VARS_VALIDUPATH vol, name
+
+#define VFS_FUNC_ARGS_CHOWN const struct vol *vol, const char *path, uid_t uid, gid_t gid
+#define VFS_FUNC_VARS_CHOWN vol, path, uid, gid
+
+#define VFS_FUNC_ARGS_RENAMEDIR const struct vol *vol, const char *oldpath, const char *newpath
+#define VFS_FUNC_VARS_RENAMEDIR vol, oldpath, newpath
+
+#define VFS_FUNC_ARGS_DELETECURDIR const struct vol *vol
+#define VFS_FUNC_VARS_DELETECURDIR vol
+
+#define VFS_FUNC_ARGS_SETFILEMODE const struct vol *vol, const char *name, mode_t mode, struct stat *st
+#define VFS_FUNC_VARS_SETFILEMODE vol, name, mode, st
+
+#define VFS_FUNC_ARGS_SETDIRMODE const struct vol *vol, const char *name, mode_t mode, struct stat *st
+#define VFS_FUNC_VARS_SETDIRMODE vol, name, mode, st
+
+#define VFS_FUNC_ARGS_SETDIRUNIXMODE const struct vol *vol, const char *name, mode_t mode, struct stat *st
+#define VFS_FUNC_VARS_SETDIRUNIXMODE vol, name, mode, st
+
+#define VFS_FUNC_ARGS_SETDIROWNER const struct vol *vol, const char *name, uid_t uid, gid_t gid
+#define VFS_FUNC_VARS_SETDIROWNER vol, name, uid, gid
+
+#define VFS_FUNC_ARGS_DELETEFILE const struct vol *vol, const char *file
+#define VFS_FUNC_VARS_DELETEFILE vol, file
+
+#define VFS_FUNC_ARGS_RENAMEFILE const struct vol *vol, const char *src, const char *dst
+#define VFS_FUNC_VARS_RENAMEFILE vol, src, dst
+
+#define VFS_FUNC_ARGS_ACL const struct vol *vol, const char *path, int cmd, int count, void *aces
+#define VFS_FUNC_VARS_ACL vol, path, cmd, count, aces
+
+#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, int * 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_GETCONTENT const struct vol * restrict vol, char * restrict rbuf, int * 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_LIST const struct vol * restrict vol, char * restrict attrnamebuf, int * restrict buflen, const char * restrict uname, int oflag
+#define VFS_FUNC_VARS_EA_LIST vol, attrnamebuf, buflen, uname, 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
+#define VFS_FUNC_VARS_EA_SET vol, uname, attruname, ibuf, attrsize, oflag
+
+#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
+
struct vfs_ops {
/* low level adouble fn */
- char *(*ad_path)(const char *, int);
+ char *(*ad_path) (const char *, int); /* name is ad_path because it was too
+ much work to change all calls to
+ sth. different eg vfs_path */
/* */
- int (*validupath)(const struct vol *, const char *);
- int (*rf_chown)(const struct vol *, const char *path, uid_t owner, gid_t group);
- int (*rf_renamedir)(const struct vol *, const char *oldpath, const char *newpath);
- int (*rf_deletecurdir)(const struct vol *);
- int (*rf_setfilmode)(const struct vol *, const char * name, mode_t mode, struct stat *st);
- int (*rf_setdirmode)(const struct vol *, const char * name, mode_t mode, struct stat *st);
- int (*rf_setdirunixmode)(const struct vol *, const char * name, mode_t mode, struct stat *st);
-
- int (*rf_setdirowner)(const struct vol *, const char *path, uid_t owner, gid_t group);
-
- int (*rf_deletefile)(const struct vol *, const char * );
- int (*rf_renamefile)(const struct vol *, const char *oldpath, const char *newpath);
-#ifdef HAVE_NFSv4_ACLS
- int (*rf_acl)(const struct vol *, const char *path, int cmd, int count, ace_t *aces);
- int (*rf_remove_acl)(const struct vol *, const char *path, int dir);
-#endif
+ int (*vfs_validupath) (VFS_FUNC_ARGS_VALIDUPATH);
+ int (*vfs_chown) (VFS_FUNC_ARGS_CHOWN);
+ int (*vfs_renamedir) (VFS_FUNC_ARGS_RENAMEDIR);
+ int (*vfs_deletecurdir) (VFS_FUNC_ARGS_DELETECURDIR);
+ int (*vfs_setfilmode) (VFS_FUNC_ARGS_SETFILEMODE);
+ int (*vfs_setdirmode) (VFS_FUNC_ARGS_SETDIRMODE);
+ int (*vfs_setdirunixmode)(VFS_FUNC_ARGS_SETDIRUNIXMODE);
+ int (*vfs_setdirowner) (VFS_FUNC_ARGS_SETDIROWNER);
+ int (*vfs_deletefile) (VFS_FUNC_ARGS_DELETEFILE);
+ int (*vfs_renamefile) (VFS_FUNC_ARGS_RENAMEFILE);
+
+ /* ACLs */
+ int (*vfs_acl) (VFS_FUNC_ARGS_ACL);
+ int (*vfs_remove_acl) (VFS_FUNC_ARGS_REMOVE_ACL);
/* Extended Attributes */
- int (*get_easize)(const struct vol * restrict, char * restrict rbuf, int * restrict rbuflen, const char * restrict uname, int oflag, const char * restrict attruname);
- int (*get_eacontent)(const struct vol * restrict , char * restrict rbuf, int * restrict rbuflen, const char * restrict uname, int oflag, const char * restrict attruname, int maxreply);
- int (*list_eas)(const struct vol * restrict , char * restrict attrnamebuf, int * restrict buflen, const char * restrict uname, int oflag);
- int (*set_ea)(const struct vol * restrict , const char * restrict uname, const char * restrict attruname, const char * restrict ibuf, size_t attrsize, int oflag);
- int (*remove_ea)(const struct vol * restrict , const char * restrict uname, const char * restrict attruname, int oflag);
+ int (*vfs_ea_getsize) (VFS_FUNC_ARGS_EA_GETSIZE);
+ int (*vfs_ea_getcontent) (VFS_FUNC_ARGS_EA_GETCONTENT);
+ int (*vfs_ea_list) (VFS_FUNC_ARGS_EA_LIST);
+ int (*vfs_ea_set) (VFS_FUNC_ARGS_EA_SET);
+ int (*vfs_ea_remove) (VFS_FUNC_ARGS_EA_REMOVE);
};
extern void initvol_vfs(struct vol * restrict vol);
-/* VFS inderected funcs ... : */
-/* ...default adouble EAs */
-extern int get_easize(const struct vol * restrict vol, char * restrict rbuf, int * restrict rbuflen, const char * restrict uname, int oflag, const char * restrict attruname);
-extern int get_eacontent(const struct vol * restrict vol, char * restrict rbuf, int * restrict rbuflen, const char * restrict uname, int oflag, const char * restrict attruname, int maxreply);
-extern int list_eas(const struct vol * restrict vol, char * restrict attrnamebuf, int * restrict buflen, const char * restrict uname, int oflag);
-extern int set_ea(const struct vol * restrict vol, const char * restrict uname, const char * restrict attruname, const char * restrict ibuf, size_t attrsize, int oflag);
-extern int remove_ea(const struct vol * restrict vol, const char * restrict uname, const char * restrict attruname, int oflag);
-
-/* ... Solaris native EAs */
-#ifdef HAVE_SOLARIS_EAS
-extern int sol_get_easize(const struct vol * restrict vol, char * restrict rbuf, int * restrict rbuflen, const char * restrict uname, int oflag, const char * restrict attruname);
-extern int sol_get_eacontent(const struct vol * restrict vol, char * restrict rbuf, int * restrict rbuflen, const char * restrict uname, int oflag, char * restrict attruname, int maxreply);
-extern int sol_list_eas(const struct vol * restrict vol, char * restrict attrnamebuf, int * restrict buflen, const char * restrict uname, int oflag);
-extern int sol_set_ea(const struct vol * restrict vol, const char * restrict uname, const char * restrict attruname, const char * restrict ibuf,size_t attrsize, int oflag);
-extern int sol_remove_ea(const struct vol * restrict vol, const char * restrict uname, const char * restrict attruname, int oflag);
-#endif /* HAVE_SOLARIS_EAS */
-
-/* Solaris NFSv4 ACL stuff */
-#ifdef HAVE_NFSv4_ACLS
-extern int get_nfsv4_acl(const char *name, ace_t **retAces);
-extern int remove_acl(const char *name);
-#endif /* HAVE_NFSv4_ACLS */
-
#endif /* ATALK_VFS_H */
/*
- $Id: ea.c,v 1.2 2009-10-02 14:57:57 franklahm Exp $
+ $Id: ea.c,v 1.3 2009-10-14 15:04:01 franklahm Exp $
Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
This program is free software; you can redistribute it and/or modify
* Arguments:
*
* ea (rw) pointer to struct ea
- * uname (r) name of file
* attruname (r) name of EA
* attrsize (r) size of ea
* bitmap (r) bitmap from FP func
* Otherwise realloc and put entry at the end. Increments ea->ea_count.
*/
static int ea_addentry(struct ea * restrict ea,
- const char * restrict uname,
const char * restrict attruname,
size_t attrsize,
int bitmap)
* Arguments:
*
* ea (rw) pointer to struct ea
- * uname (r) name of EA
- * attruname (r) size of ea
+ * attruname (r) EA name
*
* Returns: new number of EA entries, -1 on error
*
* ea_close and pack_buffer must honor this.
*/
static int ea_delentry(struct ea * restrict ea,
- const char * restrict uname,
const char * restrict attruname)
{
int ret = 0, count = 0;
if (ea->ea_count == 0) {
+ LOG(log_error, logtype_afpd, "ea_delentry('%s'): illegal ea_count of 0 on deletion");
return -1;
}
*(uint16_t *)ptr = 0; /* count */
ea->ea_size = EA_HEADER_SIZE;
+ ea->ea_inited = EA_INITED;
exit:
if (err != 0) {
return -1;
}
- if ((stat(uname, &st)) != 0) {
- LOG(log_debug, logtype_afpd, "ea_open: cant stat: %s", uname);
- return -1;
- }
-
- /* set it all to 0 */
+ /* Set it all to 0 */
memset(ea, 0, sizeof(struct ea));
ea->vol = vol; /* ea_close needs it */
}
exit:
- if (ret != 0) {
+ if (ret == 0) {
+ ea->ea_inited = EA_INITED;
+ } else {
if (ea->ea_data) {
free(ea->ea_data);
ea->ea_data = NULL;
ea->ea_fd = -1;
}
}
+
return ret;
}
LOG(log_debug, logtype_afpd, "ea_close('%s')", ea->filename);
+ if (ea->ea_inited != EA_INITED) {
+ LOG(log_warning, logtype_afpd, "ea_close('%s'): non initialized ea", ea->filename);
+ return 0;
+ }
+
/* pack header and write it to disk if it was opened EA_RDWR*/
if (ea->ea_flags & EA_RDWR) {
if ((pack_header(ea)) != 0) {
return AFPERR_MISC;
}
- if ((ea_addentry(&ea, uname, attruname, attrsize, oflag)) == -1) {
+ if ((ea_addentry(&ea, attruname, attrsize, oflag)) == -1) {
LOG(log_error, logtype_afpd, "set_ea('%s'): ea_addentry error", uname);
ret = AFPERR_MISC;
goto exit;
return AFPERR_MISC;
}
- if ((ea_delentry(&ea, uname, attruname)) == -1) {
+ if ((ea_delentry(&ea, attruname)) == -1) {
LOG(log_error, logtype_afpd, "remove_ea('%s'): ea_delentry error", uname);
ret = AFPERR_MISC;
goto exit;
}
#endif /* HAVE_SOLARIS_EAS */
+
+/******************************************************************************************
+ * EA VFS funcs that deal with file/dir cp/mv/rm
+ ******************************************************************************************/
+
+int ea_deletefile(VFS_FUNC_ARGS_DELETEFILE)
+{
+ LOG(log_debug, logtype_afpd, "ea_deletefile('%s')", file);
+
+ int count = 0, ret = AFP_OK;
+ struct ea ea;
+
+ /* Open EA stuff */
+ if ((ea_open(vol, file, EA_RDWR, &ea)) != 0) {
+ if (errno == ENOENT)
+ /* no EA files, nothing to do */
+ return AFP_OK;
+ else {
+ LOG(log_error, logtype_afpd, "ea_deletefile('%s'): error calling ea_open", file);
+ return AFPERR_MISC;
+ }
+ }
+
+ while (count < ea.ea_count) {
+ if ((delete_ea_file(&ea, (*ea.ea_entries)[count].ea_name)) != 0) {
+ ret = AFPERR_MISC;
+ continue;
+ }
+ free((*ea.ea_entries)[count].ea_name);
+ (*ea.ea_entries)[count].ea_name = NULL;
+ count++;
+ }
+
+ /* ea_close removes the EA header file for us because all names are NULL */
+ if ((ea_close(&ea)) != 0) {
+ LOG(log_error, logtype_afpd, "ea_deletefile('%s'): error closing ea handle", file);
+ return AFPERR_MISC;
+ }
+
+ return ret;
+}
+
+int ea_renamefile(VFS_FUNC_ARGS_RENAMEFILE)
+{
+ int count = 0;
+ int ret = AFP_OK;
+ size_t easize;
+ char srceapath[ MAXPATHLEN + 1];
+ char *eapath;
+ char *eaname;
+ struct ea srcea;
+ struct ea dstea;
+ struct adouble ad;
+
+ LOG(log_debug, logtype_afpd, "ea_renamefile('%s'/'%s')", src, dst);
+
+
+ /* Open EA stuff */
+ if ((ea_open(vol, src, EA_RDWR, &srcea)) != 0) {
+ if (errno == ENOENT)
+ /* no EA files, nothing to do */
+ return AFP_OK;
+ else {
+ LOG(log_error, logtype_afpd, "ea_renamefile('%s'/'%s'): ea_open error: '%s'", src, dst, src);
+ return AFPERR_MISC;
+ }
+ }
+
+ if ((ea_open(vol, dst, EA_RDWR | EA_CREATE, &dstea)) != 0) {
+ if (errno == ENOENT) {
+ /* Possibly the .AppleDouble folder didn't exist, we create it and try again */
+ ad_init(&ad, vol->v_adouble, vol->v_ad_options);
+ if ((ad_open(dst, ADFLAGS_HF, O_RDWR | O_CREAT, 0666, &ad)) != 0) {
+ LOG(log_error, logtype_afpd, "ea_renamefile('%s/%s'): ad_open error: '%s'", src, dst, dst);
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+ ad_close(&ad, ADFLAGS_HF);
+ if ((ea_open(vol, dst, EA_RDWR | EA_CREATE, &dstea)) != 0) {
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+ }
+ }
+
+ /* Loop through all EAs: */
+ while (count < srcea.ea_count) {
+ /* Move EA */
+ eaname = (*srcea.ea_entries)[count].ea_name;
+ easize = (*srcea.ea_entries)[count].ea_size;
+
+ /* Build src and dst paths for rename() */
+ eapath = ea_path(&srcea, eaname);
+ strcpy(srceapath, eapath);
+ eapath = ea_path(&dstea, eaname);
+
+ LOG(log_maxdebug, logtype_afpd, "ea_renamefile('%s/%s'): moving EA '%s' to '%s'",
+ src, dst, srceapath, eapath);
+
+ /* Add EA to dstea */
+ if ((ea_addentry(&dstea, eaname, easize, 0)) == -1) {
+ LOG(log_error, logtype_afpd, "ea_renamefile('%s/%s'): moving EA '%s' to '%s'",
+ src, dst, srceapath, eapath);
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+
+ /* Remove EA entry from srcea */
+ if ((ea_delentry(&srcea, eaname)) == -1) {
+ LOG(log_error, logtype_afpd, "ea_renamefile('%s/%s'): moving EA '%s' to '%s'",
+ src, dst, srceapath, eapath);
+ ea_delentry(&dstea, eaname);
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+
+ /* Now rename the EA */
+ if ((rename( srceapath, eapath)) < 0) {
+ LOG(log_error, logtype_afpd, "ea_renamefile('%s/%s'): moving EA '%s' to '%s'",
+ src, dst, srceapath, eapath);
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+
+ count++;
+ }
+
+
+exit:
+ ea_close(&srcea);
+ ea_close(&dstea);
+ return ret;
+}
#include <atalk/afp.h>
#include <atalk/adouble.h>
#include <atalk/vfs.h>
+#include <atalk/ea.h>
+#include <atalk/acl.h>
#include <atalk/logger.h>
#include <atalk/util.h>
#include <atalk/volume.h>
#include <atalk/directory.h>
-#ifdef HAVE_NFSv4_ACLS
-extern int remove_acl(const char *name);
-#endif
-
struct perm {
uid_t uid;
gid_t gid;
strcasecmp(name,".AppleDesktop");
}
-static int validupath_adouble(const struct vol *vol, const char *name)
+static int validupath_adouble(VFS_FUNC_ARGS_VALIDUPATH)
{
return (vol->v_flags & AFPVOL_USEDOTS) ?
netatalk_name(name) && strcasecmp(name,".Parent"): name[0] != '.';
}
/* ----------------- */
-static int RF_chown_adouble(const struct vol *vol, const char *path, uid_t uid, gid_t gid)
-
+static int RF_chown_adouble(VFS_FUNC_ARGS_CHOWN)
{
struct stat st;
char *ad_p;
}
/* ----------------- */
-static int RF_renamedir_adouble(const struct vol *vol _U_, const char *oldpath _U_, const char *newpath _U_)
+static int RF_renamedir_adouble(VFS_FUNC_ARGS_RENAMEDIR)
{
return 0;
}
return 0;
}
-static int RF_deletecurdir_adouble(const struct vol *vol)
+static int RF_deletecurdir_adouble(VFS_FUNC_ARGS_DELETECURDIR)
{
int err;
return setfilmode(name, ad_hf_mode(mode), st, v_umask);
}
-static int RF_setfilmode_adouble(const struct vol *vol, const char * name, mode_t mode, struct stat *st)
+static int RF_setfilmode_adouble(VFS_FUNC_ARGS_SETFILEMODE)
{
return adouble_setfilmode(vol->vfs->ad_path( name, ADFLAGS_HF ), mode, st, vol->v_umask);
}
/* ----------------- */
-static int RF_setdirunixmode_adouble(const struct vol *vol, const char * name, mode_t mode, struct stat *st)
+static int RF_setdirunixmode_adouble(VFS_FUNC_ARGS_SETDIRUNIXMODE)
{
char *adouble = vol->vfs->ad_path( name, ADFLAGS_DIR );
int dropbox = vol->v_flags;
return 0;
}
-static int RF_setdirmode_adouble(const struct vol *vol, const char * name, mode_t mode, struct stat *st _U_)
+static int RF_setdirmode_adouble(VFS_FUNC_ARGS_SETDIRMODE)
{
int dropbox = vol->v_flags;
mode_t hf_mode = ad_hf_mode(mode);
return 0;
}
-static int RF_setdirowner_adouble(const struct vol *vol, const char *name, uid_t uid, gid_t gid)
-
+static int RF_setdirowner_adouble(VFS_FUNC_ARGS_SETDIROWNER)
{
int noadouble = vol_noadouble(vol);
char *adouble_p;
}
/* ----------------- */
-static int RF_deletefile_adouble(const struct vol *vol, const char *file )
+static int RF_deletefile_adouble(VFS_FUNC_ARGS_DELETEFILE)
{
return netatalk_unlink(vol->vfs->ad_path( file, ADFLAGS_HF));
}
/* ----------------- */
-static int RF_renamefile_adouble(const struct vol *vol, const char *src, const char *dst)
+static int RF_renamefile_adouble(VFS_FUNC_ARGS_RENAMEFILE)
{
char adsrc[ MAXPATHLEN + 1];
int err = 0;
}
#ifdef HAVE_NFSv4_ACLS
-static int RF_acl(const struct vol *vol, const char *path, int cmd, int count, ace_t *aces)
+static int RF_solaris_acl(VFS_FUNC_ARGS_ACL)
{
static char buf[ MAXPATHLEN + 1];
struct stat st;
return 0;
}
-static int RF_remove_acl(const struct vol *vol, const char *path, int dir)
+static int RF_solaris_remove_acl(VFS_FUNC_ARGS_REMOVE_ACL)
{
int ret;
static char buf[ MAXPATHLEN + 1];
return 0;
}
-static int RF_chown_ads(const struct vol *vol, const char *path, uid_t uid, gid_t gid)
-
+static int RF_chown_ads(VFS_FUNC_ARGS_CHOWN)
{
struct stat st;
char *ad_p;
return netatalk_unlink(name);
}
-static int ads_delete_rf(char *name)
+static int ads_delete_rf(char *name)
{
int err;
return ads_delete_rf(name);
}
-static int RF_deletecurdir_ads(const struct vol *vol _U_)
+static int RF_deletecurdir_ads(VFS_FUNC_ARGS_DELETECURDIR)
{
int err;
return 0;
}
-static int RF_setfilmode_ads(const struct vol *vol, const char * name, mode_t mode, struct stat *st)
+static int RF_setfilmode_ads(VFS_FUNC_ARGS_SETFILEMODE)
{
return ads_setfilmode(ad_dir(vol->vfs->ad_path( name, ADFLAGS_HF )), mode, st, vol->v_umask);
}
/* ------------------- */
-static int RF_setdirunixmode_ads(const struct vol *vol, const char * name, mode_t mode, struct stat *st)
+static int RF_setdirunixmode_ads(VFS_FUNC_ARGS_SETDIRUNIXMODE)
{
char *adouble = vol->vfs->ad_path( name, ADFLAGS_DIR );
char ad_p[ MAXPATHLEN + 1];
return 0;
}
-static int RF_setdirmode_ads(const struct vol *vol, const char * name, mode_t mode, struct stat *st _U_)
+static int RF_setdirmode_ads(VFS_FUNC_ARGS_SETDIRMODE)
{
char *adouble = vol->vfs->ad_path( name, ADFLAGS_DIR );
char ad_p[ MAXPATHLEN + 1];
return 0;
}
-static int RF_setdirowner_ads(const struct vol *vol, const char *name, uid_t uid, gid_t gid)
+static int RF_setdirowner_ads(VFS_FUNC_ARGS_SETDIROWNER)
{
int noadouble = vol_noadouble(vol);
char adouble_p[ MAXPATHLEN + 1];
}
/* ------------------- */
-static int RF_deletefile_ads(const struct vol *vol, const char *file )
+static int RF_deletefile_ads(VFS_FUNC_ARGS_DELETEFILE)
{
char *ad_p = ad_dir(vol->vfs->ad_path(file, ADFLAGS_HF ));
}
/* --------------------------- */
-static int RF_renamefile_ads(const struct vol *vol, const char *src, const char *dst)
+static int RF_renamefile_ads(VFS_FUNC_ARGS_RENAMEFILE)
{
char adsrc[ MAXPATHLEN + 1];
int err = 0;
/*************************************************************************
* osx adouble format
************************************************************************/
-static int validupath_osx(const struct vol *vol, const char *name)
+static int validupath_osx(VFS_FUNC_ARGS_VALIDUPATH)
{
return strncmp(name,"._", 2) && (
(vol->v_flags & AFPVOL_USEDOTS) ? netatalk_name(name): name[0] != '.');
}
/* ---------------- */
-static int RF_renamedir_osx(const struct vol *vol, const char *oldpath, const char *newpath)
+static int RF_renamedir_osx(VFS_FUNC_ARGS_RENAMEDIR)
{
/* We simply move the corresponding ad file as well */
char tempbuf[258]="._";
}
/* ---------------- */
-static int RF_deletecurdir_osx(const struct vol *vol)
+static int RF_deletecurdir_osx(VFS_FUNC_ARGS_DELETECURDIR)
{
return netatalk_unlink( vol->vfs->ad_path(".",0) );
}
/* ---------------- */
-static int RF_setdirunixmode_osx(const struct vol *vol, const char * name, mode_t mode, struct stat *st)
+static int RF_setdirunixmode_osx(VFS_FUNC_ARGS_SETDIRUNIXMODE)
{
return adouble_setfilmode(vol->vfs->ad_path( name, ADFLAGS_DIR ), mode, st, vol->v_umask);
}
/* ---------------- */
-static int
-RF_setdirmode_osx(const struct vol *vol _U_, const char *name _U_, mode_t mode _U_, struct stat *st _U_)
+static int RF_setdirmode_osx(VFS_FUNC_ARGS_SETDIRMODE)
{
return 0;
}
/* ---------------- */
-static int
-RF_setdirowner_osx(const struct vol *vol _U_, const char *path _U_, uid_t uid _U_, gid_t gid _U_)
+static int RF_setdirowner_osx(VFS_FUNC_ARGS_SETDIROWNER)
{
return 0;
}
/* ---------------- */
-static int RF_renamefile_osx(const struct vol *vol, const char *src, const char *dst)
+static int RF_renamefile_osx(VFS_FUNC_ARGS_RENAMEFILE)
{
char adsrc[ MAXPATHLEN + 1];
int err = 0;
return 0;
}
+/********************************************************************************************
+ * VFS chaining
+ ********************************************************************************************/
+
+/*
+ * Up until we really start stacking many VFS modules on top of one another or use
+ * dynamic module loading like we do for UAMs, up until then we just stack VFS modules
+ * via an fixed size array.
+ * All VFS funcs must return AFP_ERR codes. When a func in the chain returns an error
+ * this error code will be returned to the caller, BUT the chain in followed and all
+ * following funcs are called in order to give them a chance.
+ */
+
+/*
+ * Currently the maximum will be:
+ * main adouble module + EA module + ACL module + NULL = 4.
+ * NULL is an end of array marker.
+ */
+static struct vfs_ops *vfs[4] = { NULL };
+
+/*
+ * Define most VFS funcs with macros as they all do the same.
+ * Only "ad_path" and "validupath" will NOT do stacking and only
+ * call the func from the first module.
+ */
+#define VFS_MFUNC(name, args, vars) \
+ static int vfs_ ## name(args) \
+ { \
+ int i = 0, ret = AFP_OK, err; \
+ while (vfs[i]) { \
+ if (vfs[i]->vfs_ ## name) { \
+ err = vfs[i]->vfs_ ## name (vars); \
+ if ((ret == AFP_OK) && (err != AFP_OK)) \
+ ret = err; \
+ } \
+ i ++; \
+ } \
+ return ret; \
+ }
+
+VFS_MFUNC(chown, VFS_FUNC_ARGS_CHOWN, VFS_FUNC_VARS_CHOWN)
+VFS_MFUNC(renamedir, VFS_FUNC_ARGS_RENAMEDIR, VFS_FUNC_VARS_RENAMEDIR)
+VFS_MFUNC(deletecurdir, VFS_FUNC_ARGS_DELETECURDIR, VFS_FUNC_VARS_DELETECURDIR)
+VFS_MFUNC(setfilmode, VFS_FUNC_ARGS_SETFILEMODE, VFS_FUNC_VARS_SETFILEMODE)
+VFS_MFUNC(setdirmode, VFS_FUNC_ARGS_SETDIRMODE, VFS_FUNC_VARS_SETDIRMODE)
+VFS_MFUNC(setdirunixmode, VFS_FUNC_ARGS_SETDIRUNIXMODE, VFS_FUNC_VARS_SETDIRUNIXMODE)
+VFS_MFUNC(setdirowner, VFS_FUNC_ARGS_SETDIROWNER, VFS_FUNC_VARS_SETDIROWNER)
+VFS_MFUNC(deletefile, VFS_FUNC_ARGS_DELETEFILE, VFS_FUNC_VARS_DELETEFILE)
+VFS_MFUNC(renamefile, VFS_FUNC_ARGS_RENAMEFILE, VFS_FUNC_VARS_RENAMEFILE)
+VFS_MFUNC(acl, VFS_FUNC_ARGS_ACL, VFS_FUNC_VARS_ACL)
+VFS_MFUNC(remove_acl, VFS_FUNC_ARGS_REMOVE_ACL, VFS_FUNC_VARS_REMOVE_ACL)
+VFS_MFUNC(ea_getsize, VFS_FUNC_ARGS_EA_GETSIZE, VFS_FUNC_VARS_EA_GETSIZE)
+VFS_MFUNC(ea_getcontent, VFS_FUNC_ARGS_EA_GETCONTENT, VFS_FUNC_VARS_EA_GETCONTENT)
+VFS_MFUNC(ea_list, VFS_FUNC_ARGS_EA_LIST, VFS_FUNC_VARS_EA_LIST)
+VFS_MFUNC(ea_set, VFS_FUNC_ARGS_EA_SET, VFS_FUNC_VARS_EA_SET)
+VFS_MFUNC(ea_remove, VFS_FUNC_ARGS_EA_REMOVE, VFS_FUNC_VARS_EA_REMOVE)
+
+static char *vfs_path(const char *path, int flags)
+{
+ return vfs[0]->ad_path(path, flags);
+}
+
+static int vfs_validupath(VFS_FUNC_ARGS_VALIDUPATH)
+{
+ return vfs[0]->vfs_validupath(VFS_FUNC_VARS_VALIDUPATH);
+}
+
+/*
+ * These function pointers get called from the lib users via vol->vfs->func.
+ * These funcs are defined via the macros above.
+ */
+struct vfs_ops vfs_master_funcs = {
+ vfs_path,
+ vfs_validupath,
+ vfs_chown,
+ vfs_renamedir,
+ vfs_deletecurdir,
+ vfs_setfilmode,
+ vfs_setdirmode,
+ vfs_setdirunixmode,
+ vfs_setdirowner,
+ vfs_deletefile,
+ vfs_renamefile,
+ vfs_acl,
+ vfs_remove_acl,
+ vfs_ea_getsize,
+ vfs_ea_getcontent,
+ vfs_ea_list,
+ vfs_ea_set,
+ vfs_ea_remove
+};
+
+/*
+ * Primary adouble modules: default, osx, sfm
+ */
+
static struct vfs_ops netatalk_adouble = {
/* ad_path: */ ad_path,
/* validupath: */ validupath_adouble,
/* rf_setdirowner: */ RF_setdirowner_adouble,
/* rf_deletefile: */ RF_deletefile_adouble,
/* rf_renamefile: */ RF_renamefile_adouble,
-#ifdef HAVE_NFSv4_ACLS
- /* rf_acl: */ RF_acl,
- /* rf_remove_acl */ RF_remove_acl
-#endif
};
static struct vfs_ops netatalk_adouble_osx = {
/* rf_renamefile: */ RF_renamefile_ads,
};
+/*
+ * Secondary vfs modules for Extended Attributes
+ */
+
+struct vfs_ops netatalk_ea_adouble = {
+ /* ad_path: */ NULL,
+ /* validupath: */ NULL,
+ /* rf_chown: */ NULL,
+ /* rf_renamedir: */ NULL,
+ /* rf_deletecurdir: */ NULL,
+ /* rf_setfilmode: */ NULL,
+ /* rf_setdirmode: */ NULL,
+ /* rf_setdirunixmode: */ NULL,
+ /* rf_setdirowner: */ NULL,
+ /* rf_deletefile: */ ea_deletefile,
+ /* rf_renamefile: */ ea_renamefile,
+ /* rf_acl: */ NULL,
+ /* rf_remove_acl */ NULL,
+ /* ea_getsize */ get_easize,
+ /* ea_getcontent */ get_eacontent,
+ /* ea_list */ list_eas,
+ /* ea_set */ set_ea,
+ /* ea_remove */ remove_ea
+};
+
+#ifdef HAVE_SOLARIS_EAS
+struct vfs_ops netatalk_ea_solaris = {
+ /* ad_path: */ NULL,
+ /* validupath: */ NULL,
+ /* rf_chown: */ NULL,
+ /* rf_renamedir: */ NULL,
+ /* rf_deletecurdir: */ NULL,
+ /* rf_setfilmode: */ NULL,
+ /* rf_setdirmode: */ NULL,
+ /* rf_setdirunixmode: */ NULL,
+ /* rf_setdirowner: */ NULL,
+ /* rf_deletefile: */ NULL,
+ /* rf_renamefile: */ NULL,
+ /* rf_acl: */ NULL,
+ /* rf_remove_acl */ NULL,
+ /* ea_getsize */ sol_get_easize,
+ /* ea_getcontent */ sol_get_eacontent,
+ /* ea_list */ sol_list_eas,
+ /* ea_set */ sol_set_ea,
+ /* ea_remove */ sol_remove_ea
+};
+#endif
+
+/*
+ * Tertiary attributes for ACLs
+ */
+
+#ifdef HAVE_NFSv4_ACLS
+struct vfs_ops netatalk_solaris_acl_adouble = {
+ /* ad_path: */ NULL,
+ /* validupath: */ NULL,
+ /* rf_chown: */ NULL,
+ /* rf_renamedir: */ NULL,
+ /* rf_deletecurdir: */ NULL,
+ /* rf_setfilmode: */ NULL,
+ /* rf_setdirmode: */ NULL,
+ /* rf_setdirunixmode: */ NULL,
+ /* rf_setdirowner: */ NULL,
+ /* rf_deletefile: */ NULL,
+ /* rf_renamefile: */ NULL,
+ /* rf_acl: */ RF_solaris_acl,
+ /* rf_remove_acl */ RF_remove_acl
+};
+#endif
+
/* ---------------- */
void initvol_vfs(struct vol *vol)
{
- /* adouble stuff */
+ vol->vfs = &vfs_master_funcs;
+
+ /* Default adouble stuff */
if (vol->v_adouble == AD_VERSION2_OSX) {
- vol->vfs = &netatalk_adouble_osx;
+ vfs[0] = &netatalk_adouble_osx;
}
else if (vol->v_adouble == AD_VERSION1_SFM) {
- vol->vfs = &netatalk_adouble_sfm;
+ vfs[0] = &netatalk_adouble_sfm;
}
else {
- vol->vfs = &netatalk_adouble;
+ vfs[0] = &netatalk_adouble;
}
/* Extended Attributes */
#ifdef HAVE_SOLARIS_EAS
LOG(log_debug, logtype_afpd, "initvol_vfs: Enabling EA support with Solaris native EAs.");
-
- netatalk_adouble.list_eas = sol_list_eas;
- netatalk_adouble.get_easize = sol_get_easize;
- netatalk_adouble.get_eacontent = sol_get_eacontent;
- netatalk_adouble.set_ea = sol_set_ea;
- netatalk_adouble.remove_ea = sol_remove_ea;
+ vfs[1] = &netatalk_ea_solaris;
#else
LOG(log_error, logtype_afpd, "initvol_vfs: Can't enable Solaris EA support.");
goto enable_adea;
enable_adea:
/* default: AFPVOL_EA_AD */
LOG(log_debug, logtype_afpd, "initvol_vfs: Enabling EA support with adouble files.");
-
- netatalk_adouble.set_ea = set_ea;
- netatalk_adouble.list_eas = list_eas;
- netatalk_adouble.get_easize = get_easize;
- netatalk_adouble.get_eacontent = get_eacontent;
- netatalk_adouble.remove_ea = remove_ea;
+ vfs[1] = &netatalk_ea_adouble;
}
+
+ /* ACLs */
+#ifdef HAVE_NFSv4_ACLS
+ vfs[2] = &netatalk_solaris_acl_adouble;
+#endif
}