From: Ralph Boehme Date: Sun, 15 Sep 2013 15:21:23 +0000 (+0200) Subject: Merge remote-tracking branch 'origin/branch-netatalk-3-0' into develop X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=netatalk.git;a=commitdiff_plain;h=4021b76ce3f3e51756e9d59b4a5a045ad6398dc8;hp=b85e88cc0e408268df912f6c10607ad72991c21e Merge remote-tracking branch 'origin/branch-netatalk-3-0' into develop Conflicts: NEWS VERSION doc/manpages/man5/afp.conf.5.xml doc/www/ReleaseNotes libatalk/util/netatalk_conf.c macros/summary.m4 man/man5/afp.conf.5.in --- diff --git a/NEWS b/NEWS index 5ab6e8a9..9fe7aef1 100644 --- a/NEWS +++ b/NEWS @@ -9,12 +9,31 @@ Changes in 3.1.0 * UPD: Add configure option --with-afpstats for overriding the result of autodetecting dbus-glib presence +Changes in 3.0.6 +================ +* FIX: charset conversion failed when copying from Mac OS 9. Bug #523. +* UPD: Don't force S_ISGID for directories on FreeBSD. Bug #525. +* NEW: Add support for ZFS ACLs on FreeBSD with libsunacl. From FR#83. +* FIX: Active Directory LDAP queries for ACL support with new options + "ldap user filter" and "ldap group filter". Bug #526. + Changes in 3.0.5 ================ * FIX: Fix a crash when using pam_winbind. Fixes bug #516. * NEW: New global/volume option "ignored attributes" * FIX: "afp listen" option failed to take IPv6 addresses. Bug #515. * FIX: Fix a possible crash in set_groups. Bug #518. +* NEW: Send optional AFP messages for vetoed files, new option + "veto message" can be used to enable sending messages. + Then whenever a client tries to access any file or directory + with a vetoed name, it will be sent an AFP message indicating + the name and the directory. From FR #81. +* NEW: New boolean volume option "delete veto files". If this option is + set to yes, then Netatalk will attempt to recursively delete any + vetoed files and directories. FR #82. +* UPD: systemd unit dir is /usr/lib/systemd/system . +* FIX: Saving files from application like MS Word may result in the file + loosing metadata like the Finder label. Bug #521. Changes in 3.0.4 ================ @@ -25,7 +44,7 @@ Changes in 3.0.4 lead to a failure setting the size of a files ressource fork. This affected application like Adobe Photoshop where saving files may fail. Fixes bug #511. -* UPD: Enhance ACL mapping, change global ACL option 'map acl' to take +* UPD: Enhance ACL mapping, change global ACL option 'map acls' to take the following options: "none", "rights" (default), "mode". none = no mapping, this resembles the previous false/no setting rights = map ACLs to Finder UARights, this resembles the previous diff --git a/bin/ad/ad_util.c b/bin/ad/ad_util.c index a168eed8..7d4d2fb9 100644 --- a/bin/ad/ad_util.c +++ b/bin/ad/ad_util.c @@ -51,6 +51,9 @@ #ifdef HAVE_SOLARIS_ACLS #include #endif /* HAVE_SOLARIS_ACLS */ +#ifdef HAVE_FREEBSD_SUNACL +#include +#endif #ifdef HAVE_POSIX_ACLS #include diff --git a/configure.ac b/configure.ac index a570f097..6eec7f4e 100644 --- a/configure.ac +++ b/configure.ac @@ -215,7 +215,7 @@ AC_SUBST(UAMS_PATH) AM_CONDITIONAL(SOLARIS_MODULE, test x$solaris_module = xyes) AM_CONDITIONAL(HAVE_LIBGCRYPT, test x$neta_cv_have_libgcrypt = xyes) AM_CONDITIONAL(HAVE_OPENSSL, test x$neta_cv_have_openssl = xyes) -AM_CONDITIONAL(HAVE_ACLS, test x"$with_acl_support" = x"yes") +AM_CONDITIONAL(HAVE_ACLS, test x"$ac_cv_have_acls" = x"yes") AM_CONDITIONAL(HAVE_LDAP, test x"$netatalk_cv_ldap" = x"yes") AM_CONDITIONAL(USE_DHX, test x$neta_cv_compile_dhx = xyes) AM_CONDITIONAL(USE_DHX2, test x$neta_cv_compile_dhx2 = xyes) diff --git a/doc/manpages/man5/afp.conf.5.xml b/doc/manpages/man5/afp.conf.5.xml index f346e371..4b1b14d6 100644 --- a/doc/manpages/man5/afp.conf.5.xml +++ b/doc/manpages/man5/afp.conf.5.xml @@ -5,7 +5,7 @@ 5 - 30 Apr 2013 + 13 Sep 2013 @NETATALK_VERSION@ @@ -673,10 +673,10 @@ This specifies the DSI server quantum. The default value is - 1 MB. The maximum value is 0xFFFFFFFFF, the minimum is 32000. If - you specify a value that is out of range, the default value will - be set. Do not change this value unless you're absolutely sure, - what you're doing + 0x100000 (1 MiB). The maximum value is 0xFFFFFFFFF, the minimum is + 32000. If you specify a value that is out of range, the default + value will be set. Do not change this value unless you're + absolutely sure, what you're doing @@ -935,6 +935,18 @@ + + veto message = BOOLEAN (default: + no) (G) + + + Send optional AFP messages for vetoed files. Then whenever a + client tries to access any file or directory with a vetoed name, + it will be sent an AFP message indicating the name and the + directory. + + + vol dbpath = path (G) @@ -1315,6 +1327,16 @@ + + ldap group attr = dn + (G) + + + Name of the LDAP attribute with the groups short + name. + + + ldap uuid string = STRING (G) @@ -1340,7 +1362,8 @@ internal UUID representation is converted to and from the binary format used in the objectGUID attribute found on objects in Active Directory when interacting with the server. - + See also the options and + . string @@ -1362,14 +1385,27 @@ - ldap group attr = dn + ldap user filter = STRING (default: unused) (G) - Name of the LDAP attribute with the groups short - name. + Optional LDAP filter that matches user objects. This is necessary for Active Directory + environments where users and groups are stored in the same directory subtree. + Recommended setting for Active Directory: objectClass=user. + + + + + ldap group filter = STRING (default: unused) + (G) + + + Optional LDAP filter that matches group objects. This is necessary for Active Directory + environments where users and groups are stored in the same directory subtree. + Recommended setting for Active Directory: objectClass=group. + @@ -1733,6 +1769,23 @@ + + delete veto files = BOOLEAN + (default: no) (V) + + + This option is used when Netatalk is attempting to delete a + directory that contains one or more vetoed files or directories + (see the veto files option). If this option is set to no (the + default) then if a directory contains any non-vetoed files or + directories then the directory delete will fail. This is usually + what you want. + If this option is set to yes, then Netatalk will attempt to + recursively delete any files and directories within the vetoed + directory. + + + follow symlinks = BOOLEAN (default: no) (V) diff --git a/doc/manual/upgrade.xml b/doc/manual/upgrade.xml index 43e5e696..2d85e74c 100644 --- a/doc/manual/upgrade.xml +++ b/doc/manual/upgrade.xml @@ -1,7 +1,7 @@ - 7.29.2013 + 9.6.2013 Frank @@ -9,7 +9,7 @@ Lahm - 29 Jul, 2013 + 6 Sep, 2013 Upgrading from Netatalk 2 @@ -569,8 +569,8 @@ -server_quantum server quantum - 303840 - 303840 + 303840 + 1048576 (G) - diff --git a/doc/www/ReleaseNotes b/doc/www/ReleaseNotes index 07674bf8..49e9b8c7 100644 --- a/doc/www/ReleaseNotes +++ b/doc/www/ReleaseNotes @@ -60,6 +60,24 @@ Changes in 3.1-alpha1 result of autodetecting dbus-glib presence +Changes in 3.0.5 +~~~~~~~~~~~~~~~~ +* FIX: Fix a crash when using pam_winbind. Fixes bug #516. +* NEW: New global/volume option "ignored attributes" +* FIX: "afp listen" option failed to take IPv6 addresses. Bug #515. +* FIX: Fix a possible crash in set_groups. Bug #518. +* NEW: Send optional AFP messages for vetoed files, new option + "veto messages" can be used to enable sending messages. + Then whenever a client tries to access any file or directory + with a vetoed name, it will be sent an AFP message indicating + the name and the directory. From FR #81. +* NEW: New boolean volume option "delete veto files". If this option is + set to yes, then Netatalk will attempt to recursively delete any + vetoed files and directories. FR #82. +* UPD: systemd unit dir is /usr/lib/systemd/system . +* FIX: Saving files from application like MS Word may result in the file + loosing metadata like the Finder label. Bug #521. + Changes in 3.0.4 ~~~~~~~~~~~~~~~~ * FIX: Opening files without metadata EA may result in an invalid diff --git a/etc/afpd/acl_mappings.h b/etc/afpd/acl_mappings.h index 87ff5dec..7906aeec 100644 --- a/etc/afpd/acl_mappings.h +++ b/etc/afpd/acl_mappings.h @@ -18,6 +18,9 @@ #ifdef HAVE_SOLARIS_ACLS #include #endif +#ifdef HAVE_FREEBSD_SUNACL +#include +#endif #include "acls.h" @@ -35,7 +38,7 @@ struct ace_rights_map { uint32_t to; }; -#ifdef HAVE_SOLARIS_ACLS +#if (defined HAVE_SOLARIS_ACLS || defined HAVE_FREEBSD_SUNACL) struct ace_rights_map nfsv4_to_darwin_rights[] = { {ACE_READ_DATA, DARWIN_ACE_READ_DATA}, {ACE_WRITE_DATA, DARWIN_ACE_WRITE_DATA}, @@ -97,6 +100,6 @@ struct darwin_to_nfsv4_flags_map darwin_to_nfsv4_flags[] = { {DARWIN_ACE_FLAGS_INHERITED, ACE_INHERITED_ACE}, {0,0} }; -#endif /* HAVE_SOLARIS_ACLS */ +#endif /* HAVE_SOLARIS_ACLS || HAVE_FREEBSD_SUNACL */ #endif /* ACL_MAPPINGS */ diff --git a/etc/afpd/acls.c b/etc/afpd/acls.c index d162b994..f914c8e4 100644 --- a/etc/afpd/acls.c +++ b/etc/afpd/acls.c @@ -27,6 +27,9 @@ #ifdef HAVE_SOLARIS_ACLS #include #endif +#ifdef HAVE_FREEBSD_SUNACL +#include +#endif #ifdef HAVE_POSIX_ACLS #include #endif @@ -76,7 +79,7 @@ * Solaris funcs ********************************************************/ -#ifdef HAVE_SOLARIS_ACLS +#ifdef HAVE_NFSV4_ACLS /*! * Compile access rights for a user to one file-system object @@ -362,7 +365,7 @@ EC_CLEANUP: free(name); EC_EXIT; } -#endif /* HAVE_SOLARIS_ACLS */ +#endif /* HAVE_NFSV4_ACLS */ /******************************************************** * POSIX 1e funcs @@ -975,7 +978,7 @@ static int map_acl(int type, void *acl, darwin_ace_t *buf, int ace_count) switch (type & MAP_MASK) { -#ifdef HAVE_SOLARIS_ACLS +#ifdef HAVE_NFSV4_ACLS case SOLARIS_2_DARWIN: mapped_aces = map_aces_solaris_to_darwin( acl, buf, ace_count); break; @@ -983,7 +986,7 @@ static int map_acl(int type, void *acl, darwin_ace_t *buf, int ace_count) case DARWIN_2_SOLARIS: mapped_aces = map_aces_darwin_to_solaris( buf, acl, ace_count); break; -#endif /* HAVE_SOLARIS_ACLS */ +#endif /* HAVE_NFSV4_ACLS */ #ifdef HAVE_POSIX_ACLS case POSIX_DEFAULT_2_DARWIN: @@ -1019,7 +1022,7 @@ static int get_and_map_acl(char *name, char *rbuf, size_t *rbuflen) int mapped_aces = 0; int dirflag; char *darwin_ace_count = rbuf; -#ifdef HAVE_SOLARIS_ACLS +#ifdef HAVE_NFSV4_ACLS int ace_count = 0; ace_t *aces = NULL; #endif @@ -1033,10 +1036,10 @@ static int get_and_map_acl(char *name, char *rbuf, size_t *rbuflen) *rbuf = 0; rbuf += 4; -#ifdef HAVE_SOLARIS_ACLS +#ifdef HAVE_NFSV4_ACLS EC_NEG1(ace_count = get_nfsv4_acl(name, &aces)); EC_NEG1(mapped_aces = map_acl(SOLARIS_2_DARWIN, aces, (darwin_ace_t *)rbuf, ace_count)); -#endif /* HAVE_SOLARIS_ACLS */ +#endif /* HAVE_NFSV4_ACLS */ #ifdef HAVE_POSIX_ACLS acl_t defacl = NULL , accacl = NULL; @@ -1074,7 +1077,7 @@ static int get_and_map_acl(char *name, char *rbuf, size_t *rbuflen) EC_STATUS(0); EC_CLEANUP: -#ifdef HAVE_SOLARIS_ACLS +#ifdef HAVE_NFSV4_ACLS if (aces) free(aces); #endif #ifdef HAVE_POSIX_ACLS @@ -1092,7 +1095,7 @@ static int remove_acl(const struct vol *vol,const char *path, int dir) { int ret = AFP_OK; -#if (defined HAVE_SOLARIS_ACLS || defined HAVE_POSIX_ACLS) +#if (defined HAVE_NFSV4_ACLS || defined HAVE_POSIX_ACLS) /* Ressource etc. first */ if ((ret = vol->vfs->vfs_remove_acl(vol, path, dir)) != AFP_OK) return ret; @@ -1110,7 +1113,7 @@ static int remove_acl(const struct vol *vol,const char *path, int dir) We will store inherited ACEs first, which is Darwins canonical order. - returns AFPerror code */ -#ifdef HAVE_SOLARIS_ACLS +#ifdef HAVE_NFSV4_ACLS static int set_acl(const struct vol *vol, char *name, int inherit, @@ -1186,28 +1189,27 @@ static int set_acl(const struct vol *vol, if ((ret = (vol->vfs->vfs_acl(vol, name, ACE_SETACL, new_aces_count, new_aces))) != 0) { LOG(log_debug, logtype_afpd, "set_acl: error setting acl: %s", strerror(errno)); switch (errno) { - case EACCES: - case EPERM: - EC_STATUS(AFPERR_ACCESS); - break; case ENOENT: - EC_STATUS(AFP_OK); break; + case EACCES: + case EPERM: + EC_EXIT_STATUS(AFPERR_ACCESS); default: - EC_STATUS(AFPERR_MISC); - break; + EC_EXIT_STATUS(AFPERR_MISC); } - goto EC_CLEANUP; } + if ((ret = (acl(name, ACE_SETACL, new_aces_count, new_aces))) != 0) { LOG(log_error, logtype_afpd, "set_acl: error setting acl: %s", strerror(errno)); - if (errno == (EACCES | EPERM)) - EC_STATUS(AFPERR_ACCESS); - else if (errno == ENOENT) - EC_STATUS(AFPERR_NOITEM); - else - EC_STATUS(AFPERR_MISC); - goto EC_CLEANUP; + switch (errno) { + case EACCES: + case EPERM: + EC_EXIT_STATUS(AFPERR_ACCESS); + case ENOENT: + EC_EXIT_STATUS(AFPERR_NOITEM); + default: + EC_EXIT_STATUS(AFPERR_MISC); + } } EC_STATUS(AFP_OK); @@ -1219,7 +1221,7 @@ EC_CLEANUP: LOG(log_debug9, logtype_afpd, "set_acl: END"); EC_EXIT; } -#endif /* HAVE_SOLARIS_ACLS */ +#endif /* HAVE_NFSV4_ACLS */ #ifdef HAVE_POSIX_ACLS #ifndef HAVE_ACL_FROM_MODE @@ -1420,7 +1422,7 @@ static int check_acl_access(const AFPObj *obj, allowed_rights = curdir->d_rights_cache; LOG(log_debug, logtype_afpd, "check_access: allowed rights from dircache: 0x%08x", allowed_rights); } else { -#ifdef HAVE_SOLARIS_ACLS +#ifdef HAVE_NFSV4_ACLS EC_ZERO_LOG(solaris_acl_rights(obj, path, &st, NULL, &allowed_rights)); #endif #ifdef HAVE_POSIX_ACLS @@ -1453,7 +1455,7 @@ static int check_acl_access(const AFPObj *obj, LOG(log_debug, logtype_afpd,"parent: %s", cfrombstr(parent)); EC_ZERO_LOG_ERR(lstat(cfrombstr(parent), &st), AFPERR_MISC); -#ifdef HAVE_SOLARIS_ACLS +#ifdef HAVE_NFSV4_ACLS EC_ZERO_LOG(solaris_acl_rights(obj, cfrombstr(parent), &st, NULL, &parent_rights)); #endif #ifdef HAVE_POSIX_ACLS @@ -1766,7 +1768,7 @@ int acltoownermode(const AFPObj *obj, const struct vol *vol, char *path, struct LOG(log_maxdebug, logtype_afpd, "acltoownermode(\"%s/%s\", 0x%02x)", getcwdpath(), path, ma->ma_user); -#ifdef HAVE_SOLARIS_ACLS +#ifdef HAVE_NFSV4_ACLS EC_ZERO_LOG(solaris_acl_rights(obj, path, st, ma, NULL)); #endif diff --git a/etc/afpd/acls.h b/etc/afpd/acls.h index c48f03a9..4d423af5 100644 --- a/etc/afpd/acls.h +++ b/etc/afpd/acls.h @@ -18,6 +18,9 @@ #ifdef HAVE_SOLARIS_ACLS #include #endif +#ifdef HAVE_FREEBSD_SUNACL +#include +#endif #include /* for atalk_uuid_t */ @@ -34,10 +37,10 @@ * the wire! We will ignore and spoil em. */ -#ifdef HAVE_SOLARIS_ACLS +#ifdef HAVE_NFSV4_ACLS /* Some stuff for the handling of NFSv4 ACLs */ #define ACE_TRIVIAL (ACE_OWNER | ACE_GROUP | ACE_EVERYONE) -#endif /* HAVE_SOLARIS_ACLS */ +#endif /* HAVE_NFSV4_ACLS */ /* FPGet|Set Bitmap */ enum { diff --git a/etc/afpd/directory.c b/etc/afpd/directory.c index 0bbfade2..07a2bb7d 100644 --- a/etc/afpd/directory.c +++ b/etc/afpd/directory.c @@ -1172,6 +1172,14 @@ struct path *cname(struct vol *vol, struct dir *dir, char **cpath) /* the name is illegal */ LOG(log_info, logtype_afpd, "cname: illegal path: '%s'", ret.u_name); afp_errno = AFPERR_PARAM; + if (vol->v_obj->options.flags & OPTION_VETOMSG) { + bstring message = bformat("Attempt to access vetoed file or directory \"%s\" in directory \"%s\"", + ret.u_name, bdata(dir->d_u_name)); + if (setmessage(bdata(message)) == 0) + /* Client may make multiple attempts, only send the message the first time */ + kill(getpid(), SIGUSR2); + bdestroy(message); + } return NULL; } @@ -2280,7 +2288,6 @@ int deletecurdir(struct vol *vol) struct dirent *de; struct stat st; struct dir *fdir, *pdir; - DIR *dp; struct adouble ad; uint16_t ashort; int err; @@ -2303,33 +2310,11 @@ int deletecurdir(struct vol *vol) } err = vol->vfs->vfs_deletecurdir(vol); if (err) { - LOG(log_error, logtype_afpd, "deletecurdir: error deleting .AppleDouble in \"%s\"", + LOG(log_error, logtype_afpd, "deletecurdir: error deleting AppleDouble files in \"%s\"", cfrombstr(curdir->d_fullpath)); return err; } - /* now get rid of dangling symlinks */ - if ((dp = opendir("."))) { - while ((de = readdir(dp))) { - /* skip this and previous directory */ - if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) - continue; - - /* bail if it's not a symlink */ - if ((lstat(de->d_name, &st) == 0) && !S_ISLNK(st.st_mode)) { - LOG(log_error, logtype_afpd, "deletecurdir(\"%s\"): not empty", - bdata(curdir->d_fullpath)); - closedir(dp); - return AFPERR_DIRNEMPT; - } - - if ((err = netatalk_unlink(de->d_name))) { - closedir(dp); - return err; - } - } - } - if (movecwd(vol, pdir) < 0) { err = afp_errno; goto delete_done; @@ -2339,24 +2324,29 @@ int deletecurdir(struct vol *vol) cfrombstr(curdir->d_fullpath)); err = netatalk_rmdir_all_errors(-1, cfrombstr(fdir->d_u_name)); - if ( err == AFP_OK || err == AFPERR_NOOBJ) { - AFP_CNID_START("cnid_delete"); - cnid_delete(vol->v_cdb, fdir->d_did); - AFP_CNID_DONE(); - dir_remove( vol, fdir ); - } else { + + switch (err) { + case AFP_OK: + case AFPERR_NOOBJ: + break; + case AFPERR_DIRNEMPT: + if (delete_vetoed_files(vol, bdata(fdir->d_u_name), false) != 0) + goto delete_done; + err = AFP_OK; + break; + default: LOG(log_error, logtype_afpd, "deletecurdir(\"%s\"): netatalk_rmdir_all_errors error", cfrombstr(curdir->d_fullpath)); + goto delete_done; } + AFP_CNID_START("cnid_delete"); + cnid_delete(vol->v_cdb, fdir->d_did); + AFP_CNID_DONE(); + + dir_remove( vol, fdir ); + delete_done: - if (dp) { - /* inode is used as key for cnid. - * Close the descriptor only after cnid_delete - * has been called. - */ - closedir(dp); - } return err; } diff --git a/etc/afpd/file.c b/etc/afpd/file.c index 44b57d58..edb55ea3 100644 --- a/etc/afpd/file.c +++ b/etc/afpd/file.c @@ -2209,6 +2209,42 @@ int afp_exchangefiles(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U } goto err_temp_to_dest; } + + if (AD_META_OPEN(adsp) || AD_META_OPEN(addp)) { + struct adouble adtmp; + bool opened_ads, opened_add; + + ad_init(&adtmp, vol); + ad_init_offsets(&adtmp); + + if (!AD_META_OPEN(adsp)) { + if (ad_open(adsp, p, ADFLAGS_HF) != 0) + return -1; + opened_ads = true; + } + + if (!AD_META_OPEN(addp)) { + if (ad_open(addp, upath, ADFLAGS_HF) != 0) + return -1; + opened_add = true; + } + + if (ad_copy_header(&adtmp, adsp) != 0) + goto err_temp_to_dest; + if (ad_copy_header(adsp, addp) != 0) + goto err_temp_to_dest; + if (ad_copy_header(addp, &adtmp) != 0) + goto err_temp_to_dest; + ad_flush(adsp); + ad_flush(addp); + + if (opened_ads) + ad_close(adsp, ADFLAGS_HF); + if (opened_add) + ad_close(addp, ADFLAGS_HF); + } + + /* FIXME: we should switch ressource fork too */ /* here we need to reopen if crossdev */ if (sid && ad_setid(addp, destst.st_dev, destst.st_ino, sid, sdir->d_did, vol->v_stamp)) diff --git a/etc/afpd/filedir.c b/etc/afpd/filedir.c index 234a26e5..f35edfc9 100644 --- a/etc/afpd/filedir.c +++ b/etc/afpd/filedir.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "directory.h" #include "dircache.h" @@ -468,6 +469,83 @@ int afp_rename(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size return( rc ); } +/* + * Recursivley delete vetoed files and directories if the volume option is set + * + * @param vol (r) volume handle + * @param upath (r) path of directory + * + * If the volume option delete veto files is set, this function recursively scans the + * directory "upath" for vetoed files and tries deletes these, the it will try to delete + * the directory. That may fail if the directory contains normal files that aren't vetoed. + * + * @returns 0 if the directory upath and all of its contents were deleted, otherwise -1. + * If the volume option is not set it returns -1. + */ +int delete_vetoed_files(struct vol *vol, const char *upath, bool in_vetodir) +{ + EC_INIT; + DIR *dp = NULL; + struct dirent *de; + struct stat sb; + int pwd = -1; + bool vetoed; + + if (!(vol->v_flags & AFPVOL_DELVETO)) + return -1; + + EC_NEG1( pwd = open(".", O_RDONLY)); + EC_ZERO( chdir(upath) ); + EC_NULL( dp = opendir(".") ); + + while ((de = readdir(dp))) { + if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) + continue; + + if (stat(de->d_name, &sb) != 0) { + LOG(log_error, logtype_afpd, "delete_vetoed_files(\"%s/%s\"): %s", + upath, de->d_name, strerror(errno)); + EC_EXIT_STATUS(AFPERR_DIRNEMPT); + } + + if (in_vetodir || veto_file(vol->v_veto, de->d_name)) + vetoed = true; + else + vetoed = false; + + if (vetoed) { + LOG(log_debug, logtype_afpd, "delete_vetoed_files(\"%s/%s\"): deleting vetoed file", + upath, de->d_name); + switch (sb.st_mode & S_IFMT) { + case S_IFDIR: + /* recursion */ + EC_ZERO( delete_vetoed_files(vol, de->d_name, vetoed)); + break; + case S_IFREG: + case S_IFLNK: + EC_ZERO( netatalk_unlink(de->d_name) ); + break; + default: + break; + } + } + } + + EC_ZERO_LOG( fchdir(pwd) ); + pwd = -1; + EC_ZERO_LOG( rmdir(upath) ); + +EC_CLEANUP: + if (dp) + closedir(dp); + if (pwd != -1) { + if (fchdir(pwd) != 0) + ret = -1; + } + + EC_EXIT; +} + /* ------------------------------- */ int afp_delete(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) { @@ -512,7 +590,9 @@ int afp_delete(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size if (rmdir(upath) != 0) { switch (errno) { case ENOTEMPTY: - return AFPERR_DIRNEMPT; + if (delete_vetoed_files(vol, upath, false) != 0) + return AFPERR_DIRNEMPT; + break; case EACCES: return AFPERR_ACCESS; default: diff --git a/etc/afpd/filedir.h b/etc/afpd/filedir.h index 02c9ac15..f72e5445 100644 --- a/etc/afpd/filedir.h +++ b/etc/afpd/filedir.h @@ -15,6 +15,7 @@ extern int veto_file (const char *veto_str, const char *path); extern int check_name (const struct vol *vol, char *name); extern int matchfile2dirperms (char *, struct vol *, int); +extern int delete_vetoed_files(struct vol *vol, const char *upath, bool in_vetodir); /* FP functions */ int afp_moveandrename (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); diff --git a/etc/afpd/fork.c b/etc/afpd/fork.c index 0c988828..350b5711 100644 --- a/etc/afpd/fork.c +++ b/etc/afpd/fork.c @@ -66,10 +66,10 @@ static int getforkparams(const AFPObj *obj, struct ofork *ofork, uint16_t bitmap vol = ofork->of_vol; dir = dirlookup(vol, ofork->of_did); - if (NULL == (path.m_name = utompath(vol, of_name(ofork), dir->d_did, utf8_encoding(obj)))) { + if (NULL == (path.u_name = mtoupath(vol, of_name(ofork), dir->d_did, utf8_encoding(obj)))) { return( AFPERR_MISC ); } - path.u_name = of_name(ofork); + path.m_name = of_name(ofork); path.id = 0; st = &path.st; if ( bitmap & ( (1< +#endif +#ifdef HAVE_FREEBSD_SUNACL +#include +#endif + +#ifdef HAVE_NFSV4_ACLS #define chmod_acl nfsv4_chmod @@ -34,7 +40,7 @@ extern int strip_nontrivial_aces(ace_t **saces, int sacecount); extern ace_t *concat_aces(ace_t *aces1, int ace1count, ace_t *aces2, int ace2count); extern int nfsv4_chmod(char *name, mode_t mode); -#endif /* HAVE_SOLARIS_ACLS */ +#endif /* HAVE_NFSV4_ACLS */ #ifdef HAVE_POSIX_ACLS #include diff --git a/include/atalk/adouble.h b/include/atalk/adouble.h index c0f4098d..0a66ad26 100644 --- a/include/atalk/adouble.h +++ b/include/atalk/adouble.h @@ -219,7 +219,7 @@ struct adouble { int ad_reso_refcount; off_t ad_rlen; /* ressource fork len with AFP 3.0 * * the header parameter size is too small. */ - char *ad_name; /* name (UTF8-MAC) */ + char *ad_name; /* mac name (maccharset or UTF8-MAC) */ struct adouble_fops *ad_ops; uint16_t ad_open_forks; /* open forks (by others) */ char ad_data[AD_DATASZ_MAX]; @@ -402,6 +402,7 @@ extern int ad_mkdir (const char *, mode_t); struct vol; extern void ad_init (struct adouble *, const struct vol * restrict); extern void ad_init_old (struct adouble *ad, int flags, int options); +extern int ad_init_offsets(struct adouble *ad); extern int ad_open (struct adouble *ad, const char *path, int adflags, ...); extern int ad_openat (struct adouble *, int dirfd, const char *path, int adflags, ...); extern int ad_refresh (const char *path, struct adouble *); diff --git a/include/atalk/directory.h b/include/atalk/directory.h index a2759aa1..d3764e53 100644 --- a/include/atalk/directory.h +++ b/include/atalk/directory.h @@ -36,7 +36,7 @@ /* setgid directories */ #ifndef DIRBITS -# ifdef AFS +# if (defined AFS) || (defined FREEBSD) # define DIRBITS 0 # else /* AFS */ # define DIRBITS S_ISGID diff --git a/include/atalk/ea.h b/include/atalk/ea.h index 22897037..fbbafafa 100644 --- a/include/atalk/ea.h +++ b/include/atalk/ea.h @@ -33,9 +33,13 @@ #include #endif +/* FIXME: are the ACL includes really neccessary here ? */ #ifdef HAVE_SOLARIS_ACLS #include #endif +#ifdef HAVE_FREEBSD_SUNACL +#include +#endif #ifndef ENOATTR #define ENOATTR ENODATA diff --git a/include/atalk/globals.h b/include/atalk/globals.h index 6c29ee02..11a35867 100644 --- a/include/atalk/globals.h +++ b/include/atalk/globals.h @@ -48,7 +48,7 @@ #define OPTION_CLOSEVOL (1 << 1) #define OPTION_SERVERNOTIF (1 << 2) #define OPTION_NOSENDFILE (1 << 3) -/* #define OPTION_CUSTOMICON (1 << 4) */ +#define OPTION_VETOMSG (1 << 4) /* whether to send an AFP message for veto file access */ #define OPTION_AFP_READ_LOCK (1 << 5) /* whether to do AFP spec conforming read locks (default: no) */ #define OPTION_ANNOUNCESSH (1 << 6) #define OPTION_UUID (1 << 7) @@ -165,7 +165,7 @@ extern const char *Cnid_port; extern int get_afp_errno (const int param); extern void afp_options_init (struct afp_options *); extern void afp_options_parse_cmdline(AFPObj *obj, int ac, char **av); -extern void setmessage (const char *); +extern int setmessage (const char *); extern void readmessage (AFPObj *); /* afp_util.c */ diff --git a/include/atalk/ldapconfig.h b/include/atalk/ldapconfig.h index adc2a99d..f01e0a06 100644 --- a/include/atalk/ldapconfig.h +++ b/include/atalk/ldapconfig.h @@ -21,6 +21,8 @@ extern char *ldap_uuid_string; extern char *ldap_name_attr; extern char *ldap_group_attr; extern char *ldap_uid_attr; +extern char *ldap_userfilter; +extern char *ldap_groupfilter; extern int ldap_uuid_encoding; typedef enum { diff --git a/include/atalk/vfs.h b/include/atalk/vfs.h index 0bd50796..6021c150 100644 --- a/include/atalk/vfs.h +++ b/include/atalk/vfs.h @@ -62,7 +62,7 @@ #define VFS_FUNC_ARGS_COPYFILE const struct vol *vol, int sfd, const char *src, const char *dst #define VFS_FUNC_VARS_COPYFILE vol, sfd, src, dst -#ifdef HAVE_SOLARIS_ACLS +#ifdef HAVE_NFSV4_ACLS #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 #endif diff --git a/include/atalk/volume.h b/include/atalk/volume.h index c3ebd39b..7172887a 100644 --- a/include/atalk/volume.h +++ b/include/atalk/volume.h @@ -135,6 +135,7 @@ struct vol { #define AFPVOL_SEARCHDB (1 << 25) /* Use fast CNID db search instead of filesystem */ #define AFPVOL_NONETIDS (1 << 26) /* signal the client it shall do privelege mapping */ #define AFPVOL_FOLLOWSYM (1 << 27) /* follow symlinks on the server, default is not to */ +#define AFPVOL_DELVETO (1 << 28) /* delete veto files and dirs */ /* Extended Attributes vfs indirection */ #define AFPVOL_EA_NONE 0 /* No EAs */ diff --git a/libatalk/acl/ldap.c b/libatalk/acl/ldap.c index f04c5aef..e805a990 100644 --- a/libatalk/acl/ldap.c +++ b/libatalk/acl/ldap.c @@ -31,6 +31,7 @@ #include #include #include /* For struct ldap_pref */ +#include typedef enum { KEEPALIVE = 1 @@ -54,6 +55,8 @@ char *ldap_uuid_string; char *ldap_name_attr; char *ldap_group_attr; char *ldap_uid_attr; +char *ldap_userfilter; +char *ldap_groupfilter; int ldap_uuid_encoding; struct ldap_pref ldap_prefs[] = { @@ -72,6 +75,9 @@ struct ldap_pref ldap_prefs[] = { {&ldap_group_attr, "ldap group attr", 0, 0, -1, -1}, {&ldap_uid_attr, "ldap uid attr", 0, 0, 0, 0}, {&ldap_uuid_encoding, "ldap uuid encoding", 1, 1, 0, 0}, + {&ldap_userfilter, "ldap user filter", 0, 0, 0, 0}, + {&ldap_groupfilter, "ldap group filter", 0, 0, 0, 0}, + {&ldap_auth_pw, "ldap auth pw", 0, 0, 0, 0}, {NULL, NULL, 0, 0, 0, 0} }; @@ -256,6 +262,69 @@ cleanup: return ret; } +/*! + * Generate LDAP filter string for UUID query + + * @param[in] uuidstr the UUID as string + * @param[in] attr_filter optional attribute + * @returns pointer to static filter string + */ +static char *gen_uuid_filter(const char *uuidstr_in, const char *attr_filter) +{ + EC_INIT; + int len; + const char *uuidstr = uuidstr_in; + +#define MAX_FILTER_SIZE 512 + static char filter[MAX_FILTER_SIZE]; + char stripped[MAX_FILTER_SIZE]; + +#define LDAP_BIN_UUID_LEN 49 /* LDAP Binary Notation is \XX * 16 bytes of UUID + terminator = 49 */ + char ldap_bytes[LDAP_BIN_UUID_LEN]; + + if (ldap_uuid_encoding == LDAP_UUID_ENCODING_MSGUID) { + /* Convert to LDAP-safe binary encoding for direct query of AD objectGUID attribute */ + int i = 0, s = 0; + char c; + while ((c = uuidstr[i])) { + if((c >='a' && c <= 'f') + || (c >= 'A' && c <= 'F') + || (c >= '0' && c <= '9')) { + stripped[s++] = toupper(c); + } + i++; + } + + snprintf(ldap_bytes, LDAP_BIN_UUID_LEN, + "\\%c%c\\%c%c\\%c%c\\%c%c\\%c%c\\%c%c\\%c%c\\%c%c" + "\\%c%c\\%c%c\\%c%c\\%c%c\\%c%c\\%c%c\\%c%c\\%c%c", + /* Data1 (uint32) */ + stripped[6], stripped[7], stripped[4], stripped[5], + stripped[2], stripped[3], stripped[0], stripped[1], + /* Data2 (uint16) */ + stripped[10], stripped[11], stripped[8], stripped[9], + /* Data3 (uint16) */ + stripped[14], stripped[15], stripped[12], stripped[13], + /* Data4 (uint64) */ + stripped[16], stripped[17], stripped[18], stripped[19], + stripped[20], stripped[21], stripped[22], stripped[23], + stripped[24], stripped[25], stripped[26], stripped[27], + stripped[28], stripped[29], stripped[30], stripped[31]); + uuidstr = ldap_bytes; + } + + if (attr_filter) { + len = snprintf(filter, 256, "(&(%s=%s)(%s))", ldap_uuid_attr, uuidstr, attr_filter); + } else { + len = snprintf(filter, 256, "%s=%s", ldap_uuid_attr, uuidstr); + } + +EC_CLEANUP: + if (ret != 0) + return NULL; + return filter; +} + /******************************************************** * Interface ********************************************************/ @@ -332,76 +401,50 @@ int ldap_getuuidfromname( const char *name, uuidtype_t type, char **uuid_string) * returns 0 on success, -1 on errror */ int ldap_getnamefromuuid( const char *uuidstr, char **name, uuidtype_t *type) { - int ret; - int len; - char filter[256]; /* this should really be enough. we dont want to malloc everything! */ + EC_INIT; + char *filter; char *attributes[] = { NULL, NULL}; if (!ldap_config_valid) - return -1; - - if(ldap_uuid_encoding == LDAP_UUID_ENCODING_MSGUID) { - /* Convert to LDAP-safe binary encoding for direct query of AD objectGUID attribute */ - char* stripped = malloc(strlen(uuidstr)); - - int i = 0; - int s = 0; - char c; - while ((c = uuidstr[i])) { - if((c >='a' && c <= 'f') - || (c >= 'A' && c <= 'F') - || (c >= '0' && c <= '9')) { - stripped[s++] = toupper(c); - } - i++; - } + EC_FAIL; - /* LDAP Binary Notation is \XX * 16 bytes of UUID + terminator = 49 */ - char* ldap_bytes = malloc(49); - snprintf(ldap_bytes, 49, - "\\%c%c\\%c%c\\%c%c\\%c%c\\%c%c\\%c%c\\%c%c\\%c%c" - "\\%c%c\\%c%c\\%c%c\\%c%c\\%c%c\\%c%c\\%c%c\\%c%c", - /* Data1 (uint32) */ - stripped[6], stripped[7], stripped[4], stripped[5], - stripped[2], stripped[3], stripped[0], stripped[1], - /* Data2 (uint16) */ - stripped[10], stripped[11], stripped[8], stripped[9], - /* Data3 (uint16) */ - stripped[14], stripped[15], stripped[12], stripped[13], - /* Data4 (uint64) */ - stripped[16], stripped[17], stripped[18], stripped[19], - stripped[20], stripped[21], stripped[22], stripped[23], - stripped[24], stripped[25], stripped[26], stripped[27], - stripped[28], stripped[29], stripped[30], stripped[31]); - len = snprintf( filter, 256, "%s=%s", ldap_uuid_attr, ldap_bytes); - - free(ldap_bytes); - free(stripped); - } else { - len = snprintf( filter, 256, "%s=%s", ldap_uuid_attr, uuidstr); - } + /* + * Search groups first as group acls are probably used more often. + * Note the special case of AD where users and groups are stored + * under the same subtree. + */ - if (len >= 256 || len == -1) { - LOG(log_error, logtype_default, "ldap_getnamefromuuid: filter overflow:%d, \"%s\"", len, filter); - return -1; - } - /* search groups first. group acls are probably used more often */ attributes[0] = ldap_group_attr; - ret = ldap_getattr_fromfilter_withbase_scope( ldap_groupbase, filter, attributes, ldap_groupscope, KEEPALIVE, name); - if (ret == -1) - return -1; + EC_NULL( filter = gen_uuid_filter(uuidstr, ldap_groupfilter) ); + EC_NEG1( ret = ldap_getattr_fromfilter_withbase_scope( + ldap_groupbase, + filter, + attributes, + ldap_groupscope, + KEEPALIVE, + name) ); if (ret == 1) { *type = UUID_GROUP; - return 0; + EC_EXIT_STATUS(0); } attributes[0] = ldap_name_attr; - ret = ldap_getattr_fromfilter_withbase_scope( ldap_userbase, filter, attributes, ldap_userscope, KEEPALIVE, name); + EC_NULL( filter = gen_uuid_filter(uuidstr, ldap_userfilter) ); + EC_NEG1( ret = ldap_getattr_fromfilter_withbase_scope( + ldap_userbase, + filter, + attributes, + ldap_userscope, + KEEPALIVE, + name) ); if (ret == 1) { *type = UUID_USER; - return 0; + EC_EXIT_STATUS(0); } - return -1; + EC_FAIL; + +EC_CLEANUP: + EC_EXIT; } #endif /* HAVE_LDAP */ diff --git a/libatalk/acl/unix.c b/libatalk/acl/unix.c index cc69d8ad..9b22511e 100644 --- a/libatalk/acl/unix.c +++ b/libatalk/acl/unix.c @@ -35,7 +35,7 @@ #include #include -#ifdef HAVE_SOLARIS_ACLS +#ifdef HAVE_NFSV4_ACLS /* Get ACL. Allocates storage as needed. Caller must free. * Returns no of ACEs or -1 on error. */ @@ -276,7 +276,7 @@ exit: return ret; } -#endif /* HAVE_SOLARIS_ACLS */ +#endif /* HAVE_NFSV4_ACLS */ #ifdef HAVE_POSIX_ACLS diff --git a/libatalk/adouble/ad_open.c b/libatalk/adouble/ad_open.c index 6915cbb1..06c3c71e 100644 --- a/libatalk/adouble/ad_open.c +++ b/libatalk/adouble/ad_open.c @@ -311,19 +311,16 @@ static uint32_t get_eid(uint32_t eid) return 0; } -/* ----------------------------------- */ -static int new_ad_header(struct adouble *ad, const char *path, struct stat *stp, int adflags) + +/** + * Initialize offset pointers + */ +int ad_init_offsets(struct adouble *ad) { const struct entry *eid; - uint16_t ashort; - struct stat st; - LOG(log_debug, logtype_ad, "new_ad_header(\"%s\")", path); - - if (ad->ad_magic == AD_MAGIC) { - LOG(log_debug, logtype_ad, "new_ad_header(\"%s\"): already initialized", path); + if (ad->ad_magic == AD_MAGIC) return 0; - } ad->ad_magic = AD_MAGIC; ad->ad_version = ad->ad_vers & 0x0f0000; @@ -346,6 +343,21 @@ static int new_ad_header(struct adouble *ad, const char *path, struct stat *stp, eid++; } + return 0; +} + +/* ----------------------------------- */ +static int new_ad_header(struct adouble *ad, const char *path, struct stat *stp, int adflags) +{ + const struct entry *eid; + uint16_t ashort; + struct stat st; + + LOG(log_debug, logtype_ad, "new_ad_header(\"%s\")", path); + + if (ad_init_offsets(ad) != 0) + return -1; + /* set default creator/type fields */ memcpy(ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRTYPEOFF,"\0\0\0\0", 4); memcpy(ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRCREATOFF,"\0\0\0\0", 4); diff --git a/libatalk/libatalk-3.0.5.abi b/libatalk/libatalk-3.0.5.abi new file mode 100644 index 00000000..2425dc62 --- /dev/null +++ b/libatalk/libatalk-3.0.5.abi @@ -0,0 +1,568 @@ +acl_ldap_freeconfig: void (void) +acl_ldap_readconfig: int (dictionary *) +ad_close: int (struct adouble *, int) +ad_convert: int (const char *, const struct stat *, const struct vol *, const char **) +ad_copy_header: int (struct adouble *, struct adouble *) +add_cachebyname: int (const char *, const uuidp_t, const uuidtype_t, const long unsigned int) +add_cachebyuuid: int (uuidp_t, const char *, uuidtype_t, const long unsigned int) +add_charset: charset_t (const char *) +ad_dir: char *(const char *) +ad_dtruncate: int (struct adouble *, const off_t) +adflags2logstr: const char *(int) +ad_flush: int (struct adouble *) +ad_forcegetid: uint32_t (struct adouble *) +adf_pread: ssize_t (struct ad_fd *, void *, size_t, off_t) +adf_pwrite: ssize_t (struct ad_fd *, const void *, size_t, off_t) +ad_getattr: int (const struct adouble *, uint16_t *) +ad_getdate: int (const struct adouble *, unsigned int, uint32_t *) +ad_getentryoff: off_t (const struct adouble *, int) +ad_getfuid: uid_t (void) +ad_getid: uint32_t (struct adouble *, const dev_t, const ino_t, const cnid_t, const void *) +ad_hf_mode: mode_t (mode_t) +ad_init: void (struct adouble *, const struct vol *) +ad_init_offsets: int (struct adouble *) +ad_init_old: void (struct adouble *, int, int) +ad_lock: int (struct adouble *, uint32_t, int, off_t, off_t, int) +ad_metadata: int (const char *, int, struct adouble *) +ad_metadataat: int (int, const char *, int, struct adouble *) +ad_mkdir: int (const char *, mode_t) +ad_mode: int (const char *, mode_t) +ad_open: int (struct adouble *, const char *, int, ...) +ad_openat: int (struct adouble *, int, const char *, int, ...) +ad_openforks: uint16_t (struct adouble *, uint16_t) +ad_path: const char *(const char *, int) +ad_path_ea: const char *(const char *, int) +ad_path_osx: const char *(const char *, int) +ad_read: ssize_t (struct adouble *, const uint32_t, off_t, char *, const size_t) +ad_readfile_init: int (const struct adouble *, const int, off_t *, const int) +ad_rebuild_adouble_header_ea: int (struct adouble *) +ad_rebuild_adouble_header_v2: int (struct adouble *) +ad_refresh: int (const char *, struct adouble *) +ad_reso_size: off_t (const char *, int, struct adouble *) +ad_rtruncate: int (struct adouble *, const char *, const off_t) +ad_setattr: int (const struct adouble *, const uint16_t) +ad_setdate: int (struct adouble *, unsigned int, uint32_t) +ad_setfuid: int (const uid_t) +ad_setid: int (struct adouble *, const dev_t, const ino_t, const uint32_t, const cnid_t, const void *) +ad_setname: int (struct adouble *, const char *) +ad_size: off_t (const struct adouble *, const uint32_t) +ad_stat: int (const char *, struct stat *) +ad_testlock: int (struct adouble *, int, const off_t) +ad_tmplock: int (struct adouble *, uint32_t, int, off_t, off_t, int) +ad_unlock: void (struct adouble *, const int, int) +ad_valid_header_osx: int (const char *) +ad_write: ssize_t (struct adouble *, uint32_t, off_t, int, const char *, size_t) +afp_config_free: void (AFPObj *) +afp_config_parse: int (AFPObj *, char *) +allow_severity: 5 +apply_ip_mask: void (struct sockaddr *, int) +atalkdict_del: void (dictionary *) +atalkdict_dump: void (dictionary *, FILE *) +atalkdict_get: const char *(const dictionary *, const char *, const char *, const char *) +atalkdict_hash: unsigned int (char *) +atalkdict_new: dictionary *(int) +atalkdict_set: int (dictionary *, char *, char *, char *) +atalkdict_unset: void (dictionary *, char *, char *) +atalk_iconv: size_t (atalk_iconv_t, const char **, size_t *, char **, size_t *) +atalk_iconv_close: int (atalk_iconv_t) +atalk_iconv_open: atalk_iconv_t (const char *, const char *) +atalk_iniparser_dump: void (const dictionary *, FILE *) +atalk_iniparser_dump_ini: void (const dictionary *, FILE *) +atalk_iniparser_find_entry: int (const dictionary *, const char *) +atalk_iniparser_freedict: void (dictionary *) +atalk_iniparser_getboolean: int (const dictionary *, const char *, const char *, int) +atalk_iniparser_getdouble: double (const dictionary *, const char *, const char *, double) +atalk_iniparser_getint: int (const dictionary *, const char *, const char *, int) +atalk_iniparser_getnsec: int (const dictionary *) +atalk_iniparser_getsecname: const char *(const dictionary *, int) +atalk_iniparser_getstrdup: char *(const dictionary *, const char *, const char *, const char *) +atalk_iniparser_getstring: const char *(const dictionary *, const char *, const char *, const char *) +atalk_iniparser_load: dictionary *(const char *) +atalk_iniparser_set: int (dictionary *, char *, char *, char *) +atalk_iniparser_unset: void (dictionary *, char *, char *) +atalk_register_charset: int (struct charset_functions *) +balloc: int (bstring, int) +ballocmin: int (bstring, int) +basename_safe: const char *(const char *) +bassign: int (bstring, const_bstring) +bassignblk: int (bstring, const void *, int) +bassigncstr: int (bstring, const char *) +bassignformat: int (bstring, const char *, ...) +bassigngets: int (bstring, bNgetc, void *, char) +bassignmidstr: int (bstring, const_bstring, int, int) +bcatblk: int (bstring, const void *, int) +bcatcstr: int (bstring, const char *) +bconcat: int (bstring, const_bstring) +bconchar: int (bstring, char) +bcstrfree: int (char *) +bdelete: int (bstring, int, int) +bdestroy: int (bstring) +become_root: void (void) +bfindreplace: int (bstring, const_bstring, const_bstring, int) +bfindreplacecaseless: int (bstring, const_bstring, const_bstring, int) +bformat: bstring (const char *, ...) +bformata: int (bstring, const char *, ...) +bfromcstr: bstring (const char *) +bfromcstralloc: bstring (int, const char *) +bgetsa: int (bstring, bNgetc, void *, char) +bgetstream: bstring (bNgetc, void *, char) +binchr: int (const_bstring, int, const_bstring) +binchrr: int (const_bstring, int, const_bstring) +binsert: int (bstring, int, const_bstring, unsigned char) +binsertch: int (bstring, int, int, unsigned char) +binstr: int (const_bstring, int, const_bstring) +binstrcaseless: int (const_bstring, int, const_bstring) +binstrr: int (const_bstring, int, const_bstring) +binstrrcaseless: int (const_bstring, int, const_bstring) +biseq: int (const_bstring, const_bstring) +biseqcaseless: int (const_bstring, const_bstring) +biseqcstr: int (const_bstring, const char *) +biseqcstrcaseless: int (const_bstring, const char *) +bisstemeqblk: int (const_bstring, const void *, int) +bisstemeqcaselessblk: int (const_bstring, const void *, int) +bjoin: bstring (const struct bstrList *, const_bstring) +bjoinInv: bstring (const struct bstrList *, const_bstring) +blk2bstr: bstring (const void *, int) +bltrimws: int (bstring) +bmidstr: bstring (const_bstring, int, int) +bninchr: int (const_bstring, int, const_bstring) +bninchrr: int (const_bstring, int, const_bstring) +bpattern: int (bstring, int) +bread: bstring (bNread, void *) +breada: int (bstring, bNread, void *) +brefcstr: bstring (char *) +breplace: int (bstring, int, int, const_bstring, unsigned char) +brtrimws: int (bstring) +bsbufflength: int (struct bStream *, int) +bsclose: void *(struct bStream *) +bseof: int (const struct bStream *) +bsetstr: int (bstring, int, const_bstring, unsigned char) +bsopen: struct bStream *(bNread, void *) +bspeek: int (bstring, const struct bStream *) +bsplit: struct bstrList *(const_bstring, unsigned char) +bsplitcb: int (const_bstring, unsigned char, int, int (*)(void *, int, int), void *) +bsplits: struct bstrList *(const_bstring, const_bstring) +bsplitscb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *) +bsplitstr: struct bstrList *(const_bstring, const_bstring) +bsplitstrcb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *) +bsread: int (bstring, struct bStream *, int) +bsreada: int (bstring, struct bStream *, int) +bsreadln: int (bstring, struct bStream *, char) +bsreadlna: int (bstring, struct bStream *, char) +bsreadlns: int (bstring, struct bStream *, const_bstring) +bsreadlnsa: int (bstring, struct bStream *, const_bstring) +bssplitscb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *) +bssplitstrcb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *) +bstr2cstr: char *(const_bstring, char) +bstrchrp: int (const_bstring, int, int) +bstrcmp: int (const_bstring, const_bstring) +bstrcpy: bstring (const_bstring) +bstricmp: int (const_bstring, const_bstring) +bstrListAlloc: int (struct bstrList *, int) +bstrListAllocMin: int (struct bstrList *, int) +bstrListCreate: struct bstrList *(void) +bstrListCreateMin: struct bstrList *(int) +bstrListDestroy: int (struct bstrList *) +bstrListPop: bstring (struct bstrList *) +bstrListPush: int (struct bstrList *, bstring) +bstrncmp: int (const_bstring, const_bstring, int) +bstrnicmp: int (const_bstring, const_bstring, int) +bstrrchrp: int (const_bstring, int, int) +bsunread: int (struct bStream *, const_bstring) +btolower: int (bstring) +btoupper: int (bstring) +btrimws: int (bstring) +btrunc: int (bstring, int) +bunrefcstr: int (bstring) +bvcformata: int (bstring, int, const char *, struct __va_list_tag *) +charset_decompose: size_t (charset_t, char *, size_t, char *, size_t) +charset_mac_centraleurope: {name = "MAC_CENTRALEUROPE", kTextEncoding = 29, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_chinese_simp: {name = "MAC_CHINESE_SIMP", kTextEncoding = 25, pull = , push = , flags = 85, iname = "EUC-CN", prev = 0x0, next = 0x0} +charset_mac_chinese_trad: {name = "MAC_CHINESE_TRAD", kTextEncoding = 2, pull = , push = , flags = 85, iname = "BIG-5", prev = 0x0, next = 0x0} +charset_mac_cyrillic: {name = "MAC_CYRILLIC", kTextEncoding = 7, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_greek: {name = "MAC_GREEK", kTextEncoding = 6, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_hebrew: {name = "MAC_HEBREW", kTextEncoding = 5, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_japanese: {name = "MAC_JAPANESE", kTextEncoding = 1, pull = , push = , flags = 85, iname = "SHIFT_JIS", prev = 0x0, next = 0x0} +charset_mac_korean: {name = "MAC_KOREAN", kTextEncoding = 3, pull = , push = , flags = 85, iname = "EUC-KR", prev = 0x0, next = 0x0} +charset_mac_roman: {name = "MAC_ROMAN", kTextEncoding = 0, pull = , push = , flags = 21, iname = 0x0, prev = 0x0, next = 0x0} +charset_mac_turkish: {name = "MAC_TURKISH", kTextEncoding = 35, pull = , push = , flags = 17, iname = 0x0, prev = 0x0, next = 0x0} +charset_precompose: size_t (charset_t, char *, size_t, char *, size_t) +charset_strlower: size_t (charset_t, const char *, size_t, char *, size_t) +charset_strupper: size_t (charset_t, const char *, size_t, char *, size_t) +charset_to_ucs2_allocate: size_t (charset_t, uint16_t **, const char *) +charset_to_utf8_allocate: size_t (charset_t, char **, const char *) +charset_utf8: {name = "UTF8", kTextEncoding = 134217987, pull = , push = , flags = 22, iname = 0x0, prev = 0x0, next = 0x0} +charset_utf8_mac: {name = "UTF8-MAC", kTextEncoding = 134217987, pull = , push = , flags = 27, iname = 0x0, prev = 0x0, next = 0x0} +check_lockfile: int (const char *, const char *) +cjk_char_pull: size_t (uint16_t, uint16_t *, const uint32_t *) +cjk_char_push: size_t (uint16_t, uint8_t *) +cjk_compose: uint16_t (uint16_t, uint16_t, const uint32_t *, size_t) +cjk_compose_seq: uint16_t (const uint16_t *, size_t *, const uint32_t *, size_t) +cjk_generic_pull: size_t (size_t (*)(uint16_t *, const uint8_t *, size_t *), void *, char **, size_t *, char **, size_t *) +cjk_generic_push: size_t (size_t (*)(uint8_t *, const uint16_t *, size_t *), void *, char **, size_t *, char **, size_t *) +cjk_lookup: uint16_t (uint16_t, const cjk_index_t *, const uint16_t *) +cnid_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, const char *, const size_t, cnid_t) +cnid_close: void (struct _cnid_db *) +cnid_dbd_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_dbd_close: void (struct _cnid_db *) +cnid_dbd_delete: int (struct _cnid_db *, const cnid_t) +cnid_dbd_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_dbd_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_dbd_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_dbd_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_dbd_module: {name = "dbd", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 0} +cnid_dbd_open: struct _cnid_db *(struct cnid_open_args *) +cnid_dbd_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_dbd_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_dbd_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_dbd_wipe: int (struct _cnid_db *) +cnid_delete: int (struct _cnid_db *, cnid_t) +cnid_find: int (struct _cnid_db *, const char *, size_t, void *, size_t) +cnid_get: cnid_t (struct _cnid_db *, const cnid_t, char *, const size_t) +cnid_getstamp: int (struct _cnid_db *, void *, const size_t) +cnid_init: void (void) +cnid_last_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_last_close: void (struct _cnid_db *) +cnid_last_delete: int (struct _cnid_db *, const cnid_t) +cnid_last_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_last_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_last_module: {name = "last", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 0} +cnid_last_open: struct _cnid_db *(struct cnid_open_args *) +cnid_last_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_last_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_lookup: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t) +cnid_open: struct _cnid_db *(const char *, mode_t, char *, int, const char *, const char *) +cnid_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t, cnid_t) +cnid_register: void (struct _cnid_module *) +cnid_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_tdb_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t) +cnid_tdb_close: void (struct _cnid_db *) +cnid_tdb_delete: int (struct _cnid_db *, const cnid_t) +cnid_tdb_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t) +cnid_tdb_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t) +cnid_tdb_module: {name = "tdb", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 12} +cnid_tdb_open: struct _cnid_db *(struct cnid_open_args *) +cnid_tdb_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t) +cnid_tdb_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t) +cnid_update: int (struct _cnid_db *, const cnid_t, const struct stat *, const cnid_t, char *, const size_t) +cnid_wipe: int (struct _cnid_db *) +compare_ip: int (const struct sockaddr *, const struct sockaddr *) +convert_charset: size_t (charset_t, charset_t, charset_t, const char *, size_t, char *, size_t, uint16_t *) +convert_string: size_t (charset_t, charset_t, const void *, size_t, void *, size_t) +convert_string_allocate: size_t (charset_t, charset_t, const void *, size_t, char **) +copy_ea: int (const char *, int, const char *, const char *, mode_t) +copy_file: int (int, const char *, const char *, mode_t) +copy_file_fd: int (int, int) +copy_fork: int (int, struct adouble *, struct adouble *) +create_lockfile: int (const char *, const char *) +daemonize: int (int, int) +decompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *) +deny_severity: 3 +dequeue: void *(q_t *) +_diacasemap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 231, 203, 229, 128, 204, 129, 130, 131, 233, 230, 232, 234, 237, 235, 236, 132, 238, 241, 239, 133, 205, 242, 244, 243, 134, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 198, 183, 184, 184, 186, 187, 188, 189, 174, 175, 192, 193, 194, 195, 196, 197, 198, 199...} +_dialowermap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 138, 140, 141, 142, 150, 154, 159, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 132, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 190, 191, 176, 177, 178, 179, 180, 181, 198, 183, 185, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199...} +dir_rx_set: int (mode_t) +dsi_attention: int (DSI *, AFPUserBytes) +dsi_close: void (DSI *) +dsi_cmdreply: int (DSI *, const int) +dsi_disconnect: int (DSI *) +dsi_free: void (DSI *) +dsi_getsession: int (DSI *, server_child_t *, int, afp_child_t **) +dsi_getstatus: void (DSI *) +dsi_init: DSI *(AFPObj *, const char *, const char *, const char *) +dsi_opensession: void (DSI *) +dsi_read: ssize_t (DSI *, void *, const size_t) +dsi_readdone: void (DSI *) +dsi_readinit: ssize_t (DSI *, void *, const size_t, const size_t, const int) +dsi_stream_read: size_t (DSI *, void *, const size_t) +dsi_stream_read_file: ssize_t (DSI *, const int, off_t, const size_t, const int) +dsi_stream_receive: int (DSI *) +dsi_stream_send: int (DSI *, void *, size_t) +dsi_stream_write: ssize_t (DSI *, void *, const size_t, int) +dsi_tcp_init: int (DSI *, const char *, const char *, const char *) +dsi_tickle: int (DSI *) +dsi_write: size_t (DSI *, void *, const size_t) +dsi_writeflush: void (DSI *) +dsi_writeinit: size_t (DSI *, void *, const size_t) +ea_chmod_dir: int (const struct vol *, const char *, mode_t, struct stat *) +ea_chmod_file: int (const struct vol *, const char *, mode_t, struct stat *) +ea_chown: int (const struct vol *, const char *, uid_t, gid_t) +ea_close: int (struct ea *) +ea_copyfile: int (const struct vol *, int, const char *, const char *) +ea_deletefile: int (const struct vol *, int, const char *) +ea_open: int (const struct vol *, const char *, eaflags_t, struct ea *) +ea_openat: int (const struct vol *, int, const char *, eaflags_t, struct ea *) +ea_path: char *(const struct ea *, const char *, int) +ea_renamefile: int (const struct vol *, int, const char *, const char *) +enqueue: qnode_t *(q_t *, void *) +fault_setup: void (void (*)(void *)) +fdset_add_fd: void (int, struct pollfd **, struct polldata **, int *, int *, int, enum fdtype, void *) +fdset_del_fd: void (struct pollfd **, struct polldata **, int *, int *, int) +find_charset_functions: struct charset_functions *(const char *) +_fini: +free_charset_names: void (void) +freeifacelist: void (char **) +fullpathname: const char *(const char *) +getcwdpath: const char *(void) +getdefextmap: struct extmap *(void) +get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int) +get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *) +getextmap: struct extmap *(const char *) +getifacelist: char **(void) +getip_port: unsigned int (const struct sockaddr *) +getip_string: const char *(const struct sockaddr *) +getnamefromuuid: int (const uuidp_t, char **, uuidtype_t *) +getuuidfromname: int (const char *, uuidtype_t, unsigned char *) +getvolbyname: struct vol *(const char *) +getvolbypath: struct vol *(AFPObj *, const char *) +getvolbyvid: struct vol *(const uint16_t) +getvolumes: struct vol *(void) +gmem: int (gid_t, int, gid_t *) +_init: +init_iconv: void (void) +initline: void (int, char *) +initvol_vfs: void (struct vol *) +ipc_child_state: int (AFPObj *, uint16_t) +ipc_child_write: int (int, uint16_t, int, void *) +ipc_server_read: int (server_child_t *, int) +islower_sp: int (uint32_t) +islower_w: int (uint16_t) +isupper_sp: int (uint32_t) +isupper_w: int (uint16_t) +ldap_auth_dn: 0x0 +ldap_auth_method: 0 +ldap_auth_pw: 0x0 +ldap_config_valid: 0 +ldap_getnamefromuuid: int (const char *, char **, uuidtype_t *) +ldap_getuuidfromname: int (const char *, uuidtype_t, char **) +ldap_group_attr: 0x0 +ldap_groupbase: 0x0 +ldap_groupscope: 0 +ldap_name_attr: 0x0 +ldap_prefs: {{pref = 0x0, name = "ldap server", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth method", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth dn", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap auth pw", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap userbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap userscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid string", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap name attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap group attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uid attr", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap uuid encoding", strorint = 1, intfromarray = 1, valid = 0, valid_save = 0}, {pref = 0x0, name = 0x0, strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}} +ldap_server: 0x0 +ldap_uid_attr: 0x0 +ldap_userbase: 0x0 +ldap_userscope: 0 +ldap_uuid_attr: 0x0 +ldap_uuid_encoding: 0 +ldap_uuid_string: 0x0 +list_eas: int (const struct vol *, char *, size_t *, const char *, int) +load_charset: int (struct vol *) +load_volumes: int (AFPObj *) +localuuid_from_id: void (unsigned char *, uuidtype_t, unsigned int) +lock_reg: int (int, int, int, off_t, int, off_t) +log_config: {inited = false, syslog_opened = false, console = false, processname = '\0' , syslog_facility = 0, syslog_display_options = 0} +make_log_entry: void (enum loglevels, enum logtypes, const char *, int, char *, ...) +make_tdb_data: unsigned char *(uint32_t, const struct stat *, const cnid_t, const char *, const size_t) +mb_generic_pull: size_t (int (*)(uint16_t *, const unsigned char *), void *, char **, size_t *, char **, size_t *) +mb_generic_push: size_t (int (*)(unsigned char *, uint16_t), void *, char **, size_t *, char **, size_t *) +netatalk_panic: void (const char *) +netatalk_rmdir: int (int, const char *) +netatalk_rmdir_all_errors: int (int, const char *) +netatalk_unlink: int (const char *) +netatalk_unlinkat: int (int, const char *) +nftw: int (const char *, nftw_func_t, dir_notification_func_t, int, int) +ochdir: int (const char *, int) +ochmod: int (char *, mode_t, const struct stat *, int) +ochown: int (const char *, uid_t, gid_t, int) +opendirat: DIR *(int, const char *) +openflags2logstr: const char *(int) +ostat: int (const char *, struct stat *, int) +ostatat: int (int, const char *, struct stat *, int) +parseline: int (int, char *) +posix_chmod: int (const char *, mode_t) +posix_fchmod: int (int, mode_t) +precompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *) +prefs_array: {{pref = "ldap auth method", valuestring = "none", value = 0}, {pref = "ldap auth method", valuestring = "simple", value = 128}, {pref = "ldap auth method", valuestring = "sasl", value = 163}, {pref = "ldap userscope", valuestring = "base", value = 0}, {pref = "ldap userscope", valuestring = "one", value = 1}, {pref = "ldap userscope", valuestring = "sub", value = 2}, {pref = "ldap groupscope", valuestring = "base", value = 0}, {pref = "ldap groupscope", valuestring = "one", value = 1}, {pref = "ldap groupscope", valuestring = "sub", value = 2}, {pref = "ldap uuid encoding", valuestring = "ms-guid", value = 1}, {pref = "ldap uuid encoding", valuestring = "string", value = 0}, {pref = 0x0, valuestring = 0x0, value = 0}} +prequeue: qnode_t *(q_t *, void *) +print_groups: const char *(int, gid_t *) +queue_destroy: void (q_t *, void (*)(void *)) +queue_init: q_t *(void) +randombytes: void (void *, int) +readt: ssize_t (int, void *, const size_t, int, int) +realpath_safe: char *(const char *) +recv_fd: int (int, int) +rel_path_in_vol: bstring (const char *, const char *) +remove_acl_vfs: int (const char *) +remove_ea: int (const struct vol *, const char *, const char *, int) +run_cmd: int (const char *, char **) +search_cachebyname: int (const char *, uuidtype_t *, unsigned char *) +search_cachebyuuid: int (uuidp_t, char **, uuidtype_t *) +send_fd: int (int, int) +server_child_add: afp_child_t *(server_child_t *, pid_t, int) +server_child_alloc: server_child_t *(int) +server_child_free: void (server_child_t *) +server_child_kill: void (server_child_t *, int) +server_child_kill_one_by_id: void (server_child_t *, pid_t, uid_t, uint32_t, char *, uint32_t) +server_child_remove: int (server_child_t *, pid_t) +server_child_resolve: afp_child_t *(server_child_t *, id_t) +server_child_transfer_session: int (server_child_t *, pid_t, uid_t, int, uint16_t) +server_lock: pid_t (char *, char *, int) +server_reset_signal: void (void) +set_charset_name: int (charset_t, const char *) +set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int) +setfilmode: int (const struct vol *, const char *, mode_t, struct stat *) +set_groups: int (AFPObj *, struct passwd *) +setnonblock: int (int, int) +set_processname: void (const char *) +setuplog: void (const char *, const char *) +statat: int (int, const char *, struct stat *) +strcasechr_sp: uint16_t *(const uint16_t *, uint32_t) +strcasechr_w: uint16_t *(const uint16_t *, uint16_t) +strcasecmp_w: int (const uint16_t *, const uint16_t *) +strcasestr_w: uint16_t *(const uint16_t *, const uint16_t *) +strcat_w: uint16_t *(uint16_t *, const uint16_t *) +strchr_w: uint16_t *(const uint16_t *, uint16_t) +strcmp_w: int (const uint16_t *, const uint16_t *) +strdiacasecmp: int (const char *, const char *) +strdup_w: uint16_t *(const uint16_t *) +stripped_slashes_basename: char *(char *) +strlcat: size_t (char *, const char *, size_t) +strlcpy: size_t (char *, const char *, size_t) +strlen_w: size_t (const uint16_t *) +strlower_w: int (uint16_t *) +strncasecmp_w: int (const uint16_t *, const uint16_t *, size_t) +strncat_w: uint16_t *(uint16_t *, const uint16_t *, const size_t) +strncmp_w: int (const uint16_t *, const uint16_t *, size_t) +strncpy_w: uint16_t *(uint16_t *, const uint16_t *, const size_t) +strndiacasecmp: int (const char *, const char *, size_t) +strndup_w: uint16_t *(const uint16_t *, size_t) +strnlen_w: size_t (const uint16_t *, size_t) +strstr_w: uint16_t *(const uint16_t *, const uint16_t *) +strtok_quote: char *(char *, const char *) +strupper_w: int (uint16_t *) +sys_ea_copyfile: int (const struct vol *, int, const char *, const char *) +sys_fgetxattr: ssize_t (int, const char *, void *, size_t) +sys_fsetxattr: int (int, const char *, const void *, size_t, int) +sys_ftruncate: int (int, off_t) +sys_get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int) +sys_get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *) +sys_getxattr: ssize_t (const char *, const char *, void *, size_t) +sys_getxattrfd: int (int, const char *, int, ...) +sys_lgetxattr: ssize_t (const char *, const char *, void *, size_t) +sys_list_eas: int (const struct vol *, char *, size_t *, const char *, int) +sys_listxattr: ssize_t (const char *, char *, size_t) +sys_llistxattr: ssize_t (const char *, char *, size_t) +sys_lremovexattr: int (const char *, const char *) +sys_lsetxattr: int (const char *, const char *, const void *, size_t, int) +sys_remove_ea: int (const struct vol *, const char *, const char *, int) +sys_removexattr: int (const char *, const char *) +sys_sendfile: ssize_t (int, int, off_t *, size_t) +sys_set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int) +sys_setxattr: int (const char *, const char *, const void *, size_t, int) +tdb_add_flags: void (struct tdb_context *, unsigned int) +tdb_allocate: tdb_off_t (struct tdb_context *, tdb_len_t, struct tdb_record *) +tdb_alloc_read: unsigned char *(struct tdb_context *, tdb_off_t, tdb_len_t) +tdb_append: int (struct tdb_context *, TDB_DATA, TDB_DATA) +tdb_brlock: int (struct tdb_context *, tdb_off_t, int, int, int, size_t) +tdb_brlock_upgrade: int (struct tdb_context *, tdb_off_t, size_t) +tdb_chainlock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_mark: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_nonblock: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_read: int (struct tdb_context *, TDB_DATA) +tdb_chainlock_unmark: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock: int (struct tdb_context *, TDB_DATA) +tdb_chainunlock_read: int (struct tdb_context *, TDB_DATA) +tdb_check: int (struct tdb_context *, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_close: int (struct tdb_context *) +tdb_convert: void *(void *, uint32_t) +tdb_delete: int (struct tdb_context *, TDB_DATA) +tdb_do_delete: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_dump_all: void (struct tdb_context *) +tdb_enable_seqnum: void (struct tdb_context *) +tdb_error: enum TDB_ERROR (struct tdb_context *) +tdb_errorstr: const char *(struct tdb_context *) +tdb_exists: int (struct tdb_context *, TDB_DATA) +tdb_expand: int (struct tdb_context *, tdb_off_t) +tdb_fd: int (struct tdb_context *) +tdb_fetch: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_find_lock_hash: tdb_off_t (struct tdb_context *, TDB_DATA, uint32_t, int, struct tdb_record *) +tdb_firstkey: TDB_DATA (struct tdb_context *) +tdb_free: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_freelist_size: int (struct tdb_context *) +tdb_get_flags: int (struct tdb_context *) +tdb_get_logging_private: void *(struct tdb_context *) +tdb_get_seqnum: int (struct tdb_context *) +tdb_hash_size: int (struct tdb_context *) +tdb_increment_seqnum_nonblock: void (struct tdb_context *) +tdb_io_init: void (struct tdb_context *) +tdb_lock: int (struct tdb_context *, int, int) +tdb_lockall: int (struct tdb_context *) +tdb_lockall_mark: int (struct tdb_context *) +tdb_lockall_nonblock: int (struct tdb_context *) +tdb_lockall_read: int (struct tdb_context *) +tdb_lockall_read_nonblock: int (struct tdb_context *) +tdb_lockall_unmark: int (struct tdb_context *) +tdb_lock_nonblock: int (struct tdb_context *, int, int) +tdb_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_log_fn: tdb_log_func (struct tdb_context *) +tdb_map_size: size_t (struct tdb_context *) +tdb_mmap: void (struct tdb_context *) +tdb_munmap: int (struct tdb_context *) +tdb_name: const char *(struct tdb_context *) +tdb_nextkey: TDB_DATA (struct tdb_context *, TDB_DATA) +tdb_null: {dptr = 0x0, dsize = 0} +tdb_ofs_read: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_ofs_write: int (struct tdb_context *, tdb_off_t, tdb_off_t *) +tdb_open: struct tdb_context *(const char *, int, int, int, mode_t) +tdb_open_ex: struct tdb_context *(const char *, int, int, int, mode_t, const struct tdb_logging_context *, tdb_hash_func) +tdb_parse_data: int (struct tdb_context *, TDB_DATA, tdb_off_t, tdb_len_t, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_parse_record: int (struct tdb_context *, TDB_DATA, int (*)(TDB_DATA, TDB_DATA, void *), void *) +tdb_printfreelist: int (struct tdb_context *) +tdb_rec_free_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_rec_write: int (struct tdb_context *, tdb_off_t, struct tdb_record *) +tdb_remove_flags: void (struct tdb_context *, unsigned int) +tdb_reopen: int (struct tdb_context *) +tdb_reopen_all: int (int) +tdb_repack: int (struct tdb_context *) +tdb_setalarm_sigptr: void (struct tdb_context *, volatile sig_atomic_t *) +tdb_set_logging_function: void (struct tdb_context *, const struct tdb_logging_context *) +tdb_set_max_dead: void (struct tdb_context *, int) +tdb_store: int (struct tdb_context *, TDB_DATA, TDB_DATA, int) +_tdb_transaction_cancel: int (struct tdb_context *) +tdb_transaction_cancel: int (struct tdb_context *) +tdb_transaction_commit: int (struct tdb_context *) +tdb_transaction_lock: int (struct tdb_context *, int) +tdb_transaction_prepare_commit: int (struct tdb_context *) +tdb_transaction_recover: int (struct tdb_context *) +tdb_transaction_start: int (struct tdb_context *) +tdb_transaction_unlock: int (struct tdb_context *) +tdb_traverse: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *) +tdb_unlock: int (struct tdb_context *, int, int) +tdb_unlockall: int (struct tdb_context *) +tdb_unlockall_read: int (struct tdb_context *) +tdb_unlock_record: int (struct tdb_context *, tdb_off_t) +tdb_validate_freelist: int (struct tdb_context *, int *) +tdb_wipe_all: int (struct tdb_context *) +tdb_write_lock_record: int (struct tdb_context *, tdb_off_t) +tdb_write_unlock_record: int (struct tdb_context *, tdb_off_t) +tokenize_ip_port: int (const char *, char **, char **) +tolower_sp: uint32_t (uint32_t) +tolower_w: uint16_t (uint16_t) +toupper_sp: uint32_t (uint32_t) +toupper_w: uint16_t (uint16_t) +type_configs: {{set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}} +ucs2_to_charset: size_t (charset_t, const uint16_t *, char *, size_t) +ucs2_to_charset_allocate: size_t (charset_t, char **, const uint16_t *) +unbecome_root: void (void) +unix_rename: int (int, const char *, int, const char *) +unix_strlower: size_t (const char *, size_t, char *, size_t) +unix_strupper: size_t (const char *, size_t, char *, size_t) +unload_volumes: void (AFPObj *) +utf8_charlen: size_t (char *) +utf8_decompose: size_t (char *, size_t, char *, size_t) +utf8_precompose: size_t (char *, size_t, char *, size_t) +utf8_strlen_validate: size_t (char *) +utf8_strlower: size_t (const char *, size_t, char *, size_t) +utf8_strupper: size_t (const char *, size_t, char *, size_t) +utf8_to_charset_allocate: size_t (charset_t, char **, const char *) +uuid_bin2string: const char *(const unsigned char *) +uuidcache_dump: void (void) +uuid_string2bin: void (const char *, unsigned char *) +uuidtype: {"", "USER", "GROUP", "LOCAL"} +volume_free: void (struct vol *) +volume_unlink: void (struct vol *) +writet: ssize_t (int, void *, const size_t, int, int) diff --git a/libatalk/util/netatalk_conf.c b/libatalk/util/netatalk_conf.c index e1dec578..d6fb4a17 100644 --- a/libatalk/util/netatalk_conf.c +++ b/libatalk/util/netatalk_conf.c @@ -232,7 +232,7 @@ static int check_vol_acl_support(const struct vol *vol) { int ret = 0; -#ifdef HAVE_SOLARIS_ACLS +#ifdef HAVE_NFSV4_ACLS ace_t *aces = NULL; ret = 1; if (get_nfsv4_acl(vol->v_path, &aces) == -1) @@ -245,7 +245,7 @@ static int check_vol_acl_support(const struct vol *vol) ret = 0; #endif -#ifdef HAVE_SOLARIS_ACLS +#ifdef HAVE_NFSV4_ACLS if (aces) free(aces); #endif #ifdef HAVE_POSIX_ACLS @@ -776,6 +776,8 @@ static struct vol *creatvol(AFPObj *obj, volume->v_flags |= AFPVOL_SPOTLIGHT; obj->options.flags |= OPTION_SPOTLIGHT; } + if (getoption_bool(obj->iniconfig, section, "delete veto files", preset, 0)) + volume->v_flags |= AFPVOL_DELVETO; if (getoption_bool(obj->iniconfig, section, "preexec close", preset, 0)) volume->v_preexec_close = 1; @@ -1765,6 +1767,8 @@ int afp_config_parse(AFPObj *AFPObj, char *processname) options->flags |= OPTION_AFP_READ_LOCK; if (atalk_iniparser_getboolean(config, INISEC_GLOBAL, "spotlight", 0)) options->flags |= OPTION_SPOTLIGHT_VOL; + if (atalk_iniparser_getboolean(config, INISEC_GLOBAL, "veto message", 0)) + options->flags |= OPTION_VETOMSG; if (!atalk_iniparser_getboolean(config, INISEC_GLOBAL, "save password", 1)) options->passwdbits |= PASSWD_NOSAVE; if (atalk_iniparser_getboolean(config, INISEC_GLOBAL, "set password", 0)) diff --git a/libatalk/vfs/acl.c b/libatalk/vfs/acl.c index d7c8eb62..027aba1b 100644 --- a/libatalk/vfs/acl.c +++ b/libatalk/vfs/acl.c @@ -30,7 +30,7 @@ #include #include -#ifdef HAVE_SOLARIS_ACLS +#ifdef HAVE_NFSV4_ACLS /* Removes all non-trivial ACLs from object. Returns full AFPERR code. */ int remove_acl_vfs(const char *name) @@ -86,7 +86,7 @@ exit: return ret; } -#endif /* HAVE_SOLARIS_ACLS */ +#endif /* HAVE_NFSV4_ACLS */ #ifdef HAVE_POSIX_ACLS /*! diff --git a/libatalk/vfs/unix.c b/libatalk/vfs/unix.c index bc90c75a..79e4fd33 100644 --- a/libatalk/vfs/unix.c +++ b/libatalk/vfs/unix.c @@ -74,6 +74,7 @@ int netatalk_rmdir_all_errors(int dirfd, const char *name) case ENOENT : return AFPERR_NOOBJ; case ENOTEMPTY : + case EEXIST: return AFPERR_DIRNEMPT; case EPERM: case EACCES : diff --git a/libatalk/vfs/vfs.c b/libatalk/vfs/vfs.c index d79ac05e..52c6ea84 100644 --- a/libatalk/vfs/vfs.c +++ b/libatalk/vfs/vfs.c @@ -348,7 +348,7 @@ EC_CLEANUP: EC_EXIT; } -#ifdef HAVE_SOLARIS_ACLS +#ifdef HAVE_NFSV4_ACLS static int RF_solaris_acl(VFS_FUNC_ARGS_ACL) { static char buf[ MAXPATHLEN + 1]; @@ -467,9 +467,15 @@ static int deletecurdir_ea_osx_chkifempty_loop(const struct vol *vol, struct dir static int deletecurdir_ea_osx_loop(const struct vol *vol, struct dirent *de, char *name, void *data _U_, int flag _U_) { int ret; - - if ((ret = netatalk_unlink(name)) != 0) - return ret; + struct stat sb; + + if (strncmp(name, "._", strlen("._")) == 0) { + if (lstat(name, &sb) != 0) + return -1; + if (S_ISREG(sb.st_mode)) + if ((ret = netatalk_unlink(name)) != 0) + return ret; + } return 0; } @@ -480,17 +486,6 @@ static int RF_deletecurdir_ea(VFS_FUNC_ARGS_DELETECURDIR) #ifndef HAVE_EAFD int err; /* delete stray ._AppleDouble files */ - - /* first check if there's really no other file besides files starting with ._ */ - if ((err = for_each_adouble("deletecurdir_ea_osx", ".", - deletecurdir_ea_osx_chkifempty_loop, - vol, NULL, 0)) != 0) { - if (err == 1) - return AFPERR_DIRNEMPT; - return AFPERR_MISC; - } - - /* Now delete orphaned ._ files */ if ((err = for_each_adouble("deletecurdir_ea_osx", ".", deletecurdir_ea_osx_loop, vol, NULL, 0)) != 0) @@ -796,7 +791,7 @@ static struct vfs_ops netatalk_ea_sys = { * Tertiary VFS modules for ACLs */ -#ifdef HAVE_SOLARIS_ACLS +#ifdef HAVE_NFSV4_ACLS static struct vfs_ops netatalk_solaris_acl_adouble = { /* validupath: */ NULL, /* rf_chown: */ NULL, @@ -864,7 +859,7 @@ void initvol_vfs(struct vol *vol) } /* ACLs */ -#ifdef HAVE_SOLARIS_ACLS +#ifdef HAVE_NFSV4_ACLS vol->vfs_modules[2] = &netatalk_solaris_acl_adouble; #endif #ifdef HAVE_POSIX_ACLS diff --git a/macros/netatalk.m4 b/macros/netatalk.m4 index 1c230f7c..72daa01e 100644 --- a/macros/netatalk.m4 +++ b/macros/netatalk.m4 @@ -474,7 +474,7 @@ AC_DEFUN([AC_NETATALK_INIT_STYLE], [ ;; "redhat-systemd") AC_MSG_RESULT([enabling redhat-style systemd support]) - ac_cv_init_dir="/lib/systemd/system" + ac_cv_init_dir="/usr/lib/systemd/system" ;; "suse") AC_MSG_ERROR([--with-init-style=suse is obsoleted. Use suse-sysv or suse-systemd.]) @@ -485,7 +485,7 @@ AC_DEFUN([AC_NETATALK_INIT_STYLE], [ ;; "suse-systemd") AC_MSG_RESULT([enabling suse-style systemd support (>=openSUSE12.1)]) - ac_cv_init_dir="/lib/systemd/system" + ac_cv_init_dir="/usr/lib/systemd/system" ;; "gentoo") AC_MSG_RESULT([enabling gentoo-style initscript support]) @@ -505,7 +505,7 @@ AC_DEFUN([AC_NETATALK_INIT_STYLE], [ ;; "systemd") AC_MSG_RESULT([enabling general systemd support]) - ac_cv_init_dir="/lib/systemd/system" + ac_cv_init_dir="/usr/lib/systemd/system" ;; "none") AC_MSG_RESULT([disabling init-style support]) @@ -752,7 +752,7 @@ dnl Check for LDAP support, for client-side ACL visibility AC_DEFUN([AC_NETATALK_LDAP], [ AC_MSG_CHECKING(for LDAP (necessary for client-side ACL visibility)) AC_ARG_WITH(ldap, - [AS_HELP_STRING([--with-ldap], + [AS_HELP_STRING([--with-ldap[[=PATH]]], [LDAP support (default=auto)])], netatalk_cv_ldap=$withval, netatalk_cv_ldap=auto @@ -805,6 +805,7 @@ LIBS="$save_LIBS" dnl Check for ACL support AC_DEFUN([AC_NETATALK_ACL], [ +ac_cv_have_acls=no AC_MSG_CHECKING(whether to support ACLs) AC_ARG_WITH(acls, [AS_HELP_STRING([--with-acls], @@ -822,112 +823,125 @@ AC_MSG_RESULT($with_acl_support) if test x"$with_acl_support" = x"no"; then AC_MSG_RESULT(Disabling ACL support) - AC_DEFINE(HAVE_NO_ACLS,1,[Whether no ACLs support should be built in]) -else - with_acl_support=yes fi -if test x"$with_acl_support" = x"yes" ; then - AC_MSG_NOTICE(checking whether ACL support is available:) +# Platform specific checks +if test x"$with_acl_support" != x"no" ; then case "$host_os" in - *sysv5*) - AC_MSG_NOTICE(Using UnixWare ACLs) - AC_DEFINE(HAVE_UNIXWARE_ACLS,1,[Whether UnixWare ACLs are available]) - ;; *solaris*) AC_MSG_NOTICE(Using solaris ACLs) - AC_DEFINE(HAVE_SOLARIS_ACLS,1,[Whether solaris ACLs are available]) + AC_DEFINE(HAVE_SOLARIS_ACLS,1,[Whether Solaris ACLs are available]) + AC_DEFINE(HAVE_NFSV4_ACLS,1,[Whether NFSv4 ACLs are available]) ACL_LIBS="$ACL_LIBS -lsec" + ac_cv_have_acls=yes ;; - *hpux*) - AC_MSG_NOTICE(Using HPUX ACLs) - AC_DEFINE(HAVE_HPUX_ACLS,1,[Whether HPUX ACLs are available]) - ;; - *irix*) - AC_MSG_NOTICE(Using IRIX ACLs) - AC_DEFINE(HAVE_IRIX_ACLS,1,[Whether IRIX ACLs are available]) - ;; - *aix*) - AC_MSG_NOTICE(Using AIX ACLs) - AC_DEFINE(HAVE_AIX_ACLS,1,[Whether AIX ACLs are available]) - ;; - *osf*) - AC_MSG_NOTICE(Using Tru64 ACLs) - AC_DEFINE(HAVE_TRU64_ACLS,1,[Whether Tru64 ACLs are available]) - ACL_LIBS="$ACL_LIBS -lpacl" + *freebsd*) + AC_MSG_NOTICE(checking whether libsunacl is available) + sunacl_include_path="/usr/local/include" + sunacl_lib_path="/usr/local/lib" + + save_CPPFLAGS=$CPPFLAGS + save_LDFLAGS=$LDFLAGS + save_LIBS=$LIBS + + CPPFLAGS="-I$sunacl_include_path $CPPFLAGS" + AC_CHECK_HEADER([sunacl.h]) + + LDFLAGS="-L$sunacl_lib_path $LDFLAGS" + AC_CHECK_LIB([sunacl], [acl]) + + if test x"$ac_cv_header_sunacl_h" = x"yes" -a x"$ac_cv_lib_sunacl_acl" = x"yes" ; then + AC_MSG_NOTICE([Enabling support for ZFS ACLs using libsunacl]) + ac_cv_have_acls=yes + CFLAGS="-I$sunacl_include_path $CFLAGS" + ACL_LIBS="$ACL_LIBS -L$sunacl_lib_path -lsunacl" + AC_DEFINE(HAVE_FREEBSD_SUNACL, 1, [Whether FreeBSD ZFS ACLs with libsunacl are available]) + AC_DEFINE(HAVE_NFSV4_ACLS,1,[Whether NFSv4 ACLs are available]) + else + AC_MSG_NOTICE([libsunacl not found, disabling ZFS ACL support]) + fi + + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS ;; - *darwin*) - AC_MSG_NOTICE(ACLs on Darwin currently not supported) - AC_DEFINE(HAVE_NO_ACLS,1,[Whether no ACLs support is available]) + esac +fi + +if test x"$with_acl_support" != x"no" -a x"$ac_cv_have_acls" != x"yes" ; then + # Runtime checks for POSIX ACLs + AC_CHECK_LIB(acl,acl_get_file,[ACL_LIBS="$ACL_LIBS -lacl"]) + case "$host_os" in + *linux*) + AC_CHECK_LIB(attr,getxattr,[ACL_LIBS="$ACL_LIBS -lattr"]) ;; - *) - AC_CHECK_LIB(acl,acl_get_file,[ACL_LIBS="$ACL_LIBS -lacl"]) - case "$host_os" in - *linux*) - AC_CHECK_LIB(attr,getxattr,[ACL_LIBS="$ACL_LIBS -lattr"]) - ;; - esac - AC_CACHE_CHECK([for POSIX ACL support],netatalk_cv_HAVE_POSIX_ACLS,[ + esac + + AC_CACHE_CHECK([for POSIX ACL support],netatalk_cv_HAVE_POSIX_ACLS,[ + acl_LIBS=$LIBS + LIBS="$LIBS $ACL_LIBS" + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ + #include + #include + ]], [[ + acl_t acl; + int entry_id; + acl_entry_t *entry_p; + return acl_get_entry(acl, entry_id, entry_p); + ]])], + [netatalk_cv_HAVE_POSIX_ACLS=yes; ac_cv_have_acls=yes], + [netatalk_cv_HAVE_POSIX_ACLS=no; ac_cv_have_acls=no] + ) + LIBS=$acl_LIBS + ]) + + if test x"$netatalk_cv_HAVE_POSIX_ACLS" = x"yes"; then + AC_MSG_NOTICE(Using POSIX ACLs) + AC_DEFINE(HAVE_POSIX_ACLS,1,[Whether POSIX ACLs are available]) + + AC_CACHE_CHECK([for acl_get_perm_np],netatalk_cv_HAVE_ACL_GET_PERM_NP,[ acl_LIBS=$LIBS LIBS="$LIBS $ACL_LIBS" AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[ - acl_t acl; - int entry_id; - acl_entry_t *entry_p; - return acl_get_entry(acl, entry_id, entry_p); - ]])],[netatalk_cv_HAVE_POSIX_ACLS=yes],[netatalk_cv_HAVE_POSIX_ACLS=no - with_acl_support=no]) + acl_permset_t permset_d; + acl_perm_t perm; + return acl_get_perm_np(permset_d, perm); + ]])],[netatalk_cv_HAVE_ACL_GET_PERM_NP=yes],[netatalk_cv_HAVE_ACL_GET_PERM_NP=no]) LIBS=$acl_LIBS ]) - if test x"$netatalk_cv_HAVE_POSIX_ACLS" = x"yes"; then - AC_MSG_NOTICE(Using POSIX ACLs) - AC_DEFINE(HAVE_POSIX_ACLS,1,[Whether POSIX ACLs are available]) - AC_CACHE_CHECK([for acl_get_perm_np],netatalk_cv_HAVE_ACL_GET_PERM_NP,[ - acl_LIBS=$LIBS - LIBS="$LIBS $ACL_LIBS" - AC_LINK_IFELSE([AC_LANG_PROGRAM([[ - #include - #include - ]], [[ - acl_permset_t permset_d; - acl_perm_t perm; - return acl_get_perm_np(permset_d, perm); - ]])],[netatalk_cv_HAVE_ACL_GET_PERM_NP=yes],[netatalk_cv_HAVE_ACL_GET_PERM_NP=no]) - LIBS=$acl_LIBS - ]) - if test x"$netatalk_cv_HAVE_ACL_GET_PERM_NP" = x"yes"; then - AC_DEFINE(HAVE_ACL_GET_PERM_NP,1,[Whether acl_get_perm_np() is available]) - fi - - - AC_CACHE_CHECK([for acl_from_mode], netatalk_cv_HAVE_ACL_FROM_MODE,[ - acl_LIBS=$LIBS - LIBS="$LIBS $ACL_LIBS" - AC_CHECK_FUNCS(acl_from_mode, - [netatalk_cv_HAVE_ACL_FROM_MODE=yes], - [netatalk_cv_HAVE_ACL_FROM_MODE=no]) - LIBS=$acl_LIBS - ]) - if test x"netatalk_cv_HAVE_ACL_FROM_MODE" = x"yes"; then - AC_DEFINE(HAVE_ACL_FROM_MODE,1,[Whether acl_from_mode() is available]) - fi + if test x"$netatalk_cv_HAVE_ACL_GET_PERM_NP" = x"yes"; then + AC_DEFINE(HAVE_ACL_GET_PERM_NP,1,[Whether acl_get_perm_np() is available]) + fi - else - AC_MSG_NOTICE(ACL support is not avaliable) - AC_DEFINE(HAVE_NO_ACLS,1,[Whether no ACLs support is available]) + AC_CACHE_CHECK([for acl_from_mode], netatalk_cv_HAVE_ACL_FROM_MODE,[ + acl_LIBS=$LIBS + LIBS="$LIBS $ACL_LIBS" + AC_CHECK_FUNCS(acl_from_mode, + [netatalk_cv_HAVE_ACL_FROM_MODE=yes], + [netatalk_cv_HAVE_ACL_FROM_MODE=no] + ) + LIBS=$acl_LIBS + ]) + if test x"netatalk_cv_HAVE_ACL_FROM_MODE" = x"yes"; then + AC_DEFINE(HAVE_ACL_FROM_MODE,1,[Whether acl_from_mode() is available]) fi - ;; - esac + fi fi -if test x"$with_acl_support" = x"yes" ; then - AC_CHECK_HEADERS([acl/libacl.h]) - AC_DEFINE(HAVE_ACLS,1,[Whether ACLs support is available]) - AC_SUBST(ACL_LIBS) +if test x"$ac_cv_have_acls" = x"no" ; then + if test x"$with_acl_support" = x"yes" ; then + AC_MSG_ERROR(ACL support requested but not found) + else + AC_MSG_NOTICE(ACL support is not avaliable) + fi +else + AC_CHECK_HEADERS([acl/libacl.h]) + AC_DEFINE(HAVE_ACLS,1,[Whether ACLs support is available]) fi +AC_SUBST(ACL_LIBS) ]) dnl Check for Extended Attributes support diff --git a/macros/summary.m4 b/macros/summary.m4 index e64debfd..e72fb6a2 100644 --- a/macros/summary.m4 +++ b/macros/summary.m4 @@ -11,7 +11,7 @@ AC_DEFUN([AC_NETATALK_CONFIG_SUMMARY], [ fi AC_MSG_RESULT([ AFP:]) AC_MSG_RESULT([ Extended Attributes: $neta_cv_eas]) - AC_MSG_RESULT([ ACL support: $with_acl_support]) + AC_MSG_RESULT([ ACL support: $ac_cv_have_acls]) AC_MSG_RESULT([ Spotlight: $ac_cv_have_tracker]) AC_MSG_RESULT([ CNID:]) AC_MSG_RESULT([ backends: $compiled_backends]) diff --git a/man/man5/afp.conf.5.in b/man/man5/afp.conf.5.in index f8ade925..b6d250c5 100644 --- a/man/man5/afp.conf.5.in +++ b/man/man5/afp.conf.5.in @@ -600,6 +600,13 @@ spotlight = \fIBOOLEAN\fR (default: \fIno\fR) \fB(G)/(V)\fR Whether to enable Spotlight searches\&. Note: once the global option is enabled, any volume that is not enabled won\*(Aqt be searchable at all\&. .RE .PP +veto message = \fIBOOLEAN\fR (default: \fIno\fR) \fB(G)\fR +.RS 4 +Use section +\fBname\fR +as option preset for all volumes (when set in the [Global] section) or for one volume (when set in that volume\*(Aqs section)\&. +.RE +.PP vol dbpath = \fIpath\fR \fB(G)\fR .RS 4 Sets the database information to be stored in path\&. You have to specify a writable location, even if the volume is read only\&. The default is @@ -819,6 +826,11 @@ ldap name attr = \fIdn\fR \fB(G)\fR Name of the LDAP attribute with the users short name\&. .RE .PP +ldap group attr = \fIdn\fR \fB(G)\fR +.RS 4 +Name of the LDAP attribute with the groups short name\&. +.RE +.PP ldap uuid string = \fISTRING\fR \fB(G)\fR .RS 4 Format of the uuid string in the directory\&. A series of x and \-, where every x denotes a value 0\-9a\-f and every \- is a separator\&. @@ -829,6 +841,11 @@ Default: xxxxxxxx\-xxxx\-xxxx\-xxxx\-xxxxxxxxxxxx ldap uuid encoding = \fIstring | ms\-guid (default: string)\fR \fB(G)\fR .RS 4 Format of the UUID of the LDAP attribute, allows usage of the binary objectGUID fields from Active Directory\&. If left unspecified, string is the default, which passes through the ASCII UUID returned by most other LDAP stores\&. If set to ms\-guid, the internal UUID representation is converted to and from the binary format used in the objectGUID attribute found on objects in Active Directory when interacting with the server\&. +.sp +See also the options +\fBldap user filter\fR +and +\fBldap group filter\fR\&. .PP string .RS 4 @@ -841,9 +858,20 @@ Binary objectGUID from Active Directory .RE .RE .PP -ldap group attr = \fIdn\fR \fB(G)\fR +ldap user filter = \fISTRING (default: unused)\fR \fB(G)\fR .RS 4 -Name of the LDAP attribute with the groups short name\&. +Optional LDAP filter that matches user objects\&. This is necessary for Active Directory environments where users and groups are stored in the same directory subtree\&. +.sp +Recommended setting for Active Directory: +\fIobjectClass=user\fR\&. +.RE +.PP +ldap group filter = \fISTRING (default: unused)\fR \fB(G)\fR +.RS 4 +Optional LDAP filter that matches group objects\&. This is necessary for Active Directory environments where users and groups are stored in the same directory subtree\&. +.sp +Recommended setting for Active Directory: +\fIobjectClass=group\fR\&. .RE .SH "EXPLANATION OF VOLUME PARAMETERS" .SS "Parameters" @@ -1061,6 +1089,13 @@ is performed when accessing filesystems from clients\&. This is generally useful on volumes and do the conversion with that\&. Then this option can be set to no\&. .RE .PP +delete veto files = \fIBOOLEAN\fR (default: \fIno\fR) \fB(V)\fR +.RS 4 +This option is used when Netatalk is attempting to delete a directory that contains one or more vetoed files or directories (see the veto files option)\&. If this option is set to no (the default) then if a directory contains any non\-vetoed files or directories then the directory delete will fail\&. This is usually what you want\&. +.sp +If this option is set to yes, then Netatalk will attempt to recursively delete any files and directories within the vetoed directory\&. +.RE +.PP follow symlinks = \fIBOOLEAN\fR (default: \fIno\fR) \fB(V)\fR .RS 4 The default setting is false thus symlinks are not followed on the server\&. This is the same behaviour as OS X\*(Aqs AFP server\&. Setting the option to true causes afpd to follow symlinks on the server\&. symlinks may point outside of the AFP volume, currently afpd doesn\*(Aqt do any checks for "wide symlinks"\&.