#include "volume.h"
#include "unix.h"
+#ifdef HAVE_NFSv4_ACLS
+extern int remove_acl(const char *name);
+#endif
+
struct perm {
uid_t uid;
gid_t gid;
static int ads_setfilmode(const char * name, mode_t mode, struct stat *st)
{
- mode_t dir_mode = mode;
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 )))
{
char *adouble = vol->vfs->ad_path( name, ADFLAGS_DIR );
char ad_p[ MAXPATHLEN + 1];
- int dropbox = (vol->v_flags & AFPVOL_DROPBOX);
+ 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) < 0 && !vol_noadouble(vol))
+ if (stickydirmode(ad_dir(ad_p), DIRBITS | mode, dropbox) < 0)
return -1;
/* .AppleDouble/.Parent */
- if (stickydirmode(ad_p, DIRBITS | mode, dropbox) < 0 && !vol_noadouble(vol))
+ if (stickydirmode(ad_p, DIRBITS | mode, dropbox) < 0)
return -1;
}
return -1;
if (!dir_rx_set(mode)) {
- if (stickydirmode(ad_p, DIRBITS | mode, dropbox) < 0 && !vol_noadouble(vol))
+ if (stickydirmode(ad_p, DIRBITS | mode, dropbox) < 0)
return -1 ;
- if (stickydirmode(ad_dir(ad_p), DIRBITS | mode, dropbox) < 0 && !vol_noadouble(vol))
+ if (stickydirmode(ad_dir(ad_p), DIRBITS | mode, dropbox) < 0)
return -1;
}
return 0;
struct dir_mode param;
param.mode = mode;
- param.dropbox = (vol->v_flags & AFPVOL_DROPBOX);
+ param.dropbox = vol->v_flags;
strlcpy(ad_p,ad_dir(adouble), sizeof(ad_p));
if (dir_rx_set(mode)) {
/* .AppleDouble */
- if (stickydirmode(ad_dir(ad_p), DIRBITS | mode, param.dropbox) < 0 && !vol_noadouble(vol))
+ if (stickydirmode(ad_dir(ad_p), DIRBITS | mode, param.dropbox) < 0)
return -1;
}
return -1;
if (!dir_rx_set(mode)) {
- if (stickydirmode(ad_dir(ad_p), DIRBITS | mode, param.dropbox) < 0 && !vol_noadouble(vol))
+ if (stickydirmode(ad_dir(ad_p), DIRBITS | mode, param.dropbox) < 0 )
return -1;
}
return 0;
struct adouble ad;
if (stat(adsrc, &st)) /* source has no ressource fork, */
- return AFP_OK;
+ return 0;
/* We are here because :
* -there's no dest folder.
static int validupath_adouble(const struct vol *vol, const char *name)
{
- return (vol->v_flags & AFPVOL_USEDOTS) ? strncasecmp(name,".Apple", 6) && strcasecmp(name, ".Parent")
+ return (vol->v_flags & AFPVOL_USEDOTS) ?
+ strcasecmp(name,".AppleDB") &&
+ strcasecmp(name,".AppleDouble") &&
+ strcasecmp(name,".AppleDesktop") &&
+ strcasecmp(name,".Parent")
: name[0] != '.';
}
static int RF_setdirunixmode_adouble(const struct vol *vol, const char * name, mode_t mode, struct stat *st)
{
char *adouble = vol->vfs->ad_path( name, ADFLAGS_DIR );
- int dropbox = (vol->v_flags & AFPVOL_DROPBOX);
+ int dropbox = vol->v_flags;
if (dir_rx_set(mode)) {
- if (stickydirmode(ad_dir(adouble), DIRBITS | mode, dropbox) < 0 && !vol_noadouble(vol))
+ if (stickydirmode(ad_dir(adouble), DIRBITS | mode, dropbox) < 0 )
return -1;
}
return -1;
if (!dir_rx_set(mode)) {
- if (stickydirmode(ad_dir(adouble), DIRBITS | mode, dropbox) < 0 && !vol_noadouble(vol))
+ if (stickydirmode(ad_dir(adouble), DIRBITS | mode, dropbox) < 0 )
return -1 ;
}
return 0;
static int RF_setdirmode_adouble(const struct vol *vol, const char * name, mode_t mode, struct stat *st _U_)
{
- int dropbox = (vol->v_flags & AFPVOL_DROPBOX);
+ int dropbox = vol->v_flags;
mode_t hf_mode = ad_hf_mode(mode);
char *adouble = vol->vfs->ad_path( name, ADFLAGS_DIR );
char *adouble_p = ad_dir(adouble);
if (dir_rx_set(mode)) {
- if (stickydirmode(ad_dir(adouble), DIRBITS | mode, dropbox) < 0 && !vol_noadouble(vol))
+ if (stickydirmode(ad_dir(adouble), DIRBITS | mode, dropbox) < 0)
return -1;
}
return -1;
if (!dir_rx_set(mode)) {
- if (stickydirmode(ad_dir(adouble), DIRBITS | mode, dropbox) < 0 && !vol_noadouble(vol))
+ if (stickydirmode(ad_dir(adouble), DIRBITS | mode, dropbox) < 0)
return -1 ;
}
return 0;
struct adouble ad;
if (stat(adsrc, &st)) /* source has no ressource fork, */
- return AFP_OK;
+ return 0;
/* We are here because :
* -there's no dest folder.
return 0;
}
+#ifdef HAVE_NFSv4_ACLS
+static int RF_acl(const struct vol *vol, const char *path, int cmd, int count, ace_t *aces)
+{
+ static char buf[ MAXPATHLEN + 1];
+ struct stat st;
+
+ if ((stat(path, &st)) != 0)
+ return -1;
+ if (S_ISDIR(st.st_mode)) {
+ if ((snprintf(buf, MAXPATHLEN, "%s/.AppleDouble",path)) < 0)
+ 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->vfs->ad_path(path, ADFLAGS_DIR), cmd, count, aces)) != 0)
+ return -1;
+ } else
+ /* set ACL on ressource fork */
+ if ((acl(vol->vfs->ad_path(path, ADFLAGS_HF), cmd, count, aces)) != 0)
+ return -1;
+
+ return 0;
+}
+
+static int RF_remove_acl(const struct vol *vol, const char *path, int dir)
+{
+ int ret;
+ static char buf[ MAXPATHLEN + 1];
+
+ if (dir) {
+ if ((snprintf(buf, MAXPATHLEN, "%s/.AppleDouble",path)) < 0)
+ return AFPERR_MISC;
+ /* remove ACL from .AppleDouble/.Parent first */
+ if ((ret = remove_acl(vol->vfs->ad_path(path, ADFLAGS_DIR))) != AFP_OK)
+ return ret;
+ /* now remove from .AppleDouble dir */
+ if ((ret = remove_acl(buf)) != AFP_OK)
+ return ret;
+ } else
+ /* remove ACL from ressource fork */
+ if ((ret = remove_acl(vol->vfs->ad_path(path, ADFLAGS_HF))) != AFP_OK)
+ return ret;
+
+ return AFP_OK;
+}
+#endif
+
struct vfs_ops netatalk_adouble = {
/* ad_path: */ ad_path,
/* validupath: */ validupath_adouble,
/* rf_setdirowner: */ RF_setdirowner_adouble,
/* rf_deletefile: */ RF_deletefile_adouble,
/* rf_renamefile: */ RF_renamefile_adouble,
+#ifdef HAVE_NFSv4_ACLS
+ /* rf_acl: */ RF_acl,
+ /* rf_remove_acl */ RF_remove_acl
+#endif
};
/* =======================================
int RF_renamefile_osx(const struct vol *vol, const char *src, const char *dst)
{
char adsrc[ MAXPATHLEN + 1];
+ int err = 0;
strcpy( adsrc, vol->vfs->ad_path( src, 0 ));
- return unix_rename( adsrc, vol->vfs->ad_path( dst, 0 ));
+
+ if (unix_rename( adsrc, vol->vfs->ad_path( dst, 0 )) < 0) {
+ struct stat st;
+
+ err = errno;
+ if (errno == ENOENT && stat(adsrc, &st)) /* source has no ressource fork, */
+ return 0;
+ errno = err;
+ return -1;
+ }
+ return 0;
}
struct vfs_ops netatalk_adouble_osx = {
/* rf_renamefile: */ RF_renamefile_ads,
};
+/* =======================================
+ samba sfm format
+ ad_path shouldn't be set here
+ */
+struct vfs_ops netatalk_adouble_sfm = {
+ /* ad_path: */ ad_path_sfm,
+ /* validupath: */ validupath_adouble,
+ /* rf_chown: */ RF_chown_ads,
+ /* rf_renamedir: */ RF_renamedir_adouble,
+ /* rf_deletecurdir: */ RF_deletecurdir_ads,
+ /* rf_setfilmode: */ RF_setfilmode_ads,
+ /* rf_setdirmode: */ RF_setdirmode_ads,
+ /* rf_setdirunixmode:*/ RF_setdirunixmode_ads,
+ /* rf_setdirowner: */ RF_setdirowner_ads,
+ /* rf_deletefile: */ RF_deletefile_ads,
+ /* rf_renamefile: */ RF_renamefile_ads,
+};
+
/* ---------------- */
void initvol_vfs(struct vol *vol)
{
else if (vol->v_adouble == AD_VERSION1_ADS) {
vol->vfs = &netatalk_adouble_ads;
}
+ else if (vol->v_adouble == AD_VERSION1_SFM) {
+ vol->vfs = &netatalk_adouble_sfm;
+ }
else {
vol->vfs = &netatalk_adouble;
}