/*
- * $Id: file.c,v 1.98 2005-05-25 18:32:04 didg Exp $
+ * $Id: file.c,v 1.141 2010/03/12 15:16:49 franklahm Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
#endif /* ! HAVE_MEMCPY */
#endif /* STDC_HEADERS */
-#include <atalk/adouble.h>
#include <utime.h>
-#include <dirent.h>
#include <errno.h>
-
-#include <atalk/logger.h>
#include <sys/param.h>
-
+#include <atalk/adouble.h>
+#include <atalk/vfs.h>
+#include <atalk/logger.h>
#include <atalk/afp.h>
#include <atalk/util.h>
#include <atalk/cnid.h>
+#include <atalk/unix.h>
+
#include "directory.h"
+#include "dircache.h"
#include "desktop.h"
#include "volume.h"
#include "fork.h"
}
/* FIXME path : unix or mac name ? (for now it's unix name ) */
-void *get_finderinfo(const char *upath, struct adouble *adp, void *data)
+void *get_finderinfo(const struct vol *vol, const char *upath, struct adouble *adp, void *data, int islink)
{
struct extmap *em;
void *ad_finder = NULL;
else {
memcpy(data, ufinderi, ADEDLEN_FINDERI);
chk_ext = 1;
- if (*upath == '.') { /* make it invisible */
+ if (vol_inv_dots(vol) && *upath == '.') { /* make it invisible */
u_int16_t ashort;
ashort = htons(FINDERINFO_INVISIBLE);
- memcpy(data + FINDERINFO_FRFLAGOFF, &ashort, sizeof(ashort));
+ memcpy((char *)data + FINDERINFO_FRFLAGOFF, &ashort, sizeof(ashort));
}
}
+
+ if (islink){
+ u_int16_t linkflag;
+ memcpy(&linkflag, (char *)data + FINDERINFO_FRFLAGOFF, 2);
+ linkflag |= htons(FINDERINFO_ISALIAS);
+ memcpy((char *)data + FINDERINFO_FRFLAGOFF, &linkflag, 2);
+ memcpy((char *)data + FINDERINFO_FRTYPEOFF,"slnk",4);
+ memcpy((char *)data + FINDERINFO_FRCREATOFF,"rhap",4);
+ chk_ext = 0;
+ }
+
/** Only enter if no appledouble information and no finder information found. */
if (chk_ext && (em = getextmap( upath ))) {
memcpy(data, em->em_type, sizeof( em->em_type ));
if (aint > 255) /* FIXME safeguard, anyway if no ascii char it's game over*/
aint = 255;
- utf8 = vol->v_mac?htonl(vol->v_mac->kTextEncoding):0; /* htonl(utf8) */
+ utf8 = vol->v_kTextEncoding;
memcpy(data, &utf8, sizeof(utf8));
data += sizeof(utf8);
(1 << FILPBIT_RFLEN) |\
(1 << FILPBIT_EXTRFLEN) |\
(1 << FILPBIT_PDINFO) |\
+ (1 << FILPBIT_FNUM) |\
(1 << FILPBIT_UNIXPR)))
-/* -------------------------- */
-u_int32_t get_id(struct vol *vol, struct adouble *adp, const struct stat *st,
- const cnid_t did, char *upath, const int len)
+/*!
+ * @brief Get CNID for did/upath args both from database and adouble file
+ *
+ * 1. Get the objects CNID as stored in its adouble file
+ * 2. Get the objects CNID from the database
+ * 3. If there's a problem with a "dbd" database, fallback to "tdb" in memory
+ * 4. In case 2 and 3 differ, store 3 in the adouble file
+ *
+ * @param vol (rw) volume
+ * @param adp (rw) adouble struct of object upath, might be NULL
+ * @param st (r) stat of upath, must NOT be NULL
+ * @param did (r) parent CNID of upath
+ * @param upath (r) name of object
+ * @param len (r) strlen of upath
+ */
+uint32_t get_id(struct vol *vol,
+ struct adouble *adp,
+ const struct stat *st,
+ const cnid_t did,
+ const char *upath,
+ const int len)
{
-u_int32_t aint = 0;
-
-#if AD_VERSION > AD_VERSION1
-
- if ((aint = ad_getid(adp, st->st_dev, st->st_ino, did, vol->v_stamp))) {
- return aint;
- }
-#endif
+ static int first = 1; /* mark if this func is called the first time */
+ u_int32_t adcnid;
+ u_int32_t dbcnid = CNID_INVALID;
+restart:
if (vol->v_cdb != NULL) {
- aint = cnid_add(vol->v_cdb, st, did, upath, len, aint);
+ /* prime aint with what we think is the cnid, set did to zero for
+ catching moved files */
+ adcnid = ad_getid(adp, st->st_dev, st->st_ino, 0, vol->v_stamp); /* (1) */
+
+ dbcnid = cnid_add(vol->v_cdb, st, did, upath, len, adcnid); /* (2) */
/* Throw errors if cnid_add fails. */
- if (aint == CNID_INVALID) {
+ if (dbcnid == CNID_INVALID) {
switch (errno) {
case CNID_ERR_CLOSE: /* the db is closed */
break;
case CNID_ERR_PARAM:
LOG(log_error, logtype_afpd, "get_id: Incorrect parameters passed to cnid_add");
afp_errno = AFPERR_PARAM;
- return CNID_INVALID;
+ goto exit;
case CNID_ERR_PATH:
afp_errno = AFPERR_PARAM;
- return CNID_INVALID;
+ goto exit;
default:
+ /* Close CNID backend if "dbd" and switch to temp in-memory "tdb" */
+ /* we have to do it here for "dbd" because it uses "lazy opening" */
+ /* In order to not end in a loop somehow with goto restart below */
+ /* */
+ if (first && (strcmp(vol->v_cnidscheme, "dbd") == 0)) { /* (3) */
+ cnid_close(vol->v_cdb);
+ free(vol->v_cnidscheme);
+ vol->v_cnidscheme = strdup("tdb");
+
+ int flags = CNID_FLAG_MEMORY;
+ if ((vol->v_flags & AFPVOL_NODEV)) {
+ flags |= CNID_FLAG_NODEV;
+ }
+ LOG(log_error, logtype_afpd, "Reopen volume %s using in memory temporary CNID DB.",
+ vol->v_path);
+ vol->v_cdb = cnid_open(vol->v_path, vol->v_umask, "tdb", flags, NULL, NULL);
+ if (vol->v_cdb) {
+ /* deactivate cnid caching/storing in AppleDouble files and set ro mode*/
+ vol->v_flags &= ~AFPVOL_CACHE;
+ vol->v_flags |= AFPVOL_RO;
+#ifdef SERVERTEXT
+ /* kill ourself with SIGUSR2 aka msg pending */
+ setmessage("Something wrong with the volume's CNID DB, using temporary CNID DB instead."
+ "Check server messages for details. Switching to read-only mode.");
+ kill(getpid(), SIGUSR2);
+#endif
+ goto restart; /* not try again with the temp CNID db */
+ } else {
+#ifdef SERVERTEXT
+ setmessage("Something wrong with the volume's CNID DB, using temporary CNID DB failed too!"
+ "Check server messages for details, can't recover from this state!");
+#endif
+ }
+ }
afp_errno = AFPERR_MISC;
- return CNID_INVALID;
+ goto exit;
}
}
-#if AD_VERSION > AD_VERSION1
- else if (adp ) {
- /* update the ressource fork
- * for a folder adp is always null
- */
- if (ad_setid(adp, st->st_dev, st->st_ino, aint, did, vol->v_stamp)) {
- ad_flush(adp, ADFLAGS_HF);
+ else if (adp && (adcnid != dbcnid)) { /* 4 */
+ /* Update the ressource fork. For a folder adp is always null */
+ LOG(log_note, logtype_afpd, "get_id: calling ad_setid(old: %u, new: %u)",
+ htonl(adcnid), htonl(dbcnid));
+ if (ad_setid(adp, st->st_dev, st->st_ino, dbcnid, did, vol->v_stamp)) {
+ ad_flush(adp);
}
}
-#endif
}
- return aint;
+
+exit:
+ first = 0;
+ return dbcnid;
}
/* -------------------------- */
int getmetadata(struct vol *vol,
u_int16_t bitmap,
struct path *path, struct dir *dir,
- char *buf, int *buflen, struct adouble *adp, int attrbits )
+ char *buf, size_t *buflen, struct adouble *adp)
{
char *data, *l_nameoff = NULL, *upath;
char *utf_nameoff = NULL;
struct stat *st;
struct maccess ma;
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "begin getmetadata:");
-#endif /* DEBUG */
-
upath = path->u_name;
st = &path->st;
-
data = buf;
if ( ((bitmap & ( (1 << FILPBIT_FINFO)|(1 << FILPBIT_LNAME)|(1 <<FILPBIT_PDINFO) ) ) && !path->m_name)
|| (bitmap & ( (1 << FILPBIT_LNAME) ) && utf8_encoding()) /* FIXME should be m_name utf8 filename */
|| (bitmap & (1 << FILPBIT_FNUM))) {
- if (!path->id)
- id = get_id(vol, adp, st, dir->d_did, upath, strlen(upath));
- else
+ if (!path->id) {
+ struct dir *cachedfile;
+ int len = strlen(upath);
+ if ((cachedfile = dircache_search_by_name(vol, dir, upath, len)) != NULL)
+ id = cachedfile->d_did;
+ else {
+ id = get_id(vol, adp, st, dir->d_did, upath, len);
+
+ /* Add it to the cache */
+ LOG(log_debug, logtype_afpd, "getmetadata: caching: did:%u, \"%s\", cnid:%u",
+ ntohl(dir->d_did), upath, ntohl(id));
+
+ /* Get macname from unixname first */
+ if (path->m_name == NULL) {
+ if ((path->m_name = utompath(vol, upath, id, utf8_encoding())) == NULL) {
+ LOG(log_error, logtype_afpd, "getmetadata: utompath error");
+ exit(EXITERR_SYS);
+ }
+ }
+
+ if ((cachedfile = dir_new(path->m_name, upath, vol, dir->d_did, id, NULL)) == NULL) {
+ LOG(log_error, logtype_afpd, "getmetadata: error from dir_new");
+ exit(EXITERR_SYS);
+ }
+ if ((dircache_add(cachedfile)) != 0) {
+ LOG(log_error, logtype_afpd, "getmetadata: fatal dircache error");
+ exit(EXITERR_SYS);
+ }
+ }
+ } else {
id = path->id;
- if (id == 0)
+ }
+
+ if (id == CNID_INVALID)
return afp_errno;
+
if (!path->m_name) {
path->m_name = utompath(vol, upath, id, utf8_encoding());
}
case FILPBIT_ATTR :
if ( adp ) {
ad_getattr(adp, &ashort);
- } else if (*upath == '.') {
+ } else if (vol_inv_dots(vol) && *upath == '.') {
ashort = htons(ATTRBIT_INVISIBLE);
} else
ashort = 0;
if ((ma.ma_user & AR_UWRITE)) {
accessmode( upath, &ma, dir , st);
if (!(ma.ma_user & AR_UWRITE)) {
- attrbits |= ATTRBIT_NOWRITE;
+ ashort |= htons(ATTRBIT_NOWRITE);
}
}
#endif
- if (attrbits)
- ashort = htons(ntohs(ashort) | attrbits);
memcpy(data, &ashort, sizeof( ashort ));
data += sizeof( ashort );
+ LOG(log_debug, logtype_afpd, "metadata('%s'): AFP Attributes: %04x",
+ path->u_name, ntohs(ashort));
break;
case FILPBIT_PDID :
memcpy(data, &dir->d_did, sizeof( u_int32_t ));
data += sizeof( u_int32_t );
+ LOG(log_debug, logtype_afpd, "metadata('%s'): Parent DID: %u",
+ path->u_name, ntohl(dir->d_did));
break;
case FILPBIT_CDATE :
break;
case FILPBIT_FINFO :
- get_finderinfo(upath, adp, (char *)data);
+ get_finderinfo(vol, upath, adp, (char *)data,S_ISLNK(st->st_mode));
data += ADEDLEN_FINDERI;
break;
case FILPBIT_FNUM :
memcpy(data, &id, sizeof( id ));
data += sizeof( id );
+ LOG(log_debug, logtype_afpd, "metadata('%s'): CNID: %u",
+ path->u_name, ntohl(id));
break;
case FILPBIT_DFLEN :
int getfilparams(struct vol *vol,
u_int16_t bitmap,
struct path *path, struct dir *dir,
- char *buf, int *buflen )
+ char *buf, size_t *buflen )
{
struct adouble ad, *adp;
- struct ofork *of;
- char *upath;
- u_int16_t attrbits = 0;
int opened = 0;
int rc;
-#ifdef DEBUG
- LOG(log_info, logtype_default, "begin getfilparams:");
-#endif /* DEBUG */
-
opened = PARAM_NEED_ADP(bitmap);
adp = NULL;
+
if (opened) {
+ char *upath;
+ int flags = (bitmap & (1 << FILPBIT_ATTR))?ADFLAGS_OPENFORKS:0;
+
+ adp = of_ad(vol, path, &ad);
upath = path->u_name;
- if ((of = of_findname(path))) {
- adp = of->of_ad;
- attrbits = ((of->of_ad->ad_df.adf_refcount > 0) ? ATTRBIT_DOPEN : 0);
- attrbits |= ((of->of_ad->ad_hf.adf_refcount > of->of_ad->ad_df.adf_refcount)? ATTRBIT_ROPEN : 0);
- } else {
- ad_init(&ad, vol->v_adouble, vol->v_ad_options);
- adp = &ad;
- }
- if ( ad_metadata( upath, 0, adp) < 0 ) {
+ if ( ad_metadata( upath, flags|ADFLAGS_CREATE, adp) < 0 ) {
switch (errno) {
case EACCES:
LOG(log_error, logtype_afpd, "getfilparams(%s): %s: check resource fork permission?",
break;
}
}
- if (adp) {
- /* FIXME
- we need to check if the file is open by another process.
- it's slow so we only do it if we have to:
- - bitmap is requested.
- - we don't already have the answer!
- */
- if ((bitmap & (1 << FILPBIT_ATTR))) {
- if (!(attrbits & ATTRBIT_ROPEN)) {
- attrbits |= ad_testlock(adp, ADEID_RFORK, AD_FILELOCK_OPEN_RD) > 0? ATTRBIT_ROPEN : 0;
- attrbits |= ad_testlock(adp, ADEID_RFORK, AD_FILELOCK_OPEN_WR) > 0? ATTRBIT_ROPEN : 0;
- }
- if (!(attrbits & ATTRBIT_DOPEN)) {
- attrbits |= ad_testlock(adp, ADEID_DFORK, AD_FILELOCK_OPEN_RD) > 0? ATTRBIT_DOPEN : 0;
- attrbits |= ad_testlock(adp, ADEID_DFORK, AD_FILELOCK_OPEN_WR) > 0? ATTRBIT_DOPEN : 0;
- }
- }
- }
}
- rc = getmetadata(vol, bitmap, path, dir, buf, buflen, adp, attrbits);
+ rc = getmetadata(vol, bitmap, path, dir, buf, buflen, adp);
if ( adp ) {
ad_close_metadata( adp);
}
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "end getfilparams:");
-#endif /* DEBUG */
return( rc );
}
/* ----------------------------- */
-int afp_createfile(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj *obj;
-char *ibuf, *rbuf _U_;
-int ibuflen _U_, *rbuflen;
+int afp_createfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
{
struct adouble ad, *adp;
struct vol *vol;
char *path, *upath;
int creatf, did, openf, retvalue = AFP_OK;
u_int16_t vid;
- int ret;
struct path *s_path;
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "begin afp_createfile:");
-#endif /* DEBUG */
-
*rbuflen = 0;
ibuf++;
creatf = (unsigned char) *ibuf++;
}
upath = s_path->u_name;
- if (0 != (ret = check_name(vol, upath)))
- return ret;
/* if upath is deleted we already in trouble anyway */
if ((of = of_findname(s_path))) {
openf = O_RDWR|O_CREAT|O_EXCL;
}
- if ( ad_open( upath, vol_noadouble(vol)|ADFLAGS_DF|ADFLAGS_HF|ADFLAGS_NOHF,
+ if ( ad_open( upath, ADFLAGS_DF|ADFLAGS_HF|ADFLAGS_NOHF|ADFLAGS_CREATE,
openf, 0666, adp) < 0 ) {
switch ( errno ) {
case EROFS:
return( AFPERR_EXIST );
case EACCES :
return( AFPERR_ACCESS );
+ case EDQUOT:
+ case ENOSPC :
+ return( AFPERR_DFULL );
default :
return( AFPERR_PARAM );
}
}
- if ( ad_hfileno( adp ) == -1 ) {
+ if ( ad_reso_fileno( adp ) == -1 ) { /* Hard META / HF */
/* on noadouble volumes, just creating the data fork is ok */
if (vol_noadouble(vol)) {
ad_close( adp, ADFLAGS_DF );
path = s_path->m_name;
ad_setname(adp, path);
- ad_flush( adp, ADFLAGS_DF|ADFLAGS_HF );
+ ad_flush( adp);
ad_close( adp, ADFLAGS_DF|ADFLAGS_HF );
createfile_done:
setvoltime(obj, vol );
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "end afp_createfile");
-#endif /* DEBUG */
-
return (retvalue);
}
-int afp_setfilparams(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj *obj;
-char *ibuf, *rbuf _U_;
-int ibuflen _U_, *rbuflen;
+int afp_setfilparams(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
{
struct vol *vol;
struct dir *dir;
int did, rc;
u_int16_t vid, bitmap;
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "begin afp_setfilparams:");
-#endif /* DEBUG */
-
*rbuflen = 0;
ibuf += 2;
setvoltime(obj, vol );
}
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "end afp_setfilparams:");
-#endif /* DEBUG */
-
return( rc );
}
int bit, isad = 1, err = AFP_OK;
char *upath;
u_char achar, *fdType, xyy[4]; /* uninitialized, OK 310105 */
- u_int16_t ashort, bshort;
+ u_int16_t ashort, bshort, oshort;
u_int32_t aint;
u_int32_t upriv;
u_int16_t upriv_bit = 0;
u_char finder_buf[32];
#ifdef DEBUG
- LOG(log_info, logtype_afpd, "begin setfilparams:");
+ LOG(log_debug9, logtype_afpd, "begin setfilparams:");
#endif /* DEBUG */
- upath = path->u_name;
adp = of_ad(vol, path, &ad);
-
+ upath = path->u_name;
if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
return AFPERR_ACCESS;
case FILPBIT_FINFO :
change_mdate = 1;
memcpy(finder_buf, buf, 32 );
+ if (memcmp(buf,"slnkrhap",8)==0 && !S_ISLNK(path->st.st_mode)){
+ // SLFINFO
+ int fp;
+ ssize_t len;
+ int erc=1;
+ char buf[PATH_MAX+1];
+ if ((fp=open(path->u_name,O_RDONLY))>=0){
+ if ((len=read(fp,buf,PATH_MAX+1))){
+ if (unlink(path->u_name)==0){
+ buf[len]=0;
+ erc = symlink(buf, path->u_name);
+ if (!erc)
+ of_stat(path);
+ }
+ }
+ close(fp);
+ }
+ if (erc!=0){
+ err=AFPERR_BITMAP;
+ goto setfilparam_done;
+ }
+ }
buf += 32;
break;
case FILPBIT_UNIXPR :
/* second try with adouble open
*/
- if ( ad_open_metadata( upath, vol_noadouble(vol), O_CREAT, adp) < 0) {
- /* for some things, we don't need an adouble header */
- if (f_bitmap & ~(1<<FILPBIT_MDATE)) {
- return vol_noadouble(vol) ? AFP_OK : AFPERR_ACCESS;
+ if ( ad_open_metadata( upath, 0, O_CREAT, adp) < 0) {
+ LOG(log_debug, logtype_afpd, "setfilparams: ad_open_metadata error");
+ /*
+ * For some things, we don't need an adouble header:
+ * - change of modification date
+ * - UNIX privs (Bug-ID #2863424)
+ */
+ if (!vol_noadouble(vol) && (f_bitmap & ~(1<<FILPBIT_MDATE | 1<<FILPBIT_UNIXPR))) {
+ LOG(log_debug, logtype_afpd, "setfilparams: need adouble access");
+ return AFPERR_ACCESS;
}
+ LOG(log_debug, logtype_afpd, "setfilparams: no adouble perms, but only FILPBIT_MDATE and/or FILPBIT_UNIXPR");
isad = 0;
} else if ((ad_get_HF_flags( adp ) & O_CREAT) ) {
ad_setname(adp, path->m_name);
switch( bit ) {
case FILPBIT_ATTR :
ad_getattr(adp, &bshort);
- if ((bshort & htons(ATTRBIT_INVISIBLE)) !=
- (ashort & htons(ATTRBIT_INVISIBLE) & htons(ATTRBIT_SETCLR)) )
- change_parent_mdate = 1;
+ oshort = bshort;
if ( ntohs( ashort ) & ATTRBIT_SETCLR ) {
bshort |= htons( ntohs( ashort ) & ~ATTRBIT_SETCLR );
} else {
bshort &= ~ashort;
}
+ if ((bshort & htons(ATTRBIT_INVISIBLE)) != (oshort & htons(ATTRBIT_INVISIBLE)))
+ change_parent_mdate = 1;
ad_setattr(adp, bshort);
break;
case FILPBIT_CDATE :
}
if (isad) {
- ad_flush_metadata( adp);
+ ad_flush( adp);
ad_close_metadata( adp);
}
}
#ifdef DEBUG
- LOG(log_info, logtype_afpd, "end setfilparams:");
+ LOG(log_debug9, logtype_afpd, "end setfilparams:");
#endif /* DEBUG */
return err;
}
* renamefile and copyfile take the old and new unix pathnames
* and the new mac name.
*
+ * sdir_fd source dir fd to which src path is relative (for openat et al semantics)
+ * passing -1 means this is not used, src path is a full path
* src the source path
* dst the dest filename in current dir
* newname the dest mac name
* adp adouble struct of src file, if open, or & zeroed one
*
*/
-int renamefile(vol, src, dst, newname, adp )
-const struct vol *vol;
-char *src, *dst, *newname;
-struct adouble *adp;
+int renamefile(const struct vol *vol, int sdir_fd, char *src, char *dst, char *newname, struct adouble *adp)
{
int rc;
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "begin renamefile:");
-#endif /* DEBUG */
-
- if ( unix_rename( src, dst ) < 0 ) {
+ if ( unix_rename( sdir_fd, src, -1, dst ) < 0 ) {
switch ( errno ) {
case ENOENT :
return( AFPERR_NOOBJ );
* get two files, it's fixable for our process (eg reopen the new file, get the
* locks, and so on. But it doesn't solve the case with a second process
*/
- if (adp->ad_df.adf_refcount || adp->ad_hf.adf_refcount) {
+ if (adp->ad_open_forks) {
/* FIXME warning in syslog so admin'd know there's a conflict ?*/
return AFPERR_OLOCK; /* little lie */
}
- if (AFP_OK != ( rc = copyfile(vol, vol, src, dst, newname, NULL )) ) {
+ if (AFP_OK != ( rc = copyfile(vol, vol, sdir_fd, src, dst, newname, NULL )) ) {
/* on error copyfile delete dest */
return( rc );
}
- return deletefile(vol, src, 0);
+ return deletefile(vol, sdir_fd, src, 0);
default :
return( AFPERR_PARAM );
}
}
- if (vol->vfs->rf_renamefile(vol, src, dst) < 0 ) {
+ if (vol->vfs->vfs_renamefile(vol, sdir_fd, src, dst) < 0 ) {
int err;
err = errno;
* we know we are on the same device
*/
if (err) {
- unix_rename( dst, src );
+ unix_rename(-1, dst, sdir_fd, src );
/* return the first error */
switch ( err) {
case ENOENT :
*/
if (!ad_open( dst, ADFLAGS_HF, O_RDWR, 0666, adp)) {
ad_setname(adp, newname);
- ad_flush( adp, ADFLAGS_HF );
+ ad_flush( adp );
ad_close( adp, ADFLAGS_HF );
}
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "end renamefile:");
-#endif /* DEBUG */
return( AFP_OK );
}
/* -----------------------------------
*/
-int afp_copyfile(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj *obj;
-char *ibuf, *rbuf _U_;
-int ibuflen _U_, *rbuflen;
+int afp_copyfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
{
struct vol *s_vol, *d_vol;
struct dir *dir;
struct adouble ad, *adp;
int denyreadset;
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "begin afp_copyfile:");
-#endif /* DEBUG */
-
*rbuflen = 0;
ibuf += 2;
}
denyreadset = (getforkmode(adp, ADEID_DFORK, AD_FILELOCK_DENY_RD) != 0 ||
getforkmode(adp, ADEID_RFORK, AD_FILELOCK_DENY_RD) != 0 );
- ad_close( adp, ADFLAGS_DF |ADFLAGS_HF );
+
if (denyreadset) {
- return AFPERR_DENYCONF;
+ retvalue = AFPERR_DENYCONF;
+ goto copy_exit;
}
newname = obj->newtmp;
p = ctoupath( s_vol, curdir, newname );
if (!p) {
- return AFPERR_PARAM;
-
+ retvalue = AFPERR_PARAM;
+ goto copy_exit;
}
+
#ifdef FORCE_UIDGID
/* FIXME svid != dvid && dvid's user can't read svid */
#endif
if (NULL == ( d_vol = getvolbyvid( dvid )) ) {
- return( AFPERR_PARAM );
+ retvalue = AFPERR_PARAM;
+ goto copy_exit;
}
- if (d_vol->v_flags & AFPVOL_RO)
- return AFPERR_VLOCK;
+ if (d_vol->v_flags & AFPVOL_RO) {
+ retvalue = AFPERR_VLOCK;
+ goto copy_exit;
+ }
if (NULL == ( dir = dirlookup( d_vol, ddid )) ) {
- return afp_errno;
+ retvalue = afp_errno;
+ goto copy_exit;
}
if (( s_path = cname( d_vol, dir, &ibuf )) == NULL ) {
- return get_afp_errno(AFPERR_NOOBJ);
+ retvalue = get_afp_errno(AFPERR_NOOBJ);
+ goto copy_exit;
}
+
if ( *s_path->m_name != '\0' ) {
- path_error(s_path, AFPERR_PARAM);
+ retvalue =path_error(s_path, AFPERR_NOOBJ);
+ goto copy_exit;
}
/* one of the handful of places that knows about the path type */
if (copy_path_name(d_vol, newname, ibuf) < 0) {
- return( AFPERR_PARAM );
+ retvalue = AFPERR_PARAM;
+ goto copy_exit;
}
/* newname is always only a filename so curdir *is* its
* parent folder
*/
if (NULL == (upath = mtoupath(d_vol, newname, curdir->d_did, utf8_encoding()))) {
- return( AFPERR_PARAM );
+ retvalue =AFPERR_PARAM;
+ goto copy_exit;
}
- if ( (err = copyfile(s_vol, d_vol, p, upath , newname, adp)) < 0 ) {
- return err;
+
+ if ( (err = copyfile(s_vol, d_vol, -1, p, upath , newname, adp)) < 0 ) {
+ retvalue = err;
+ goto copy_exit;
}
curdir->offcnt++;
setvoltime(obj, d_vol );
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "end afp_copyfile:");
-#endif /* DEBUG */
-
+copy_exit:
+ ad_close( adp, ADFLAGS_DF |ADFLAGS_HF );
return( retvalue );
}
/* ----------------------- */
-static __inline__ int copy_all(const int dfd, const void *buf,
+static int copy_all(const int dfd, const void *buf,
size_t buflen)
{
ssize_t cc;
#ifdef DEBUG
- LOG(log_info, logtype_afpd, "begin copy_all:");
+ LOG(log_debug9, logtype_afpd, "begin copy_all:");
#endif /* DEBUG */
while (buflen > 0) {
}
#ifdef DEBUG
- LOG(log_info, logtype_afpd, "end copy_all:");
+ LOG(log_debug9, logtype_afpd, "end copy_all:");
#endif /* DEBUG */
return 0;
}
-/* -------------------------- */
-static int copy_fd(int dfd, int sfd)
+/* --------------------------
+ * copy only the fork data stream
+*/
+static int copy_fork(int eid, struct adouble *add, struct adouble *ads)
{
ssize_t cc;
int err = 0;
char filebuf[8192];
+ int sfd, dfd;
+ if (eid == ADEID_DFORK) {
+ sfd = ad_data_fileno(ads);
+ dfd = ad_data_fileno(add);
+ }
+ else {
+ sfd = ad_reso_fileno(ads);
+ dfd = ad_reso_fileno(add);
+ }
+
+ if ((off_t)-1 == lseek(sfd, ad_getentryoff(ads, eid), SEEK_SET))
+ return -1;
+
+ if ((off_t)-1 == lseek(dfd, ad_getentryoff(add, eid), SEEK_SET))
+ return -1;
+
#if 0 /* ifdef SENDFILE_FLAVOR_LINUX */
/* doesn't work With 2.6 FIXME, only check for EBADFD ? */
off_t offset = 0;
}
/* ----------------------------------
- * if newname is NULL (from directory.c) we don't want to copy ressource fork.
+ * if newname is NULL (from directory.c) we don't want to copy the resource fork.
* because we are doing it elsewhere.
* currently if newname is NULL then adp is NULL.
*/
-int copyfile(s_vol, d_vol, src, dst, newname, adp )
-const struct vol *s_vol, *d_vol;
-char *src, *dst, *newname;
-struct adouble *adp;
+int copyfile(const struct vol *s_vol,
+ const struct vol *d_vol,
+ int sfd,
+ char *src,
+ char *dst,
+ char *newname,
+ struct adouble *adp)
{
struct adouble ads, add;
int err = 0;
int ret_err = 0;
int adflags;
- int noadouble = vol_noadouble(d_vol);
int stat_result;
struct stat st;
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "begin copyfile:");
-#endif /* DEBUG */
+ LOG(log_debug, logtype_afpd, "copyfile(sfd:%d,s:'%s',d:'%s',n:'%s')",
+ sfd, src, dst, newname);
if (adp == NULL) {
ad_init(&ads, s_vol->v_adouble, s_vol->v_ad_options);
adp = &ads;
}
- ad_init(&add, d_vol->v_adouble, d_vol->v_ad_options);
+
adflags = ADFLAGS_DF;
if (newname) {
adflags |= ADFLAGS_HF;
}
- if (ad_open(src , adflags | ADFLAGS_NOHF, O_RDONLY, 0, adp) < 0) {
+ if (ad_openat(sfd, src, adflags | ADFLAGS_NOHF, O_RDONLY, 0, adp) < 0) {
ret_err = errno;
goto done;
}
- if (ad_hfileno(adp) == -1) {
+ if (ad_meta_fileno(adp) == -1 && ad_reso_fileno(adp) == -1) { /* META / HF */
/* no resource fork, don't create one for dst file */
adflags &= ~ADFLAGS_HF;
}
- stat_result = fstat(ad_dfileno(adp), &st); /* saving stat exit code, thus saving us on one more stat later on */
+ stat_result = fstat(ad_data_fileno(adp), &st); /* saving stat exit code, thus saving us on one more stat later on */
if (stat_result < 0) {
/* unlikely but if fstat fails, the default file mode will be 0666. */
st.st_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
}
- if (ad_open(dst , adflags | noadouble, O_RDWR|O_CREAT|O_EXCL, st.st_mode, &add) < 0) {
+ ad_init(&add, d_vol->v_adouble, d_vol->v_ad_options);
+ if (ad_open(dst , adflags, O_RDWR|O_CREAT|O_EXCL, st.st_mode, &add) < 0) {
ret_err = errno;
ad_close( adp, adflags );
if (EEXIST != ret_err) {
- deletefile(d_vol, dst, 0);
+ deletefile(d_vol, -1, dst, 0);
goto done;
}
return AFPERR_EXIST;
}
- /* XXX if the source and the dest don't use the same resource type it's broken
- */
- if (ad_hfileno(adp) == -1 || 0 == (err = copy_fd(ad_hfileno(&add), ad_hfileno(adp)))){
+
+ /*
+ * 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_fd(ad_dfileno(&add), ad_dfileno(adp));
+ if ((err = copy_fork(ADEID_DFORK, &add, adp)) == 0) {
+ err = d_vol->vfs->vfs_copyfile(d_vol, sfd, src, dst);
+ }
}
- /* Now, reopen destination file */
if (err < 0) {
ret_err = errno;
}
- ad_close( adp, adflags );
-
- if (ad_close( &add, adflags ) <0) {
- deletefile(d_vol, dst, 0);
- ret_err = errno;
- goto done;
- }
if (!ret_err && newname && (adflags & ADFLAGS_HF)) {
/* set the new name in the resource fork */
- ad_init(&add, d_vol->v_adouble, d_vol->v_ad_options);
- if (ad_open(dst , ADFLAGS_HF | noadouble, O_RDWR, 0666, &add) < 0) {
- ret_err = errno;
- }
- else {
- ad_setname(&add, newname);
- ad_flush( &add, ADFLAGS_HF );
- if (ad_close( &add, ADFLAGS_HF ) <0) {
- ret_err = errno;
- }
- }
+ ad_copy_header(&add, adp);
+ ad_setname(&add, newname);
+ ad_flush( &add );
}
+ ad_close( adp, adflags );
+
+ if (ad_close( &add, adflags ) <0) {
+ ret_err = errno;
+ }
if (ret_err) {
- deletefile(d_vol, dst, 0);
+ deletefile(d_vol, -1, dst, 0);
}
else if (stat_result == 0) {
/* set dest modification date to src date */
struct utimbuf ut;
-#if 0
- if (vol_unix_priv(d_vol)) {
- /* unix priv, use source priv. XXX should be done in ad_open? */
- setfilunixmode(d_vol, dst, st.st_mode);
- }
-#endif
+
ut.actime = ut.modtime = st.st_mtime;
utime(dst, &ut);
/* FIXME netatalk doesn't use resource fork file date
*/
}
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "end copyfile:");
-#endif /* DEBUG */
-
done:
switch ( ret_err ) {
case 0:
ad_open always try to open file RDWR first and ad_lock takes care of
WRITE lock on read only file.
*/
-int deletefile( vol, file, checkAttrib )
-const struct vol *vol;
-char *file;
-int checkAttrib;
+
+static int check_attrib(struct adouble *adp)
+{
+u_int16_t bshort = 0;
+
+ ad_getattr(adp, &bshort);
+ /*
+ * Does kFPDeleteInhibitBit (bit 8) set?
+ */
+ if ((bshort & htons(ATTRBIT_NODELETE))) {
+ return AFPERR_OLOCK;
+ }
+ if ((bshort & htons(ATTRBIT_DOPEN | ATTRBIT_ROPEN))) {
+ return AFPERR_BUSY;
+ }
+ return 0;
+}
+/*
+ * dirfd can be used for unlinkat semantics
+ */
+int deletefile(const struct vol *vol, int dirfd, char *file, int checkAttrib)
{
struct adouble ad;
- struct adouble *adp = &ad;
+ struct adouble *adp = NULL;
int adflags, err = AFP_OK;
+ int meta = 0;
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "begin deletefile:");
-#endif /* DEBUG */
-
- /* try to open both forks at once */
- adflags = ADFLAGS_DF|ADFLAGS_HF;
- ad_init(&ad, vol->v_adouble, vol->v_ad_options); /* OK */
- while(1) {
- if ( ad_open( file, adflags, O_RDONLY, 0, &ad ) < 0 ) {
- switch (errno) {
- case ENOENT:
- if (adflags == ADFLAGS_DF)
- return AFPERR_NOOBJ;
-
- /* that failed. now try to open just the data fork */
- adflags = ADFLAGS_DF;
- continue;
+ LOG(log_debug, logtype_afpd, "deletefile('%s')", file);
- case EACCES:
- adp = NULL; /* maybe it's a file with no write mode for us */
- break; /* was return AFPERR_ACCESS;*/
- case EROFS:
- return AFPERR_VLOCK;
- default:
- return( AFPERR_PARAM );
+ ad_init(&ad, vol->v_adouble, vol->v_ad_options);
+ if (checkAttrib) {
+ /* was EACCESS error try to get only metadata */
+ /* we never want to create a resource fork here, we are going to delete it
+ * moreover sometimes deletefile is called with a no existent file and
+ * ad_open would create a 0 byte resource fork
+ */
+ if ( ad_metadataat(dirfd, file, ADFLAGS_OPENFORKS, &ad) == 0 ) {
+ if ((err = check_attrib(&ad))) {
+ ad_close_metadata(&ad);
+ return err;
}
+ meta = 1;
}
- break; /* from the while */
}
- /*
- * Does kFPDeleteInhibitBit (bit 8) set?
- */
- if (checkAttrib) {
- u_int16_t bshort;
-
- if ( ad_metadata( file , 0, &ad) == 0 ) {
- ad_getattr(&ad, &bshort);
- ad_close_metadata( &ad);
- if ((bshort & htons(ATTRBIT_NODELETE))) {
- return AFPERR_OLOCK;
- }
+
+ /* try to open both forks at once */
+ adflags = ADFLAGS_DF;
+ if ( ad_openat(dirfd, file, adflags |ADFLAGS_HF|ADFLAGS_NOHF, O_RDONLY, 0, &ad ) < 0 ) {
+ switch (errno) {
+ case ENOENT:
+ err = AFPERR_NOOBJ;
+ goto end;
+ case EACCES: /* maybe it's a file with no write mode for us */
+ break; /* was return AFPERR_ACCESS;*/
+ case EROFS:
+ err = AFPERR_VLOCK;
+ goto end;
+ default:
+ err = AFPERR_PARAM;
+ goto end;
}
}
-
- if (adp && (adflags & ADFLAGS_HF) ) {
+ else {
+ adp = &ad;
+ }
+
+ if ( adp && ad_reso_fileno( adp ) != -1 ) { /* there's a resource fork */
+ adflags |= ADFLAGS_HF;
/* FIXME we have a pb here because we want to know if a file is open
* there's a 'priority inversion' if you can't open the ressource fork RW
* you can delete it if it's open because you can't get a write lock.
* FIXME it doesn't work for RFORK open read only and fork open without deny mode
*/
if (ad_tmplock(&ad, ADEID_RFORK, ADLOCK_WR |ADLOCK_FILELOCK, 0, 0, 0) < 0 ) {
- ad_close( &ad, adflags );
- return( AFPERR_BUSY );
+ err = AFPERR_BUSY;
+ goto end;
}
}
if (adp && ad_tmplock( &ad, ADEID_DFORK, ADLOCK_WR, 0, 0, 0 ) < 0) {
err = AFPERR_BUSY;
- }
- else if (!(err = vol->vfs->rf_deletefile(vol, file)) && !(err = netatalk_unlink( file )) ) {
+ } else if (!(err = vol->vfs->vfs_deletefile(vol, dirfd, file)) && !(err = netatalk_unlinkat(dirfd, file )) ) {
cnid_t id;
- if (checkAttrib && (id = cnid_get(vol->v_cdb, curdir->d_did, file, strlen(file))))
- {
+ if (checkAttrib && (id = cnid_get(vol->v_cdb, curdir->d_did, file, strlen(file)))) {
cnid_delete(vol->v_cdb, id);
}
}
+
+end:
+ if (meta)
+ ad_close_metadata(&ad);
+
if (adp)
ad_close( &ad, adflags ); /* ad_close removes locks if any */
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "end deletefile:");
-#endif /* DEBUG */
-
return err;
}
/* ------------------------------------ */
/* return a file id */
-int afp_createid(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj *obj _U_;
-char *ibuf, *rbuf;
-int ibuflen _U_, *rbuflen;
+int afp_createid(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
{
struct stat *st;
struct vol *vol;
u_short vid;
struct path *s_path;
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "begin afp_createid:");
-#endif /* DEBUG */
-
*rbuflen = 0;
ibuf += 2;
return AFP_OK;
}
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "ending afp_createid...:");
-#endif /* DEBUG */
return afp_errno;
}
cnid_t did = param->did;
cnid_t aint;
- memset(&path, 0, sizeof(path));
-
- if ( stat(de->d_name, &path.st)<0 )
+ if ( lstat(de->d_name, &path.st)<0 )
return 0;
/* update or add to cnid */
return 0;
}
if (ad_setid(adp, path.st.st_dev, path.st.st_ino, aint, did, vol->v_stamp)) {
- ad_flush_metadata(adp);
+ ad_flush(adp);
}
ad_close_metadata(adp);
}
}
/* FIXME use of_statdir ? */
- if (stat(name, &st)) {
+ if (lstat(name, &st)) {
return -1;
}
/* ------------------------------
resolve a file id */
-int afp_resolveid(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj *obj _U_;
-char *ibuf, *rbuf;
-int ibuflen _U_, *rbuflen;
+int afp_resolveid(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
{
struct vol *vol;
struct dir *dir;
char *upath;
struct path path;
- int err, buflen, retry=0;
+ int err, retry=0;
+ size_t buflen;
cnid_t id, cnid;
u_int16_t vid, bitmap;
static char buffer[12 + MAXPATHLEN + 1];
int len = 12 + MAXPATHLEN + 1;
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "begin afp_resolveid:");
-#endif /* DEBUG */
-
*rbuflen = 0;
ibuf += 2;
return AFPERR_NOID;
}
retry:
- memset(&path, 0, sizeof(path));
if (NULL == (upath = cnid_resolve(vol->v_cdb, &id, buffer, len)) ) {
return AFPERR_NOID; /* was AFPERR_BADID, but help older Macs */
}
if (NULL == ( dir = dirlookup( vol, id )) ) {
return AFPERR_NOID; /* idem AFPERR_PARAM */
}
- path.u_name = upath;
if (movecwd(vol, dir) < 0) {
switch (errno) {
case EACCES:
}
}
+ memset(&path, 0, sizeof(path));
+ path.u_name = upath;
if ( of_stat(&path) < 0 ) {
#ifdef ESTALE
/* with nfs and our working directory is deleted */
}
/* directories are bad */
- if (S_ISDIR(path.st.st_mode))
- return AFPERR_BADTYPE;
+ if (S_ISDIR(path.st.st_mode)) {
+ /* OS9 and OSX don't return the same error code */
+ return (afp_version >=30)?AFPERR_NOID:AFPERR_BADTYPE;
+ }
memcpy(&bitmap, ibuf, sizeof(bitmap));
bitmap = ntohs( bitmap );
*rbuflen = buflen + sizeof(bitmap);
memcpy(rbuf, ibuf, sizeof(bitmap));
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "end afp_resolveid:");
-#endif /* DEBUG */
-
return AFP_OK;
}
/* ------------------------------ */
-int afp_deleteid(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj *obj _U_;
-char *ibuf, *rbuf _U_;
-int ibuflen _U_, *rbuflen;
+int afp_deleteid(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
{
struct stat st;
struct vol *vol;
static char buffer[12 + MAXPATHLEN + 1];
int len = 12 + MAXPATHLEN + 1;
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "begin afp_deleteid:");
-#endif /* DEBUG */
-
*rbuflen = 0;
ibuf += 2;
}
if (NULL == ( dir = dirlookup( vol, id )) ) {
+ if (afp_errno == AFPERR_NOOBJ) {
+ err = AFPERR_NOOBJ;
+ goto delete;
+ }
return( AFPERR_PARAM );
}
err = AFP_OK;
- if ((movecwd(vol, dir) < 0) || (stat(upath, &st) < 0)) {
+ if ((movecwd(vol, dir) < 0) || (lstat(upath, &st) < 0)) {
switch (errno) {
case EACCES:
case EPERM:
else if (S_ISDIR(st.st_mode)) /* directories are bad */
return AFPERR_BADTYPE;
+delete:
if (cnid_delete(vol->v_cdb, fileid)) {
switch (errno) {
case EROFS:
}
}
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "end afp_deleteid:");
-#endif /* DEBUG */
-
return err;
}
}
else {
ret = ad_open( path->u_name, ADFLAGS_HF, O_RDONLY, 0, adp);
- if ( !ret && ad_hfileno(adp) != -1 && !(adp->ad_hf.adf_flags & ( O_RDWR | O_WRONLY))) {
+ /* META and HF */
+ if ( !ret && ad_reso_fileno(adp) != -1 && !(adp->ad_resource_fork.adf_flags & ( O_RDWR | O_WRONLY))) {
/* from AFP spec.
* The user must have the Read & Write privilege for both files in order to use this command.
*/
#define APPLETEMP ".AppleTempXXXXXX"
-int afp_exchangefiles(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj *obj;
-char *ibuf, *rbuf _U_ ;
-int ibuflen _U_, *rbuflen;
+int afp_exchangefiles(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
{
struct stat srcst, destst;
struct vol *vol;
uid_t uid;
gid_t gid;
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "begin afp_exchangefiles:");
-#endif /* DEBUG */
-
*rbuflen = 0;
ibuf += 2;
}
/* now, quickly rename the file. we error if we can't. */
- if ((err = renamefile(vol, p, temp, temp, adsp)) != AFP_OK)
+ if ((err = renamefile(vol, -1, p, temp, temp, adsp)) != AFP_OK)
goto err_exchangefile;
of_rename(vol, s_of, sdir, spath, curdir, temp);
/* rename destination to source */
- if ((err = renamefile(vol, upath, p, spath, addp)) != AFP_OK)
+ if ((err = renamefile(vol, -1, upath, p, spath, addp)) != AFP_OK)
goto err_src_to_tmp;
of_rename(vol, d_of, curdir, path->m_name, sdir, spath);
/* rename temp to destination */
- if ((err = renamefile(vol, temp, upath, path->m_name, adsp)) != AFP_OK)
+ if ((err = renamefile(vol, -1, temp, upath, path->m_name, adsp)) != AFP_OK)
goto err_dest_to_src;
of_rename(vol, s_of, curdir, temp, curdir, path->m_name);
if (did) {
cnid_delete(vol->v_cdb, did);
}
- if ((did && ( (crossdev && stat( upath, &srcst) < 0) ||
+ if ((did && ( (crossdev && lstat( upath, &srcst) < 0) ||
cnid_update(vol->v_cdb, did, &srcst, curdir->d_did,upath, dlen) < 0))
||
- (sid && ( (crossdev && stat(p, &destst) < 0) ||
+ (sid && ( (crossdev && lstat(p, &destst) < 0) ||
cnid_update(vol->v_cdb, sid, &destst, sdir->d_did,supath, slen) < 0))
) {
switch (errno) {
/* here we need to reopen if crossdev */
if (sid && ad_setid(addp, destst.st_dev, destst.st_ino, sid, sdir->d_did, vol->v_stamp))
{
- ad_flush( addp, ADFLAGS_HF );
+ ad_flush( addp );
}
if (did && ad_setid(adsp, srcst.st_dev, srcst.st_ino, did, curdir->d_did, vol->v_stamp))
{
- ad_flush( adsp, ADFLAGS_HF );
+ ad_flush( adsp );
}
/* change perms, src gets dest perm and vice versa */
exit(EXITERR_SYS);
}
-#ifdef DEBUG
- LOG(log_info, logtype_afpd, "ending afp_exchangefiles:");
-#endif /* DEBUG */
-
err = AFP_OK;
goto err_exchangefile;
* properly. */
err_temp_to_dest:
/* rename dest to temp */
- renamefile(vol, upath, temp, temp, adsp);
+ renamefile(vol, -1, upath, temp, temp, adsp);
of_rename(vol, s_of, curdir, upath, curdir, temp);
err_dest_to_src:
/* rename source back to dest */
- renamefile(vol, p, upath, path->m_name, addp);
+ renamefile(vol, -1, p, upath, path->m_name, addp);
of_rename(vol, d_of, sdir, spath, curdir, path->m_name);
err_src_to_tmp:
/* rename temp back to source */
- renamefile(vol, temp, p, spath, adsp);
+ renamefile(vol, -1, temp, p, spath, adsp);
of_rename(vol, s_of, curdir, temp, sdir, spath);
err_exchangefile:
- if ( !s_of && adsp && ad_hfileno(adsp) != -1 ) {
+ if ( !s_of && adsp && ad_meta_fileno(adsp) != -1 ) { /* META */
ad_close(adsp, ADFLAGS_HF);
}
- if ( !d_of && addp && ad_hfileno(addp) != -1 ) {
+ if ( !d_of && addp && ad_meta_fileno(addp) != -1 ) {/* META */
ad_close(addp, ADFLAGS_HF);
}