2 * Copyright (c) 1990,1993 Regents of The University of Michigan.
3 * All Rights Reserved. See COPYRIGHT.
14 #include <sys/param.h>
16 #include <sys/types.h>
18 #include <sys/socket.h>
20 #include <netatalk/endian.h>
21 #include <netatalk/at.h>
23 #include <atalk/dsi.h>
24 #include <atalk/atp.h>
25 #include <atalk/asp.h>
26 #include <atalk/afp.h>
27 #include <atalk/adouble.h>
28 #include <atalk/util.h>
29 #include <atalk/cnid.h>
34 #include "directory.h"
38 #define BYTELOCK_MAX 0x7FFFFFFFU
40 struct ofork *writtenfork;
42 static int getforkparams(ofork, bitmap, buf, buflen, attrbits )
47 const u_int16_t attrbits;
51 char *data, *nameoff = NULL, *upath;
52 int bit = 0, isad = 1;
56 if ( ad_hfileno( ofork->of_ad ) == -1 ) {
59 aint = ad_getentrylen( ofork->of_ad, ADEID_RFORK );
60 if ( ad_refresh( ofork->of_ad ) < 0 ) {
61 syslog( LOG_ERR, "getforkparams: ad_refresh: %m");
62 return( AFPERR_PARAM );
64 /* See afp_closefork() for why this is bad */
65 ad_setentrylen( ofork->of_ad, ADEID_RFORK, aint );
68 /* can only get the length of the opened fork */
69 if (((bitmap & (1<<FILPBIT_DFLEN)) && (ofork->of_flags & AFPFORK_RSRC)) ||
70 ((bitmap & (1<<FILPBIT_RFLEN)) && (ofork->of_flags & AFPFORK_DATA))) {
71 return( AFPERR_BITMAP );
74 if ( bitmap & ( 1<<FILPBIT_DFLEN | 1<<FILPBIT_FNUM |
75 (1 << FILPBIT_CDATE) | (1 << FILPBIT_MDATE) |
76 (1 << FILPBIT_BDATE))) {
77 upath = mtoupath(ofork->of_vol, ofork->of_name);
78 if ( ad_dfileno( ofork->of_ad ) == -1 ) {
79 if ( stat( upath, &st ) < 0 )
80 return( AFPERR_NOOBJ );
82 if ( fstat( ad_dfileno( ofork->of_ad ), &st ) < 0 ) {
83 return( AFPERR_BITMAP );
89 while ( bitmap != 0 ) {
90 while (( bitmap & 1 ) == 0 ) {
98 ad_getattr(ofork->of_ad, &ashort);
103 ashort = htons(ntohs(ashort) | attrbits);
104 memcpy(data, &ashort, sizeof( ashort ));
105 data += sizeof( ashort );
109 memcpy(data, &ofork->of_dir->d_did, sizeof( aint ));
110 data += sizeof( aint );
115 (ad_getdate(ofork->of_ad, AD_DATE_CREATE, &aint) < 0))
116 aint = AD_DATE_FROM_UNIX(st.st_mtime);
117 memcpy(data, &aint, sizeof( aint ));
118 data += sizeof( aint );
123 (ad_getdate(ofork->of_ad, AD_DATE_MODIFY, &aint) < 0) ||
124 (AD_DATE_TO_UNIX(aint) < st.st_mtime))
125 aint = AD_DATE_FROM_UNIX(st.st_mtime);
126 memcpy(data, &aint, sizeof( aint ));
127 data += sizeof( aint );
132 (ad_getdate(ofork->of_ad, AD_DATE_BACKUP, &aint) < 0))
133 aint = AD_DATE_START;
134 memcpy(data, &aint, sizeof( aint ));
135 data += sizeof( aint );
140 (void *) ad_entry(ofork->of_ad, ADEID_FINDERI) :
141 (void *) ufinderi, 32);
143 memcmp( ad_entry( ofork->of_ad, ADEID_FINDERI ),
144 ufinderi, 8 ) == 0 ) {
145 memcpy(data, ufinderi, 8 );
146 if (( em = getextmap( ofork->of_name )) != NULL ) {
147 memcpy(data, em->em_type, sizeof( em->em_type ));
148 memcpy(data + 4, em->em_creator,
149 sizeof( em->em_creator ));
157 data += sizeof(u_int16_t);
161 memset(data, 0, sizeof(u_int16_t));
162 data += sizeof(u_int16_t);
167 * See file.c getfilparams() for why this is done this
170 #if AD_VERSION > AD_VERSION1
172 memcpy(&aint, ad_entry(ofork->of_ad, ADEID_DID), sizeof(aint));
176 if (!(aint = cnid_add(ofork->of_vol->v_db, &st,
177 ofork->of_dir->d_did,
178 upath, strlen(upath), aint))) {
183 aint = ( st.st_dev << 16 ) | ( st.st_ino & 0x0000ffff );
185 #if AD_VERSION > AD_VERSION1
188 memcpy(data, &aint, sizeof( aint ));
189 data += sizeof( aint );
193 aint = htonl( st.st_size );
194 memcpy(data, &aint, sizeof( aint ));
195 data += sizeof( aint );
200 aint = htonl( ad_getentrylen( ofork->of_ad, ADEID_RFORK ));
204 memcpy(data, &aint, sizeof( aint ));
205 data += sizeof( aint );
209 return( AFPERR_BITMAP );
216 ashort = htons( data - buf );
217 memcpy(nameoff, &ashort, sizeof( ashort ));
218 aint = strlen( ofork->of_name );
219 aint = ( aint > MACFILELEN ) ? MACFILELEN : aint;
221 memcpy(data, ofork->of_name, aint );
225 *buflen = data - buf;
229 int afp_openfork(obj, ibuf, ibuflen, rbuf, rbuflen )
232 int ibuflen, *rbuflen;
236 struct ofork *ofork, *opened;
237 struct adouble *adsame = NULL;
238 int buflen, ret, adflags, eid, lockop;
240 u_int16_t vid, bitmap, access, ofrefnum, attrbits = 0;
241 char fork, *path, *upath;
245 memcpy(&vid, ibuf, sizeof( vid ));
249 if (( vol = getvolbyvid( vid )) == NULL ) {
250 return( AFPERR_PARAM );
253 memcpy(&did, ibuf, sizeof( did ));
254 ibuf += sizeof( int );
256 if (( dir = dirsearch( vol, did )) == NULL ) {
257 return( AFPERR_NOOBJ );
260 memcpy(&bitmap, ibuf, sizeof( bitmap ));
261 bitmap = ntohs( bitmap );
262 ibuf += sizeof( bitmap );
263 memcpy(&access, ibuf, sizeof( access ));
264 access = ntohs( access );
265 ibuf += sizeof( access );
267 if ((vol->v_flags & AFPVOL_RO) && (access & OPENACC_WR)) {
271 if (( path = cname( vol, dir, &ibuf )) == NULL ) {
272 return( AFPERR_NOOBJ );
275 if ( fork == OPENFORK_DATA ) {
277 adflags = ADFLAGS_DF|ADFLAGS_HF;
280 adflags = ADFLAGS_HF;
283 /* XXX: this probably isn't the best way to do this. the already
284 open bits should really be set if the fork is opened by any
285 program, not just this one. however, that's problematic to do
286 if we can't write lock files somewhere. opened is also passed to
287 ad_open so that we can keep file locks together. */
288 if ((opened = of_findname(vol, curdir, path))) {
289 attrbits = ((opened->of_flags & AFPFORK_RSRC) ? ATTRBIT_ROPEN : 0) |
290 ((opened->of_flags & AFPFORK_DATA) ? ATTRBIT_DOPEN : 0);
291 adsame = opened->of_ad;
294 if (( ofork = of_alloc(vol, curdir, path, &ofrefnum, eid,
296 return( AFPERR_NFILE );
299 /* try opening in read-write mode with a fallback to read-only
300 * if we don't need write access. */
301 upath = mtoupath(vol, path);
303 if (ad_open(upath, adflags, O_RDWR, 0, ofork->of_ad) < 0) {
308 if (access & OPENACC_WR)
311 if (ad_open(upath, adflags, O_RDONLY, 0, ofork->of_ad) < 0) {
312 /* check for a read-only data fork */
313 if ((adflags != ADFLAGS_HF) &&
314 (ad_open(upath, ADFLAGS_DF, O_RDONLY, 0, ofork->of_ad) < 0))
317 adflags = ADFLAGS_DF;
324 /* see if client asked for the data fork */
325 if (fork == OPENFORK_DATA) {
326 if (((access & OPENACC_WR) &&
327 (ad_open(upath, ADFLAGS_DF, O_RDWR, 0, ofork->of_ad) < 0))
328 || (ad_open(upath, ADFLAGS_DF, O_RDONLY, 0,
329 ofork->of_ad) < 0)) {
332 adflags = ADFLAGS_DF;
334 } else if (stat(upath, &st) == 0) {
335 /* here's the deal. we only try to create the resource
336 * fork if the user wants to open it for write access. */
337 if ((access & OPENACC_WR) &&
338 (ad_open(upath, adflags, O_RDWR | O_CREAT,
339 0666, ofork->of_ad) < 0))
351 ret = AFPERR_BADTYPE;
355 syslog( LOG_ERR, "afp_openfork: ad_open: %m" );
362 if ((adflags & ADFLAGS_HF) &&
363 (ad_getoflags( ofork->of_ad, ADFLAGS_HF ) & O_CREAT)) {
364 ad_setentrylen( ofork->of_ad, ADEID_NAME, strlen( path ));
365 memcpy(ad_entry( ofork->of_ad, ADEID_NAME ), path,
366 ad_getentrylen( ofork->of_ad, ADEID_NAME ));
367 ad_flush( ofork->of_ad, adflags );
370 if (( ret = getforkparams(ofork, bitmap, rbuf + 2 * sizeof( u_int16_t ),
371 &buflen, attrbits )) != AFP_OK ) {
372 ad_close( ofork->of_ad, adflags );
376 *rbuflen = buflen + 2 * sizeof( u_int16_t );
377 bitmap = htons( bitmap );
378 memcpy(rbuf, &bitmap, sizeof( u_int16_t ));
379 rbuf += sizeof( u_int16_t );
382 * synchronization locks:
385 * 1) attempt a read lock to see if we have read or write
387 * 2) if that succeeds, set a write lock to correspond to the
388 * deny mode requested.
389 * 3) whenever a file is read/written, locks get set which
393 /* don't try to lock non-existent rforks. */
394 if ((eid == ADEID_DFORK) || (ad_hfileno(ofork->of_ad) != -1)) {
396 /* try to see if we have access. */
398 if (access & OPENACC_WR) {
399 ofork->of_flags |= AFPFORK_ACCWR;
400 ret = ad_lock(ofork->of_ad, eid, ADLOCK_RD | ADLOCK_FILELOCK,
401 AD_FILELOCK_WR, 1, ofrefnum);
404 if (!ret && (access & OPENACC_RD)) {
405 ofork->of_flags |= AFPFORK_ACCRD;
406 ret = ad_lock(ofork->of_ad, eid, ADLOCK_RD | ADLOCK_FILELOCK,
407 AD_FILELOCK_RD, 1, ofrefnum);
410 /* can we access the fork? */
412 ad_close( ofork->of_ad, adflags );
415 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
416 return (AFPERR_DENYCONF);
419 /* now try to set the deny lock. if the fork is open for read or
420 * write, a read lock will already have been set. otherwise, we upgrade
421 * our lock to a write lock.
423 * NOTE: we can't write lock a read-only file. on those, we just
424 * make sure that we have a read lock set. that way, we at least prevent
425 * someone else from really setting a deny read/write on the file. */
426 lockop = (ad_getoflags(ofork->of_ad, eid) & O_RDWR) ?
427 ADLOCK_WR : ADLOCK_RD;
428 ret = (access & OPENACC_DWR) ? ad_lock(ofork->of_ad, eid,
429 lockop | ADLOCK_FILELOCK |
430 ADLOCK_UPGRADE, AD_FILELOCK_WR, 1,
432 if (!ret && (access & OPENACC_DRD))
433 ret = ad_lock(ofork->of_ad, eid, lockop | ADLOCK_FILELOCK |
434 ADLOCK_UPGRADE, AD_FILELOCK_RD, 1, ofrefnum);
438 ad_close( ofork->of_ad, adflags );
441 case EAGAIN: /* return data anyway */
445 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
446 return( AFPERR_DENYCONF );
450 syslog( LOG_ERR, "afp_openfork: ad_lock: %m" );
451 return( AFPERR_PARAM );
456 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
462 return (access & OPENACC_WR) ? AFPERR_LOCK : AFPERR_ACCESS;
466 int afp_setforkparams(obj, ibuf, ibuflen, rbuf, rbuflen )
469 int ibuflen, *rbuflen;
473 u_int16_t ofrefnum, bitmap;
477 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
478 ibuf += sizeof( ofrefnum );
479 memcpy(&bitmap, ibuf, sizeof(bitmap));
480 bitmap = ntohs(bitmap);
481 ibuf += sizeof( bitmap );
482 memcpy(&size, ibuf, sizeof( size ));
483 size = ntohl( size );
486 if (( ofork = of_find( ofrefnum )) == NULL ) {
487 syslog( LOG_ERR, "afp_setforkparams: of_find: %m" );
488 return( AFPERR_PARAM );
491 if (ofork->of_vol->v_flags & AFPVOL_RO)
494 if ((ofork->of_flags & AFPFORK_ACCWR) == 0)
495 return AFPERR_ACCESS;
500 if ((bitmap == (1<<FILPBIT_DFLEN)) && (ofork->of_flags & AFPFORK_DATA)) {
501 err = ad_dtruncate( ofork->of_ad, size );
503 goto afp_setfork_err;
504 } else if ((bitmap == (1<<FILPBIT_RFLEN)) &&
505 (ofork->of_flags & AFPFORK_RSRC)) {
506 ad_refresh( ofork->of_ad );
507 err = ad_rtruncate(ofork->of_ad, size);
509 goto afp_setfork_err;
511 if (ad_flush( ofork->of_ad, ADFLAGS_HF ) < 0) {
512 syslog( LOG_ERR, "afp_setforkparams: ad_flush: %m" );
513 return( AFPERR_PARAM );
516 return AFPERR_BITMAP;
519 if ( flushfork( ofork ) < 0 ) {
520 syslog( LOG_ERR, "afp_setforkparams: flushfork: %m" );
535 return AFPERR_ACCESS;
546 /* for this to work correctly, we need to check for locks before each
547 * read and write. that's most easily handled by always doing an
548 * appropriate check before each ad_read/ad_write. other things
549 * that can change files like truncate are handled internally to those
552 #define ENDBIT(a) ((a) & 0x80)
553 #define UNLOCKBIT(a) ((a) & 0x01)
554 int afp_bytelock(obj, ibuf, ibuflen, rbuf, rbuflen )
557 int ibuflen, *rbuflen;
560 int32_t offset, length;
567 /* figure out parameters */
569 flags = *ibuf; /* first bit = endflag, lastbit = lockflag */
571 memcpy(&ofrefnum, ibuf, sizeof(ofrefnum));
572 ibuf += sizeof(ofrefnum);
574 if (( ofork = of_find( ofrefnum )) == NULL ) {
575 syslog( LOG_ERR, "afp_bytelock: of_find: %m" );
576 return( AFPERR_PARAM );
579 if ( ofork->of_flags & AFPFORK_DATA) {
581 } else if (ofork->of_flags & AFPFORK_RSRC) {
586 memcpy(&offset, ibuf, sizeof( offset ));
587 offset = ntohl(offset);
588 ibuf += sizeof(offset);
590 memcpy(&length, ibuf, sizeof( length ));
591 length = ntohl(length);
592 if (length == 0xFFFFFFFF)
593 length = BYTELOCK_MAX;
594 else if (length <= 0) {
596 } else if ((length >= AD_FILELOCK_BASE) &&
597 (ad_hfileno(ofork->of_ad) == -1))
601 offset += ad_size(ofork->of_ad, eid);
603 if (offset < 0) /* error if we have a negative offset */
606 /* if the file is a read-only file, we use read locks instead of
607 * write locks. that way, we can prevent anyone from initiating
609 if (ad_lock(ofork->of_ad, eid, UNLOCKBIT(flags) ? ADLOCK_CLR :
610 ((ad_getoflags(ofork->of_ad, eid) & O_RDWR) ?
611 ADLOCK_WR : ADLOCK_RD), offset, length,
612 ofork->of_refnum) < 0) {
616 return UNLOCKBIT(flags) ? AFPERR_NORANGE : AFPERR_LOCK;
622 return UNLOCKBIT(flags) ? AFPERR_NORANGE : AFPERR_RANGEOVR;
631 offset = htonl(offset);
632 memcpy(rbuf, &offset, sizeof( offset ));
633 *rbuflen = sizeof( offset );
639 static __inline__ int crlf( of )
644 if ( ad_hfileno( of->of_ad ) == -1 ||
645 memcmp( ufinderi, ad_entry( of->of_ad, ADEID_FINDERI ),
647 if (( em = getextmap( of->of_name )) == NULL ||
648 memcmp( "TEXT", em->em_type, sizeof( em->em_type )) == 0 ) {
654 if ( memcmp( ufinderi,
655 ad_entry( of->of_ad, ADEID_FINDERI ), 4 ) == 0 ) {
664 static __inline__ ssize_t read_file(struct ofork *ofork, int eid,
665 int offset, u_char nlmask,
666 u_char nlchar, char *rbuf,
667 int *rbuflen, const int xlate)
673 cc = ad_read(ofork->of_ad, eid, offset, rbuf, *rbuflen);
675 syslog( LOG_ERR, "afp_read: ad_read: %m" );
677 return( AFPERR_PARAM );
679 if ( cc < *rbuflen ) {
687 for ( p = rbuf, q = p + cc; p < q; ) {
688 if (( *p++ & nlmask ) == nlchar ) {
699 * If this file is of type TEXT, then swap \012 to \015.
702 for ( p = rbuf, q = p + cc; p < q; p++ ) {
703 if ( *p == '\012' ) {
705 } else if ( *p == '\015' ) {
714 return( AFPERR_EOF );
719 int afp_read(obj, ibuf, ibuflen, rbuf, rbuflen)
722 int ibuflen, *rbuflen;
726 int32_t offset, saveoff, reqcount;
727 int cc, err, eid, xlate = 0;
729 u_char nlmask, nlchar;
732 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
733 ibuf += sizeof( u_short );
735 if (( ofork = of_find( ofrefnum )) == NULL ) {
736 syslog( LOG_ERR, "afp_read: of_find: %m" );
741 if ((ofork->of_flags & AFPFORK_ACCRD) == 0) {
746 memcpy(&offset, ibuf, sizeof( offset ));
747 offset = ntohl( offset );
748 ibuf += sizeof( offset );
749 memcpy(&reqcount, ibuf, sizeof( reqcount ));
750 reqcount = ntohl( reqcount );
751 ibuf += sizeof( reqcount );
756 /* if we wanted to be picky, we could add in the following
757 * bit: if (afp_version == 11 && !(nlmask == 0xFF || !nlmask))
759 if (reqcount < 0 || offset < 0) {
764 if ( ofork->of_flags & AFPFORK_DATA) {
766 xlate = (ofork->of_vol->v_flags & AFPVOL_CRLF) ? crlf(ofork) : 0;
767 } else if (ofork->of_flags & AFPFORK_RSRC) {
769 } else { /* fork wasn't opened. this should never really happen. */
774 /* zero request count */
780 /* reqcount isn't always truthful. we need to deal with that. */
781 if ((size = ad_size(ofork->of_ad, eid)) == 0) {
787 if (ad_tmplock(ofork->of_ad, eid, ADLOCK_RD, saveoff, reqcount) < 0) {
792 #define min(a,b) ((a)<(b)?(a):(b))
793 *rbuflen = min( reqcount, *rbuflen );
794 err = read_file(ofork, eid, offset, nlmask, nlchar, rbuf, rbuflen,
799 /* dsi can stream requests. we can only do this if we're not checking
800 * for an end-of-line character. oh well. */
801 if ((obj->proto == AFPPROTO_DSI) && (*rbuflen < reqcount) && !nlmask) {
802 DSI *dsi = obj->handle;
804 /* subtract off the offset */
806 if (reqcount > size) {
811 if (obj->options.flags & OPTION_DEBUG) {
812 printf( "(read) reply: %d/%d, %d\n", *rbuflen,
813 reqcount, dsi->clientID);
814 bprint(rbuf, *rbuflen);
819 /* dsi_readinit() returns size of next read buffer. by this point,
820 * we know that we're sending some data. if we fail, something
821 * horrible happened. */
822 if ((*rbuflen = dsi_readinit(dsi, rbuf, *rbuflen, reqcount, err)) < 0)
825 /* due to the nature of afp packets, we have to exit if we get
826 an error. we can't do this with translation on. */
827 #ifdef HAVE_SENDFILE_READ
828 if (!(xlate || (obj->options.flags & OPTION_DEBUG))) {
829 if (ad_readfile(ofork->of_ad, eid, dsi->socket, offset,
830 dsi->datasize) < 0) {
834 syslog(LOG_ERR, "afp_read: ad_readfile: %m");
846 /* fill up our buffer. */
847 while (*rbuflen > 0) {
848 cc = read_file(ofork, eid, offset, nlmask, nlchar, rbuf,
854 if (obj->options.flags & OPTION_DEBUG) {
855 printf( "(read) reply: %d, %d\n", *rbuflen, dsi->clientID);
856 bprint(rbuf, *rbuflen);
859 /* dsi_read() also returns buffer size of next allocation */
860 cc = dsi_read(dsi, rbuf, *rbuflen); /* send it off */
869 syslog(LOG_ERR, "afp_read: %m");
871 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
876 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
884 int afp_flush(obj, ibuf, ibuflen, rbuf, rbuflen )
887 int ibuflen, *rbuflen;
895 memcpy(&vid, ibuf, sizeof(vid));
896 if (( vol = getvolbyvid( vid )) == NULL ) {
897 return( AFPERR_PARAM );
904 int afp_flushfork(obj, ibuf, ibuflen, rbuf, rbuflen )
907 int ibuflen, *rbuflen;
914 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
916 if (( ofork = of_find( ofrefnum )) == NULL ) {
917 syslog( LOG_ERR, "afp_flushfork: of_find: %m" );
918 return( AFPERR_PARAM );
921 if ( flushfork( ofork ) < 0 ) {
922 syslog( LOG_ERR, "afp_flushfork: %m" );
928 /* this is very similar to closefork */
929 int flushfork( ofork )
933 int len, err = 0, doflush = 0;
935 if ( ad_dfileno( ofork->of_ad ) != -1 &&
936 fsync( ad_dfileno( ofork->of_ad )) < 0 ) {
937 syslog( LOG_ERR, "flushfork: dfile(%d) %m",
938 ad_dfileno(ofork->of_ad) );
942 if ( ad_hfileno( ofork->of_ad ) != -1 ) {
943 if (ofork->of_flags & AFPFORK_RSRC) {
944 len = ad_getentrylen(ofork->of_ad, ADEID_RFORK);
945 ad_refresh(ofork->of_ad);
946 if (len != ad_getentrylen(ofork->of_ad, ADEID_RFORK)) {
947 ad_setentrylen(ofork->of_ad, ADEID_RFORK, len);
952 if ((ofork->of_flags & AFPFORK_DIRTY) &&
953 (gettimeofday(&tv, NULL) == 0)) {
954 ad_setdate(ofork->of_ad, AD_DATE_MODIFY|AD_DATE_UNIX, tv.tv_sec);
955 ofork->of_flags &= ~AFPFORK_DIRTY;
959 /* flush the header. */
960 if (doflush && (ad_flush(ofork->of_ad, ADFLAGS_HF) < 0))
963 if (fsync( ad_hfileno( ofork->of_ad )) < 0)
967 syslog( LOG_ERR, "flushfork: hfile(%d) %m",
968 ad_hfileno(ofork->of_ad) );
974 int afp_closefork(obj, ibuf, ibuflen, rbuf, rbuflen )
977 int ibuflen, *rbuflen;
981 int adflags, aint, doflush = 0;
986 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
988 if (( ofork = of_find( ofrefnum )) == NULL ) {
989 syslog( LOG_ERR, "afp_closefork: of_find: %m" );
990 return( AFPERR_PARAM );
994 if ((ofork->of_flags & AFPFORK_DATA) &&
995 (ad_dfileno( ofork->of_ad ) != -1)) {
996 adflags |= ADFLAGS_DF;
999 if ( ad_hfileno( ofork->of_ad ) != -1 ) {
1000 adflags |= ADFLAGS_HF;
1002 aint = ad_getentrylen( ofork->of_ad, ADEID_RFORK );
1003 ad_refresh( ofork->of_ad );
1004 if ((ofork->of_flags & AFPFORK_DIRTY) &&
1005 (gettimeofday(&tv, NULL) == 0)) {
1006 ad_setdate(ofork->of_ad, AD_DATE_MODIFY | AD_DATE_UNIX,
1012 * Only set the rfork's length if we're closing the rfork.
1014 if ((ofork->of_flags & AFPFORK_RSRC) && aint !=
1015 ad_getentrylen( ofork->of_ad, ADEID_RFORK )) {
1016 ad_setentrylen( ofork->of_ad, ADEID_RFORK, aint );
1020 ad_flush( ofork->of_ad, adflags );
1024 if ( ad_close( ofork->of_ad, adflags ) < 0 ) {
1025 syslog( LOG_ERR, "afp_closefork: ad_close: %m" );
1026 return( AFPERR_PARAM );
1029 of_dealloc( ofork );
1034 static __inline__ ssize_t write_file(struct ofork *ofork, int eid,
1035 off_t offset, char *rbuf,
1036 size_t rbuflen, const int xlate)
1042 * If this file is of type TEXT, swap \015 to \012.
1045 for ( p = rbuf, q = p + rbuflen; p < q; p++ ) {
1046 if ( *p == '\015' ) {
1048 } else if ( *p == '\012' ) {
1054 if (( cc = ad_write(ofork->of_ad, eid, offset, 0,
1055 rbuf, rbuflen)) < 0 ) {
1060 return( AFPERR_DFULL );
1062 syslog( LOG_ERR, "afp_write: ad_write: %m" );
1063 return( AFPERR_PARAM );
1070 /* FPWrite. NOTE: on an error, we always use afp_write_err as
1071 * the client may have sent us a bunch of data that's not reflected
1072 * in reqcount et al. */
1073 int afp_write(obj, ibuf, ibuflen, rbuf, rbuflen)
1076 int ibuflen, *rbuflen;
1078 struct ofork *ofork;
1079 int32_t offset, saveoff, reqcount;
1080 int endflag, eid, xlate = 0, err = AFP_OK;
1084 /* figure out parameters */
1086 endflag = ENDBIT(*ibuf);
1088 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1089 ibuf += sizeof( ofrefnum );
1090 memcpy(&offset, ibuf, sizeof( offset ));
1091 offset = ntohl( offset );
1092 ibuf += sizeof( offset );
1093 memcpy(&reqcount, ibuf, sizeof( reqcount ));
1094 reqcount = ntohl( reqcount );
1095 ibuf += sizeof( reqcount );
1097 if (( ofork = of_find( ofrefnum )) == NULL ) {
1098 syslog( LOG_ERR, "afp_write: of_find: %m" );
1103 if ((ofork->of_flags & AFPFORK_ACCWR) == 0) {
1104 err = AFPERR_ACCESS;
1109 writtenfork = ofork;
1112 if ( ofork->of_flags & AFPFORK_DATA) {
1114 xlate = (ofork->of_vol->v_flags & AFPVOL_CRLF) ? crlf(ofork) : 0;
1115 } else if (ofork->of_flags & AFPFORK_RSRC) {
1118 err = AFPERR_ACCESS; /* should never happen */
1123 offset += ad_size(ofork->of_ad, eid);
1125 /* handle bogus parameters */
1126 if (reqcount < 0 || offset < 0) {
1131 /* offset can overflow on 64-bit capable filesystems.
1132 * report disk full if that's going to happen. */
1133 if (offset + reqcount < 0) {
1138 if (!reqcount) { /* handle request counts of 0 */
1140 offset = htonl(offset);
1141 memcpy(rbuf, &offset, sizeof(offset));
1146 if (ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, saveoff,
1152 /* this is yucky, but dsi can stream i/o and asp can't */
1153 switch (obj->proto) {
1156 if (asp_wrtcont(obj->handle, rbuf, rbuflen) < 0) {
1158 syslog( LOG_ERR, "afp_write: asp_wrtcont: %m" );
1159 return( AFPERR_PARAM );
1162 if (obj->options.flags & OPTION_DEBUG) {
1163 printf("(write) len: %d\n", *rbuflen);
1164 bprint(rbuf, *rbuflen);
1167 if ((cc = write_file(ofork, eid, offset, rbuf, *rbuflen,
1170 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
1175 #endif /* no afp/asp */
1179 DSI *dsi = obj->handle;
1181 /* find out what we have already and write it out. */
1182 cc = dsi_writeinit(dsi, rbuf, *rbuflen);
1184 (cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
1185 dsi_writeflush(dsi);
1187 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
1192 #if 0 /*def HAVE_SENDFILE_WRITE*/
1193 if (!(xlate || obj->options.flags & OPTION_DEBUG)) {
1194 if ((cc = ad_writefile(ofork->of_ad, eid, dsi->socket,
1195 offset, dsi->datasize)) < 0) {
1203 syslog( LOG_ERR, "afp_write: ad_writefile: %m" );
1204 goto afp_write_loop;
1206 dsi_writeflush(dsi);
1208 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
1214 goto afp_write_done;
1218 /* loop until everything gets written. currently
1219 * dsi_write handles the end case by itself. */
1221 while ((cc = dsi_write(dsi, rbuf, *rbuflen))) {
1222 if ( obj->options.flags & OPTION_DEBUG ) {
1223 printf("(write) command cont'd: %d\n", cc);
1227 if ((cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
1228 dsi_writeflush(dsi);
1230 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
1241 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
1242 if ( ad_hfileno( ofork->of_ad ) != -1 )
1243 ofork->of_flags |= AFPFORK_DIRTY;
1245 offset = htonl( offset );
1246 #if defined(__GNUC__) && defined(HAVE_GCC_MEMCPY_BUG)
1247 bcopy(&offset, rbuf, sizeof(offset));
1249 memcpy(rbuf, &offset, sizeof(offset));
1251 *rbuflen = sizeof(offset);
1255 if (obj->proto == AFPPROTO_DSI) {
1256 dsi_writeinit(obj->handle, rbuf, *rbuflen);
1257 dsi_writeflush(obj->handle);
1260 *rbuflen = (err == AFP_OK) ? sizeof(offset) : 0;
1265 int afp_getforkparams(obj, ibuf, ibuflen, rbuf, rbuflen )
1268 int ibuflen, *rbuflen;
1270 struct ofork *ofork;
1272 u_int16_t ofrefnum, bitmap;
1275 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1276 ibuf += sizeof( ofrefnum );
1277 memcpy(&bitmap, ibuf, sizeof( bitmap ));
1278 bitmap = ntohs( bitmap );
1279 ibuf += sizeof( bitmap );
1282 if (( ofork = of_find( ofrefnum )) == NULL ) {
1283 syslog( LOG_ERR, "afp_getforkparams: of_find: %m" );
1284 return( AFPERR_PARAM );
1287 if (( ret = getforkparams( ofork, bitmap,
1288 rbuf + sizeof( u_short ), &buflen, 0 )) != AFP_OK ) {
1292 *rbuflen = buflen + sizeof( u_short );
1293 bitmap = htons( bitmap );
1294 memcpy(rbuf, &bitmap, sizeof( bitmap ));