]> arthur.barton.de Git - netatalk.git/blobdiff - etc/afpd/vfs_adouble.c
osx adouble, don't return an error if there's no source resource file when renaming...
[netatalk.git] / etc / afpd / vfs_adouble.c
index a80ae02d70324afca4d489c6c18f0f2975c716a0..c40b1c9fd515883b0096cf19217c4a7b9fd60317 100644 (file)
 #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;
@@ -174,8 +178,8 @@ static int ads_setfilmode_loop(struct dirent *de _U_, char *name, void *data, in
 
 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 )))
@@ -214,18 +218,18 @@ static int RF_setdirunixmode_ads(const struct vol *vol, const char * name, mode_
 {
     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;
     }
 
@@ -233,9 +237,9 @@ static int RF_setdirunixmode_ads(const struct vol *vol, const char * name, mode_
         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;
@@ -282,13 +286,13 @@ static int RF_setdirmode_ads(const struct vol *vol, const char * name, mode_t mo
     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;
     }
 
@@ -296,7 +300,7 @@ static int RF_setdirmode_ads(const struct vol *vol, const char * name, mode_t mo
         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;
@@ -385,7 +389,7 @@ int RF_renamefile_ads(const struct vol *vol, const char *src, const char *dst)
                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. 
@@ -423,7 +427,11 @@ int RF_renamefile_ads(const struct vol *vol, const char *src, const char *dst)
 
 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] != '.';
 }
 
@@ -492,10 +500,10 @@ static int RF_setfilmode_adouble(const struct vol *vol, const char * name, mode_
 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;
     }
 
@@ -503,7 +511,7 @@ static int RF_setdirunixmode_adouble(const struct vol *vol, const char * name, m
         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;
@@ -530,13 +538,13 @@ static int setdirmode_adouble_loop(struct dirent *de _U_, char *name, void *data
 
 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;
     }
 
@@ -544,7 +552,7 @@ static int RF_setdirmode_adouble(const struct vol *vol, const char * name, mode_
         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;
@@ -617,7 +625,7 @@ int RF_renamefile_adouble(const struct vol *vol, const char *src, const char *ds
                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. 
@@ -646,6 +654,54 @@ int RF_renamefile_adouble(const struct vol *vol, const char *src, const char *ds
        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,
@@ -658,6 +714,10 @@ struct vfs_ops netatalk_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
 };
 
 /* =======================================
@@ -706,9 +766,20 @@ RF_setdirowner_osx(const struct vol *vol _U_, const char *path _U_, uid_t uid _U
 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 = {
@@ -742,6 +813,24 @@ struct vfs_ops netatalk_adouble_ads = {
     /* 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)
 {
@@ -751,6 +840,9 @@ 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;
     }