2 * $Id: fork.c,v 1.16 2002-01-17 16:19:06 jmarcus Exp $
4 * Copyright (c) 1990,1993 Regents of The University of Michigan.
5 * All Rights Reserved. See COPYRIGHT.
10 #endif /* HAVE_CONFIG_H */
15 #endif /* HAVE_UNISTD_H */
18 #endif /* HAVE_FCNTL_H */
22 #include <atalk/logger.h>
24 #include <sys/param.h>
26 #include <sys/types.h>
28 #include <sys/socket.h>
30 #include <netatalk/endian.h>
31 #include <netatalk/at.h>
33 #include <atalk/dsi.h>
34 #include <atalk/atp.h>
35 #include <atalk/asp.h>
36 #include <atalk/afp.h>
37 #include <atalk/adouble.h>
38 #include <atalk/util.h>
40 #include <atalk/cnid.h>
46 #include "directory.h"
50 #define BYTELOCK_MAX 0x7FFFFFFFU
52 struct ofork *writtenfork;
54 static int getforkparams(ofork, bitmap, buf, buflen, attrbits )
59 const u_int16_t attrbits;
62 struct stat hst, lst, *lstp;
63 #else /* USE_LASTDID */
68 char *data, *nameoff = NULL, *upath;
69 int bit = 0, isad = 1;
73 if ( ad_hfileno( ofork->of_ad ) == -1 ) {
76 aint = ad_getentrylen( ofork->of_ad, ADEID_RFORK );
77 if ( ad_refresh( ofork->of_ad ) < 0 ) {
78 LOG(log_error, logtype_default, "getforkparams: ad_refresh: %s", strerror(errno) );
79 return( AFPERR_PARAM );
81 /* See afp_closefork() for why this is bad */
82 ad_setentrylen( ofork->of_ad, ADEID_RFORK, aint );
85 /* can only get the length of the opened fork */
86 if (((bitmap & (1<<FILPBIT_DFLEN)) && (ofork->of_flags & AFPFORK_RSRC)) ||
87 ((bitmap & (1<<FILPBIT_RFLEN)) && (ofork->of_flags & AFPFORK_DATA))) {
88 return( AFPERR_BITMAP );
91 if ( bitmap & ( 1<<FILPBIT_DFLEN | 1<<FILPBIT_FNUM |
92 (1 << FILPBIT_CDATE) | (1 << FILPBIT_MDATE) |
93 (1 << FILPBIT_BDATE))) {
94 upath = mtoupath(ofork->of_vol, ofork->of_name);
95 if ( ad_dfileno( ofork->of_ad ) == -1 ) {
96 if ( stat( upath, &st ) < 0 )
97 return( AFPERR_NOOBJ );
99 if ( fstat( ad_dfileno( ofork->of_ad ), &st ) < 0 ) {
100 return( AFPERR_BITMAP );
106 while ( bitmap != 0 ) {
107 while (( bitmap & 1 ) == 0 ) {
115 ad_getattr(ofork->of_ad, &ashort);
120 ashort = htons(ntohs(ashort) | attrbits);
121 memcpy(data, &ashort, sizeof( ashort ));
122 data += sizeof( ashort );
126 memcpy(data, &ofork->of_dir->d_did, sizeof( aint ));
127 data += sizeof( aint );
132 (ad_getdate(ofork->of_ad, AD_DATE_CREATE, &aint) < 0))
133 aint = AD_DATE_FROM_UNIX(st.st_mtime);
134 memcpy(data, &aint, sizeof( aint ));
135 data += sizeof( aint );
140 (ad_getdate(ofork->of_ad, AD_DATE_MODIFY, &aint) < 0) ||
141 (AD_DATE_TO_UNIX(aint) < st.st_mtime))
142 aint = AD_DATE_FROM_UNIX(st.st_mtime);
143 memcpy(data, &aint, sizeof( aint ));
144 data += sizeof( aint );
149 (ad_getdate(ofork->of_ad, AD_DATE_BACKUP, &aint) < 0))
150 aint = AD_DATE_START;
151 memcpy(data, &aint, sizeof( aint ));
152 data += sizeof( aint );
157 (void *) ad_entry(ofork->of_ad, ADEID_FINDERI) :
158 (void *) ufinderi, 32);
160 memcmp( ad_entry( ofork->of_ad, ADEID_FINDERI ),
161 ufinderi, 8 ) == 0 ) {
162 memcpy(data, ufinderi, 8 );
163 if (( em = getextmap( ofork->of_name )) != NULL ) {
164 memcpy(data, em->em_type, sizeof( em->em_type ));
165 memcpy(data + 4, em->em_creator,
166 sizeof( em->em_creator ));
174 data += sizeof(u_int16_t);
178 memset(data, 0, sizeof(u_int16_t));
179 data += sizeof(u_int16_t);
184 #if AD_VERSION > AD_VERSION1
185 /* look in AD v2 header */
187 memcpy(&aint, ad_entry(ofork->of_ad, ADEID_DID), sizeof(aint));
188 #endif /* AD_VERSION > AD_VERSION1 */
191 aint = cnid_add(ofork->of_vol->v_db, &st,
192 ofork->of_dir->d_did,
193 upath, strlen(upath), aint);
194 if (aint > CNID_MAX) {
197 LOG(log_error, logtype_default, "getforkparams: Incorrect parameters passed to cnid_add");
198 return(AFPERR_PARAM);
200 return(AFPERR_PARAM);
209 aint = htonl(( st.st_dev << 16 ) | ( st.st_ino & 0x0000ffff ));
210 #else /* USE_LASTDID */
211 lstp = lstat(upath, &lst) < 0 ? st : &lst;
213 aint = htonl( afpd_st_cnid ( lstp ) );
215 aint = htonl(CNID(lstp, 1));
216 #endif /* DID_MTAB */
217 #endif /* USE_LASTDID */
220 memcpy(data, &aint, sizeof( aint ));
221 data += sizeof( aint );
225 aint = htonl( st.st_size );
226 memcpy(data, &aint, sizeof( aint ));
227 data += sizeof( aint );
232 aint = htonl( ad_getentrylen( ofork->of_ad, ADEID_RFORK ));
236 memcpy(data, &aint, sizeof( aint ));
237 data += sizeof( aint );
241 return( AFPERR_BITMAP );
248 ashort = htons( data - buf );
249 memcpy(nameoff, &ashort, sizeof( ashort ));
250 aint = strlen( ofork->of_name );
251 aint = ( aint > MACFILELEN ) ? MACFILELEN : aint;
253 memcpy(data, ofork->of_name, aint );
257 *buflen = data - buf;
261 int afp_openfork(obj, ibuf, ibuflen, rbuf, rbuflen )
264 int ibuflen, *rbuflen;
268 struct ofork *ofork, *opened;
269 struct adouble *adsame = NULL;
270 int buflen, ret, adflags, eid, lockop;
272 u_int16_t vid, bitmap, access, ofrefnum, attrbits = 0;
273 char fork, *path, *upath;
277 memcpy(&vid, ibuf, sizeof( vid ));
281 if (( vol = getvolbyvid( vid )) == NULL ) {
282 return( AFPERR_PARAM );
285 memcpy(&did, ibuf, sizeof( did ));
286 ibuf += sizeof( int );
288 if (( dir = dirsearch( vol, did )) == NULL ) {
289 return( AFPERR_NOOBJ );
292 memcpy(&bitmap, ibuf, sizeof( bitmap ));
293 bitmap = ntohs( bitmap );
294 ibuf += sizeof( bitmap );
295 memcpy(&access, ibuf, sizeof( access ));
296 access = ntohs( access );
297 ibuf += sizeof( access );
299 if ((vol->v_flags & AFPVOL_RO) && (access & OPENACC_WR)) {
303 if (( path = cname( vol, dir, &ibuf )) == NULL ) {
304 return( AFPERR_NOOBJ );
307 if ( fork == OPENFORK_DATA ) {
309 adflags = ADFLAGS_DF|ADFLAGS_HF;
312 adflags = ADFLAGS_HF;
315 /* XXX: this probably isn't the best way to do this. the already
316 open bits should really be set if the fork is opened by any
317 program, not just this one. however, that's problematic to do
318 if we can't write lock files somewhere. opened is also passed to
319 ad_open so that we can keep file locks together. */
320 if ((opened = of_findname(vol, curdir, path))) {
321 attrbits = ((opened->of_flags & AFPFORK_RSRC) ? ATTRBIT_ROPEN : 0) |
322 ((opened->of_flags & AFPFORK_DATA) ? ATTRBIT_DOPEN : 0);
323 adsame = opened->of_ad;
326 if (( ofork = of_alloc(vol, curdir, path, &ofrefnum, eid,
328 return( AFPERR_NFILE );
330 if (access & OPENACC_WR) {
331 /* try opening in read-write mode */
332 upath = mtoupath(vol, path);
334 if (ad_open(upath, adflags, O_RDWR, 0, ofork->of_ad) < 0) {
346 /* see if client asked for the data fork */
347 if (fork == OPENFORK_DATA) {
348 if (ad_open(upath, ADFLAGS_DF, O_RDWR, 0, ofork->of_ad) < 0) {
351 adflags = ADFLAGS_DF;
353 } else if (stat(upath, &st) == 0) {
354 /* here's the deal. we only try to create the resource
355 * fork if the user wants to open it for write acess. */
356 if (ad_open(upath, adflags, O_RDWR | O_CREAT, 0666, ofork->of_ad) < 0)
368 ret = AFPERR_BADTYPE;
372 LOG(log_error, logtype_default, "afp_openfork: ad_open: %s", strerror(errno) );
379 /* try opening in read-only mode */
380 upath = mtoupath(vol, path);
382 if (ad_open(upath, adflags, O_RDONLY, 0, ofork->of_ad) < 0) {
387 /* check for a read-only data fork */
388 if ((adflags != ADFLAGS_HF) &&
389 (ad_open(upath, ADFLAGS_DF, O_RDONLY, 0, ofork->of_ad) < 0))
392 adflags = ADFLAGS_DF;
398 /* see if client asked for the data fork */
399 if (fork == OPENFORK_DATA) {
400 if (ad_open(upath, ADFLAGS_DF, O_RDONLY, 0, ofork->of_ad) < 0) {
403 adflags = ADFLAGS_DF;
405 } else if (stat(upath, &st) != 0) {
416 ret = AFPERR_BADTYPE;
420 LOG(log_error, logtype_default, "afp_openfork: ad_open: %s", strerror(errno) );
427 if ((adflags & ADFLAGS_HF) &&
428 (ad_getoflags( ofork->of_ad, ADFLAGS_HF ) & O_CREAT)) {
429 ad_setentrylen( ofork->of_ad, ADEID_NAME, strlen( path ));
430 memcpy(ad_entry( ofork->of_ad, ADEID_NAME ), path,
431 ad_getentrylen( ofork->of_ad, ADEID_NAME ));
432 ad_flush( ofork->of_ad, adflags );
435 if (( ret = getforkparams(ofork, bitmap, rbuf + 2 * sizeof( u_int16_t ),
436 &buflen, attrbits )) != AFP_OK ) {
437 ad_close( ofork->of_ad, adflags );
441 *rbuflen = buflen + 2 * sizeof( u_int16_t );
442 bitmap = htons( bitmap );
443 memcpy(rbuf, &bitmap, sizeof( u_int16_t ));
444 rbuf += sizeof( u_int16_t );
447 * synchronization locks:
450 * 1) attempt a read lock to see if we have read or write
452 * 2) if that succeeds, set a write lock to correspond to the
453 * deny mode requested.
454 * 3) whenever a file is read/written, locks get set which
458 /* don't try to lock non-existent rforks. */
459 if ((eid == ADEID_DFORK) || (ad_hfileno(ofork->of_ad) != -1)) {
461 /* try to see if we have access. */
463 if (access & OPENACC_WR) {
464 ofork->of_flags |= AFPFORK_ACCWR;
465 ret = ad_lock(ofork->of_ad, eid, ADLOCK_RD | ADLOCK_FILELOCK,
466 AD_FILELOCK_WR, 1, ofrefnum);
469 if (!ret && (access & OPENACC_RD)) {
470 ofork->of_flags |= AFPFORK_ACCRD;
471 ret = ad_lock(ofork->of_ad, eid, ADLOCK_RD | ADLOCK_FILELOCK,
472 AD_FILELOCK_RD, 1, ofrefnum);
475 /* can we access the fork? */
477 ad_close( ofork->of_ad, adflags );
480 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
481 return (AFPERR_DENYCONF);
484 /* now try to set the deny lock. if the fork is open for read or
485 * write, a read lock will already have been set. otherwise, we upgrade
486 * our lock to a write lock.
488 * NOTE: we can't write lock a read-only file. on those, we just
489 * make sure that we have a read lock set. that way, we at least prevent
490 * someone else from really setting a deny read/write on the file. */
491 lockop = (ad_getoflags(ofork->of_ad, eid) & O_RDWR) ?
492 ADLOCK_WR : ADLOCK_RD;
493 ret = (access & OPENACC_DWR) ? ad_lock(ofork->of_ad, eid,
494 lockop | ADLOCK_FILELOCK |
495 ADLOCK_UPGRADE, AD_FILELOCK_WR, 1,
497 if (!ret && (access & OPENACC_DRD))
498 ret = ad_lock(ofork->of_ad, eid, lockop | ADLOCK_FILELOCK |
499 ADLOCK_UPGRADE, AD_FILELOCK_RD, 1, ofrefnum);
503 ad_close( ofork->of_ad, adflags );
506 case EAGAIN: /* return data anyway */
510 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
511 return( AFPERR_DENYCONF );
515 LOG(log_error, logtype_default, "afp_openfork: ad_lock: %s", strerror(errno) );
516 return( AFPERR_PARAM );
521 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
527 return (access & OPENACC_WR) ? AFPERR_LOCK : AFPERR_ACCESS;
531 int afp_setforkparams(obj, ibuf, ibuflen, rbuf, rbuflen )
534 int ibuflen, *rbuflen;
538 u_int16_t ofrefnum, bitmap;
542 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
543 ibuf += sizeof( ofrefnum );
544 memcpy(&bitmap, ibuf, sizeof(bitmap));
545 bitmap = ntohs(bitmap);
546 ibuf += sizeof( bitmap );
547 memcpy(&size, ibuf, sizeof( size ));
548 size = ntohl( size );
551 if (( ofork = of_find( ofrefnum )) == NULL ) {
552 LOG(log_error, logtype_default, "afp_setforkparams: of_find: %s", strerror(errno) );
553 return( AFPERR_PARAM );
556 if (ofork->of_vol->v_flags & AFPVOL_RO)
559 if ((ofork->of_flags & AFPFORK_ACCWR) == 0)
560 return AFPERR_ACCESS;
565 if ((bitmap == (1<<FILPBIT_DFLEN)) && (ofork->of_flags & AFPFORK_DATA)) {
566 err = ad_dtruncate( ofork->of_ad, size );
568 goto afp_setfork_err;
569 } else if ((bitmap == (1<<FILPBIT_RFLEN)) &&
570 (ofork->of_flags & AFPFORK_RSRC)) {
571 ad_refresh( ofork->of_ad );
572 err = ad_rtruncate(ofork->of_ad, size);
574 goto afp_setfork_err;
576 if (ad_flush( ofork->of_ad, ADFLAGS_HF ) < 0) {
577 LOG(log_error, logtype_default, "afp_setforkparams: ad_flush: %s",
579 return( AFPERR_PARAM );
582 return AFPERR_BITMAP;
585 if ( flushfork( ofork ) < 0 ) {
586 LOG(log_error, logtype_default, "afp_setforkparams: flushfork: %s", strerror(errno) );
601 return AFPERR_ACCESS;
612 /* for this to work correctly, we need to check for locks before each
613 * read and write. that's most easily handled by always doing an
614 * appropriate check before each ad_read/ad_write. other things
615 * that can change files like truncate are handled internally to those
618 #define ENDBIT(a) ((a) & 0x80)
619 #define UNLOCKBIT(a) ((a) & 0x01)
620 int afp_bytelock(obj, ibuf, ibuflen, rbuf, rbuflen )
623 int ibuflen, *rbuflen;
626 int32_t offset, length;
633 /* figure out parameters */
635 flags = *ibuf; /* first bit = endflag, lastbit = lockflag */
637 memcpy(&ofrefnum, ibuf, sizeof(ofrefnum));
638 ibuf += sizeof(ofrefnum);
640 if (( ofork = of_find( ofrefnum )) == NULL ) {
641 LOG(log_error, logtype_default, "afp_bytelock: of_find: %s", strerror(errno) );
642 return( AFPERR_PARAM );
645 if ( ofork->of_flags & AFPFORK_DATA) {
647 } else if (ofork->of_flags & AFPFORK_RSRC) {
652 memcpy(&offset, ibuf, sizeof( offset ));
653 offset = ntohl(offset);
654 ibuf += sizeof(offset);
656 memcpy(&length, ibuf, sizeof( length ));
657 length = ntohl(length);
658 if (length == 0xFFFFFFFF)
659 length = BYTELOCK_MAX;
660 else if (length <= 0) {
662 } else if ((length >= AD_FILELOCK_BASE) &&
663 (ad_hfileno(ofork->of_ad) == -1))
667 offset += ad_size(ofork->of_ad, eid);
669 if (offset < 0) /* error if we have a negative offset */
672 /* if the file is a read-only file, we use read locks instead of
673 * write locks. that way, we can prevent anyone from initiating
675 if (ad_lock(ofork->of_ad, eid, UNLOCKBIT(flags) ? ADLOCK_CLR :
676 ((ad_getoflags(ofork->of_ad, eid) & O_RDWR) ?
677 ADLOCK_WR : ADLOCK_RD), offset, length,
678 ofork->of_refnum) < 0) {
682 return UNLOCKBIT(flags) ? AFPERR_NORANGE : AFPERR_LOCK;
688 return UNLOCKBIT(flags) ? AFPERR_NORANGE : AFPERR_RANGEOVR;
697 offset = htonl(offset);
698 memcpy(rbuf, &offset, sizeof( offset ));
699 *rbuflen = sizeof( offset );
705 static __inline__ int crlf( of )
710 if ( ad_hfileno( of->of_ad ) == -1 ||
711 memcmp( ufinderi, ad_entry( of->of_ad, ADEID_FINDERI ),
713 if (( em = getextmap( of->of_name )) == NULL ||
714 memcmp( "TEXT", em->em_type, sizeof( em->em_type )) == 0 ) {
720 if ( memcmp( ufinderi,
721 ad_entry( of->of_ad, ADEID_FINDERI ), 4 ) == 0 ) {
730 static __inline__ ssize_t read_file(struct ofork *ofork, int eid,
731 int offset, u_char nlmask,
732 u_char nlchar, char *rbuf,
733 int *rbuflen, const int xlate)
739 cc = ad_read(ofork->of_ad, eid, offset, rbuf, *rbuflen);
741 LOG(log_error, logtype_default, "afp_read: ad_read: %s", strerror(errno) );
743 return( AFPERR_PARAM );
745 if ( cc < *rbuflen ) {
753 for ( p = rbuf, q = p + cc; p < q; ) {
754 if (( *p++ & nlmask ) == nlchar ) {
765 * If this file is of type TEXT, then swap \012 to \015.
768 for ( p = rbuf, q = p + cc; p < q; p++ ) {
769 if ( *p == '\012' ) {
771 } else if ( *p == '\015' ) {
780 return( AFPERR_EOF );
785 int afp_read(obj, ibuf, ibuflen, rbuf, rbuflen)
788 int ibuflen, *rbuflen;
792 int32_t offset, saveoff, reqcount;
793 int cc, err, eid, xlate = 0;
795 u_char nlmask, nlchar;
798 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
799 ibuf += sizeof( u_short );
801 if (( ofork = of_find( ofrefnum )) == NULL ) {
802 LOG(log_error, logtype_default, "afp_read: of_find: %s", strerror(errno) );
807 if ((ofork->of_flags & AFPFORK_ACCRD) == 0) {
812 memcpy(&offset, ibuf, sizeof( offset ));
813 offset = ntohl( offset );
814 ibuf += sizeof( offset );
815 memcpy(&reqcount, ibuf, sizeof( reqcount ));
816 reqcount = ntohl( reqcount );
817 ibuf += sizeof( reqcount );
822 /* if we wanted to be picky, we could add in the following
823 * bit: if (afp_version == 11 && !(nlmask == 0xFF || !nlmask))
825 if (reqcount < 0 || offset < 0) {
830 if ( ofork->of_flags & AFPFORK_DATA) {
832 xlate = (ofork->of_vol->v_flags & AFPVOL_CRLF) ? crlf(ofork) : 0;
833 } else if (ofork->of_flags & AFPFORK_RSRC) {
835 } else { /* fork wasn't opened. this should never really happen. */
840 /* zero request count */
846 /* reqcount isn't always truthful. we need to deal with that. */
847 if ((size = ad_size(ofork->of_ad, eid)) == 0) {
853 if (ad_tmplock(ofork->of_ad, eid, ADLOCK_RD, saveoff, reqcount) < 0) {
858 #define min(a,b) ((a)<(b)?(a):(b))
859 *rbuflen = min( reqcount, *rbuflen );
860 err = read_file(ofork, eid, offset, nlmask, nlchar, rbuf, rbuflen,
865 /* dsi can stream requests. we can only do this if we're not checking
866 * for an end-of-line character. oh well. */
867 if ((obj->proto == AFPPROTO_DSI) && (*rbuflen < reqcount) && !nlmask) {
868 DSI *dsi = obj->handle;
870 /* subtract off the offset */
872 if (reqcount > size) {
877 if (obj->options.flags & OPTION_DEBUG) {
878 printf( "(read) reply: %d/%d, %d\n", *rbuflen,
879 reqcount, dsi->clientID);
880 bprint(rbuf, *rbuflen);
885 /* dsi_readinit() returns size of next read buffer. by this point,
886 * we know that we're sending some data. if we fail, something
887 * horrible happened. */
888 if ((*rbuflen = dsi_readinit(dsi, rbuf, *rbuflen, reqcount, err)) < 0)
891 /* due to the nature of afp packets, we have to exit if we get
892 an error. we can't do this with translation on. */
893 #ifdef HAVE_SENDFILE_READ
894 if (!(xlate || (obj->options.flags & OPTION_DEBUG))) {
895 if (ad_readfile(ofork->of_ad, eid, dsi->socket, offset,
896 dsi->datasize) < 0) {
900 LOG(log_error, logtype_default, "afp_read: ad_readfile: %s", strerror(errno));
910 #endif /* HAVE_SENDFILE_READ */
912 /* fill up our buffer. */
913 while (*rbuflen > 0) {
914 cc = read_file(ofork, eid, offset, nlmask, nlchar, rbuf,
920 if (obj->options.flags & OPTION_DEBUG) {
921 printf( "(read) reply: %d, %d\n", *rbuflen, dsi->clientID);
922 bprint(rbuf, *rbuflen);
925 /* dsi_read() also returns buffer size of next allocation */
926 cc = dsi_read(dsi, rbuf, *rbuflen); /* send it off */
935 LOG(log_error, logtype_default, "afp_read: %s", strerror(errno));
937 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
942 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
950 int afp_flush(obj, ibuf, ibuflen, rbuf, rbuflen )
953 int ibuflen, *rbuflen;
961 memcpy(&vid, ibuf, sizeof(vid));
962 if (( vol = getvolbyvid( vid )) == NULL ) {
963 return( AFPERR_PARAM );
970 int afp_flushfork(obj, ibuf, ibuflen, rbuf, rbuflen )
973 int ibuflen, *rbuflen;
980 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
982 if (( ofork = of_find( ofrefnum )) == NULL ) {
983 LOG(log_error, logtype_default, "afp_flushfork: of_find: %s", strerror(errno) );
984 return( AFPERR_PARAM );
987 if ( flushfork( ofork ) < 0 ) {
988 LOG(log_error, logtype_default, "afp_flushfork: %s", strerror(errno) );
994 /* this is very similar to closefork */
995 int flushfork( ofork )
999 int len, err = 0, doflush = 0;
1001 if ( ad_dfileno( ofork->of_ad ) != -1 &&
1002 fsync( ad_dfileno( ofork->of_ad )) < 0 ) {
1003 LOG(log_error, logtype_default, "flushfork: dfile(%d) %s",
1004 ad_dfileno(ofork->of_ad), strerror(errno) );
1008 if ( ad_hfileno( ofork->of_ad ) != -1 ) {
1010 /* read in the rfork length */
1011 len = ad_getentrylen(ofork->of_ad, ADEID_RFORK);
1012 ad_refresh(ofork->of_ad);
1014 /* set the date if we're dirty */
1015 if ((ofork->of_flags & AFPFORK_DIRTY) &&
1016 (gettimeofday(&tv, NULL) == 0)) {
1017 ad_setdate(ofork->of_ad, AD_DATE_MODIFY|AD_DATE_UNIX, tv.tv_sec);
1018 ofork->of_flags &= ~AFPFORK_DIRTY;
1022 /* if we're actually flushing this fork, make sure to set the
1023 * length. otherwise, just use the stored length */
1024 if ((ofork->of_flags & AFPFORK_RSRC) &&
1025 (len != ad_getentrylen(ofork->of_ad, ADEID_RFORK))) {
1026 ad_setentrylen(ofork->of_ad, ADEID_RFORK, len);
1031 /* flush the header (if it is a resource fork) */
1032 if (ofork->of_flags & AFPFORK_RSRC)
1033 if (doflush && (ad_flush(ofork->of_ad, ADFLAGS_HF) < 0))
1036 if (fsync( ad_hfileno( ofork->of_ad )) < 0)
1040 LOG(log_error, logtype_default, "flushfork: hfile(%d) %s",
1041 ad_hfileno(ofork->of_ad), strerror(errno) );
1047 int afp_closefork(obj, ibuf, ibuflen, rbuf, rbuflen )
1050 int ibuflen, *rbuflen;
1052 struct ofork *ofork;
1054 int adflags, aint, doflush = 0;
1059 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1061 if (( ofork = of_find( ofrefnum )) == NULL ) {
1062 LOG(log_error, logtype_default, "afp_closefork: of_find: %s", strerror(errno) );
1063 return( AFPERR_PARAM );
1067 if ((ofork->of_flags & AFPFORK_DATA) &&
1068 (ad_dfileno( ofork->of_ad ) != -1)) {
1069 adflags |= ADFLAGS_DF;
1072 if ( ad_hfileno( ofork->of_ad ) != -1 ) {
1073 adflags |= ADFLAGS_HF;
1075 aint = ad_getentrylen( ofork->of_ad, ADEID_RFORK );
1076 ad_refresh( ofork->of_ad );
1077 if ((ofork->of_flags & AFPFORK_DIRTY) &&
1078 (gettimeofday(&tv, NULL) == 0)) {
1079 ad_setdate(ofork->of_ad, AD_DATE_MODIFY | AD_DATE_UNIX,
1085 * Only set the rfork's length if we're closing the rfork.
1087 if ((ofork->of_flags & AFPFORK_RSRC) && aint !=
1088 ad_getentrylen( ofork->of_ad, ADEID_RFORK )) {
1089 ad_setentrylen( ofork->of_ad, ADEID_RFORK, aint );
1093 ad_flush( ofork->of_ad, adflags );
1097 if ( ad_close( ofork->of_ad, adflags ) < 0 ) {
1098 LOG(log_error, logtype_default, "afp_closefork: ad_close: %s", strerror(errno) );
1099 return( AFPERR_PARAM );
1102 of_dealloc( ofork );
1107 static __inline__ ssize_t write_file(struct ofork *ofork, int eid,
1108 off_t offset, char *rbuf,
1109 size_t rbuflen, const int xlate)
1115 * If this file is of type TEXT, swap \015 to \012.
1118 for ( p = rbuf, q = p + rbuflen; p < q; p++ ) {
1119 if ( *p == '\015' ) {
1121 } else if ( *p == '\012' ) {
1127 if (( cc = ad_write(ofork->of_ad, eid, offset, 0,
1128 rbuf, rbuflen)) < 0 ) {
1133 return( AFPERR_DFULL );
1135 LOG(log_error, logtype_default, "afp_write: ad_write: %s", strerror(errno) );
1136 return( AFPERR_PARAM );
1143 /* FPWrite. NOTE: on an error, we always use afp_write_err as
1144 * the client may have sent us a bunch of data that's not reflected
1145 * in reqcount et al. */
1146 int afp_write(obj, ibuf, ibuflen, rbuf, rbuflen)
1149 int ibuflen, *rbuflen;
1151 struct ofork *ofork;
1152 int32_t offset, saveoff, reqcount;
1153 int endflag, eid, xlate = 0, err = AFP_OK;
1157 /* figure out parameters */
1159 endflag = ENDBIT(*ibuf);
1161 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1162 ibuf += sizeof( ofrefnum );
1163 memcpy(&offset, ibuf, sizeof( offset ));
1164 offset = ntohl( offset );
1165 ibuf += sizeof( offset );
1166 memcpy(&reqcount, ibuf, sizeof( reqcount ));
1167 reqcount = ntohl( reqcount );
1168 ibuf += sizeof( reqcount );
1170 if (( ofork = of_find( ofrefnum )) == NULL ) {
1171 LOG(log_error, logtype_default, "afp_write: of_find: %s", strerror(errno) );
1176 if ((ofork->of_flags & AFPFORK_ACCWR) == 0) {
1177 err = AFPERR_ACCESS;
1182 writtenfork = ofork;
1185 if ( ofork->of_flags & AFPFORK_DATA) {
1187 xlate = (ofork->of_vol->v_flags & AFPVOL_CRLF) ? crlf(ofork) : 0;
1188 } else if (ofork->of_flags & AFPFORK_RSRC) {
1191 err = AFPERR_ACCESS; /* should never happen */
1196 offset += ad_size(ofork->of_ad, eid);
1198 /* handle bogus parameters */
1199 if (reqcount < 0 || offset < 0) {
1204 /* offset can overflow on 64-bit capable filesystems.
1205 * report disk full if that's going to happen. */
1206 if (offset + reqcount < 0) {
1211 if (!reqcount) { /* handle request counts of 0 */
1213 offset = htonl(offset);
1214 memcpy(rbuf, &offset, sizeof(offset));
1219 if (ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, saveoff,
1225 /* this is yucky, but dsi can stream i/o and asp can't */
1226 switch (obj->proto) {
1229 if (asp_wrtcont(obj->handle, rbuf, rbuflen) < 0) {
1231 LOG(log_error, logtype_default, "afp_write: asp_wrtcont: %s", strerror(errno) );
1232 return( AFPERR_PARAM );
1235 if (obj->options.flags & OPTION_DEBUG) {
1236 printf("(write) len: %d\n", *rbuflen);
1237 bprint(rbuf, *rbuflen);
1240 if ((cc = write_file(ofork, eid, offset, rbuf, *rbuflen,
1243 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
1248 #endif /* no afp/asp */
1252 DSI *dsi = obj->handle;
1254 /* find out what we have already and write it out. */
1255 cc = dsi_writeinit(dsi, rbuf, *rbuflen);
1257 (cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
1258 dsi_writeflush(dsi);
1260 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
1265 #if 0 /*def HAVE_SENDFILE_WRITE*/
1266 if (!(xlate || obj->options.flags & OPTION_DEBUG)) {
1267 if ((cc = ad_writefile(ofork->of_ad, eid, dsi->socket,
1268 offset, dsi->datasize)) < 0) {
1276 LOG(log_error, logtype_default, "afp_write: ad_writefile: %s", strerror(errno) );
1277 goto afp_write_loop;
1279 dsi_writeflush(dsi);
1281 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
1287 goto afp_write_done;
1289 #endif /* 0, was HAVE_SENDFILE_WRITE */
1291 /* loop until everything gets written. currently
1292 * dsi_write handles the end case by itself. */
1294 while ((cc = dsi_write(dsi, rbuf, *rbuflen))) {
1295 if ( obj->options.flags & OPTION_DEBUG ) {
1296 printf("(write) command cont'd: %d\n", cc);
1300 if ((cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
1301 dsi_writeflush(dsi);
1303 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
1314 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
1315 if ( ad_hfileno( ofork->of_ad ) != -1 )
1316 ofork->of_flags |= AFPFORK_DIRTY;
1318 offset = htonl( offset );
1319 #if defined(__GNUC__) && defined(HAVE_GCC_MEMCPY_BUG)
1320 bcopy(&offset, rbuf, sizeof(offset));
1321 #else /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */
1322 memcpy(rbuf, &offset, sizeof(offset));
1323 #endif /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */
1324 *rbuflen = sizeof(offset);
1328 if (obj->proto == AFPPROTO_DSI) {
1329 dsi_writeinit(obj->handle, rbuf, *rbuflen);
1330 dsi_writeflush(obj->handle);
1333 *rbuflen = (err == AFP_OK) ? sizeof(offset) : 0;
1338 int afp_getforkparams(obj, ibuf, ibuflen, rbuf, rbuflen )
1341 int ibuflen, *rbuflen;
1343 struct ofork *ofork;
1345 u_int16_t ofrefnum, bitmap;
1348 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1349 ibuf += sizeof( ofrefnum );
1350 memcpy(&bitmap, ibuf, sizeof( bitmap ));
1351 bitmap = ntohs( bitmap );
1352 ibuf += sizeof( bitmap );
1355 if (( ofork = of_find( ofrefnum )) == NULL ) {
1356 LOG(log_error, logtype_default, "afp_getforkparams: of_find: %s", strerror(errno) );
1357 return( AFPERR_PARAM );
1360 if (( ret = getforkparams( ofork, bitmap,
1361 rbuf + sizeof( u_short ), &buflen, 0 )) != AFP_OK ) {
1365 *rbuflen = buflen + sizeof( u_short );
1366 bitmap = htons( bitmap );
1367 memcpy(rbuf, &bitmap, sizeof( bitmap ));