#include <atalk/errchk.h>
#include <atalk/bstrlib.h>
#include <atalk/bstradd.h>
+#include <atalk/compat.h>
struct perm {
uid_t uid;
gid_t gid;
};
-typedef int (*rf_loop)(struct dirent *, char *, void *, int , mode_t );
+typedef int (*rf_loop)(const struct vol *, struct dirent *, char *, void *, int);
/* ----------------------------- */
static int
-for_each_adouble(const char *from, const char *name, rf_loop fn, void *data, int flag, mode_t v_umask)
+for_each_adouble(const char *from, const char *name, rf_loop fn, const struct vol *vol, void *data, int flag)
{
char buf[ MAXPATHLEN + 1];
char *m;
}
strlcat(buf, de->d_name, sizeof(buf));
- if (fn && (ret = fn(de, buf, data, flag, v_umask))) {
+ if (fn && (ret = fn(vol, de, buf, data, flag))) {
closedir(dp);
return ret;
}
return ret;
}
-/*******************************************************************************
- * classic adouble format
- *******************************************************************************/
-
static int netatalk_name(const char *name)
{
- return strcasecmp(name,".AppleDouble") &&
- strcasecmp(name,".AppleDB") &&
- strcasecmp(name,".AppleDesktop");
+ return strcmp(name,".AppleDB") && strcmp(name,".AppleDesktop");
}
+/*******************************************************************************
+ * classic adouble format
+ *******************************************************************************/
+
static int validupath_adouble(VFS_FUNC_ARGS_VALIDUPATH)
{
if (name[0] != '.')
return 1;
- if (!(vol->v_flags & AFPVOL_USEDOTS))
- return 0;
-
- return netatalk_name(name) && strcasecmp(name,".Parent");
+ return netatalk_name(name) && strcmp(name,".AppleDouble") && strcasecmp(name,".Parent");
}
/* ----------------- */
static int RF_chown_adouble(VFS_FUNC_ARGS_CHOWN)
{
struct stat st;
- char *ad_p;
+ const char *ad_p;
ad_p = vol->ad_path(path, ADFLAGS_HF );
}
/* ----------------- */
-static int deletecurdir_adouble_loop(struct dirent *de, char *name, void *data _U_, int flag _U_, mode_t v_umask)
+static int deletecurdir_adouble_loop(const struct vol *vol, struct dirent *de, char *name, void *data _U_, int flag _U_)
{
struct stat st;
int err;
/* bail if the file exists in the current directory.
* note: this will not fail with dangling symlinks */
- if (stat(de->d_name, &st) == 0)
+ if (lstat(de->d_name, &st) == 0)
return AFPERR_DIRNEMPT;
if ((err = netatalk_unlink(name)))
/* delete stray .AppleDouble files. this happens to get .Parent files
as well. */
- if ((err = for_each_adouble("deletecurdir", ".AppleDouble", deletecurdir_adouble_loop, NULL, 1, vol->v_umask)))
+ if ((err = for_each_adouble("deletecurdir", ".AppleDouble", deletecurdir_adouble_loop, vol, NULL, 1)))
return err;
return netatalk_rmdir(-1, ".AppleDouble" );
}
/* ----------------- */
-static int adouble_setfilmode(const char * name, mode_t mode, struct stat *st, mode_t v_umask)
+static int adouble_setfilmode(const struct vol *vol, const char *name, mode_t mode, struct stat *st)
{
- return setfilmode(name, ad_hf_mode(mode), st, v_umask);
+ return setfilmode(vol, name, ad_hf_mode(mode), st);
}
static int RF_setfilmode_adouble(VFS_FUNC_ARGS_SETFILEMODE)
{
- return adouble_setfilmode(vol->ad_path(name, ADFLAGS_HF ), mode, st, vol->v_umask);
+ return adouble_setfilmode(vol, vol->ad_path(name, ADFLAGS_HF ), mode, st);
}
/* ----------------- */
static int RF_setdirunixmode_adouble(VFS_FUNC_ARGS_SETDIRUNIXMODE)
{
- char *adouble = vol->ad_path(name, ADFLAGS_DIR );
- int dropbox = vol->v_flags;
+ const char *adouble = vol->ad_path(name, ADFLAGS_DIR );
if (dir_rx_set(mode)) {
- if (stickydirmode(ad_dir(adouble), DIRBITS | mode, dropbox, vol->v_umask) < 0 )
+ if (chmod_acl(ad_dir(adouble), (DIRBITS | mode) & ~vol->v_umask) < 0 )
return -1;
}
- if (adouble_setfilmode(vol->ad_path(name, ADFLAGS_DIR ), mode, st, vol->v_umask) < 0)
+ if (adouble_setfilmode(vol, vol->ad_path(name, ADFLAGS_DIR ), mode, st) < 0)
return -1;
if (!dir_rx_set(mode)) {
- if (stickydirmode(ad_dir(adouble), DIRBITS | mode, dropbox, vol->v_umask) < 0 )
+ if (chmod_acl(ad_dir(adouble), (DIRBITS | mode) & ~vol->v_umask) < 0 )
return -1 ;
}
return 0;
}
/* ----------------- */
-static int setdirmode_adouble_loop(struct dirent *de _U_, char *name, void *data, int flag, mode_t v_umask)
+static int setdirmode_adouble_loop(const struct vol *vol, struct dirent *de _U_, char *name, void *data, int flag)
{
mode_t hf_mode = *(mode_t *)data;
struct stat st;
- if ( stat( name, &st ) < 0 ) {
+ if (ostat(name, &st, vol_syml_opt(vol)) < 0 ) {
if (flag)
return 0;
LOG(log_error, logtype_afpd, "setdirmode: stat %s: %s", name, strerror(errno) );
}
else if (!S_ISDIR(st.st_mode)) {
- if (setfilmode(name, hf_mode , &st, v_umask) < 0) {
+ if (setfilmode(vol, name, hf_mode, &st) < 0) {
/* FIXME what do we do then? */
}
}
static int RF_setdirmode_adouble(VFS_FUNC_ARGS_SETDIRMODE)
{
- int dropbox = vol->v_flags;
mode_t hf_mode = ad_hf_mode(mode);
- char *adouble = vol->ad_path(name, ADFLAGS_DIR );
- char *adouble_p = ad_dir(adouble);
+ const char *adouble = vol->ad_path(name, ADFLAGS_DIR );
+ const char *adouble_p = ad_dir(adouble);
if (dir_rx_set(mode)) {
- if (stickydirmode(ad_dir(adouble), DIRBITS | mode, dropbox, vol->v_umask) < 0)
+ if (chmod_acl(ad_dir(adouble), (DIRBITS | mode) & ~vol->v_umask) < 0)
return -1;
}
- if (for_each_adouble("setdirmode", adouble_p, setdirmode_adouble_loop, &hf_mode, vol_noadouble(vol), vol->v_umask))
+ if (for_each_adouble("setdirmode", adouble_p, setdirmode_adouble_loop, vol, &hf_mode, 0))
return -1;
if (!dir_rx_set(mode)) {
- if (stickydirmode(ad_dir(adouble), DIRBITS | mode, dropbox, vol->v_umask) < 0)
+ if (chmod_acl(ad_dir(adouble), (DIRBITS | mode) & ~vol->v_umask) < 0)
return -1 ;
}
return 0;
}
-/* ----------------- */
-static int setdirowner_adouble_loop(struct dirent *de _U_, char *name, void *data, int flag _U_, mode_t v_umask _U_)
-{
- struct perm *owner = data;
-
- if ( chown( name, owner->uid, owner->gid ) < 0 && errno != EPERM ) {
- LOG(log_debug, logtype_afpd, "setdirowner: chown %d/%d %s: %s",
- owner->uid, owner->gid, fullpathname(name), strerror(errno) );
- /* return ( -1 ); Sometimes this is okay */
- }
- return 0;
-}
-
static int RF_setdirowner_adouble(VFS_FUNC_ARGS_SETDIROWNER)
{
- int noadouble = vol_noadouble(vol);
- char *adouble_p;
- struct stat st;
- struct perm owner;
-
- owner.uid = uid;
- owner.gid = gid;
-
- adouble_p = ad_dir(vol->ad_path(name, ADFLAGS_DIR ));
-
- if (for_each_adouble("setdirowner", adouble_p, setdirowner_adouble_loop, &owner, noadouble, vol->v_umask))
- return -1;
-
- /*
- * We cheat: we know that chown doesn't do anything.
- */
- if ( stat( ".AppleDouble", &st ) < 0) {
- if (errno == ENOENT && noadouble)
- return 0;
- LOG(log_error, logtype_afpd, "setdirowner: stat %s: %s", fullpathname(".AppleDouble"), strerror(errno) );
- return -1;
- }
- if ( gid && gid != st.st_gid && chown( ".AppleDouble", uid, gid ) < 0 && errno != EPERM ) {
+ if (lchown(".AppleDouble", uid, gid) < 0 && errno != EPERM ) {
LOG(log_debug, logtype_afpd, "setdirowner: chown %d/%d %s: %s",
- uid, gid,fullpathname(".AppleDouble"), strerror(errno) );
- /* return ( -1 ); Sometimes this is okay */
+ uid, gid,fullpathname(".AppleDouble"), strerror(errno));
}
return 0;
}
if (errno == ENOENT) {
struct adouble ad;
- if (lstatat(dirfd, adsrc, &st)) /* source has no ressource fork, */
+ if (ostatat(dirfd, adsrc, &st, vol_syml_opt(vol))) /* source has no ressource fork, */
return 0;
/* We are here because :
* create .AppleDouble if the file is already opened, so we
* use a diff one, it's not a pb,ie it's not the same file, yet.
*/
- ad_init(&ad, vol->v_adouble, vol->v_ad_options);
- if (!ad_open(dst, ADFLAGS_HF, O_RDWR | O_CREAT, 0666, &ad)) {
+ ad_init(&ad, vol);
+ if (ad_open(&ad, dst, ADFLAGS_HF | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666) == 0) {
ad_close(&ad, ADFLAGS_HF);
if (!unix_rename(dirfd, adsrc, -1, vol->ad_path(dst, 0 )) )
err = 0;
EC_ZERO(bcatcstr(d, name));
}
- EC_ZERO(copy_file(sfd, cfrombstr(s), cfrombstr(d), 0666));
+ /* ignore errors */
+ if (copy_file(sfd, cfrombstr(s), cfrombstr(d), 0666) != 0)
+ if (errno != ENOENT)
+ EC_FAIL;
EC_CLEANUP:
bdestroy(s);
EC_EXIT;
}
-#ifdef HAVE_SOLARIS_ACLS
+#ifdef HAVE_NFSV4_ACLS
static int RF_solaris_acl(VFS_FUNC_ARGS_ACL)
{
static char buf[ MAXPATHLEN + 1];
struct stat st;
int len;
- if ((stat(path, &st)) != 0)
- return -1;
- if (S_ISDIR(st.st_mode)) {
- len = snprintf(buf, MAXPATHLEN, "%s/.AppleDouble",path);
- if (len < 0 || len >= MAXPATHLEN)
- return -1;
- /* set acl on .AppleDouble dir first */
- if ((acl(buf, cmd, count, aces)) != 0)
- return -1;
- /* now set ACL on ressource fork */
- if ((acl(vol->ad_path(path, ADFLAGS_DIR), cmd, count, aces)) != 0)
- return -1;
- } else
- /* set ACL on ressource fork */
- if ((acl(vol->ad_path(path, ADFLAGS_HF), cmd, count, aces)) != 0)
- return -1;
-
- return 0;
+ if ((stat(path, &st)) != 0) {
+ if (errno == ENOENT)
+ return AFP_OK;
+ return AFPERR_MISC;
+ }
+ if (!S_ISDIR(st.st_mode)) {
+ /* set ACL on ressource fork */
+ if ((acl(vol->ad_path(path, ADFLAGS_HF), cmd, count, aces)) != 0)
+ return AFPERR_MISC;
+ }
+ return AFP_OK;
}
static int RF_solaris_remove_acl(VFS_FUNC_ARGS_REMOVE_ACL)
static char buf[ MAXPATHLEN + 1];
int len;
- if (dir) {
- len = snprintf(buf, MAXPATHLEN, "%s/.AppleDouble",path);
- if (len < 0 || len >= MAXPATHLEN)
- return AFPERR_MISC;
- /* remove ACL from .AppleDouble/.Parent first */
- if ((ret = remove_acl_vfs(vol->ad_path(path, ADFLAGS_DIR))) != AFP_OK)
- return ret;
- /* now remove from .AppleDouble dir */
- if ((ret = remove_acl_vfs(buf)) != AFP_OK)
- return ret;
- } else
- /* remove ACL from ressource fork */
- if ((ret = remove_acl_vfs(vol->ad_path(path, ADFLAGS_HF))) != AFP_OK)
- return ret;
+ if (dir)
+ return AFP_OK;
+
+ /* remove ACL from ressource fork */
+ if ((ret = remove_acl_vfs(vol->ad_path(path, ADFLAGS_HF))) != AFP_OK) {
+ if (errno == ENOENT)
+ return AFP_OK;
+ return ret;
+ }
return AFP_OK;
}
static int RF_posix_acl(VFS_FUNC_ARGS_ACL)
{
EC_INIT;
- static char buf[ MAXPATHLEN + 1];
struct stat st;
- int len;
- if (S_ISDIR(st.st_mode)) {
- len = snprintf(buf, MAXPATHLEN, "%s/.AppleDouble",path);
- if (len < 0 || len >= MAXPATHLEN)
- EC_FAIL;
- /* set acl on .AppleDouble dir first */
- EC_ZERO_LOG(acl_set_file(buf, type, acl));
+ if (stat(path, &st) == -1)
+ EC_FAIL;
- if (type == ACL_TYPE_ACCESS)
- /* set ACL on ressource fork (".Parent") too */
- EC_ZERO_LOG(acl_set_file(vol->ad_path(path, ADFLAGS_DIR), type, acl));
- } else {
+ if (!S_ISDIR(st.st_mode)) {
/* set ACL on ressource fork */
- EC_ZERO_LOG(acl_set_file(vol->ad_path(path, ADFLAGS_HF), type, acl));
+ EC_ZERO_ERR( acl_set_file(vol->ad_path(path, ADFLAGS_HF), type, acl), AFPERR_MISC );
}
EC_CLEANUP:
- if (ret != 0)
- return AFPERR_MISC;
- return AFP_OK;
+ if (errno == ENOENT)
+ EC_STATUS(AFP_OK);
+ EC_EXIT;
}
static int RF_posix_remove_acl(VFS_FUNC_ARGS_REMOVE_ACL)
{
EC_INIT;
- static char buf[ MAXPATHLEN + 1];
- int len;
- if (dir) {
- len = snprintf(buf, MAXPATHLEN, "%s/.AppleDouble",path);
- if (len < 0 || len >= MAXPATHLEN)
- return AFPERR_MISC;
- /* remove ACL from .AppleDouble/.Parent first */
- EC_ZERO_LOG_ERR(remove_acl_vfs(vol->ad_path(path, ADFLAGS_DIR)), AFPERR_MISC);
+ if (dir)
+ EC_EXIT_STATUS(AFP_OK);
- /* now remove from .AppleDouble dir */
- EC_ZERO_LOG_ERR(remove_acl_vfs(buf), AFPERR_MISC);
- } else {
- /* remove ACL from ressource fork */
- EC_ZERO_LOG_ERR(remove_acl_vfs(vol->ad_path(path, ADFLAGS_HF)), AFPERR_MISC);
- }
+ /* remove ACL from ressource fork */
+ EC_ZERO_ERR( remove_acl_vfs(vol->ad_path(path, ADFLAGS_HF)), AFPERR_MISC );
EC_CLEANUP:
+ if (errno == ENOENT)
+ EC_STATUS(AFP_OK);
EC_EXIT;
}
#endif
-/*********************************************************************************
- * sfm adouble format
- *********************************************************************************/
-static int ads_chown_loop(struct dirent *de _U_, char *name, void *data, int flag _U_, mode_t v_umask _U_)
-{
- struct perm *owner = data;
-
- if (chown( name , owner->uid, owner->gid ) < 0) {
- return -1;
- }
- return 0;
-}
-
-static int RF_chown_ads(VFS_FUNC_ARGS_CHOWN)
-{
- struct stat st;
- char *ad_p;
- struct perm owner;
-
- owner.uid = uid;
- owner.gid = gid;
-
-
- ad_p = ad_dir(vol->ad_path(path, ADFLAGS_HF ));
-
- if ( stat( ad_p, &st ) < 0 ) {
- /* ignore */
- return 0;
- }
-
- if (chown( ad_p, uid, gid ) < 0) {
- return -1;
- }
- return for_each_adouble("chown_ads", ad_p, ads_chown_loop, &owner, 1, vol->v_umask);
-}
-
-/* --------------------------------- */
-static int deletecurdir_ads1_loop(struct dirent *de _U_, char *name, void *data _U_, int flag _U_, mode_t v_umask _U_)
-{
- return netatalk_unlink(name);
-}
-
-static int ads_delete_rf(char *name)
-{
- int err;
-
- if ((err = for_each_adouble("deletecurdir", name, deletecurdir_ads1_loop, NULL, 1, 0)))
- return err;
- /* FIXME
- * it's a problem for a nfs mounted folder, there's .nfsxxx around
- * for linux the following line solve it.
- * but it could fail if rm .nfsxxx create a new .nfsyyy :(
- */
- if ((err = for_each_adouble("deletecurdir", name, deletecurdir_ads1_loop, NULL, 1, 0)))
- return err;
- return netatalk_rmdir(-1, name);
-}
-
-static int deletecurdir_ads_loop(struct dirent *de, char *name, void *data _U_, int flag _U_, mode_t v_umask _U_)
+/*************************************************************************
+ * EA adouble format
+ ************************************************************************/
+static int validupath_ea(VFS_FUNC_ARGS_VALIDUPATH)
{
- struct stat st;
-
- /* bail if the file exists in the current directory.
- * note: this will not fail with dangling symlinks */
+ if (name[0] != '.')
+ return 1;
- if (stat(de->d_name, &st) == 0) {
- return AFPERR_DIRNEMPT;
- }
- return ads_delete_rf(name);
-}
-
-static int RF_deletecurdir_ads(VFS_FUNC_ARGS_DELETECURDIR)
-{
- int err;
-
- /* delete stray .AppleDouble files. this happens to get .Parent files as well. */
- if ((err = for_each_adouble("deletecurdir", ".AppleDouble", deletecurdir_ads_loop, NULL, 1, 0)))
- return err;
-
- return netatalk_rmdir(-1, ".AppleDouble" );
-}
-
-/* ------------------- */
-struct set_mode {
- mode_t mode;
- struct stat *st;
-};
-
-static int ads_setfilmode_loop(struct dirent *de _U_, char *name, void *data, int flag _U_, mode_t v_umask)
-{
- struct set_mode *param = data;
-
- return setfilmode(name, param->mode, param->st, v_umask);
+#ifndef HAVE_EAFD
+ if (name[1] == '_')
+ return ad_valid_header_osx(name);
+#endif
+ return netatalk_name(name);
}
-static int ads_setfilmode(const char * name, mode_t mode, struct stat *st, mode_t v_umask)
+/* ----------------- */
+static int RF_chown_ea(VFS_FUNC_ARGS_CHOWN)
{
- mode_t file_mode = ad_hf_mode(mode);
- mode_t dir_mode = file_mode;
- struct set_mode param;
-
- if ((dir_mode & (S_IRUSR | S_IWUSR )))
- dir_mode |= S_IXUSR;
- if ((dir_mode & (S_IRGRP | S_IWGRP )))
- dir_mode |= S_IXGRP;
- if ((dir_mode & (S_IROTH | S_IWOTH )))
- dir_mode |= S_IXOTH;
-
- /* change folder */
- dir_mode |= DIRBITS;
- if (dir_rx_set(dir_mode)) {
- if (chmod( name, dir_mode ) < 0)
- return -1;
- }
- param.st = st;
- param.mode = file_mode;
- if (for_each_adouble("setfilmode_ads", name, ads_setfilmode_loop, ¶m, 0, v_umask) < 0)
- return -1;
-
- if (!dir_rx_set(dir_mode)) {
- if (chmod( name, dir_mode ) < 0)
- return -1;
- }
-
+#ifndef HAVE_EAFD
+ return chown(vol->ad_path(path, ADFLAGS_HF ), uid, gid);
+#endif
return 0;
}
-static int RF_setfilmode_ads(VFS_FUNC_ARGS_SETFILEMODE)
-{
- return ads_setfilmode(ad_dir(vol->ad_path(name, ADFLAGS_HF )), mode, st, vol->v_umask);
-}
-
-/* ------------------- */
-static int RF_setdirunixmode_ads(VFS_FUNC_ARGS_SETDIRUNIXMODE)
+/* ---------------- */
+static int RF_renamedir_ea(VFS_FUNC_ARGS_RENAMEDIR)
{
- char *adouble = vol->ad_path(name, ADFLAGS_DIR );
- char ad_p[ MAXPATHLEN + 1];
- int dropbox = vol->v_flags;
-
- strlcpy(ad_p,ad_dir(adouble), MAXPATHLEN + 1);
-
- if (dir_rx_set(mode)) {
-
- /* .AppleDouble */
- if (stickydirmode(ad_dir(ad_p), DIRBITS | mode, dropbox, vol->v_umask) < 0)
- return -1;
-
- /* .AppleDouble/.Parent */
- if (stickydirmode(ad_p, DIRBITS | mode, dropbox, vol->v_umask) < 0)
- return -1;
- }
-
- if (ads_setfilmode(ad_dir(vol->ad_path(name, ADFLAGS_DIR)), mode, st, vol->v_umask) < 0)
- return -1;
-
- if (!dir_rx_set(mode)) {
- if (stickydirmode(ad_p, DIRBITS | mode, dropbox, vol->v_umask) < 0)
- return -1 ;
- if (stickydirmode(ad_dir(ad_p), DIRBITS | mode, dropbox, vol->v_umask) < 0)
- return -1;
- }
return 0;
}
-/* ------------------- */
-struct dir_mode {
- mode_t mode;
- int dropbox;
-};
-
-static int setdirmode_ads_loop(struct dirent *de _U_, char *name, void *data, int flag, mode_t v_umask)
+/* Returns 1 if the entry is NOT an ._ file */
+static int deletecurdir_ea_osx_chkifempty_loop(const struct vol *vol, struct dirent *de, char *name, void *data _U_, int flag _U_)
{
+ if (de->d_name[0] != '.' || de->d_name[0] == '_')
+ return 1;
- struct dir_mode *param = data;
- int ret = 0; /* 0 ignore error, -1 */
-
- if (dir_rx_set(param->mode)) {
- if (stickydirmode(name, DIRBITS | param->mode, param->dropbox, v_umask) < 0) {
- if (flag) {
- return 0;
- }
- return ret;
- }
- }
- if (ads_setfilmode(name, param->mode, NULL, v_umask) < 0)
- return ret;
-
- if (!dir_rx_set(param->mode)) {
- if (stickydirmode(name, DIRBITS | param->mode, param->dropbox, v_umask) < 0) {
- if (flag) {
- return 0;
- }
- return ret;
- }
- }
return 0;
}
-static int RF_setdirmode_ads(VFS_FUNC_ARGS_SETDIRMODE)
+static int deletecurdir_ea_osx_loop(const struct vol *vol, struct dirent *de, char *name, void *data _U_, int flag _U_)
{
- char *adouble = vol->ad_path(name, ADFLAGS_DIR );
- char ad_p[ MAXPATHLEN + 1];
- struct dir_mode param;
-
- param.mode = mode;
- param.dropbox = vol->v_flags;
-
- strlcpy(ad_p,ad_dir(adouble), sizeof(ad_p));
+ int ret;
+ struct stat sb;
- if (dir_rx_set(mode)) {
- /* .AppleDouble */
- if (stickydirmode(ad_dir(ad_p), DIRBITS | mode, param.dropbox, vol->v_umask) < 0)
+ 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;
}
- if (for_each_adouble("setdirmode_ads", ad_dir(ad_p), setdirmode_ads_loop, ¶m, vol_noadouble(vol), vol->v_umask))
- return -1;
-
- if (!dir_rx_set(mode)) {
- if (stickydirmode(ad_dir(ad_p), DIRBITS | mode, param.dropbox, vol->v_umask) < 0 )
- return -1;
- }
return 0;
}
-/* ------------------- */
-static int setdirowner_ads1_loop(struct dirent *de _U_, char *name, void *data, int flag _U_, mode_t v_umask _U_)
+/* ---------------- */
+static int RF_deletecurdir_ea(VFS_FUNC_ARGS_DELETECURDIR)
{
- struct perm *owner = data;
+#ifndef HAVE_EAFD
+ int err;
+ /* delete stray ._AppleDouble files */
+ if ((err = for_each_adouble("deletecurdir_ea_osx", ".",
+ deletecurdir_ea_osx_loop,
+ vol, NULL, 0)) != 0)
+ return err;
- if ( chown( name, owner->uid, owner->gid ) < 0 && errno != EPERM ) {
- LOG(log_debug, logtype_afpd, "setdirowner: chown %d/%d %s: %s",
- owner->uid, owner->gid, fullpathname(name), strerror(errno) );
- /* return ( -1 ); Sometimes this is okay */
- }
+#endif
return 0;
}
-static int setdirowner_ads_loop(struct dirent *de _U_, char *name, void *data, int flag, mode_t v_umask _U_)
+/* ---------------- */
+static int RF_setdirunixmode_ea(VFS_FUNC_ARGS_SETDIRUNIXMODE)
{
- struct perm *owner = data;
-
- if (for_each_adouble("setdirowner", name, setdirowner_ads1_loop, data, flag, 0) < 0)
- return -1;
-
- if ( chown( name, owner->uid, owner->gid ) < 0 && errno != EPERM ) {
- LOG(log_debug, logtype_afpd, "setdirowner: chown %d/%d %s: %s",
- owner->uid, owner->gid, fullpathname(name), strerror(errno) );
- /* return ( -1 ); Sometimes this is okay */
- }
+#ifndef HAVE_EAFD
+#endif
return 0;
}
-static int RF_setdirowner_ads(VFS_FUNC_ARGS_SETDIROWNER)
+static int RF_setfilmode_ea(VFS_FUNC_ARGS_SETFILEMODE)
{
- int noadouble = vol_noadouble(vol);
- char adouble_p[ MAXPATHLEN + 1];
- struct stat st;
- struct perm owner;
-
- owner.uid = uid;
- owner.gid = gid;
-
- strlcpy(adouble_p, ad_dir(vol->ad_path(name, ADFLAGS_DIR )), sizeof(adouble_p));
-
- if (for_each_adouble("setdirowner", ad_dir(adouble_p), setdirowner_ads_loop, &owner, noadouble, 0))
- return -1;
-
- /*
- * We cheat: we know that chown doesn't do anything.
- */
- if ( stat( ".AppleDouble", &st ) < 0) {
- if (errno == ENOENT && noadouble)
- return 0;
- LOG(log_error, logtype_afpd, "setdirowner: stat %s: %s", fullpathname(".AppleDouble"), strerror(errno) );
- return -1;
- }
- if ( gid && gid != st.st_gid && chown( ".AppleDouble", uid, gid ) < 0 && errno != EPERM ) {
- LOG(log_debug, logtype_afpd, "setdirowner: chown %d/%d %s: %s",
- uid, gid,fullpathname(".AppleDouble"), strerror(errno) );
- /* return ( -1 ); Sometimes this is okay */
- }
+#ifndef HAVE_EAFD
+ return adouble_setfilmode(vol, vol->ad_path(name, ADFLAGS_HF ), mode, st);
+#endif
return 0;
}
-/* ------------------- */
-static int RF_deletefile_ads(VFS_FUNC_ARGS_DELETEFILE)
-{
- int ret = 0;
- int cwd = -1;
- char *ad_p;
-
- ad_p = ad_dir(vol->ad_path(file, ADFLAGS_HF ));
-
- if (dirfd != -1) {
- if (((cwd = open(".", O_RDONLY)) == -1) || (fchdir(dirfd) != 0)) {
- ret = AFPERR_MISC;
- goto exit;
- }
- }
-
- ret = ads_delete_rf(ad_p);
-
- if (dirfd != -1 && fchdir(cwd) != 0) {
- LOG(log_error, logtype_afpd, "RF_deletefile_ads: cant chdir back. exit!");
- exit(EXITERR_SYS);
- }
-
-exit:
- if (cwd != -1)
- close(cwd);
-
- return ret;
-}
-
-/* --------------------------- */
-static int RF_renamefile_ads(VFS_FUNC_ARGS_RENAMEFILE)
-{
- char adsrc[ MAXPATHLEN + 1];
- int err = 0;
-
- strcpy( adsrc, ad_dir(vol->ad_path(src, 0 )));
- if (unix_rename(dirfd, adsrc, -1, ad_dir(vol->ad_path(dst, 0 ))) < 0) {
- struct stat st;
-
- err = errno;
- if (errno == ENOENT) {
- struct adouble ad;
-
- if (lstatat(dirfd, adsrc, &st)) /* source has no ressource fork, */
- return 0;
-
- /* We are here because :
- * -there's no dest folder.
- * -there's no .AppleDouble in the dest folder.
- * if we use the struct adouble passed in parameter it will not
- * create .AppleDouble if the file is already opened, so we
- * use a diff one, it's not a pb,ie it's not the same file, yet.
- */
- ad_init(&ad, vol->v_adouble, vol->v_ad_options);
- if (!ad_open(dst, ADFLAGS_HF, O_RDWR | O_CREAT, 0666, &ad)) {
- ad_close(&ad, ADFLAGS_HF);
-
- /* We must delete it */
- RF_deletefile_ads(vol, -1, dst );
- if (!unix_rename(dirfd, adsrc, -1, ad_dir(vol->ad_path(dst, 0 ))) )
- err = 0;
- else
- err = errno;
- }
- else { /* it's something else, bail out */
- err = errno;
- }
- }
- }
- if (err) {
- errno = err;
- return -1;
- }
- return 0;
-}
-
-/*************************************************************************
- * osx adouble format
- ************************************************************************/
-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(VFS_FUNC_ARGS_RENAMEDIR)
+static int RF_setdirmode_ea(VFS_FUNC_ARGS_SETDIRMODE)
{
- /* We simply move the corresponding ad file as well */
- char tempbuf[258]="._";
- return unix_rename(dirfd, vol->ad_path(oldpath,0), -1, strcat(tempbuf,newpath));
+#ifndef HAVE_EAFD
+#endif
+ return 0;
}
/* ---------------- */
-static int RF_deletecurdir_osx(VFS_FUNC_ARGS_DELETECURDIR)
+static int RF_setdirowner_ea(VFS_FUNC_ARGS_SETDIROWNER)
{
- return netatalk_unlink( vol->ad_path(".",0) );
+#ifndef HAVE_EAFD
+#endif
+ return 0;
}
-/* ---------------- */
-static int RF_setdirunixmode_osx(VFS_FUNC_ARGS_SETDIRUNIXMODE)
+static int RF_deletefile_ea(VFS_FUNC_ARGS_DELETEFILE)
{
- return adouble_setfilmode(vol->ad_path(name, ADFLAGS_DIR ), mode, st, vol->v_umask);
+#ifndef HAVE_EAFD
+ return netatalk_unlinkat(dirfd, vol->ad_path(file, ADFLAGS_HF));
+#endif
+ return 0;
}
-
-/* ---------------- */
-static int RF_setdirmode_osx(VFS_FUNC_ARGS_SETDIRMODE)
+static int RF_copyfile_ea(VFS_FUNC_ARGS_COPYFILE)
{
+#ifdef HAVE_EAFD
+ /* the EA VFS module does this all for us */
return 0;
-}
+#endif
-/* ---------------- */
-static int RF_setdirowner_osx(VFS_FUNC_ARGS_SETDIROWNER)
-{
- return 0;
+ EC_INIT;
+ bstring s = NULL, d = NULL;
+ char *dup1 = NULL;
+ char *dup2 = NULL;
+ char *dup3 = NULL;
+ char *dup4 = NULL;
+ const char *name = NULL;
+ const char *dir = NULL;
+
+ /* get basename */
+
+ /* build src path to ._ file*/
+ EC_NULL(dup1 = strdup(src));
+ EC_NULL(name = basename(strdup(dup1)));
+
+ EC_NULL(dup2 = strdup(src));
+ EC_NULL(dir = dirname(dup2));
+ EC_NULL(s = bfromcstr(dir));
+ EC_ZERO(bcatcstr(s, "/._"));
+ EC_ZERO(bcatcstr(s, name));
+
+ /* build dst path to ._file*/
+ EC_NULL(dup4 = strdup(dst));
+ EC_NULL(name = basename(strdup(dup4)));
+
+ EC_NULL(dup3 = strdup(dst));
+ EC_NULL(dir = dirname(dup3));
+ EC_NULL(d = bfromcstr(dir));
+ EC_ZERO(bcatcstr(d, "/._"));
+ EC_ZERO(bcatcstr(d, name));
+
+ if (copy_file(sfd, cfrombstr(s), cfrombstr(d), 0666) != 0) {
+ switch (errno) {
+ case ENOENT:
+ break;
+ default:
+ LOG(log_error, logtype_afpd, "[VFS] copyfile(\"%s\" -> \"%s\"): %s",
+ cfrombstr(s), cfrombstr(d), strerror(errno));
+ EC_FAIL;
+
+ }
+ }
+
+EC_CLEANUP:
+ bdestroy(s);
+ bdestroy(d);
+ free(dup1);
+ free(dup2);
+ free(dup3);
+ free(dup4);
+ EC_EXIT;
}
/* ---------------- */
-static int RF_renamefile_osx(VFS_FUNC_ARGS_RENAMEFILE)
+static int RF_renamefile_ea(VFS_FUNC_ARGS_RENAMEFILE)
{
+#ifndef HAVE_EAFD
char adsrc[ MAXPATHLEN + 1];
int err = 0;
struct stat st;
err = errno;
- if (errno == ENOENT && lstatat(dirfd, adsrc, &st)) /* source has no ressource fork, */
+ if (errno == ENOENT && ostatat(dirfd, adsrc, &st, vol_syml_opt(vol))) /* source has no ressource fork, */
return 0;
errno = err;
return -1;
}
return 0;
+#endif
+ return 0;
}
/********************************************************************************************
};
/*
- * Primary adouble modules: default, osx, sfm
+ * Primary adouble modules: v2, ea
*/
-static struct vfs_ops netatalk_adouble = {
+static struct vfs_ops netatalk_adouble_v2 = {
/* vfs_validupath: */ validupath_adouble,
/* vfs_chown: */ RF_chown_adouble,
/* vfs_renamedir: */ RF_renamedir_adouble,
NULL
};
-static struct vfs_ops netatalk_adouble_osx = {
- /* vfs_validupath: */ validupath_osx,
- /* vfs_chown: */ RF_chown_adouble,
- /* vfs_renamedir: */ RF_renamedir_osx,
- /* vfs_deletecurdir: */ RF_deletecurdir_osx,
- /* vfs_setfilmode: */ RF_setfilmode_adouble,
- /* vfs_setdirmode: */ RF_setdirmode_osx,
- /* vfs_setdirunixmode:*/ RF_setdirunixmode_osx,
- /* vfs_setdirowner: */ RF_setdirowner_osx,
- /* vfs_deletefile: */ RF_deletefile_adouble,
- /* vfs_renamefile: */ RF_renamefile_osx,
- /* vfs_copyfile: */ NULL,
- NULL
-};
-
-/* samba sfm format. ad_path shouldn't be set her */
-static struct vfs_ops netatalk_adouble_sfm = {
- /* vfs_validupath: */ validupath_adouble,
- /* vfs_chown: */ RF_chown_ads,
- /* vfs_renamedir: */ RF_renamedir_adouble,
- /* vfs_deletecurdir: */ RF_deletecurdir_ads,
- /* vfs_setfilmode: */ RF_setfilmode_ads,
- /* vfs_setdirmode: */ RF_setdirmode_ads,
- /* vfs_setdirunixmode:*/ RF_setdirunixmode_ads,
- /* vfs_setdirowner: */ RF_setdirowner_ads,
- /* vfs_deletefile: */ RF_deletefile_ads,
- /* vfs_renamefile: */ RF_renamefile_ads,
- /* vfs_copyfile: */ NULL,
+static struct vfs_ops netatalk_adouble_ea = {
+ /* vfs_validupath: */ validupath_ea,
+ /* vfs_chown: */ RF_chown_ea,
+ /* vfs_renamedir: */ RF_renamedir_ea,
+ /* vfs_deletecurdir: */ RF_deletecurdir_ea,
+ /* vfs_setfilmode: */ RF_setfilmode_ea,
+ /* vfs_setdirmode: */ RF_setdirmode_ea,
+ /* vfs_setdirunixmode:*/ RF_setdirunixmode_ea,
+ /* vfs_setdirowner: */ RF_setdirowner_ea,
+ /* vfs_deletefile: */ RF_deletefile_ea,
+ /* vfs_renamefile: */ RF_renamefile_ea,
+ /* vfs_copyfile: */ RF_copyfile_ea,
NULL
};
* 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,
vol->vfs = &vfs_master_funcs;
/* Default adouble stuff */
- if (vol->v_adouble == AD_VERSION2_OSX) {
- vol->vfs_modules[0] = &netatalk_adouble_osx;
- vol->ad_path = ad_path_osx;
- }
- else if (vol->v_adouble == AD_VERSION1_SFM) {
- vol->vfs_modules[0] = &netatalk_adouble_sfm;
- vol->ad_path = ad_path_sfm;
- }
- else {
- vol->vfs_modules[0] = &netatalk_adouble;
+ if (vol->v_adouble == AD_VERSION2) {
+ vol->vfs_modules[0] = &netatalk_adouble_v2;
vol->ad_path = ad_path;
+ } else {
+ vol->vfs_modules[0] = &netatalk_adouble_ea;
+#ifdef HAVE_EAFD
+ vol->ad_path = ad_path_ea;
+#else
+ vol->ad_path = ad_path_osx;
+#endif
}
/* Extended Attributes */
}
/* ACLs */
-#ifdef HAVE_SOLARIS_ACLS
+#ifdef HAVE_NFSV4_ACLS
vol->vfs_modules[2] = &netatalk_solaris_acl_adouble;
#endif
#ifdef HAVE_POSIX_ACLS