2 * $Id: fork.c,v 1.4 2001-06-04 19:06:15 rufustfirefly Exp $
4 * Copyright (c) 1990,1993 Regents of The University of Michigan.
5 * All Rights Reserved. See COPYRIGHT.
20 #include <sys/param.h>
22 #include <sys/types.h>
24 #include <sys/socket.h>
26 #include <netatalk/endian.h>
27 #include <netatalk/at.h>
29 #include <atalk/dsi.h>
30 #include <atalk/atp.h>
31 #include <atalk/asp.h>
32 #include <atalk/afp.h>
33 #include <atalk/adouble.h>
34 #include <atalk/util.h>
35 #include <atalk/cnid.h>
40 #include "directory.h"
44 #define BYTELOCK_MAX 0x7FFFFFFFU
46 struct ofork *writtenfork;
48 static int getforkparams(ofork, bitmap, buf, buflen, attrbits )
53 const u_int16_t attrbits;
57 char *data, *nameoff = NULL, *upath;
58 int bit = 0, isad = 1;
62 if ( ad_hfileno( ofork->of_ad ) == -1 ) {
65 aint = ad_getentrylen( ofork->of_ad, ADEID_RFORK );
66 if ( ad_refresh( ofork->of_ad ) < 0 ) {
67 syslog( LOG_ERR, "getforkparams: ad_refresh: %m");
68 return( AFPERR_PARAM );
70 /* See afp_closefork() for why this is bad */
71 ad_setentrylen( ofork->of_ad, ADEID_RFORK, aint );
74 /* can only get the length of the opened fork */
75 if (((bitmap & (1<<FILPBIT_DFLEN)) && (ofork->of_flags & AFPFORK_RSRC)) ||
76 ((bitmap & (1<<FILPBIT_RFLEN)) && (ofork->of_flags & AFPFORK_DATA))) {
77 return( AFPERR_BITMAP );
80 if ( bitmap & ( 1<<FILPBIT_DFLEN | 1<<FILPBIT_FNUM |
81 (1 << FILPBIT_CDATE) | (1 << FILPBIT_MDATE) |
82 (1 << FILPBIT_BDATE))) {
83 upath = mtoupath(ofork->of_vol, ofork->of_name);
84 if ( ad_dfileno( ofork->of_ad ) == -1 ) {
85 if ( stat( upath, &st ) < 0 )
86 return( AFPERR_NOOBJ );
88 if ( fstat( ad_dfileno( ofork->of_ad ), &st ) < 0 ) {
89 return( AFPERR_BITMAP );
95 while ( bitmap != 0 ) {
96 while (( bitmap & 1 ) == 0 ) {
104 ad_getattr(ofork->of_ad, &ashort);
109 ashort = htons(ntohs(ashort) | attrbits);
110 memcpy(data, &ashort, sizeof( ashort ));
111 data += sizeof( ashort );
115 memcpy(data, &ofork->of_dir->d_did, sizeof( aint ));
116 data += sizeof( aint );
121 (ad_getdate(ofork->of_ad, AD_DATE_CREATE, &aint) < 0))
122 aint = AD_DATE_FROM_UNIX(st.st_mtime);
123 memcpy(data, &aint, sizeof( aint ));
124 data += sizeof( aint );
129 (ad_getdate(ofork->of_ad, AD_DATE_MODIFY, &aint) < 0) ||
130 (AD_DATE_TO_UNIX(aint) < st.st_mtime))
131 aint = AD_DATE_FROM_UNIX(st.st_mtime);
132 memcpy(data, &aint, sizeof( aint ));
133 data += sizeof( aint );
138 (ad_getdate(ofork->of_ad, AD_DATE_BACKUP, &aint) < 0))
139 aint = AD_DATE_START;
140 memcpy(data, &aint, sizeof( aint ));
141 data += sizeof( aint );
146 (void *) ad_entry(ofork->of_ad, ADEID_FINDERI) :
147 (void *) ufinderi, 32);
149 memcmp( ad_entry( ofork->of_ad, ADEID_FINDERI ),
150 ufinderi, 8 ) == 0 ) {
151 memcpy(data, ufinderi, 8 );
152 if (( em = getextmap( ofork->of_name )) != NULL ) {
153 memcpy(data, em->em_type, sizeof( em->em_type ));
154 memcpy(data + 4, em->em_creator,
155 sizeof( em->em_creator ));
163 data += sizeof(u_int16_t);
167 memset(data, 0, sizeof(u_int16_t));
168 data += sizeof(u_int16_t);
173 * See file.c getfilparams() for why this is done this
176 #if AD_VERSION > AD_VERSION1
178 memcpy(&aint, ad_entry(ofork->of_ad, ADEID_DID), sizeof(aint));
182 if (!(aint = cnid_add(ofork->of_vol->v_db, &st,
183 ofork->of_dir->d_did,
184 upath, strlen(upath), aint))) {
189 aint = ( st.st_dev << 16 ) | ( st.st_ino & 0x0000ffff );
191 #if AD_VERSION > AD_VERSION1
194 memcpy(data, &aint, sizeof( aint ));
195 data += sizeof( aint );
199 aint = htonl( st.st_size );
200 memcpy(data, &aint, sizeof( aint ));
201 data += sizeof( aint );
206 aint = htonl( ad_getentrylen( ofork->of_ad, ADEID_RFORK ));
210 memcpy(data, &aint, sizeof( aint ));
211 data += sizeof( aint );
215 return( AFPERR_BITMAP );
222 ashort = htons( data - buf );
223 memcpy(nameoff, &ashort, sizeof( ashort ));
224 aint = strlen( ofork->of_name );
225 aint = ( aint > MACFILELEN ) ? MACFILELEN : aint;
227 memcpy(data, ofork->of_name, aint );
231 *buflen = data - buf;
235 int afp_openfork(obj, ibuf, ibuflen, rbuf, rbuflen )
238 int ibuflen, *rbuflen;
242 struct ofork *ofork, *opened;
243 struct adouble *adsame = NULL;
244 int buflen, ret, adflags, eid, lockop;
246 u_int16_t vid, bitmap, access, ofrefnum, attrbits = 0;
247 char fork, *path, *upath;
251 memcpy(&vid, ibuf, sizeof( vid ));
255 if (( vol = getvolbyvid( vid )) == NULL ) {
256 return( AFPERR_PARAM );
259 memcpy(&did, ibuf, sizeof( did ));
260 ibuf += sizeof( int );
262 if (( dir = dirsearch( vol, did )) == NULL ) {
263 return( AFPERR_NOOBJ );
266 memcpy(&bitmap, ibuf, sizeof( bitmap ));
267 bitmap = ntohs( bitmap );
268 ibuf += sizeof( bitmap );
269 memcpy(&access, ibuf, sizeof( access ));
270 access = ntohs( access );
271 ibuf += sizeof( access );
273 if ((vol->v_flags & AFPVOL_RO) && (access & OPENACC_WR)) {
277 if (( path = cname( vol, dir, &ibuf )) == NULL ) {
278 return( AFPERR_NOOBJ );
281 if ( fork == OPENFORK_DATA ) {
283 adflags = ADFLAGS_DF|ADFLAGS_HF;
286 adflags = ADFLAGS_HF;
289 /* XXX: this probably isn't the best way to do this. the already
290 open bits should really be set if the fork is opened by any
291 program, not just this one. however, that's problematic to do
292 if we can't write lock files somewhere. opened is also passed to
293 ad_open so that we can keep file locks together. */
294 if ((opened = of_findname(vol, curdir, path))) {
295 attrbits = ((opened->of_flags & AFPFORK_RSRC) ? ATTRBIT_ROPEN : 0) |
296 ((opened->of_flags & AFPFORK_DATA) ? ATTRBIT_DOPEN : 0);
297 adsame = opened->of_ad;
300 if (( ofork = of_alloc(vol, curdir, path, &ofrefnum, eid,
302 return( AFPERR_NFILE );
305 /* try opening in read-write mode with a fallback to read-only
306 * if we don't need write access. */
307 upath = mtoupath(vol, path);
309 if (ad_open(upath, adflags, O_RDWR, 0, ofork->of_ad) < 0) {
314 if (access & OPENACC_WR)
317 if (ad_open(upath, adflags, O_RDONLY, 0, ofork->of_ad) < 0) {
318 /* check for a read-only data fork */
319 if ((adflags != ADFLAGS_HF) &&
320 (ad_open(upath, ADFLAGS_DF, O_RDONLY, 0, ofork->of_ad) < 0))
323 adflags = ADFLAGS_DF;
330 /* see if client asked for the data fork */
331 if (fork == OPENFORK_DATA) {
332 if (((access & OPENACC_WR) &&
333 (ad_open(upath, ADFLAGS_DF, O_RDWR, 0, ofork->of_ad) < 0))
334 || (ad_open(upath, ADFLAGS_DF, O_RDONLY, 0,
335 ofork->of_ad) < 0)) {
338 adflags = ADFLAGS_DF;
340 } else if (stat(upath, &st) == 0) {
341 /* here's the deal. we only try to create the resource
342 * fork if the user wants to open it for write access. */
343 if ((access & OPENACC_WR) &&
344 (ad_open(upath, adflags, O_RDWR | O_CREAT,
345 0666, ofork->of_ad) < 0))
357 ret = AFPERR_BADTYPE;
361 syslog( LOG_ERR, "afp_openfork: ad_open: %m" );
368 if ((adflags & ADFLAGS_HF) &&
369 (ad_getoflags( ofork->of_ad, ADFLAGS_HF ) & O_CREAT)) {
370 ad_setentrylen( ofork->of_ad, ADEID_NAME, strlen( path ));
371 memcpy(ad_entry( ofork->of_ad, ADEID_NAME ), path,
372 ad_getentrylen( ofork->of_ad, ADEID_NAME ));
373 ad_flush( ofork->of_ad, adflags );
376 if (( ret = getforkparams(ofork, bitmap, rbuf + 2 * sizeof( u_int16_t ),
377 &buflen, attrbits )) != AFP_OK ) {
378 ad_close( ofork->of_ad, adflags );
382 *rbuflen = buflen + 2 * sizeof( u_int16_t );
383 bitmap = htons( bitmap );
384 memcpy(rbuf, &bitmap, sizeof( u_int16_t ));
385 rbuf += sizeof( u_int16_t );
388 * synchronization locks:
391 * 1) attempt a read lock to see if we have read or write
393 * 2) if that succeeds, set a write lock to correspond to the
394 * deny mode requested.
395 * 3) whenever a file is read/written, locks get set which
399 /* don't try to lock non-existent rforks. */
400 if ((eid == ADEID_DFORK) || (ad_hfileno(ofork->of_ad) != -1)) {
402 /* try to see if we have access. */
404 if (access & OPENACC_WR) {
405 ofork->of_flags |= AFPFORK_ACCWR;
406 ret = ad_lock(ofork->of_ad, eid, ADLOCK_RD | ADLOCK_FILELOCK,
407 AD_FILELOCK_WR, 1, ofrefnum);
410 if (!ret && (access & OPENACC_RD)) {
411 ofork->of_flags |= AFPFORK_ACCRD;
412 ret = ad_lock(ofork->of_ad, eid, ADLOCK_RD | ADLOCK_FILELOCK,
413 AD_FILELOCK_RD, 1, ofrefnum);
416 /* can we access the fork? */
418 ad_close( ofork->of_ad, adflags );
421 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
422 return (AFPERR_DENYCONF);
425 /* now try to set the deny lock. if the fork is open for read or
426 * write, a read lock will already have been set. otherwise, we upgrade
427 * our lock to a write lock.
429 * NOTE: we can't write lock a read-only file. on those, we just
430 * make sure that we have a read lock set. that way, we at least prevent
431 * someone else from really setting a deny read/write on the file. */
432 lockop = (ad_getoflags(ofork->of_ad, eid) & O_RDWR) ?
433 ADLOCK_WR : ADLOCK_RD;
434 ret = (access & OPENACC_DWR) ? ad_lock(ofork->of_ad, eid,
435 lockop | ADLOCK_FILELOCK |
436 ADLOCK_UPGRADE, AD_FILELOCK_WR, 1,
438 if (!ret && (access & OPENACC_DRD))
439 ret = ad_lock(ofork->of_ad, eid, lockop | ADLOCK_FILELOCK |
440 ADLOCK_UPGRADE, AD_FILELOCK_RD, 1, ofrefnum);
444 ad_close( ofork->of_ad, adflags );
447 case EAGAIN: /* return data anyway */
451 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
452 return( AFPERR_DENYCONF );
456 syslog( LOG_ERR, "afp_openfork: ad_lock: %m" );
457 return( AFPERR_PARAM );
462 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
468 return (access & OPENACC_WR) ? AFPERR_LOCK : AFPERR_ACCESS;
472 int afp_setforkparams(obj, ibuf, ibuflen, rbuf, rbuflen )
475 int ibuflen, *rbuflen;
479 u_int16_t ofrefnum, bitmap;
483 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
484 ibuf += sizeof( ofrefnum );
485 memcpy(&bitmap, ibuf, sizeof(bitmap));
486 bitmap = ntohs(bitmap);
487 ibuf += sizeof( bitmap );
488 memcpy(&size, ibuf, sizeof( size ));
489 size = ntohl( size );
492 if (( ofork = of_find( ofrefnum )) == NULL ) {
493 syslog( LOG_ERR, "afp_setforkparams: of_find: %m" );
494 return( AFPERR_PARAM );
497 if (ofork->of_vol->v_flags & AFPVOL_RO)
500 if ((ofork->of_flags & AFPFORK_ACCWR) == 0)
501 return AFPERR_ACCESS;
506 if ((bitmap == (1<<FILPBIT_DFLEN)) && (ofork->of_flags & AFPFORK_DATA)) {
507 err = ad_dtruncate( ofork->of_ad, size );
509 goto afp_setfork_err;
510 } else if ((bitmap == (1<<FILPBIT_RFLEN)) &&
511 (ofork->of_flags & AFPFORK_RSRC)) {
512 ad_refresh( ofork->of_ad );
513 err = ad_rtruncate(ofork->of_ad, size);
515 goto afp_setfork_err;
517 if (ad_flush( ofork->of_ad, ADFLAGS_HF ) < 0) {
518 syslog( LOG_ERR, "afp_setforkparams: ad_flush: %m" );
519 return( AFPERR_PARAM );
522 return AFPERR_BITMAP;
525 if ( flushfork( ofork ) < 0 ) {
526 syslog( LOG_ERR, "afp_setforkparams: flushfork: %m" );
541 return AFPERR_ACCESS;
552 /* for this to work correctly, we need to check for locks before each
553 * read and write. that's most easily handled by always doing an
554 * appropriate check before each ad_read/ad_write. other things
555 * that can change files like truncate are handled internally to those
558 #define ENDBIT(a) ((a) & 0x80)
559 #define UNLOCKBIT(a) ((a) & 0x01)
560 int afp_bytelock(obj, ibuf, ibuflen, rbuf, rbuflen )
563 int ibuflen, *rbuflen;
566 int32_t offset, length;
573 /* figure out parameters */
575 flags = *ibuf; /* first bit = endflag, lastbit = lockflag */
577 memcpy(&ofrefnum, ibuf, sizeof(ofrefnum));
578 ibuf += sizeof(ofrefnum);
580 if (( ofork = of_find( ofrefnum )) == NULL ) {
581 syslog( LOG_ERR, "afp_bytelock: of_find: %m" );
582 return( AFPERR_PARAM );
585 if ( ofork->of_flags & AFPFORK_DATA) {
587 } else if (ofork->of_flags & AFPFORK_RSRC) {
592 memcpy(&offset, ibuf, sizeof( offset ));
593 offset = ntohl(offset);
594 ibuf += sizeof(offset);
596 memcpy(&length, ibuf, sizeof( length ));
597 length = ntohl(length);
598 if (length == 0xFFFFFFFF)
599 length = BYTELOCK_MAX;
600 else if (length <= 0) {
602 } else if ((length >= AD_FILELOCK_BASE) &&
603 (ad_hfileno(ofork->of_ad) == -1))
607 offset += ad_size(ofork->of_ad, eid);
609 if (offset < 0) /* error if we have a negative offset */
612 /* if the file is a read-only file, we use read locks instead of
613 * write locks. that way, we can prevent anyone from initiating
615 if (ad_lock(ofork->of_ad, eid, UNLOCKBIT(flags) ? ADLOCK_CLR :
616 ((ad_getoflags(ofork->of_ad, eid) & O_RDWR) ?
617 ADLOCK_WR : ADLOCK_RD), offset, length,
618 ofork->of_refnum) < 0) {
622 return UNLOCKBIT(flags) ? AFPERR_NORANGE : AFPERR_LOCK;
628 return UNLOCKBIT(flags) ? AFPERR_NORANGE : AFPERR_RANGEOVR;
637 offset = htonl(offset);
638 memcpy(rbuf, &offset, sizeof( offset ));
639 *rbuflen = sizeof( offset );
645 static __inline__ int crlf( of )
650 if ( ad_hfileno( of->of_ad ) == -1 ||
651 memcmp( ufinderi, ad_entry( of->of_ad, ADEID_FINDERI ),
653 if (( em = getextmap( of->of_name )) == NULL ||
654 memcmp( "TEXT", em->em_type, sizeof( em->em_type )) == 0 ) {
660 if ( memcmp( ufinderi,
661 ad_entry( of->of_ad, ADEID_FINDERI ), 4 ) == 0 ) {
670 static __inline__ ssize_t read_file(struct ofork *ofork, int eid,
671 int offset, u_char nlmask,
672 u_char nlchar, char *rbuf,
673 int *rbuflen, const int xlate)
679 cc = ad_read(ofork->of_ad, eid, offset, rbuf, *rbuflen);
681 syslog( LOG_ERR, "afp_read: ad_read: %m" );
683 return( AFPERR_PARAM );
685 if ( cc < *rbuflen ) {
693 for ( p = rbuf, q = p + cc; p < q; ) {
694 if (( *p++ & nlmask ) == nlchar ) {
705 * If this file is of type TEXT, then swap \012 to \015.
708 for ( p = rbuf, q = p + cc; p < q; p++ ) {
709 if ( *p == '\012' ) {
711 } else if ( *p == '\015' ) {
720 return( AFPERR_EOF );
725 int afp_read(obj, ibuf, ibuflen, rbuf, rbuflen)
728 int ibuflen, *rbuflen;
732 int32_t offset, saveoff, reqcount;
733 int cc, err, eid, xlate = 0;
735 u_char nlmask, nlchar;
738 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
739 ibuf += sizeof( u_short );
741 if (( ofork = of_find( ofrefnum )) == NULL ) {
742 syslog( LOG_ERR, "afp_read: of_find: %m" );
747 if ((ofork->of_flags & AFPFORK_ACCRD) == 0) {
752 memcpy(&offset, ibuf, sizeof( offset ));
753 offset = ntohl( offset );
754 ibuf += sizeof( offset );
755 memcpy(&reqcount, ibuf, sizeof( reqcount ));
756 reqcount = ntohl( reqcount );
757 ibuf += sizeof( reqcount );
762 /* if we wanted to be picky, we could add in the following
763 * bit: if (afp_version == 11 && !(nlmask == 0xFF || !nlmask))
765 if (reqcount < 0 || offset < 0) {
770 if ( ofork->of_flags & AFPFORK_DATA) {
772 xlate = (ofork->of_vol->v_flags & AFPVOL_CRLF) ? crlf(ofork) : 0;
773 } else if (ofork->of_flags & AFPFORK_RSRC) {
775 } else { /* fork wasn't opened. this should never really happen. */
780 /* zero request count */
786 /* reqcount isn't always truthful. we need to deal with that. */
787 if ((size = ad_size(ofork->of_ad, eid)) == 0) {
793 if (ad_tmplock(ofork->of_ad, eid, ADLOCK_RD, saveoff, reqcount) < 0) {
798 #define min(a,b) ((a)<(b)?(a):(b))
799 *rbuflen = min( reqcount, *rbuflen );
800 err = read_file(ofork, eid, offset, nlmask, nlchar, rbuf, rbuflen,
805 /* dsi can stream requests. we can only do this if we're not checking
806 * for an end-of-line character. oh well. */
807 if ((obj->proto == AFPPROTO_DSI) && (*rbuflen < reqcount) && !nlmask) {
808 DSI *dsi = obj->handle;
810 /* subtract off the offset */
812 if (reqcount > size) {
817 if (obj->options.flags & OPTION_DEBUG) {
818 printf( "(read) reply: %d/%d, %d\n", *rbuflen,
819 reqcount, dsi->clientID);
820 bprint(rbuf, *rbuflen);
825 /* dsi_readinit() returns size of next read buffer. by this point,
826 * we know that we're sending some data. if we fail, something
827 * horrible happened. */
828 if ((*rbuflen = dsi_readinit(dsi, rbuf, *rbuflen, reqcount, err)) < 0)
831 /* due to the nature of afp packets, we have to exit if we get
832 an error. we can't do this with translation on. */
833 #ifdef HAVE_SENDFILE_READ
834 if (!(xlate || (obj->options.flags & OPTION_DEBUG))) {
835 if (ad_readfile(ofork->of_ad, eid, dsi->socket, offset,
836 dsi->datasize) < 0) {
840 syslog(LOG_ERR, "afp_read: ad_readfile: %m");
852 /* fill up our buffer. */
853 while (*rbuflen > 0) {
854 cc = read_file(ofork, eid, offset, nlmask, nlchar, rbuf,
860 if (obj->options.flags & OPTION_DEBUG) {
861 printf( "(read) reply: %d, %d\n", *rbuflen, dsi->clientID);
862 bprint(rbuf, *rbuflen);
865 /* dsi_read() also returns buffer size of next allocation */
866 cc = dsi_read(dsi, rbuf, *rbuflen); /* send it off */
875 syslog(LOG_ERR, "afp_read: %m");
877 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
882 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
890 int afp_flush(obj, ibuf, ibuflen, rbuf, rbuflen )
893 int ibuflen, *rbuflen;
901 memcpy(&vid, ibuf, sizeof(vid));
902 if (( vol = getvolbyvid( vid )) == NULL ) {
903 return( AFPERR_PARAM );
910 int afp_flushfork(obj, ibuf, ibuflen, rbuf, rbuflen )
913 int ibuflen, *rbuflen;
920 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
922 if (( ofork = of_find( ofrefnum )) == NULL ) {
923 syslog( LOG_ERR, "afp_flushfork: of_find: %m" );
924 return( AFPERR_PARAM );
927 if ( flushfork( ofork ) < 0 ) {
928 syslog( LOG_ERR, "afp_flushfork: %m" );
934 /* this is very similar to closefork */
935 int flushfork( ofork )
939 int len, err = 0, doflush = 0;
941 if ( ad_dfileno( ofork->of_ad ) != -1 &&
942 fsync( ad_dfileno( ofork->of_ad )) < 0 ) {
943 syslog( LOG_ERR, "flushfork: dfile(%d) %m",
944 ad_dfileno(ofork->of_ad) );
948 if ( ad_hfileno( ofork->of_ad ) != -1 ) {
950 /* read in the rfork length */
951 len = ad_getentrylen(ofork->of_ad, ADEID_RFORK);
952 ad_refresh(ofork->of_ad);
954 /* set the date if we're dirty */
955 if ((ofork->of_flags & AFPFORK_DIRTY) &&
956 (gettimeofday(&tv, NULL) == 0)) {
957 ad_setdate(ofork->of_ad, AD_DATE_MODIFY|AD_DATE_UNIX, tv.tv_sec);
958 ofork->of_flags &= ~AFPFORK_DIRTY;
962 /* if we're actually flushing this fork, make sure to set the
963 * length. otherwise, just use the stored length */
964 if ((ofork->of_flags & AFPFORK_RSRC) &&
965 (len != ad_getentrylen(ofork->of_ad, ADEID_RFORK))) {
966 ad_setentrylen(ofork->of_ad, ADEID_RFORK, len);
971 /* flush the header (if it is a resource fork) */
972 if (ofork->of_flags & AFPFORK_RSRC)
973 if (doflush && (ad_flush(ofork->of_ad, ADFLAGS_HF) < 0))
976 if (fsync( ad_hfileno( ofork->of_ad )) < 0)
980 syslog( LOG_ERR, "flushfork: hfile(%d) %m",
981 ad_hfileno(ofork->of_ad) );
987 int afp_closefork(obj, ibuf, ibuflen, rbuf, rbuflen )
990 int ibuflen, *rbuflen;
994 int adflags, aint, doflush = 0;
999 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1001 if (( ofork = of_find( ofrefnum )) == NULL ) {
1002 syslog( LOG_ERR, "afp_closefork: of_find: %m" );
1003 return( AFPERR_PARAM );
1007 if ((ofork->of_flags & AFPFORK_DATA) &&
1008 (ad_dfileno( ofork->of_ad ) != -1)) {
1009 adflags |= ADFLAGS_DF;
1012 if ( ad_hfileno( ofork->of_ad ) != -1 ) {
1013 adflags |= ADFLAGS_HF;
1015 aint = ad_getentrylen( ofork->of_ad, ADEID_RFORK );
1016 ad_refresh( ofork->of_ad );
1017 if ((ofork->of_flags & AFPFORK_DIRTY) &&
1018 (gettimeofday(&tv, NULL) == 0)) {
1019 ad_setdate(ofork->of_ad, AD_DATE_MODIFY | AD_DATE_UNIX,
1025 * Only set the rfork's length if we're closing the rfork.
1027 if ((ofork->of_flags & AFPFORK_RSRC) && aint !=
1028 ad_getentrylen( ofork->of_ad, ADEID_RFORK )) {
1029 ad_setentrylen( ofork->of_ad, ADEID_RFORK, aint );
1033 ad_flush( ofork->of_ad, adflags );
1037 if ( ad_close( ofork->of_ad, adflags ) < 0 ) {
1038 syslog( LOG_ERR, "afp_closefork: ad_close: %m" );
1039 return( AFPERR_PARAM );
1042 of_dealloc( ofork );
1047 static __inline__ ssize_t write_file(struct ofork *ofork, int eid,
1048 off_t offset, char *rbuf,
1049 size_t rbuflen, const int xlate)
1055 * If this file is of type TEXT, swap \015 to \012.
1058 for ( p = rbuf, q = p + rbuflen; p < q; p++ ) {
1059 if ( *p == '\015' ) {
1061 } else if ( *p == '\012' ) {
1067 if (( cc = ad_write(ofork->of_ad, eid, offset, 0,
1068 rbuf, rbuflen)) < 0 ) {
1073 return( AFPERR_DFULL );
1075 syslog( LOG_ERR, "afp_write: ad_write: %m" );
1076 return( AFPERR_PARAM );
1083 /* FPWrite. NOTE: on an error, we always use afp_write_err as
1084 * the client may have sent us a bunch of data that's not reflected
1085 * in reqcount et al. */
1086 int afp_write(obj, ibuf, ibuflen, rbuf, rbuflen)
1089 int ibuflen, *rbuflen;
1091 struct ofork *ofork;
1092 int32_t offset, saveoff, reqcount;
1093 int endflag, eid, xlate = 0, err = AFP_OK;
1097 /* figure out parameters */
1099 endflag = ENDBIT(*ibuf);
1101 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1102 ibuf += sizeof( ofrefnum );
1103 memcpy(&offset, ibuf, sizeof( offset ));
1104 offset = ntohl( offset );
1105 ibuf += sizeof( offset );
1106 memcpy(&reqcount, ibuf, sizeof( reqcount ));
1107 reqcount = ntohl( reqcount );
1108 ibuf += sizeof( reqcount );
1110 if (( ofork = of_find( ofrefnum )) == NULL ) {
1111 syslog( LOG_ERR, "afp_write: of_find: %m" );
1116 if ((ofork->of_flags & AFPFORK_ACCWR) == 0) {
1117 err = AFPERR_ACCESS;
1122 writtenfork = ofork;
1125 if ( ofork->of_flags & AFPFORK_DATA) {
1127 xlate = (ofork->of_vol->v_flags & AFPVOL_CRLF) ? crlf(ofork) : 0;
1128 } else if (ofork->of_flags & AFPFORK_RSRC) {
1131 err = AFPERR_ACCESS; /* should never happen */
1136 offset += ad_size(ofork->of_ad, eid);
1138 /* handle bogus parameters */
1139 if (reqcount < 0 || offset < 0) {
1144 /* offset can overflow on 64-bit capable filesystems.
1145 * report disk full if that's going to happen. */
1146 if (offset + reqcount < 0) {
1151 if (!reqcount) { /* handle request counts of 0 */
1153 offset = htonl(offset);
1154 memcpy(rbuf, &offset, sizeof(offset));
1159 if (ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, saveoff,
1165 /* this is yucky, but dsi can stream i/o and asp can't */
1166 switch (obj->proto) {
1169 if (asp_wrtcont(obj->handle, rbuf, rbuflen) < 0) {
1171 syslog( LOG_ERR, "afp_write: asp_wrtcont: %m" );
1172 return( AFPERR_PARAM );
1175 if (obj->options.flags & OPTION_DEBUG) {
1176 printf("(write) len: %d\n", *rbuflen);
1177 bprint(rbuf, *rbuflen);
1180 if ((cc = write_file(ofork, eid, offset, rbuf, *rbuflen,
1183 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
1188 #endif /* no afp/asp */
1192 DSI *dsi = obj->handle;
1194 /* find out what we have already and write it out. */
1195 cc = dsi_writeinit(dsi, rbuf, *rbuflen);
1197 (cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
1198 dsi_writeflush(dsi);
1200 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
1205 #if 0 /*def HAVE_SENDFILE_WRITE*/
1206 if (!(xlate || obj->options.flags & OPTION_DEBUG)) {
1207 if ((cc = ad_writefile(ofork->of_ad, eid, dsi->socket,
1208 offset, dsi->datasize)) < 0) {
1216 syslog( LOG_ERR, "afp_write: ad_writefile: %m" );
1217 goto afp_write_loop;
1219 dsi_writeflush(dsi);
1221 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
1227 goto afp_write_done;
1231 /* loop until everything gets written. currently
1232 * dsi_write handles the end case by itself. */
1234 while ((cc = dsi_write(dsi, rbuf, *rbuflen))) {
1235 if ( obj->options.flags & OPTION_DEBUG ) {
1236 printf("(write) command cont'd: %d\n", cc);
1240 if ((cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
1241 dsi_writeflush(dsi);
1243 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
1254 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
1255 if ( ad_hfileno( ofork->of_ad ) != -1 )
1256 ofork->of_flags |= AFPFORK_DIRTY;
1258 offset = htonl( offset );
1259 #if defined(__GNUC__) && defined(HAVE_GCC_MEMCPY_BUG)
1260 bcopy(&offset, rbuf, sizeof(offset));
1262 memcpy(rbuf, &offset, sizeof(offset));
1264 *rbuflen = sizeof(offset);
1268 if (obj->proto == AFPPROTO_DSI) {
1269 dsi_writeinit(obj->handle, rbuf, *rbuflen);
1270 dsi_writeflush(obj->handle);
1273 *rbuflen = (err == AFP_OK) ? sizeof(offset) : 0;
1278 int afp_getforkparams(obj, ibuf, ibuflen, rbuf, rbuflen )
1281 int ibuflen, *rbuflen;
1283 struct ofork *ofork;
1285 u_int16_t ofrefnum, bitmap;
1288 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1289 ibuf += sizeof( ofrefnum );
1290 memcpy(&bitmap, ibuf, sizeof( bitmap ));
1291 bitmap = ntohs( bitmap );
1292 ibuf += sizeof( bitmap );
1295 if (( ofork = of_find( ofrefnum )) == NULL ) {
1296 syslog( LOG_ERR, "afp_getforkparams: of_find: %m" );
1297 return( AFPERR_PARAM );
1300 if (( ret = getforkparams( ofork, bitmap,
1301 rbuf + sizeof( u_short ), &buflen, 0 )) != AFP_OK ) {
1305 *rbuflen = buflen + sizeof( u_short );
1306 bitmap = htons( bitmap );
1307 memcpy(rbuf, &bitmap, sizeof( bitmap ));