/*
- * $Id: file.c,v 1.114 2009-10-15 10:43:13 didg Exp $
+ * $Id: file.c,v 1.115 2009-10-15 12:06:07 franklahm Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
#include <atalk/afp.h>
#include <atalk/util.h>
#include <atalk/cnid.h>
+#include <atalk/unix.h>
+
#include "directory.h"
#include "desktop.h"
#include "volume.h"
}
return AFPERR_EXIST;
}
- /* XXX if the source and the dest don't use the same resource type it's broken
- */
+
+ /*
+ * XXX if the source and the dest don't use the same resource type it's broken
+ */
if (ad_reso_fileno(adp) == -1 || 0 == (err = copy_fork(ADEID_RFORK, &add, adp))){
/* copy the data fork */
- err = copy_fork(ADEID_DFORK, &add, adp);
+ if ((err = copy_fork(ADEID_DFORK, &add, adp)) == 0) {
+ err = d_vol->vfs->vfs_copyfile(d_vol, src, dst);
+ }
}
if (err < 0) {
/*
- * $Id: unix.c,v 1.55 2009-10-14 15:04:01 franklahm Exp $
+ * $Id: unix.c,v 1.56 2009-10-15 12:06:07 franklahm Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
#include <atalk/vfs.h>
#include <atalk/afp.h>
#include <atalk/util.h>
+#include <atalk/unix.h>
#include "auth.h"
#include "directory.h"
cnid.h compat.h ddp.h dsi.h ldapconfig.h list.h logger.h \
nbp.h netddp.h pap.h paths.h rtmp.h server_child.h \
server_ipc.h tdb.h uam.h unicode.h util.h uuid.h volinfo.h \
- zip.h ea.h acl.h
+ zip.h ea.h acl.h unix.h
noinst_HEADERS = cnid_dbd_private.h
/*
- * $Id: adouble.h,v 1.45 2009-10-14 01:38:28 didg Exp $
+ * $Id: adouble.h,v 1.46 2009-10-15 12:06:07 franklahm Exp $
* Copyright (c) 1990,1991 Regents of The University of Michigan.
* All Rights Reserved.
*
#endif /* HAVE_SENDFILE_WRITE */
#endif /* 0 */
-/* ad_unix.c */
-extern int netatalk_unlink(const char *name);
-extern char *fullpathname(const char *);
-extern int netatalk_rmdir(const char *name);
-extern int setfilmode(const char *, mode_t, struct stat *, mode_t);
-extern int dir_rx_set(mode_t mode);
-extern int stickydirmode(const char *name, const mode_t mode, const int dropbox, const mode_t v_umask);
-extern int unix_rename(const char *oldpath, const char *newpath);
-
#endif /* _ATALK_ADOUBLE_H */
/*
- $Id: ea.h,v 1.2 2009-10-14 15:04:01 franklahm Exp $
+ $Id: ea.h,v 1.3 2009-10-15 12:06:07 franklahm Exp $
Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
This program is free software; you can redistribute it and/or modify
/* ... EA VFS funcs that deal with file/dir cp/mv/rm */
extern int ea_deletefile(VFS_FUNC_ARGS_DELETEFILE);
extern int ea_renamefile(VFS_FUNC_ARGS_RENAMEFILE);
+extern int ea_copyfile(VFS_FUNC_ARGS_COPYFILE);
/* Solaris native EAs */
#ifdef HAVE_SOLARIS_EAS
--- /dev/null
+/*
+ $Id: unix.h,v 1.1 2009-10-15 12:06:07 franklahm Exp $
+ Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+*/
+
+#ifndef ATALK_UNIX_H
+#define ATALK_UNIX_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+
+/* vfs/unix.c */
+extern int netatalk_unlink(const char *name);
+extern char *fullpathname(const char *);
+extern int netatalk_rmdir(const char *name);
+extern int setfilmode(const char *, mode_t, struct stat *, mode_t);
+extern int dir_rx_set(mode_t mode);
+extern int stickydirmode(const char *name, const mode_t mode, const int dropbox, const mode_t v_umask);
+extern int unix_rename(const char *oldpath, const char *newpath);
+extern int copy_file(const char *src, const char *dst, mode_t mode);
+
+#endif /* ATALK_UNIX_H */
#define VFS_FUNC_ARGS_RENAMEFILE const struct vol *vol, const char *src, const char *dst
#define VFS_FUNC_VARS_RENAMEFILE vol, src, dst
+#define VFS_FUNC_ARGS_COPYFILE const struct vol *vol, const char *src, const char *dst
+#define VFS_FUNC_VARS_COPYFILE vol, src, dst
+
#define VFS_FUNC_ARGS_ACL const struct vol *vol, const char *path, int cmd, int count, void *aces
#define VFS_FUNC_VARS_ACL vol, path, cmd, count, aces
int (*vfs_setdirowner) (VFS_FUNC_ARGS_SETDIROWNER);
int (*vfs_deletefile) (VFS_FUNC_ARGS_DELETEFILE);
int (*vfs_renamefile) (VFS_FUNC_ARGS_RENAMEFILE);
+ int (*vfs_copyfile) (VFS_FUNC_ARGS_COPYFILE);
/* ACLs */
int (*vfs_acl) (VFS_FUNC_ARGS_ACL);
/*
- $Id: ea.c,v 1.3 2009-10-14 15:04:01 franklahm Exp $
+ $Id: ea.c,v 1.4 2009-10-15 12:06:07 franklahm Exp $
Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
This program is free software; you can redistribute it and/or modify
#include <atalk/volume.h>
#include <atalk/vfs.h>
#include <atalk/util.h>
+#include <atalk/unix.h>
/*
* Store Extended Attributes inside .AppleDouble folders as follows:
ea_close(&dstea);
return ret;
}
+
+int ea_copyfile(VFS_FUNC_ARGS_COPYFILE)
+{
+ int count = 0;
+ int ret = AFP_OK;
+ size_t easize;
+ char srceapath[ MAXPATHLEN + 1];
+ char *eapath;
+ char *eaname;
+ struct ea srcea;
+ struct ea dstea;
+ struct adouble ad;
+
+ LOG(log_debug, logtype_afpd, "ea_copyfile('%s'/'%s')", src, dst);
+
+ /* Open EA stuff */
+ if ((ea_open(vol, src, EA_RDWR, &srcea)) != 0) {
+ if (errno == ENOENT)
+ /* no EA files, nothing to do */
+ return AFP_OK;
+ else {
+ LOG(log_error, logtype_afpd, "ea_copyfile('%s'/'%s'): ea_open error: '%s'", src, dst, src);
+ return AFPERR_MISC;
+ }
+ }
+
+ if ((ea_open(vol, dst, EA_RDWR | EA_CREATE, &dstea)) != 0) {
+ if (errno == ENOENT) {
+ /* Possibly the .AppleDouble folder didn't exist, we create it and try again */
+ ad_init(&ad, vol->v_adouble, vol->v_ad_options);
+ if ((ad_open(dst, ADFLAGS_HF, O_RDWR | O_CREAT, 0666, &ad)) != 0) {
+ LOG(log_error, logtype_afpd, "ea_copyfile('%s/%s'): ad_open error: '%s'", src, dst, dst);
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+ ad_close(&ad, ADFLAGS_HF);
+ if ((ea_open(vol, dst, EA_RDWR | EA_CREATE, &dstea)) != 0) {
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+ }
+ }
+
+ /* Loop through all EAs: */
+ while (count < srcea.ea_count) {
+ /* Copy EA */
+ eaname = (*srcea.ea_entries)[count].ea_name;
+ easize = (*srcea.ea_entries)[count].ea_size;
+
+ /* Build src and dst paths for copy_file() */
+ eapath = ea_path(&srcea, eaname);
+ strcpy(srceapath, eapath);
+ eapath = ea_path(&dstea, eaname);
+
+ LOG(log_maxdebug, logtype_afpd, "ea_copyfile('%s/%s'): copying EA '%s' to '%s'",
+ src, dst, srceapath, eapath);
+
+ /* Add EA to dstea */
+ if ((ea_addentry(&dstea, eaname, easize, 0)) == -1) {
+ LOG(log_error, logtype_afpd, "ea_copyfile('%s/%s'): ea_addentry('%s') error",
+ src, dst, eaname);
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+
+ /* Now copy the EA */
+ if ((copy_file( srceapath, eapath, (0666 & ~vol->v_umask))) < 0) {
+ LOG(log_error, logtype_afpd, "ea_copyfile('%s/%s'): copying EA '%s' to '%s'",
+ src, dst, srceapath, eapath);
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+
+ count++;
+ }
+
+exit:
+ ea_close(&srcea);
+ ea_close(&dstea);
+ return ret;
+}
/*
- * $Id: unix.c,v 1.1 2009-10-02 09:32:41 franklahm Exp $
+ * $Id: unix.c,v 1.2 2009-10-15 12:06:08 franklahm Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
#include <atalk/directory.h>
#include <atalk/volume.h>
#include <atalk/logger.h>
+#include <atalk/unix.h>
/* -----------------------------
a dropbox is a folder where w is set but not r eg:
}
return wd;
}
+
+int copy_file(const char *src, const char *dst, mode_t mode)
+{
+ int ret = 0;
+ int sfd = -1;
+ int dfd = -1;
+ size_t cc;
+ char filebuf[8192];
+
+ if ((sfd = open(src, O_RDONLY)) < 0) {
+ LOG(log_error, logtype_afpd, "copy_file('%s'/'%s'): open '%s' error: %s",
+ src, dst, src, strerror(errno));
+ return -1;
+ }
+
+ if ((dfd = open(dst, O_WRONLY | O_CREAT | O_EXCL, mode)) < 0) {
+ LOG(log_error, logtype_afpd, "copy_file('%s'/'%s'): open '%s' error: %s",
+ src, dst, dst, strerror(errno));
+ ret = -1;
+ goto exit;
+ }
+
+ while ((cc = read(sfd, filebuf, sizeof(filebuf)))) {
+ if (cc < 0) {
+ if (errno == EINTR)
+ continue;
+ LOG(log_error, logtype_afpd, "copy_file('%s'/'%s'): read '%s' error: %s",
+ src, dst, src, strerror(errno));
+ ret = -1;
+ goto exit;
+ }
+
+ while (cc > 0) {
+ if ((cc -= write(dfd, filebuf, cc)) < 0) {
+ if (errno == EINTR)
+ continue;
+ LOG(log_error, logtype_afpd, "copy_file('%s'/'%s'): read '%s' error: %s",
+ src, dst, dst, strerror(errno));
+ ret = -1;
+ goto exit;
+ }
+ }
+ }
+
+exit:
+ if (sfd != -1)
+ close(sfd);
+ if (dfd != -1)
+ close(dfd);
+
+ return ret;
+}
#include <atalk/util.h>
#include <atalk/volume.h>
#include <atalk/directory.h>
+#include <atalk/unix.h>
struct perm {
uid_t uid;
VFS_MFUNC(setdirowner, VFS_FUNC_ARGS_SETDIROWNER, VFS_FUNC_VARS_SETDIROWNER)
VFS_MFUNC(deletefile, VFS_FUNC_ARGS_DELETEFILE, VFS_FUNC_VARS_DELETEFILE)
VFS_MFUNC(renamefile, VFS_FUNC_ARGS_RENAMEFILE, VFS_FUNC_VARS_RENAMEFILE)
+VFS_MFUNC(copyfile, VFS_FUNC_ARGS_COPYFILE, VFS_FUNC_VARS_COPYFILE)
VFS_MFUNC(acl, VFS_FUNC_ARGS_ACL, VFS_FUNC_VARS_ACL)
VFS_MFUNC(remove_acl, VFS_FUNC_ARGS_REMOVE_ACL, VFS_FUNC_VARS_REMOVE_ACL)
VFS_MFUNC(ea_getsize, VFS_FUNC_ARGS_EA_GETSIZE, VFS_FUNC_VARS_EA_GETSIZE)
vfs_setdirowner,
vfs_deletefile,
vfs_renamefile,
+ vfs_copyfile,
vfs_acl,
vfs_remove_acl,
vfs_ea_getsize,
*/
static struct vfs_ops netatalk_adouble = {
- /* ad_path: */ ad_path,
- /* validupath: */ validupath_adouble,
- /* rf_chown: */ RF_chown_adouble,
- /* rf_renamedir: */ RF_renamedir_adouble,
- /* rf_deletecurdir: */ RF_deletecurdir_adouble,
- /* rf_setfilmode: */ RF_setfilmode_adouble,
- /* rf_setdirmode: */ RF_setdirmode_adouble,
- /* rf_setdirunixmode: */ RF_setdirunixmode_adouble,
- /* rf_setdirowner: */ RF_setdirowner_adouble,
- /* rf_deletefile: */ RF_deletefile_adouble,
- /* rf_renamefile: */ RF_renamefile_adouble,
+ /* vfs_path: */ ad_path,
+ /* vfs_validupath: */ validupath_adouble,
+ /* vfs_chown: */ RF_chown_adouble,
+ /* vfs_renamedir: */ RF_renamedir_adouble,
+ /* vfs_deletecurdir: */ RF_deletecurdir_adouble,
+ /* vfs_setfilmode: */ RF_setfilmode_adouble,
+ /* vfs_setdirmode: */ RF_setdirmode_adouble,
+ /* vfs_setdirunixmode:*/ RF_setdirunixmode_adouble,
+ /* vfs_setdirowner: */ RF_setdirowner_adouble,
+ /* vfs_deletefile: */ RF_deletefile_adouble,
+ /* vfs_renamefile: */ RF_renamefile_adouble
+ /* NULL, ... */
};
static struct vfs_ops netatalk_adouble_osx = {
- /* ad_path: */ ad_path_osx,
- /* validupath: */ validupath_osx,
- /* rf_chown: */ RF_chown_adouble,
- /* rf_renamedir: */ RF_renamedir_osx,
- /* rf_deletecurdir: */ RF_deletecurdir_osx,
- /* rf_setfilmode: */ RF_setfilmode_adouble,
- /* rf_setdirmode: */ RF_setdirmode_osx,
- /* rf_setdirunixmode:*/ RF_setdirunixmode_osx,
- /* rf_setdirowner: */ RF_setdirowner_osx,
- /* rf_deletefile: */ RF_deletefile_adouble,
- /* rf_renamefile: */ RF_renamefile_osx,
+ /* vfs_path: */ ad_path_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
};
/* samba sfm format. ad_path shouldn't be set her */
static 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,
+ /* vfs_path: */ ad_path_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,
};
/*
/* rf_setdirowner: */ NULL,
/* rf_deletefile: */ ea_deletefile,
/* rf_renamefile: */ ea_renamefile,
+ /* vfs_copyfile */ ea_copyfile,
/* rf_acl: */ NULL,
/* rf_remove_acl */ NULL,
/* ea_getsize */ get_easize,
/* rf_setdirowner: */ NULL,
/* rf_deletefile: */ NULL,
/* rf_renamefile: */ NULL,
+ /* vfs_copyfile: */ NULL,
/* rf_acl: */ NULL,
/* rf_remove_acl */ NULL,
/* ea_getsize */ sol_get_easize,
/* rf_setdirowner: */ NULL,
/* rf_deletefile: */ NULL,
/* rf_renamefile: */ NULL,
+ /* vfs_copyfile */ NULL,
/* rf_acl: */ RF_solaris_acl,
/* rf_remove_acl */ RF_remove_acl
};