X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=netatalk.git;a=blobdiff_plain;f=libatalk%2Fvfs%2Fvfs.c;h=0d1961cfa92c393065c8ab0128e72031fd57e0d0;hp=3156afe33191433b0ac43cf7db77d1cb4d05e43e;hb=c72d10d6f92fe81d040ab983768d7fdccea7fb2e;hpb=64c01c136e708085840814c92ff7cf829a794317 diff --git a/libatalk/vfs/vfs.c b/libatalk/vfs/vfs.c index 3156afe3..0d1961cf 100644 --- a/libatalk/vfs/vfs.c +++ b/libatalk/vfs/vfs.c @@ -42,17 +42,18 @@ #include #include #include +#include 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; @@ -78,7 +79,7 @@ for_each_adouble(const char *from, const char *name, rf_loop fn, void *data, int } 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; } @@ -88,33 +89,28 @@ for_each_adouble(const char *from, const char *name, rf_loop fn, void *data, int 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 ); @@ -131,7 +127,7 @@ static int RF_renamedir_adouble(VFS_FUNC_ARGS_RENAMEDIR) } /* ----------------- */ -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; @@ -139,7 +135,7 @@ static int deletecurdir_adouble_loop(struct dirent *de, char *name, void *data _ /* 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))) @@ -154,56 +150,63 @@ static int RF_deletecurdir_adouble(VFS_FUNC_ARGS_DELETECURDIR) /* 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 (ochmod(ad_dir(adouble), + (DIRBITS | mode) & ~vol->v_umask, + st, + vol_syml_opt(vol) | vol_chmod_opt(vol) + ) < 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 (ochmod(ad_dir(adouble), + (DIRBITS | mode) & ~vol->v_umask, + st, + vol_syml_opt(vol) | vol_chmod_opt(vol) + ) < 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? */ } } @@ -212,67 +215,38 @@ static int setdirmode_adouble_loop(struct dirent *de _U_, char *name, void *data 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 (ochmod(ad_dir(adouble), + (DIRBITS | mode) & ~vol->v_umask, + st, + vol_syml_opt(vol) | vol_chmod_opt(vol) + ) < 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 (ochmod(ad_dir(adouble), + (DIRBITS | mode) & ~vol->v_umask, + st, + vol_syml_opt(vol) | vol_chmod_opt(vol) + ) < 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; } @@ -297,7 +271,7 @@ static int RF_renamefile_adouble(VFS_FUNC_ARGS_RENAMEFILE) 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 : @@ -307,8 +281,8 @@ static int RF_renamefile_adouble(VFS_FUNC_ARGS_RENAMEFILE) * 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; @@ -374,7 +348,10 @@ static int RF_copyfile_adouble(VFS_FUNC_ARGS_COPYFILE) 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); @@ -387,31 +364,24 @@ 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]; 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) @@ -420,20 +390,15 @@ 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; } @@ -443,462 +408,212 @@ static int RF_solaris_remove_acl(VFS_FUNC_ARGS_REMOVE_ACL) 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; @@ -908,12 +623,14 @@ static int RF_renamefile_osx(VFS_FUNC_ARGS_RENAMEFILE) 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; } /******************************************************************************************** @@ -1003,10 +720,10 @@ static struct vfs_ops vfs_master_funcs = { }; /* - * 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, @@ -1021,34 +738,18 @@ static struct vfs_ops netatalk_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 }; @@ -1106,7 +807,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, @@ -1150,17 +851,16 @@ void initvol_vfs(struct vol *vol) 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 */ @@ -1175,7 +875,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