2 * $Id: file.c,v 1.92.2.2.2.14 2004-02-20 21:22:58 didg Exp $
4 * Copyright (c) 1990,1993 Regents of The University of Michigan.
5 * All Rights Reserved. See COPYRIGHT.
10 #endif /* HAVE_CONFIG_H */
18 #else /* STDC_HEADERS */
22 #endif /* HAVE_STRCHR */
23 char *strchr (), *strrchr ();
26 #define memcpy(d,s,n) bcopy ((s), (d), (n))
27 #define memmove(d,s,n) bcopy ((s), (d), (n))
28 #endif /* ! HAVE_MEMCPY */
29 #endif /* STDC_HEADERS */
35 #include <atalk/logger.h>
36 #include <sys/param.h>
38 #include <atalk/adouble.h>
40 #include <atalk/afp.h>
41 #include <atalk/util.h>
42 #include <atalk/cnid.h>
43 #include "directory.h"
52 /* the format for the finderinfo fields (from IM: Toolbox Essentials):
53 * field bytes subfield bytes
56 * ioFlFndrInfo 16 -> type 4 type field
57 * creator 4 creator field
58 * flags 2 finder flags:
60 * location 4 location in window
61 * folder 2 window that contains file
63 * ioFlXFndrInfo 16 -> iconID 2 icon id
65 * script 1 script system
67 * commentID 2 comment id
68 * putawayID 4 home directory id
71 const u_char ufinderi[] = {
72 'T', 'E', 'X', 'T', 'U', 'N', 'I', 'X',
73 0, 0, 0, 0, 0, 0, 0, 0,
74 0, 0, 0, 0, 0, 0, 0, 0,
75 0, 0, 0, 0, 0, 0, 0, 0
78 /* FIXME mpath : unix or mac name ? (for now it's mac name ) */
79 void *get_finderinfo(const char *mpath, struct adouble *adp, void *data)
84 if (adp && (ad_finder = ad_entry(adp, ADEID_FINDERI))) {
85 memcpy(data, ad_finder, 32);
88 memcpy(data, ufinderi, 32);
91 if ((!adp || !memcmp(ad_entry(adp, ADEID_FINDERI),ufinderi , 8 ))
92 && (em = getextmap( mpath ))
94 memcpy(data, em->em_type, sizeof( em->em_type ));
95 memcpy((char *)data + 4, em->em_creator, sizeof(em->em_creator));
100 /* ---------------------
102 char *set_name(const struct vol *vol, char *data, cnid_t pid, char *name, cnid_t id, u_int32_t utf8)
107 aint = strlen( name );
111 if (utf8_encoding()) {
112 /* but name is an utf8 mac name */
115 /* global static variable... */
117 if (!(u = mtoupath(vol, name, pid, 1)) || !(m = utompath(vol, u, id, 0))) {
126 if (aint > MACFILELEN)
133 if (aint > 255) /* FIXME safeguard, anyway if no ascii char it's game over*/
136 utf8 = vol->v_mac?htonl(vol->v_mac->kTextEncoding):0; /* htonl(utf8) */
137 memcpy(data, &utf8, sizeof(utf8));
138 data += sizeof(utf8);
141 memcpy(data, &temp, sizeof(temp));
142 data += sizeof(temp);
145 memcpy( data, src, aint );
155 * FIXME: PDINFO is UTF8 and doesn't need adp
157 #define PARAM_NEED_ADP(b) ((b) & ((1 << FILPBIT_ATTR) |\
158 (1 << FILPBIT_CDATE) |\
159 (1 << FILPBIT_MDATE) |\
160 (1 << FILPBIT_BDATE) |\
161 (1 << FILPBIT_FINFO) |\
162 (1 << FILPBIT_RFLEN) |\
163 (1 << FILPBIT_EXTRFLEN) |\
164 (1 << FILPBIT_PDINFO)))
166 /* -------------------------- */
167 u_int32_t get_id(struct vol *vol, struct adouble *adp, const struct stat *st,
168 const cnid_t did, const char *upath, const int len)
172 #if AD_VERSION > AD_VERSION1
176 char stamp[ADEDLEN_PRIVSYN];
177 /* look in AD v2 header
178 * note inode and device are opaques and not in network order
180 if (adp && sizeof(dev_t) == ad_getentrylen(adp, ADEID_PRIVDEV)) {
181 memcpy(&dev, ad_entry(adp, ADEID_PRIVDEV), sizeof(dev_t));
182 if ( sizeof(ino_t) == ad_getentrylen(adp,ADEID_PRIVINO)) {
183 memcpy(&ino, ad_entry(adp, ADEID_PRIVINO), sizeof(ino_t));
184 if (sizeof(stamp) == ad_getentrylen(adp,ADEID_PRIVSYN)) {
185 memcpy(stamp, ad_entry(adp, ADEID_PRIVSYN), sizeof(stamp));
186 if (sizeof(cnid_t) == ad_getentrylen(adp, ADEID_DID)) {
187 memcpy(&a_did, ad_entry(adp, ADEID_DID), sizeof(cnid_t));
189 if ( ((vol->v_flags & AFPVOL_NODEV) || dev == st->st_dev)
190 && ino == st->st_ino && a_did == did &&
191 !memcmp(vol->v_stamp, stamp, sizeof(stamp)) &&
192 (sizeof(cnid_t) == ad_getentrylen(adp, ADEID_PRIVID)) )
194 memcpy(&aint, ad_entry(adp, ADEID_PRIVID), sizeof(aint));
202 if (vol->v_cdb != NULL) {
203 aint = cnid_add(vol->v_cdb, st, did, upath, len, aint);
204 /* Throw errors if cnid_add fails. */
205 if (aint == CNID_INVALID) {
207 case CNID_ERR_CLOSE: /* the db is closed */
210 LOG(log_error, logtype_afpd, "get_id: Incorrect parameters passed to cnid_add");
211 afp_errno = AFPERR_PARAM;
214 afp_errno = AFPERR_PARAM;
217 afp_errno = AFPERR_MISC;
221 #if AD_VERSION > AD_VERSION1
222 else if (adp && sizeof(dev_t) == ADEDLEN_PRIVDEV && sizeof(ino_t) == ADEDLEN_PRIVINO) {
223 /* update the ressource fork
224 * for a folder adp is always null
226 ad_setid(adp,(vol->v_flags & AFPVOL_NODEV)?0:st->st_dev, st->st_ino, aint, did, vol->v_stamp);
227 ad_flush(adp, ADFLAGS_HF);
234 /* -------------------------- */
235 int getmetadata(struct vol *vol,
237 struct path *path, struct dir *dir,
238 char *buf, int *buflen, struct adouble *adp, int attrbits )
240 char *data, *l_nameoff = NULL, *upath;
241 char *utf_nameoff = NULL;
246 u_char achar, fdType[4];
252 LOG(log_info, logtype_afpd, "begin getmetadata:");
255 upath = path->u_name;
260 if ( ((bitmap & ( (1 << FILPBIT_FINFO)|(1 << FILPBIT_LNAME)|(1 <<FILPBIT_PDINFO) ) ) && !path->m_name)
261 || (bitmap & ( (1 << FILPBIT_LNAME) ) && utf8_encoding()) /* FIXME should be m_name utf8 filename */
262 || (bitmap & (1 << FILPBIT_FNUM))) {
264 id = get_id(vol, adp, st, dir->d_did, upath, strlen(upath));
268 path->m_name = utompath(vol, upath, id, utf8_encoding());
271 while ( bitmap != 0 ) {
272 while (( bitmap & 1 ) == 0 ) {
280 ad_getattr(adp, &ashort);
281 } else if (*upath == '.') {
282 ashort = htons(ATTRBIT_INVISIBLE);
286 /* FIXME do we want a visual clue if the file is read only
289 accessmode( ".", &ma, dir , NULL);
290 if ((ma.ma_user & AR_UWRITE)) {
291 accessmode( upath, &ma, dir , st);
292 if (!(ma.ma_user & AR_UWRITE)) {
293 attrbits |= ATTRBIT_NOWRITE;
298 ashort = htons(ntohs(ashort) | attrbits);
299 memcpy(data, &ashort, sizeof( ashort ));
300 data += sizeof( ashort );
304 memcpy(data, &dir->d_did, sizeof( u_int32_t ));
305 data += sizeof( u_int32_t );
309 if (!adp || (ad_getdate(adp, AD_DATE_CREATE, &aint) < 0))
310 aint = AD_DATE_FROM_UNIX(st->st_mtime);
311 memcpy(data, &aint, sizeof( aint ));
312 data += sizeof( aint );
316 if ( adp && (ad_getdate(adp, AD_DATE_MODIFY, &aint) == 0)) {
317 if ((st->st_mtime > AD_DATE_TO_UNIX(aint))) {
318 aint = AD_DATE_FROM_UNIX(st->st_mtime);
321 aint = AD_DATE_FROM_UNIX(st->st_mtime);
323 memcpy(data, &aint, sizeof( int ));
324 data += sizeof( int );
328 if (!adp || (ad_getdate(adp, AD_DATE_BACKUP, &aint) < 0))
329 aint = AD_DATE_START;
330 memcpy(data, &aint, sizeof( int ));
331 data += sizeof( int );
335 get_finderinfo(path->m_name, adp, (char *)data);
337 if (*upath == '.') { /* make it invisible */
338 ashort = htons(FINDERINFO_INVISIBLE);
339 memcpy(data + FINDERINFO_FRFLAGOFF, &ashort, sizeof(ashort));
347 data += sizeof( u_int16_t );
351 memset(data, 0, sizeof(u_int16_t));
352 data += sizeof( u_int16_t );
356 memcpy(data, &id, sizeof( id ));
357 data += sizeof( id );
361 if (st->st_size > 0xffffffff)
364 aint = htonl( st->st_size );
365 memcpy(data, &aint, sizeof( aint ));
366 data += sizeof( aint );
371 if (adp->ad_rlen > 0xffffffff)
374 aint = htonl( adp->ad_rlen);
378 memcpy(data, &aint, sizeof( aint ));
379 data += sizeof( aint );
382 /* Current client needs ProDOS info block for this file.
383 Use simple heuristic and let the Mac "type" string tell
384 us what the PD file code should be. Everything gets a
385 subtype of 0x0000 unless the original value was hashed
386 to "pXYZ" when we created it. See IA, Ver 2.
387 <shirsch@adelphia.net> */
388 case FILPBIT_PDINFO :
389 if (afp_version >= 30) { /* UTF8 name */
390 utf8 = kTextEncodingUTF8;
392 data += sizeof( u_int16_t );
394 memcpy(data, &aint, sizeof( aint ));
395 data += sizeof( aint );
399 memcpy(fdType, ad_entry( adp, ADEID_FINDERI ), 4 );
401 if ( memcmp( fdType, "TEXT", 4 ) == 0 ) {
405 else if ( memcmp( fdType, "PSYS", 4 ) == 0 ) {
409 else if ( memcmp( fdType, "PS16", 4 ) == 0 ) {
413 else if ( memcmp( fdType, "BINA", 4 ) == 0 ) {
417 else if ( fdType[0] == 'p' ) {
419 ashort = (fdType[2] * 256) + fdType[3];
433 memcpy(data, &ashort, sizeof( ashort ));
434 data += sizeof( ashort );
435 memset(data, 0, sizeof( ashort ));
436 data += sizeof( ashort );
439 case FILPBIT_EXTDFLEN:
440 aint = htonl(st->st_size >> 32);
441 memcpy(data, &aint, sizeof( aint ));
442 data += sizeof( aint );
443 aint = htonl(st->st_size);
444 memcpy(data, &aint, sizeof( aint ));
445 data += sizeof( aint );
447 case FILPBIT_EXTRFLEN:
450 aint = htonl(adp->ad_rlen >> 32);
451 memcpy(data, &aint, sizeof( aint ));
452 data += sizeof( aint );
454 aint = htonl(adp->ad_rlen);
455 memcpy(data, &aint, sizeof( aint ));
456 data += sizeof( aint );
458 case FILPBIT_UNIXPR :
459 aint = htonl(st->st_uid);
460 memcpy( data, &aint, sizeof( aint ));
461 data += sizeof( aint );
462 aint = htonl(st->st_gid);
463 memcpy( data, &aint, sizeof( aint ));
464 data += sizeof( aint );
466 aint = htonl(st->st_mode);
467 memcpy( data, &aint, sizeof( aint ));
468 data += sizeof( aint );
470 accessmode( upath, &ma, dir , st);
472 *data++ = ma.ma_user;
473 *data++ = ma.ma_world;
474 *data++ = ma.ma_group;
475 *data++ = ma.ma_owner;
479 return( AFPERR_BITMAP );
485 ashort = htons( data - buf );
486 memcpy(l_nameoff, &ashort, sizeof( ashort ));
487 data = set_name(vol, data, dir->d_did, path->m_name, id, 0);
490 ashort = htons( data - buf );
491 memcpy(utf_nameoff, &ashort, sizeof( ashort ));
492 data = set_name(vol, data, dir->d_did, path->m_name, id, utf8);
494 *buflen = data - buf;
498 /* ----------------------- */
499 int getfilparams(struct vol *vol,
501 struct path *path, struct dir *dir,
502 char *buf, int *buflen )
504 struct adouble ad, *adp;
507 u_int16_t attrbits = 0;
512 LOG(log_info, logtype_default, "begin getfilparams:");
515 opened = PARAM_NEED_ADP(bitmap);
518 upath = path->u_name;
519 if ((of = of_findname(path))) {
521 attrbits = ((of->of_ad->ad_df.adf_refcount > 0) ? ATTRBIT_DOPEN : 0);
522 attrbits |= ((of->of_ad->ad_hf.adf_refcount > of->of_ad->ad_df.adf_refcount)? ATTRBIT_ROPEN : 0);
524 ad_init(&ad, vol->v_adouble);
528 if ( ad_open( upath, ADFLAGS_HF, O_RDONLY, 0, adp) < 0 ) {
533 we need to check if the file is open by another process.
534 it's slow so we only do it if we have to:
535 - bitmap is requested.
536 - we don't already have the answer!
538 if ((bitmap & (1 << FILPBIT_ATTR))) {
539 if (!(attrbits & ATTRBIT_ROPEN)) {
541 if (!(attrbits & ATTRBIT_DOPEN)) {
546 rc = getmetadata(vol, bitmap, path, dir, buf, buflen, adp, attrbits);
548 ad_close( adp, ADFLAGS_HF );
551 LOG(log_info, logtype_afpd, "end getfilparams:");
557 /* ----------------------------- */
558 int afp_createfile(obj, ibuf, ibuflen, rbuf, rbuflen )
561 int ibuflen, *rbuflen;
563 struct adouble ad, *adp;
566 struct ofork *of = NULL;
568 int creatf, did, openf, retvalue = AFP_OK;
574 LOG(log_info, logtype_afpd, "begin afp_createfile:");
579 creatf = (unsigned char) *ibuf++;
581 memcpy(&vid, ibuf, sizeof( vid ));
582 ibuf += sizeof( vid );
584 if (NULL == ( vol = getvolbyvid( vid )) ) {
585 return( AFPERR_PARAM );
588 if (vol->v_flags & AFPVOL_RO)
591 memcpy(&did, ibuf, sizeof( did));
592 ibuf += sizeof( did );
594 if (NULL == ( dir = dirlookup( vol, did )) ) {
598 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
599 return get_afp_errno(AFPERR_PARAM);
602 if ( *s_path->m_name == '\0' ) {
603 return( AFPERR_BADTYPE );
606 upath = s_path->u_name;
607 if (0 != (ret = check_name(vol, upath)))
610 /* if upath is deleted we already in trouble anyway */
611 if ((of = of_findname(s_path))) {
614 ad_init(&ad, vol->v_adouble);
618 /* on a hard create, fail if file exists and is open */
621 openf = O_RDWR|O_CREAT|O_TRUNC;
623 /* on a soft create, if the file is open then ad_open won't fail
624 because open syscall is not called
629 openf = O_RDWR|O_CREAT|O_EXCL;
632 if ( ad_open( upath, vol_noadouble(vol)|ADFLAGS_DF|ADFLAGS_HF|ADFLAGS_NOHF,
633 openf, 0666, adp) < 0 ) {
637 case ENOENT : /* we were already in 'did folder' so chdir() didn't fail */
638 return ( AFPERR_NOOBJ );
640 return( AFPERR_EXIST );
642 return( AFPERR_ACCESS );
644 return( AFPERR_PARAM );
647 if ( ad_hfileno( adp ) == -1 ) {
648 /* on noadouble volumes, just creating the data fork is ok */
649 if (vol_noadouble(vol)) {
650 ad_close( adp, ADFLAGS_DF );
651 goto createfile_done;
653 /* FIXME with hard create on an existing file, we already
654 * corrupted the data file.
656 netatalk_unlink( upath );
657 ad_close( adp, ADFLAGS_DF );
658 return AFPERR_ACCESS;
661 path = s_path->m_name;
662 ad_setentrylen( adp, ADEID_NAME, strlen( path ));
663 memcpy(ad_entry( adp, ADEID_NAME ), path,
664 ad_getentrylen( adp, ADEID_NAME ));
665 ad_flush( adp, ADFLAGS_DF|ADFLAGS_HF );
666 ad_close( adp, ADFLAGS_DF|ADFLAGS_HF );
672 if (vol->v_flags & AFPVOL_DROPBOX) {
673 retvalue = matchfile2dirperms(upath, vol, did);
675 #endif /* DROPKLUDGE */
677 setvoltime(obj, vol );
680 LOG(log_info, logtype_afpd, "end afp_createfile");
686 int afp_setfilparams(obj, ibuf, ibuflen, rbuf, rbuflen )
689 int ibuflen, *rbuflen;
695 u_int16_t vid, bitmap;
698 LOG(log_info, logtype_afpd, "begin afp_setfilparams:");
704 memcpy(&vid, ibuf, sizeof( vid ));
705 ibuf += sizeof( vid );
706 if (NULL == ( vol = getvolbyvid( vid )) ) {
707 return( AFPERR_PARAM );
710 if (vol->v_flags & AFPVOL_RO)
713 memcpy(&did, ibuf, sizeof( did ));
714 ibuf += sizeof( did );
715 if (NULL == ( dir = dirlookup( vol, did )) ) {
716 return afp_errno; /* was AFPERR_NOOBJ */
719 memcpy(&bitmap, ibuf, sizeof( bitmap ));
720 bitmap = ntohs( bitmap );
721 ibuf += sizeof( bitmap );
723 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
724 return get_afp_errno(AFPERR_PARAM);
727 if (path_isadir(s_path)) {
728 return( AFPERR_BADTYPE ); /* it's a directory */
731 if ( s_path->st_errno != 0 ) {
732 return( AFPERR_NOOBJ );
735 if ((u_long)ibuf & 1 ) {
739 if (AFP_OK == ( rc = setfilparams(vol, s_path, bitmap, ibuf )) ) {
740 setvoltime(obj, vol );
744 LOG(log_info, logtype_afpd, "end afp_setfilparams:");
751 * cf AFP3.0.pdf page 252 for change_mdate and change_parent_mdate logic
754 extern struct path Cur_Path;
756 int setfilparams(struct vol *vol,
757 struct path *path, u_int16_t bitmap, char *buf )
759 struct adouble ad, *adp;
762 int bit = 0, isad = 1, err = AFP_OK;
764 u_char achar, *fdType, xyy[4];
765 u_int16_t ashort, bshort;
769 int change_mdate = 0;
770 int change_parent_mdate = 0;
776 LOG(log_info, logtype_afpd, "begin setfilparams:");
779 upath = path->u_name;
780 if ((of = of_findname(path))) {
783 ad_init(&ad, vol->v_adouble);
787 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
788 return AFPERR_ACCESS;
791 if (ad_open( upath, vol_noadouble(vol) | ADFLAGS_HF,
792 O_RDWR|O_CREAT, 0666, adp) < 0) {
793 /* for some things, we don't need an adouble header */
794 if (bitmap & ~(1<<FILPBIT_MDATE)) {
795 return vol_noadouble(vol) ? AFP_OK : AFPERR_ACCESS;
798 } else if ((ad_get_HF_flags( adp ) & O_CREAT) ) {
799 ad_setentrylen( adp, ADEID_NAME, strlen( path->m_name ));
800 memcpy(ad_entry( adp, ADEID_NAME ), path->m_name,
801 ad_getentrylen( adp, ADEID_NAME ));
804 while ( bitmap != 0 ) {
805 while (( bitmap & 1 ) == 0 ) {
813 memcpy(&ashort, buf, sizeof( ashort ));
814 ad_getattr(adp, &bshort);
815 if ( ntohs( ashort ) & ATTRBIT_SETCLR ) {
816 bshort |= htons( ntohs( ashort ) & ~ATTRBIT_SETCLR );
820 if ((ashort & htons(ATTRBIT_INVISIBLE)))
821 change_parent_mdate = 1;
822 ad_setattr(adp, bshort);
823 buf += sizeof( ashort );
828 memcpy(&aint, buf, sizeof(aint));
829 ad_setdate(adp, AD_DATE_CREATE, aint);
830 buf += sizeof( aint );
834 memcpy(&newdate, buf, sizeof( newdate ));
835 buf += sizeof( newdate );
840 memcpy(&aint, buf, sizeof(aint));
841 ad_setdate(adp, AD_DATE_BACKUP, aint);
842 buf += sizeof( aint );
848 if (!memcmp( ad_entry( adp, ADEID_FINDERI ), ufinderi, 8 )
850 ((em = getextmap( path->m_name )) &&
851 !memcmp(buf, em->em_type, sizeof( em->em_type )) &&
852 !memcmp(buf + 4, em->em_creator,sizeof( em->em_creator)))
853 || ((em = getdefextmap()) &&
854 !memcmp(buf, em->em_type, sizeof( em->em_type )) &&
855 !memcmp(buf + 4, em->em_creator,sizeof( em->em_creator)))
857 memcpy(buf, ufinderi, 8 );
860 memcpy(ad_entry( adp, ADEID_FINDERI ), buf, 32 );
864 case FILPBIT_UNIXPR :
865 /* Skip the UIG/GID, no way to set them from OSX clients */
866 buf += sizeof( aint );
867 buf += sizeof( aint );
870 change_parent_mdate = 1;
871 memcpy( &aint, buf, sizeof( aint ));
872 buf += sizeof( aint );
875 setfilemode(path, aint);
877 /* Client needs to set the ProDOS file info for this file.
878 Use a defined string for TEXT to support crlf
879 translations and convert all else into pXYY per Inside
880 Appletalk. Always set the creator as "pdos". Changes
881 from original by Marsha Jackson. */
882 case FILPBIT_PDINFO :
883 if (afp_version < 30) { /* else it's UTF8 name */
886 /* Keep special case to support crlf translations */
887 if ((unsigned int) achar == 0x04) {
888 fdType = (u_char *)"TEXT";
891 xyy[0] = ( u_char ) 'p';
897 memcpy(ad_entry( adp, ADEID_FINDERI ), fdType, 4 );
898 memcpy(ad_entry( adp, ADEID_FINDERI ) + 4, "pdos", 4 );
904 goto setfilparam_done;
912 if (change_mdate && newdate == 0 && gettimeofday(&tv, NULL) == 0) {
913 newdate = AD_DATE_FROM_UNIX(tv.tv_sec);
917 ad_setdate(adp, AD_DATE_MODIFY, newdate);
918 ut.actime = ut.modtime = AD_DATE_TO_UNIX(newdate);
923 ad_flush( adp, ADFLAGS_HF );
924 ad_close( adp, ADFLAGS_HF );
928 if (change_parent_mdate && gettimeofday(&tv, NULL) == 0) {
929 newdate = AD_DATE_FROM_UNIX(tv.tv_sec);
930 bitmap = 1<<FILPBIT_MDATE;
931 setdirparams(vol, &Cur_Path, bitmap, (char *)&newdate);
935 LOG(log_info, logtype_afpd, "end setfilparams:");
941 * renamefile and copyfile take the old and new unix pathnames
942 * and the new mac name.
944 * src the source path
945 * dst the dest filename in current dir
946 * newname the dest mac name
947 * adp adouble struct of src file, if open, or & zeroed one
950 int renamefile(src, dst, newname, noadouble, adp )
951 char *src, *dst, *newname;
955 char adsrc[ MAXPATHLEN + 1];
960 LOG(log_info, logtype_afpd, "begin renamefile:");
963 if ( unix_rename( src, dst ) < 0 ) {
966 return( AFPERR_NOOBJ );
969 return( AFPERR_ACCESS );
972 case EXDEV : /* Cross device move -- try copy */
973 /* NOTE: with open file it's an error because after the copy we will
974 * get two files, it's fixable for our process (eg reopen the new file, get the
975 * locks, and so on. But it doesn't solve the case with a second process
977 if (adp->ad_df.adf_refcount || adp->ad_hf.adf_refcount) {
978 /* FIXME warning in syslog so admin'd know there's a conflict ?*/
979 return AFPERR_OLOCK; /* little lie */
981 if (AFP_OK != ( rc = copyfile(src, dst, newname, noadouble )) ) {
982 /* on error copyfile delete dest */
985 return deletefile(NULL, src, 0);
987 return( AFPERR_PARAM );
991 strcpy( adsrc, ad_path( src, 0 ));
993 if (unix_rename( adsrc, ad_path( dst, 0 )) < 0 ) {
998 if (errno == ENOENT) {
1001 if (stat(adsrc, &st)) /* source has no ressource fork, */
1004 /* We are here because :
1005 * -there's no dest folder.
1006 * -there's no .AppleDouble in the dest folder.
1007 * if we use the struct adouble passed in parameter it will not
1008 * create .AppleDouble if the file is already opened, so we
1009 * use a diff one, it's not a pb,ie it's not the same file, yet.
1011 ad_init(&ad, AD_VERSION); /* FIXME */
1012 if (!ad_open(dst, ADFLAGS_HF, O_RDWR | O_CREAT, 0666, &ad)) {
1013 ad_close(&ad, ADFLAGS_HF);
1014 if (!unix_rename( adsrc, ad_path( dst, 0 )) )
1019 else { /* it's something else, bail out */
1023 /* try to undo the data fork rename,
1024 * we know we are on the same device
1027 unix_rename( dst, src );
1028 /* return the first error */
1031 return AFPERR_NOOBJ;
1034 return AFPERR_ACCESS ;
1036 return AFPERR_VLOCK;
1038 return AFPERR_PARAM ;
1043 /* don't care if we can't open the newly renamed ressource fork
1045 if ( !ad_open( dst, ADFLAGS_HF, O_RDWR, 0666, adp)) {
1046 len = strlen( newname );
1047 ad_setentrylen( adp, ADEID_NAME, len );
1048 memcpy(ad_entry( adp, ADEID_NAME ), newname, len );
1049 ad_flush( adp, ADFLAGS_HF );
1050 ad_close( adp, ADFLAGS_HF );
1053 LOG(log_info, logtype_afpd, "end renamefile:");
1059 int copy_path_name(char *newname, char *ibuf)
1066 if ( type != 2 && !(afp_version >= 30 && type == 3) ) {
1072 if (( plen = (unsigned char)*ibuf++ ) != 0 ) {
1073 strncpy( newname, ibuf, plen );
1074 newname[ plen ] = '\0';
1075 if (strlen(newname) != plen) {
1076 /* there's \0 in newname, e.g. it's a pathname not
1084 memcpy(&hint, ibuf, sizeof(hint));
1085 ibuf += sizeof(hint);
1087 memcpy(&len16, ibuf, sizeof(len16));
1088 ibuf += sizeof(len16);
1089 plen = ntohs(len16);
1092 if (plen > AFPOBJ_TMPSIZ) {
1095 strncpy( newname, ibuf, plen );
1096 newname[ plen ] = '\0';
1097 if (strlen(newname) != plen) {
1106 /* -----------------------------------
1108 int afp_copyfile(obj, ibuf, ibuflen, rbuf, rbuflen )
1111 int ibuflen, *rbuflen;
1115 char *newname, *p, *upath;
1116 struct path *s_path;
1117 u_int32_t sdid, ddid;
1118 int err, retvalue = AFP_OK;
1119 u_int16_t svid, dvid;
1122 LOG(log_info, logtype_afpd, "begin afp_copyfile:");
1128 memcpy(&svid, ibuf, sizeof( svid ));
1129 ibuf += sizeof( svid );
1130 if (NULL == ( vol = getvolbyvid( svid )) ) {
1131 return( AFPERR_PARAM );
1134 memcpy(&sdid, ibuf, sizeof( sdid ));
1135 ibuf += sizeof( sdid );
1136 if (NULL == ( dir = dirlookup( vol, sdid )) ) {
1140 memcpy(&dvid, ibuf, sizeof( dvid ));
1141 ibuf += sizeof( dvid );
1142 memcpy(&ddid, ibuf, sizeof( ddid ));
1143 ibuf += sizeof( ddid );
1145 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
1146 return get_afp_errno(AFPERR_PARAM);
1148 if ( path_isadir(s_path) ) {
1149 return( AFPERR_BADTYPE );
1152 /* don't allow copies when the file is open.
1153 * XXX: the spec only calls for read/deny write access.
1154 * however, copyfile doesn't have any of that info,
1155 * and locks need to stay coherent. as a result,
1156 * we just balk if the file is opened already. */
1158 newname = obj->newtmp;
1159 strcpy( newname, s_path->m_name );
1161 if (of_findname(s_path))
1162 return AFPERR_DENYCONF;
1164 p = ctoupath( vol, curdir, newname );
1166 return AFPERR_PARAM;
1170 /* FIXME svid != dvid && dvid's user can't read svid */
1172 if (NULL == ( vol = getvolbyvid( dvid )) ) {
1173 return( AFPERR_PARAM );
1176 if (vol->v_flags & AFPVOL_RO)
1177 return AFPERR_VLOCK;
1179 if (NULL == ( dir = dirlookup( vol, ddid )) ) {
1183 if (( s_path = cname( vol, dir, &ibuf )) == NULL ) {
1184 return get_afp_errno(AFPERR_NOOBJ);
1186 if ( *s_path->m_name != '\0' ) {
1188 return (path_isadir( s_path))? AFPERR_PARAM:AFPERR_BADTYPE ;
1190 path_error(s_path, AFPERR_PARAM);
1193 /* one of the handful of places that knows about the path type */
1194 if (copy_path_name(newname, ibuf) < 0) {
1195 return( AFPERR_PARAM );
1197 /* newname is always only a filename so curdir *is* its
1200 if (NULL == (upath = mtoupath(vol, newname, curdir->d_did, utf8_encoding()))) {
1201 return( AFPERR_PARAM );
1203 if ( (err = copyfile(p, upath , newname, vol_noadouble(vol))) < 0 ) {
1209 if (vol->v_flags & AFPVOL_DROPBOX) {
1210 retvalue=matchfile2dirperms(upath, vol, ddid); /* FIXME sdir or ddid */
1212 #endif /* DROPKLUDGE */
1214 setvoltime(obj, vol );
1217 LOG(log_info, logtype_afpd, "end afp_copyfile:");
1224 static __inline__ int copy_all(const int dfd, const void *buf,
1230 LOG(log_info, logtype_afpd, "begin copy_all:");
1233 while (buflen > 0) {
1234 if ((cc = write(dfd, buf, buflen)) < 0) {
1241 return AFPERR_DFULL;
1243 return AFPERR_VLOCK;
1245 return AFPERR_PARAM;
1252 LOG(log_info, logtype_afpd, "end copy_all:");
1258 /* -------------------------- */
1259 static int copy_fd(int dfd, int sfd)
1265 #ifdef SENDFILE_FLAVOR_LINUX
1269 #define BUF 128*1024*1024
1271 if (fstat(sfd, &st) == 0) {
1274 if ( offset >= st.st_size) {
1277 size = (st.st_size -offset > BUF)?BUF:st.st_size -offset;
1278 if ((cc = sys_sendfile(dfd, sfd, &offset, size)) < 0) {
1281 case EINVAL: /* there's no guarantee that all fs support sendfile */
1286 return AFPERR_DFULL;
1288 return AFPERR_VLOCK;
1290 return AFPERR_PARAM;
1296 lseek(sfd, offset, SEEK_SET);
1300 if ((cc = read(sfd, filebuf, sizeof(filebuf))) < 0) {
1307 if (!cc || ((err = copy_all(dfd, filebuf, cc)) < 0))
1313 /* ----------------------------------
1314 * if newname is NULL (from directory.c) we don't want to copy ressource fork.
1315 * because we are doing it elsewhere.
1317 int copyfile(src, dst, newname, noadouble )
1318 char *src, *dst, *newname;
1319 const int noadouble;
1321 struct adouble ads, add;
1322 int len, err = AFP_OK;
1327 LOG(log_info, logtype_afpd, "begin copyfile:");
1330 ad_init(&ads, 0); /* OK */
1331 ad_init(&add, 0); /* FIXME */
1332 adflags = ADFLAGS_DF;
1334 adflags |= ADFLAGS_HF;
1337 if (ad_open(src , adflags | ADFLAGS_NOHF, O_RDONLY, 0, &ads) < 0) {
1340 return( AFPERR_NOOBJ );
1342 return( AFPERR_ACCESS );
1344 return( AFPERR_PARAM );
1347 if (ad_open(dst , adflags | noadouble, O_RDWR|O_CREAT|O_EXCL, 0666, &add) < 0) {
1348 ad_close( &ads, adflags );
1349 if (EEXIST != (err = errno)) {
1350 deletefile(NULL, dst, 0);
1354 return AFPERR_EXIST;
1356 return( AFPERR_NOOBJ );
1358 return( AFPERR_ACCESS );
1360 return AFPERR_VLOCK;
1362 return( AFPERR_PARAM );
1365 if (ad_hfileno(&ads) == -1 || AFP_OK == (err = copy_fd(ad_hfileno(&add), ad_hfileno(&ads)))){
1366 /* copy the data fork */
1367 err = copy_fd(ad_dfileno(&add), ad_dfileno(&ads));
1370 /* Now, reopen destination file */
1372 if (ad_close( &add, adflags ) <0) {
1373 deletefile(NULL, dst, 0);
1374 return AFPERR_PARAM; /* FIXME */
1377 if (ad_open(dst , adflags | noadouble, O_RDWR, 0666, &add) < 0) {
1378 ad_close( &ads, adflags );
1379 deletefile(NULL, dst, 0);
1382 return( AFPERR_NOOBJ );
1384 return( AFPERR_ACCESS );
1386 return AFPERR_VLOCK;
1388 return( AFPERR_PARAM );
1394 len = strlen( newname );
1395 ad_setentrylen( &add, ADEID_NAME, len );
1396 memcpy(ad_entry( &add, ADEID_NAME ), newname, len );
1399 ad_close( &ads, adflags );
1400 ad_flush( &add, adflags );
1401 if (ad_close( &add, adflags ) <0) {
1404 if (err != AFP_OK) {
1405 deletefile(NULL, dst, 0);
1408 return( AFPERR_NOOBJ );
1410 return( AFPERR_ACCESS );
1412 return( AFPERR_PARAM );
1416 /* set dest modification date to src date */
1417 if (!stat(src, &st)) {
1420 ut.actime = ut.modtime = st.st_mtime;
1425 LOG(log_info, logtype_afpd, "end copyfile:");
1432 /* -----------------------------------
1433 vol: not NULL delete cnid entry. then we are in curdir and file is a only filename
1434 checkAttrib: 1 check kFPDeleteInhibitBit (deletfile called by afp_delete)
1436 when deletefile is called we don't have lock on it, file is closed (for us)
1437 untrue if called by renamefile
1439 ad_open always try to open file RDWR first and ad_lock takes care of
1440 WRITE lock on read only file.
1442 int deletefile( vol, file, checkAttrib )
1448 int adflags, err = AFP_OK;
1451 LOG(log_info, logtype_afpd, "begin deletefile:");
1454 /* try to open both forks at once */
1455 adflags = ADFLAGS_DF|ADFLAGS_HF;
1457 ad_init(&ad, 0); /* OK */
1458 if ( ad_open( file, adflags, O_RDONLY, 0, &ad ) < 0 ) {
1461 if (adflags == ADFLAGS_DF)
1462 return AFPERR_NOOBJ;
1464 /* that failed. now try to open just the data fork */
1465 adflags = ADFLAGS_DF;
1469 return AFPERR_ACCESS;
1471 return AFPERR_VLOCK;
1473 return( AFPERR_PARAM );
1476 break; /* from the while */
1479 * Does kFPDeleteInhibitBit (bit 8) set?
1481 if (checkAttrib && (adflags & ADFLAGS_HF)) {
1484 ad_getattr(&ad, &bshort);
1485 if ((bshort & htons(ATTRBIT_NODELETE))) {
1486 ad_close( &ad, adflags );
1487 return(AFPERR_OLOCK);
1491 if ((adflags & ADFLAGS_HF) ) {
1492 /* FIXME we have a pb here because we want to know if a file is open
1493 * there's a 'priority inversion' if you can't open the ressource fork RW
1494 * you can delete it if it's open because you can't get a write lock.
1496 * ADLOCK_FILELOCK means the whole ressource fork, not only after the
1499 * FIXME it doesn't work for RFORK open read only and fork open without deny mode
1501 if (ad_tmplock(&ad, ADEID_RFORK, ADLOCK_WR |ADLOCK_FILELOCK, 0, 0, 0) < 0 ) {
1502 ad_close( &ad, adflags );
1503 return( AFPERR_BUSY );
1507 if (ad_tmplock( &ad, ADEID_DFORK, ADLOCK_WR, 0, 0, 0 ) < 0) {
1510 else if (!(err = netatalk_unlink( ad_path( file, ADFLAGS_HF)) ) &&
1511 !(err = netatalk_unlink( file )) ) {
1513 if (vol && (id = cnid_get(vol->v_cdb, curdir->d_did, file, strlen(file))))
1515 cnid_delete(vol->v_cdb, id);
1519 ad_close( &ad, adflags ); /* ad_close removes locks if any */
1522 LOG(log_info, logtype_afpd, "end deletefile:");
1528 /* ------------------------------------ */
1529 /* return a file id */
1530 int afp_createid(obj, ibuf, ibuflen, rbuf, rbuflen )
1533 int ibuflen, *rbuflen;
1542 struct path *s_path;
1545 LOG(log_info, logtype_afpd, "begin afp_createid:");
1552 memcpy(&vid, ibuf, sizeof(vid));
1553 ibuf += sizeof(vid);
1555 if (NULL == ( vol = getvolbyvid( vid )) ) {
1556 return( AFPERR_PARAM);
1559 if (vol->v_cdb == NULL || !(vol->v_cdb->flags & CNID_FLAG_PERSISTENT)) {
1563 if (vol->v_flags & AFPVOL_RO)
1564 return AFPERR_VLOCK;
1566 memcpy(&did, ibuf, sizeof( did ));
1567 ibuf += sizeof(did);
1569 if (NULL == ( dir = dirlookup( vol, did )) ) {
1570 return afp_errno; /* was AFPERR_PARAM */
1573 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
1574 return get_afp_errno(AFPERR_NOOBJ); /* was AFPERR_PARAM */
1577 if ( path_isadir(s_path) ) {
1578 return( AFPERR_BADTYPE );
1581 upath = s_path->u_name;
1582 switch (s_path->st_errno) {
1584 break; /* success */
1587 return AFPERR_ACCESS;
1589 return AFPERR_NOOBJ;
1591 return AFPERR_PARAM;
1594 if ((id = cnid_lookup(vol->v_cdb, st, did, upath, len = strlen(upath)))) {
1595 memcpy(rbuf, &id, sizeof(id));
1596 *rbuflen = sizeof(id);
1597 return AFPERR_EXISTID;
1600 if ((id = get_id(vol, NULL, st, did, upath, len)) != CNID_INVALID) {
1601 memcpy(rbuf, &id, sizeof(id));
1602 *rbuflen = sizeof(id);
1607 LOG(log_info, logtype_afpd, "ending afp_createid...:");
1613 reenumerate_id(const struct vol *vol, char *name, cnid_t did)
1623 if (vol->v_cdb == NULL) {
1626 if (NULL == ( dp = opendir( name)) ) {
1630 for ( de = readdir( dp ); de != NULL; de = readdir( dp )) {
1631 if (NULL == check_dirent(vol, de->d_name))
1634 if ( stat(de->d_name, &st)<0 )
1637 /* update or add to cnid */
1638 aint = cnid_add(vol->v_cdb, &st, did, de->d_name, strlen(de->d_name), 0); /* ignore errors */
1640 #if AD_VERSION > AD_VERSION1
1641 if (aint != CNID_INVALID && !S_ISDIR(st.st_mode)) {
1642 ad_init(&ad, 0); /* OK */
1643 if ( ad_open( de->d_name, ADFLAGS_HF, O_RDWR, 0, &ad ) < 0 ) {
1647 ad_setid(&ad,(vol->v_flags & AFPVOL_NODEV)?0:st.st_dev, st.st_ino, aint, did, vol->v_stamp);
1648 ad_flush(&ad, ADFLAGS_HF);
1649 ad_close(&ad, ADFLAGS_HF);
1652 #endif /* AD_VERSION > AD_VERSION1 */
1661 /* ------------------------------
1662 resolve a file id */
1663 int afp_resolveid(obj, ibuf, ibuflen, rbuf, rbuflen )
1666 int ibuflen, *rbuflen;
1672 int err, buflen, retry=0;
1674 u_int16_t vid, bitmap;
1676 static char buffer[12 + MAXPATHLEN + 1];
1677 int len = 12 + MAXPATHLEN + 1;
1680 LOG(log_info, logtype_afpd, "begin afp_resolveid:");
1686 memcpy(&vid, ibuf, sizeof(vid));
1687 ibuf += sizeof(vid);
1689 if (NULL == ( vol = getvolbyvid( vid )) ) {
1690 return( AFPERR_PARAM);
1693 if (vol->v_cdb == NULL || !(vol->v_cdb->flags & CNID_FLAG_PERSISTENT)) {
1697 memcpy(&id, ibuf, sizeof( id ));
1702 if (NULL == (upath = cnid_resolve(vol->v_cdb, &id, buffer, len)) ) {
1703 return AFPERR_NOID; /* was AFPERR_BADID, but help older Macs */
1706 if (NULL == ( dir = dirlookup( vol, id )) ) {
1707 return AFPERR_NOID; /* idem AFPERR_PARAM */
1709 path.u_name = upath;
1710 if (movecwd(vol, dir) < 0) {
1714 return AFPERR_ACCESS;
1718 return AFPERR_PARAM;
1722 if ( of_stat(&path) < 0 ) {
1723 if ( errno == ENOENT && !retry) {
1724 /* cnid db is out of sync, reenumerate the directory and updated ids */
1725 reenumerate_id(vol, ".", id);
1733 return AFPERR_ACCESS;
1737 return AFPERR_PARAM;
1741 /* directories are bad */
1742 if (S_ISDIR(path.st.st_mode))
1743 return AFPERR_BADTYPE;
1745 memcpy(&bitmap, ibuf, sizeof(bitmap));
1746 bitmap = ntohs( bitmap );
1747 if (NULL == (path.m_name = utompath(vol, upath, cnid, utf8_encoding()))) {
1750 if (AFP_OK != (err = getfilparams(vol, bitmap, &path , curdir,
1751 rbuf + sizeof(bitmap), &buflen))) {
1754 *rbuflen = buflen + sizeof(bitmap);
1755 memcpy(rbuf, ibuf, sizeof(bitmap));
1758 LOG(log_info, logtype_afpd, "end afp_resolveid:");
1764 /* ------------------------------ */
1765 int afp_deleteid(obj, ibuf, ibuflen, rbuf, rbuflen )
1768 int ibuflen, *rbuflen;
1778 static char buffer[12 + MAXPATHLEN + 1];
1779 int len = 12 + MAXPATHLEN + 1;
1782 LOG(log_info, logtype_afpd, "begin afp_deleteid:");
1788 memcpy(&vid, ibuf, sizeof(vid));
1789 ibuf += sizeof(vid);
1791 if (NULL == ( vol = getvolbyvid( vid )) ) {
1792 return( AFPERR_PARAM);
1795 if (vol->v_cdb == NULL || !(vol->v_cdb->flags & CNID_FLAG_PERSISTENT)) {
1799 if (vol->v_flags & AFPVOL_RO)
1800 return AFPERR_VLOCK;
1802 memcpy(&id, ibuf, sizeof( id ));
1806 if (NULL == (upath = cnid_resolve(vol->v_cdb, &id, buffer, len)) ) {
1810 if (NULL == ( dir = dirlookup( vol, id )) ) {
1811 return( AFPERR_PARAM );
1815 if ((movecwd(vol, dir) < 0) || (stat(upath, &st) < 0)) {
1819 return AFPERR_ACCESS;
1821 /* still try to delete the id */
1825 return AFPERR_PARAM;
1828 else if (S_ISDIR(st.st_mode)) /* directories are bad */
1829 return AFPERR_BADTYPE;
1831 if (cnid_delete(vol->v_cdb, fileid)) {
1834 return AFPERR_VLOCK;
1837 return AFPERR_ACCESS;
1839 return AFPERR_PARAM;
1844 LOG(log_info, logtype_afpd, "end afp_deleteid:");
1850 #define APPLETEMP ".AppleTempXXXXXX"
1852 int afp_exchangefiles(obj, ibuf, ibuflen, rbuf, rbuflen )
1855 int ibuflen, *rbuflen;
1857 struct stat srcst, destst;
1859 struct dir *dir, *sdir;
1860 char *spath, temp[17], *p;
1861 char *supath, *upath;
1866 struct adouble *adsp;
1867 struct adouble *addp;
1877 LOG(log_info, logtype_afpd, "begin afp_exchangefiles:");
1883 memcpy(&vid, ibuf, sizeof(vid));
1884 ibuf += sizeof(vid);
1886 if (NULL == ( vol = getvolbyvid( vid )) ) {
1887 return( AFPERR_PARAM);
1890 if (vol->v_flags & AFPVOL_RO)
1891 return AFPERR_VLOCK;
1893 /* source and destination dids */
1894 memcpy(&sid, ibuf, sizeof(sid));
1895 ibuf += sizeof(sid);
1896 memcpy(&did, ibuf, sizeof(did));
1897 ibuf += sizeof(did);
1900 if (NULL == (dir = dirlookup( vol, sid )) ) {
1901 return afp_errno; /* was AFPERR_PARAM */
1904 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
1905 return get_afp_errno(AFPERR_NOOBJ);
1908 if ( path_isadir(path) ) {
1909 return( AFPERR_BADTYPE ); /* it's a dir */
1912 upath = path->u_name;
1913 switch (path->st_errno) {
1920 return AFPERR_ACCESS;
1922 return AFPERR_PARAM;
1924 ad_init(&ads, vol->v_adouble);
1926 if ((s_of = of_findname(path))) {
1927 /* reuse struct adouble so it won't break locks */
1930 memcpy(&srcst, &path->st, sizeof(struct stat));
1931 /* save some stuff */
1933 spath = obj->oldtmp;
1934 supath = obj->newtmp;
1935 strcpy(spath, path->m_name);
1936 strcpy(supath, upath); /* this is for the cnid changing */
1937 p = absupath( vol, sdir, upath);
1939 /* pathname too long */
1940 return AFPERR_PARAM ;
1943 /* look for the source cnid. if it doesn't exist, don't worry about
1945 sid = cnid_lookup(vol->v_cdb, &srcst, sdir->d_did, supath,slen = strlen(supath));
1947 if (NULL == ( dir = dirlookup( vol, did )) ) {
1948 return afp_errno; /* was AFPERR_PARAM */
1951 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
1952 return get_afp_errno(AFPERR_NOOBJ);
1955 if ( path_isadir(path) ) {
1956 return( AFPERR_BADTYPE );
1959 /* FPExchangeFiles is the only call that can return the SameObj
1961 if ((curdir == sdir) && strcmp(spath, path->m_name) == 0)
1962 return AFPERR_SAMEOBJ;
1964 switch (path->st_errno) {
1971 return AFPERR_ACCESS;
1973 return AFPERR_PARAM;
1975 ad_init(&add, vol->v_adouble);
1977 if ((d_of = of_findname( path))) {
1978 /* reuse struct adouble so it won't break locks */
1981 memcpy(&destst, &path->st, sizeof(struct stat));
1983 /* they are not on the same device and at least one is open
1985 crossdev = (srcst.st_dev != destst.st_dev);
1986 if ((d_of || s_of) && crossdev)
1989 upath = path->u_name;
1990 /* look for destination id. */
1991 did = cnid_lookup(vol->v_cdb, &destst, curdir->d_did, upath, dlen = strlen(upath));
1993 /* construct a temp name.
1994 * NOTE: the temp file will be in the dest file's directory. it
1995 * will also be inaccessible from AFP. */
1996 memcpy(temp, APPLETEMP, sizeof(APPLETEMP));
2000 /* now, quickly rename the file. we error if we can't. */
2001 if ((err = renamefile(p, temp, temp, vol_noadouble(vol), adsp)) < 0)
2002 goto err_exchangefile;
2003 of_rename(vol, s_of, sdir, spath, curdir, temp);
2005 /* rename destination to source */
2006 if ((err = renamefile(upath, p, spath, vol_noadouble(vol), addp)) < 0)
2007 goto err_src_to_tmp;
2008 of_rename(vol, d_of, curdir, path->m_name, sdir, spath);
2010 /* rename temp to destination */
2011 if ((err = renamefile(temp, upath, path->m_name, vol_noadouble(vol), adsp)) < 0)
2012 goto err_dest_to_src;
2013 of_rename(vol, s_of, curdir, temp, curdir, path->m_name);
2015 /* id's need switching. src -> dest and dest -> src.
2016 * we need to re-stat() if it was a cross device copy.
2019 cnid_delete(vol->v_cdb, sid);
2022 cnid_delete(vol->v_cdb, did);
2024 if ((did && ( (crossdev && stat( upath, &srcst) < 0) ||
2025 cnid_update(vol->v_cdb, did, &srcst, curdir->d_did,upath, dlen) < 0))
2027 (sid && ( (crossdev && stat(p, &destst) < 0) ||
2028 cnid_update(vol->v_cdb, sid, &destst, sdir->d_did,supath, slen) < 0))
2033 err = AFPERR_ACCESS;
2038 goto err_temp_to_dest;
2042 LOG(log_info, logtype_afpd, "ending afp_exchangefiles:");
2048 /* all this stuff is so that we can unwind a failed operation
2051 /* rename dest to temp */
2052 renamefile(upath, temp, temp, vol_noadouble(vol), adsp);
2053 of_rename(vol, s_of, curdir, upath, curdir, temp);
2056 /* rename source back to dest */
2057 renamefile(p, upath, path->m_name, vol_noadouble(vol), addp);
2058 of_rename(vol, d_of, sdir, spath, curdir, path->m_name);
2061 /* rename temp back to source */
2062 renamefile(temp, p, spath, vol_noadouble(vol), adsp);
2063 of_rename(vol, s_of, curdir, temp, sdir, spath);