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] != '.')
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");
}
/* ----------------- */
/* 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)))
int dropbox = vol->v_flags;
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 -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;
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, &hf_mode, 0, vol->v_umask))
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;
}
* 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(&ad, dst, ADFLAGS_HF, O_RDWR | O_CREAT, 0666) == 0) {
+ 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);
************************************************************************/
static int validupath_ea(VFS_FUNC_ARGS_VALIDUPATH)
{
- return 1;
-}
+ if (name[0] != '.')
+ return 1;
+
+ if (!(vol->v_flags & AFPVOL_USEDOTS))
+ return 0;
+
+#ifndef HAVE_EAFD
+ if (name[1] == '_')
+ return ad_valid_header_osx(name);
+#endif
+ return netatalk_name(name);
+}
/* ----------------- */
static int RF_chown_ea(VFS_FUNC_ARGS_CHOWN)
{
+#ifndef HAVE_EAFD
+ return chown(vol->ad_path(path, ADFLAGS_HF ), uid, gid);
+#endif
return 0;
}
return 0;
}
+/* Returns 1 if the entry is NOT an ._ file */
+static int deletecurdir_ea_osx_chkifempty_loop(struct dirent *de, char *name, void *data _U_, int flag _U_, mode_t v_umask _U_)
+{
+ if (de->d_name[0] != '.' || de->d_name[0] == '_')
+ return 1;
+
+ return 0;
+}
+
+static int deletecurdir_ea_osx_loop(struct dirent *de, char *name, void *data _U_, int flag _U_, mode_t v_umask _U_)
+{
+ int ret;
+
+ if ((ret = netatalk_unlink(name)) != 0)
+ return ret;
+
+ return 0;
+}
+
/* ---------------- */
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,
+ NULL, 0, 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,
+ NULL, 0, 0)) != 0)
+ return err;
+
+#endif
return 0;
}
/* ---------------- */
static int RF_setdirunixmode_ea(VFS_FUNC_ARGS_SETDIRUNIXMODE)
{
+#ifndef HAVE_EAFD
+#endif
return 0;
}
static int RF_setfilmode_ea(VFS_FUNC_ARGS_SETFILEMODE)
{
+#ifndef HAVE_EAFD
+ return adouble_setfilmode(vol->ad_path(name, ADFLAGS_HF ), mode, st, vol->v_umask);
+#endif
return 0;
}
/* ---------------- */
static int RF_setdirmode_ea(VFS_FUNC_ARGS_SETDIRMODE)
{
+#ifndef HAVE_EAFD
+#endif
return 0;
}
/* ---------------- */
static int RF_setdirowner_ea(VFS_FUNC_ARGS_SETDIROWNER)
{
+#ifndef HAVE_EAFD
+#endif
return 0;
}
static int RF_deletefile_ea(VFS_FUNC_ARGS_DELETEFILE)
{
+#ifndef HAVE_EAFD
+ return netatalk_unlinkat(dirfd, vol->ad_path(file, ADFLAGS_HF));
+#endif
return 0;
}
static int RF_copyfile_ea(VFS_FUNC_ARGS_COPYFILE)
{
+#ifdef HAVE_EAFD
+ /* the EA VFS module does this all for us */
return 0;
-}
-
-/* ---------------- */
-static int RF_renamefile_ea(VFS_FUNC_ARGS_RENAMEFILE)
-{
- return 0;
-}
-
-#if 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)
-{
- /* 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));
-}
-
-/* ---------------- */
-static int RF_deletecurdir_osx(VFS_FUNC_ARGS_DELETECURDIR)
-{
- return netatalk_unlink( vol->ad_path(".",0) );
-}
+#endif
-/* ---------------- */
-static int RF_setdirunixmode_osx(VFS_FUNC_ARGS_SETDIRUNIXMODE)
-{
- return adouble_setfilmode(vol->ad_path(name, ADFLAGS_DIR ), mode, st, vol->v_umask);
-}
+ 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;
-/* ---------------- */
-static int RF_setdirmode_osx(VFS_FUNC_ARGS_SETDIRMODE)
-{
- return 0;
-}
+ /* 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;
+
+ }
+ }
-/* ---------------- */
-static int RF_setdirowner_osx(VFS_FUNC_ARGS_SETDIROWNER)
-{
- return 0;
+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;
return -1;
}
return 0;
-}
#endif
+ return 0;
+}
/********************************************************************************************
* VFS chaining
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 */