/*
- * $Id: file.c,v 1.66 2002-10-13 16:12:31 didg Exp $
+ * $Id: file.c,v 1.83 2003-02-04 18:26:20 didg Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
return data;
}
-/*
- * FIXME: PDINFO is UTF8 and doesn't need adp
+/* ---------------------
*/
-#define PARAM_NEED_ADP(b) ((b) & ((1 << FILPBIT_ATTR) |\
- (1 << FILPBIT_CDATE) |\
- (1 << FILPBIT_MDATE) |\
- (1 << FILPBIT_BDATE) |\
- (1 << FILPBIT_FINFO) |\
- (1 << FILPBIT_RFLEN) |\
- (1 << FILPBIT_EXTRFLEN) |\
- (1 << FILPBIT_PDINFO)))
-
-
char *set_name(char *data, const char *name, u_int32_t utf8)
{
u_int32_t aint;
aint = strlen( name );
if (!utf8) {
+ if (afp_version >= 30) {
+ /* the name is in utf8 */
+ }
if (aint > MACFILELEN)
aint = MACFILELEN;
*data++ = aint;
return data;
}
+/*
+ * FIXME: PDINFO is UTF8 and doesn't need adp
+*/
+#define PARAM_NEED_ADP(b) ((b) & ((1 << FILPBIT_ATTR) |\
+ (1 << FILPBIT_CDATE) |\
+ (1 << FILPBIT_MDATE) |\
+ (1 << FILPBIT_BDATE) |\
+ (1 << FILPBIT_FINFO) |\
+ (1 << FILPBIT_RFLEN) |\
+ (1 << FILPBIT_EXTRFLEN) |\
+ (1 << FILPBIT_PDINFO)))
+
+
/* -------------------------- */
int getmetadata(struct vol *vol,
u_int16_t bitmap,
#ifndef USE_LASTDID
struct stat lst, *lstp;
#endif /* USE_LASTDID */
- char *data, *nameoff = NULL, *upath;
+ char *data, *l_nameoff = NULL, *upath;
+ char *utf_nameoff = NULL;
int bit = 0;
u_int32_t aint;
u_int16_t ashort;
break;
case FILPBIT_LNAME :
- nameoff = data;
+ l_nameoff = data;
data += sizeof( u_int16_t );
break;
us what the PD file code should be. Everything gets a
subtype of 0x0000 unless the original value was hashed
to "pXYZ" when we created it. See IA, Ver 2.
- <shirsch@ibm.net> */
+ <shirsch@adelphia.net> */
case FILPBIT_PDINFO :
if (afp_version >= 30) { /* UTF8 name */
utf8 = kTextEncodingUTF8;
- nameoff = data;
+ utf_nameoff = data;
data += sizeof( u_int16_t );
aint = 0;
memcpy(data, &aint, sizeof( aint ));
bitmap = bitmap>>1;
bit++;
}
- if ( nameoff ) {
+ if ( l_nameoff ) {
+ ashort = htons( data - buf );
+ memcpy(l_nameoff, &ashort, sizeof( ashort ));
+ data = set_name(data, path, 0);
+ }
+ if ( utf_nameoff ) {
ashort = htons( data - buf );
- memcpy(nameoff, &ashort, sizeof( ashort ));
+ memcpy(utf_nameoff, &ashort, sizeof( ashort ));
data = set_name(data, path, utf8);
}
*buflen = data - buf;
memcpy(&vid, ibuf, sizeof( vid ));
ibuf += sizeof( vid );
- if (( vol = getvolbyvid( vid )) == NULL ) {
+ if (NULL == ( vol = getvolbyvid( vid )) ) {
return( AFPERR_PARAM );
}
memcpy(&did, ibuf, sizeof( did));
ibuf += sizeof( did );
- if (( dir = dirlookup( vol, did )) == NULL ) {
- return( AFPERR_NOOBJ );
+ if (NULL == ( dir = dirlookup( vol, did )) ) {
+ return afp_errno;
}
- if (( s_path = cname( vol, dir, &ibuf )) == NULL ) {
- return( AFPERR_NOOBJ );
+ if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
+ return afp_errno;
}
if ( *s_path->m_name == '\0' ) {
ad_close( adp, ADFLAGS_DF|ADFLAGS_HF );
createfile_done:
+ curdir->offcnt++;
#ifdef DROPKLUDGE
if (vol->v_flags & AFPVOL_DROPBOX) {
memcpy(&vid, ibuf, sizeof( vid ));
ibuf += sizeof( vid );
- if (( vol = getvolbyvid( vid )) == NULL ) {
+ if (NULL == ( vol = getvolbyvid( vid )) ) {
return( AFPERR_PARAM );
}
memcpy(&did, ibuf, sizeof( did ));
ibuf += sizeof( did );
- if (( dir = dirlookup( vol, did )) == NULL ) {
- return( AFPERR_NOOBJ );
+ if (NULL == ( dir = dirlookup( vol, did )) ) {
+ return afp_errno; /* was AFPERR_NOOBJ */
}
memcpy(&bitmap, ibuf, sizeof( bitmap ));
bitmap = ntohs( bitmap );
ibuf += sizeof( bitmap );
- if (( s_path = cname( vol, dir, &ibuf )) == NULL ) {
- return( AFPERR_NOOBJ );
+ if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
+ return afp_errno;
}
- if ( *s_path->m_name == '\0' ) {
+ if (path_isadir(s_path)) {
return( AFPERR_BADTYPE ); /* it's a directory */
}
ibuf++;
}
- if (( rc = setfilparams(vol, s_path, bitmap, ibuf )) == AFP_OK ) {
+ if (AFP_OK == ( rc = setfilparams(vol, s_path, bitmap, ibuf )) ) {
setvoltime(obj, vol );
}
return vol_noadouble(vol) ? AFP_OK : AFPERR_ACCESS;
}
isad = 0;
- } else if ((ad_getoflags( adp, ADFLAGS_HF ) & O_CREAT) ) {
+ } else if ((ad_get_HF_flags( adp ) & O_CREAT) ) {
ad_setentrylen( adp, ADEID_NAME, strlen( path->m_name ));
memcpy(ad_entry( adp, ADEID_NAME ), path->m_name,
ad_getentrylen( adp, ADEID_NAME ));
break;
/* Client needs to set the ProDOS file info for this file.
- Use defined strings for the simple cases, and convert
- all else into pXYY per Inside Appletalk. Always set
- the creator as "pdos". <shirsch@ibm.net> */
+ Use a defined string for TEXT to support crlf
+ translations and convert all else into pXYY per Inside
+ Appletalk. Always set the creator as "pdos". Changes
+ from original by Marsha Jackson. */
case FILPBIT_PDINFO :
- achar = *buf;
- buf += 2;
- memcpy(&ashort, buf, sizeof( ashort ));
- ashort = ntohs( ashort );
- buf += 2;
-
- switch ( (unsigned int) achar )
- {
- case 0x04 :
- fdType = ( u_char *) "TEXT";
- break;
-
- case 0xff :
- fdType = ( u_char *) "PSYS";
- break;
-
- case 0xb3 :
- fdType = ( u_char *) "PS16";
- break;
-
- case 0x00 :
- fdType = ( u_char *) "BINA";
- break;
-
- default :
- xyy[0] = ( u_char ) 'p';
- xyy[1] = achar;
- xyy[2] = ( u_char ) ( ashort >> 8 ) & 0xff;
- xyy[3] = ( u_char ) ashort & 0xff;
- fdType = xyy;
+ if (afp_version < 30) { /* else it's UTF8 name */
+ achar = *buf;
+ buf += 2;
+ /* Keep special case to support crlf translations */
+ if ((unsigned int) achar == 0x04) {
+ fdType = (u_char *)"TEXT";
+ buf += 2;
+ } else {
+ xyy[0] = ( u_char ) 'p';
+ xyy[1] = achar;
+ xyy[3] = *buf++;
+ xyy[2] = *buf++;
+ fdType = xyy;
+ }
+ memcpy(ad_entry( adp, ADEID_FINDERI ), fdType, 4 );
+ memcpy(ad_entry( adp, ADEID_FINDERI ) + 4, "pdos", 4 );
break;
}
-
- memcpy(ad_entry( adp, ADEID_FINDERI ), fdType, 4 );
- memcpy(ad_entry( adp, ADEID_FINDERI ) + 4, "pdos", 4 );
- break;
-
-
+ /* fallthrough */
default :
err = AFPERR_BITMAP;
goto setfilparam_done;
/*
* renamefile and copyfile take the old and new unix pathnames
* and the new mac name.
- * NOTE: if we have to copy a file instead of renaming it, locks
- * will break. Anyway it's an error because then we have 2 files.
*
* src the source path
* dst the dest filename in current dir
const int noadouble;
struct adouble *adp;
{
- char adsrc[ MAXPATHLEN + 1];
- int len, rc;
-
- /*
- * Note that this is only checking the existance of the data file,
- * not the header file. The thinking is that if the data file doesn't
- * exist, but the header file does, the right thing to do is remove
- * the data file silently.
- */
-
- /* existence check moved to afp_moveandrename */
+ char adsrc[ MAXPATHLEN + 1];
+ int len;
+ int rc;
#ifdef DEBUG
LOG(log_info, logtype_afpd, "begin renamefile:");
#endif /* DEBUG */
- if ( rename( src, dst ) < 0 ) {
+ if ( unix_rename( src, dst ) < 0 ) {
switch ( errno ) {
case ENOENT :
return( AFPERR_NOOBJ );
case EROFS:
return AFPERR_VLOCK;
case EXDEV : /* Cross device move -- try copy */
+ /* NOTE: with open file it's an error because after the copy we will
+ * 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) {
+ /* FIXME warning in syslog so admin'd know there's a conflict ?*/
+ return AFPERR_OLOCK; /* little lie */
+ }
if (( rc = copyfile(src, dst, newname, noadouble )) != AFP_OK ) {
deletefile( dst, 0 );
return( rc );
}
strcpy( adsrc, ad_path( src, 0 ));
- rc = 0;
-rename_retry:
- if (rename( adsrc, ad_path( dst, 0 )) < 0 ) {
+
+ if (unix_rename( adsrc, ad_path( dst, 0 )) < 0 ) {
struct stat st;
+ int err;
+
+ err = errno;
+ if (errno == ENOENT) {
+ struct adouble ad;
- switch ( errno ) {
- case ENOENT :
- /* check for a source appledouble header. if it exists, make
- * a dest appledouble directory and do the rename again. */
- if (rc || stat(adsrc, &st) ||
- (ad_open(dst, ADFLAGS_HF, O_RDWR | O_CREAT, 0666, adp) < 0))
+ if (stat(adsrc, &st)) /* source has no ressource fork, */
return AFP_OK;
- rc++;
- ad_close(adp, ADFLAGS_HF);
- goto rename_retry;
- case EPERM:
- case EACCES :
- return( AFPERR_ACCESS );
- case EROFS:
- return AFPERR_VLOCK;
- default :
- return( AFPERR_PARAM );
+
+ /* 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.
+ */
+ memset(&ad, 0, sizeof(ad));
+ if (!ad_open(dst, ADFLAGS_HF, O_RDWR | O_CREAT, 0666, &ad)) {
+ ad_close(&ad, ADFLAGS_HF);
+ if (!unix_rename( adsrc, ad_path( dst, 0 )) )
+ err = 0;
+ else
+ err = errno;
+ }
+ else { /* it's something else, bail out */
+ err = errno;
+ }
+ }
+ /* try to undo the data fork rename,
+ * we know we are on the same device
+ */
+ if (err) {
+ unix_rename( dst, src );
+ /* return the first error */
+ switch ( err) {
+ case ENOENT :
+ return AFPERR_NOOBJ;
+ case EPERM:
+ case EACCES :
+ return AFPERR_ACCESS ;
+ case EROFS:
+ return AFPERR_VLOCK;
+ default :
+ return AFPERR_PARAM ;
+ }
}
}
- if ( ad_open( dst, ADFLAGS_HF, O_RDWR, 0666, adp) < 0 ) {
- switch ( errno ) {
- case ENOENT :
- return( AFPERR_NOOBJ );
- case EACCES :
- return( AFPERR_ACCESS );
- case EROFS:
- return AFPERR_VLOCK;
- default :
- return( AFPERR_PARAM );
- }
+ /* don't care if we can't open the newly renamed ressource fork
+ */
+ if ( !ad_open( dst, ADFLAGS_HF, O_RDWR, 0666, adp)) {
+ len = strlen( newname );
+ ad_setentrylen( adp, ADEID_NAME, len );
+ memcpy(ad_entry( adp, ADEID_NAME ), newname, len );
+ ad_flush( adp, ADFLAGS_HF );
+ ad_close( adp, ADFLAGS_HF );
}
-
- len = strlen( newname );
- ad_setentrylen( adp, ADEID_NAME, len );
- memcpy(ad_entry( adp, ADEID_NAME ), newname, len );
- ad_flush( adp, ADFLAGS_HF );
- ad_close( adp, ADFLAGS_HF );
-
#ifdef DEBUG
LOG(log_info, logtype_afpd, "end renamefile:");
#endif /* DEBUG */
u_int16_t len16;
u_int32_t hint;
- if ( type != 2 || (afp_version >= 30 && type != 3) ) {
+ if ( type != 2 && !(afp_version >= 30 && type == 3) ) {
return -1;
}
ibuf++;
if (plen) {
strncpy( newname, ibuf, plen );
newname[ plen ] = '\0';
- if (strchr(newname,'/')) {
+ if (strlen(newname) != plen) {
return -1;
}
}
memcpy(&svid, ibuf, sizeof( svid ));
ibuf += sizeof( svid );
- if (( vol = getvolbyvid( svid )) == NULL ) {
+ if (NULL == ( vol = getvolbyvid( svid )) ) {
return( AFPERR_PARAM );
}
memcpy(&sdid, ibuf, sizeof( sdid ));
ibuf += sizeof( sdid );
- if (( dir = dirlookup( vol, sdid )) == NULL ) {
- return( AFPERR_PARAM );
+ if (NULL == ( dir = dirlookup( vol, sdid )) ) {
+ return afp_errno;
}
memcpy(&dvid, ibuf, sizeof( dvid ));
memcpy(&ddid, ibuf, sizeof( ddid ));
ibuf += sizeof( ddid );
- if (( s_path = cname( vol, dir, &ibuf )) == NULL ) {
- return( AFPERR_NOOBJ );
+ if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
+ return afp_errno;
}
- if ( *s_path->m_name == '\0' ) {
+ if ( path_isadir(s_path) ) {
return( AFPERR_BADTYPE );
}
return AFPERR_DENYCONF;
p = ctoupath( vol, curdir, newname );
+ if (!p) {
+ return AFPERR_PARAM;
+
+ }
#ifdef FORCE_UIDGID
/* FIXME svid != dvid && dvid's user can't read svid */
#endif
- if (( vol = getvolbyvid( dvid )) == NULL ) {
+ if (NULL == ( vol = getvolbyvid( dvid )) ) {
return( AFPERR_PARAM );
}
if (vol->v_flags & AFPVOL_RO)
return AFPERR_VLOCK;
- if (( dir = dirlookup( vol, ddid )) == NULL ) {
- return( AFPERR_PARAM );
+ if (NULL == ( dir = dirlookup( vol, ddid )) ) {
+ return afp_errno;
}
if (( s_path = cname( vol, dir, &ibuf )) == NULL ) {
- return( AFPERR_NOOBJ );
+ return afp_errno;
}
if ( *s_path->m_name != '\0' ) {
- return( AFPERR_BADTYPE ); /* not a directory. AFPERR_PARAM? */
+ return (path_isadir( s_path))? AFPERR_PARAM:AFPERR_BADTYPE ;
}
/* one of the handful of places that knows about the path type */
if ( (err = copyfile(p, upath , newname, vol_noadouble(vol))) < 0 ) {
return err;
}
+ curdir->offcnt++;
#ifdef DROPKLUDGE
if (vol->v_flags & AFPVOL_DROPBOX) {
when deletefile is called we don't have lock on it, file is closed (for us)
untrue if called by renamefile
+
+ ad_open always try to open file RDWR first and ad_lock takes care of
+ WRITE lock on read only file.
*/
int deletefile( file, checkAttrib )
char *file;
{
struct adouble ad;
int adflags, err = AFP_OK;
- int locktype = ADLOCK_WR;
- int openmode = O_RDWR;
#ifdef DEBUG
LOG(log_info, logtype_afpd, "begin deletefile:");
#endif /* DEBUG */
+ /* try to open both forks at once */
+ adflags = ADFLAGS_DF|ADFLAGS_HF;
while(1) {
- /*
- * If can't open read/write then try again read-only. If it's open
- * read-only, we must do a read lock instead of a write lock.
- */
- /* try to open both at once */
- adflags = ADFLAGS_DF|ADFLAGS_HF;
memset(&ad, 0, sizeof(ad));
- if ( ad_open( file, adflags, openmode, 0, &ad ) < 0 ) {
+ if ( ad_open( file, adflags, O_RDONLY, 0, &ad ) < 0 ) {
switch (errno) {
case ENOENT:
- adflags = ADFLAGS_DF;
+ if (adflags == ADFLAGS_DF)
+ return AFPERR_NOOBJ;
+
/* that failed. now try to open just the data fork */
- memset(&ad, 0, sizeof(ad));
- if ( ad_open( file, adflags, openmode, 0, &ad ) < 0 ) {
- switch (errno) {
- case ENOENT:
- return AFPERR_NOOBJ;
- case EACCES:
- if(openmode == O_RDWR) {
- openmode = O_RDONLY;
- locktype = ADLOCK_RD;
- continue;
- } else {
- return AFPERR_ACCESS;
- }
- case EROFS:
- return AFPERR_VLOCK;
- default:
- return AFPERR_PARAM;
- }
- }
- break;
+ adflags = ADFLAGS_DF;
+ continue;
case EACCES:
- if(openmode == O_RDWR) {
- openmode = O_RDONLY;
- locktype = ADLOCK_RD;
- continue;
- } else {
- return AFPERR_ACCESS;
- }
+ return AFPERR_ACCESS;
case EROFS:
return AFPERR_VLOCK;
default:
* ADLOCK_FILELOCK means the whole ressource fork, not only after the
* metadatas
*
- * FIXME it doesn't for RFORK open read only and fork open without deny mode
+ * FIXME it doesn't work for RFORK open read only and fork open without deny mode
*/
- if (ad_tmplock(&ad, ADEID_RFORK, locktype |ADLOCK_FILELOCK, 0, 0) < 0 ) {
+ if (ad_tmplock(&ad, ADEID_RFORK, ADLOCK_WR |ADLOCK_FILELOCK, 0, 0, 0) < 0 ) {
ad_close( &ad, adflags );
return( AFPERR_BUSY );
}
}
- if (ad_tmplock( &ad, ADEID_DFORK, locktype, 0, 0 ) < 0) {
+ if (ad_tmplock( &ad, ADEID_DFORK, ADLOCK_WR, 0, 0, 0 ) < 0) {
err = AFPERR_BUSY;
- goto delete_unlock;
- }
-
- if ( unlink( ad_path( file, ADFLAGS_HF )) < 0 ) {
- switch ( errno ) {
- case EPERM:
- case EACCES :
- err = AFPERR_ACCESS;
- goto delete_unlock;
- case EROFS:
- err = AFPERR_VLOCK;
- goto delete_unlock;
- case ENOENT :
- break;
- default :
- err = AFPERR_PARAM;
- goto delete_unlock;
- }
}
-
- if ( unlink( file ) < 0 ) {
- switch ( errno ) {
- case EPERM:
- case EACCES :
- err = AFPERR_ACCESS;
- break;
- case EROFS:
- err = AFPERR_VLOCK;
- break;
- case ENOENT :
- break;
- default :
- err = AFPERR_PARAM;
- break;
- }
+ else if ( 0 == (err = netatalk_unlink( ad_path( file, ADFLAGS_HF )) )) {
+ err = netatalk_unlink( file );
}
-
-delete_unlock:
- if (adflags & ADFLAGS_HF)
- ad_tmplock(&ad, ADEID_RFORK, ADLOCK_CLR |ADLOCK_FILELOCK, 0, 0);
- ad_tmplock(&ad, ADEID_DFORK, ADLOCK_CLR, 0, 0);
- ad_close( &ad, adflags );
+ ad_close( &ad, adflags ); /* ad_close removes locks if any */
#ifdef DEBUG
LOG(log_info, logtype_afpd, "end deletefile:");
memcpy(&vid, ibuf, sizeof(vid));
ibuf += sizeof(vid);
- if (( vol = getvolbyvid( vid )) == NULL ) {
+ if (NULL == ( vol = getvolbyvid( vid )) ) {
return( AFPERR_PARAM);
}
memcpy(&did, ibuf, sizeof( did ));
ibuf += sizeof(did);
- if (( dir = dirlookup( vol, did )) == NULL ) {
+ if (NULL == ( dir = dirlookup( vol, did )) ) {
return( AFPERR_PARAM );
}
if (( s_path = cname( vol, dir, &ibuf )) == NULL ) {
- return( AFPERR_PARAM );
+ return afp_errno; /* was AFPERR_PARAM */
}
- if ( *s_path->m_name == '\0' ) {
+ if ( path_isadir(s_path) ) {
return( AFPERR_BADTYPE );
}
memcpy(&vid, ibuf, sizeof(vid));
ibuf += sizeof(vid);
- if (( vol = getvolbyvid( vid )) == NULL ) {
+ if (NULL == ( vol = getvolbyvid( vid )) ) {
return( AFPERR_PARAM);
}
memcpy(&id, ibuf, sizeof( id ));
ibuf += sizeof(id);
- if ((upath = cnid_resolve(vol->v_db, &id, buffer, len)) == NULL) {
+ if (NULL == (upath = cnid_resolve(vol->v_db, &id, buffer, len)) ) {
return AFPERR_NOID; /* was AFPERR_BADID, but help older Macs */
}
memcpy(&vid, ibuf, sizeof(vid));
ibuf += sizeof(vid);
- if (( vol = getvolbyvid( vid )) == NULL ) {
+ if (NULL == ( vol = getvolbyvid( vid )) ) {
return( AFPERR_PARAM);
}
ibuf += sizeof(id);
fileid = id;
- if ((upath = cnid_resolve(vol->v_db, &id, buffer, len)) == NULL) {
+ if (NULL == (upath = cnid_resolve(vol->v_db, &id, buffer, len)) ) {
return AFPERR_NOID;
}
struct adouble *addp;
struct ofork *s_of;
struct ofork *d_of;
+ int crossdev;
#ifdef CNID_DB
int slen, dlen;
memcpy(&vid, ibuf, sizeof(vid));
ibuf += sizeof(vid);
- if (( vol = getvolbyvid( vid )) == NULL ) {
+ if (NULL == ( vol = getvolbyvid( vid )) ) {
return( AFPERR_PARAM);
}
ibuf += sizeof(did);
/* source file */
- if ((dir = dirlookup( vol, sid )) == NULL ) {
+ if (NULL == (dir = dirlookup( vol, sid )) ) {
return( AFPERR_PARAM );
}
- if (( path = cname( vol, dir, &ibuf )) == NULL ) {
- return( AFPERR_PARAM );
+ if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
+ return afp_errno; /* was AFPERR_PARAM */
}
- if ( *path->m_name == '\0' ) {
+ if ( path_isadir(path) ) {
return( AFPERR_BADTYPE ); /* it's a dir */
}
strcpy(spath, path->m_name);
strcpy(supath, upath); /* this is for the cnid changing */
p = absupath( vol, sdir, upath);
+ if (!p) {
+ /* pathname too long */
+ return AFPERR_PARAM ;
+ }
/* look for the source cnid. if it doesn't exist, don't worry about
* it. */
slen = strlen(supath));
#endif /* CNID_DB */
- if (( dir = dirlookup( vol, did )) == NULL ) {
+ if (NULL == ( dir = dirlookup( vol, did )) ) {
return( AFPERR_PARAM );
}
- if (( path = cname( vol, dir, &ibuf )) == NULL ) {
+ if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
return( AFPERR_PARAM );
}
- if ( *path->m_name == '\0' ) {
+ if ( path_isadir(path) ) {
return( AFPERR_BADTYPE );
}
* error */
if ((curdir == sdir) && strcmp(spath, path->m_name) == 0)
return AFPERR_SAMEOBJ;
- memcpy(&srcst, &path->st, sizeof(struct stat));
- switch (errno) {
+ switch (path->st_errno) {
case 0:
break;
case ENOENT:
/* they are not on the same device and at least one is open
*/
- if ((d_of || s_of) && srcst.st_dev != destst.st_dev)
+ crossdev = (srcst.st_dev != destst.st_dev);
+ if ((d_of || s_of) && crossdev)
return AFPERR_MISC;
upath = path->u_name;
of_rename(vol, s_of, curdir, temp, curdir, path->m_name);
#ifdef CNID_DB
- /* id's need switching. src -> dest and dest -> src. */
- if (sid && (cnid_update(vol->v_db, sid, &destst, curdir->d_did,
- upath, dlen) < 0)) {
- switch (errno) {
- case EPERM:
- case EACCES:
- err = AFPERR_ACCESS;
- break;
- default:
- err = AFPERR_PARAM;
- }
- goto err_temp_to_dest;
+ /* id's need switching. src -> dest and dest -> src.
+ * we need to re-stat() if it was a cross device copy.
+ */
+ if (sid) {
+ cnid_delete(vol->v_db, sid);
}
-
- if (did && (cnid_update(vol->v_db, did, &srcst, sdir->d_did,
- supath, slen) < 0)) {
+ if (did) {
+ cnid_delete(vol->v_db, did);
+ }
+ if ((did && ( (crossdev && stat( upath, &srcst) < 0) ||
+ cnid_update(vol->v_db, did, &srcst, curdir->d_did,upath, dlen) < 0))
+ ||
+ (sid && ( (crossdev && stat(p, &destst) < 0) ||
+ cnid_update(vol->v_db, sid, &destst, sdir->d_did,supath, slen) < 0))
+ ) {
switch (errno) {
case EPERM:
case EACCES:
default:
err = AFPERR_PARAM;
}
-
- if (sid)
- cnid_update(vol->v_db, sid, &srcst, sdir->d_did, supath, slen);
goto err_temp_to_dest;
}
#endif /* CNID_DB */