2 * Copyright (c) 1990,1993 Regents of The University of Michigan.
3 * All Rights Reserved. See COPYRIGHT.
18 #include <sys/param.h>
20 #include <sys/types.h>
22 #include <sys/socket.h>
24 #include <netatalk/endian.h>
25 #include <netatalk/at.h>
27 #include <atalk/dsi.h>
28 #include <atalk/atp.h>
29 #include <atalk/asp.h>
30 #include <atalk/afp.h>
31 #include <atalk/adouble.h>
32 #include <atalk/util.h>
33 #include <atalk/cnid.h>
38 #include "directory.h"
42 #define BYTELOCK_MAX 0x7FFFFFFFU
44 struct ofork *writtenfork;
46 static int getforkparams(ofork, bitmap, buf, buflen, attrbits )
51 const u_int16_t attrbits;
55 char *data, *nameoff = NULL, *upath;
56 int bit = 0, isad = 1;
60 if ( ad_hfileno( ofork->of_ad ) == -1 ) {
63 aint = ad_getentrylen( ofork->of_ad, ADEID_RFORK );
64 if ( ad_refresh( ofork->of_ad ) < 0 ) {
65 syslog( LOG_ERR, "getforkparams: ad_refresh: %m");
66 return( AFPERR_PARAM );
68 /* See afp_closefork() for why this is bad */
69 ad_setentrylen( ofork->of_ad, ADEID_RFORK, aint );
72 /* can only get the length of the opened fork */
73 if (((bitmap & (1<<FILPBIT_DFLEN)) && (ofork->of_flags & AFPFORK_RSRC)) ||
74 ((bitmap & (1<<FILPBIT_RFLEN)) && (ofork->of_flags & AFPFORK_DATA))) {
75 return( AFPERR_BITMAP );
78 if ( bitmap & ( 1<<FILPBIT_DFLEN | 1<<FILPBIT_FNUM |
79 (1 << FILPBIT_CDATE) | (1 << FILPBIT_MDATE) |
80 (1 << FILPBIT_BDATE))) {
81 upath = mtoupath(ofork->of_vol, ofork->of_name);
82 if ( ad_dfileno( ofork->of_ad ) == -1 ) {
83 if ( stat( upath, &st ) < 0 )
84 return( AFPERR_NOOBJ );
86 if ( fstat( ad_dfileno( ofork->of_ad ), &st ) < 0 ) {
87 return( AFPERR_BITMAP );
93 while ( bitmap != 0 ) {
94 while (( bitmap & 1 ) == 0 ) {
102 ad_getattr(ofork->of_ad, &ashort);
107 ashort = htons(ntohs(ashort) | attrbits);
108 memcpy(data, &ashort, sizeof( ashort ));
109 data += sizeof( ashort );
113 memcpy(data, &ofork->of_dir->d_did, sizeof( aint ));
114 data += sizeof( aint );
119 (ad_getdate(ofork->of_ad, AD_DATE_CREATE, &aint) < 0))
120 aint = AD_DATE_FROM_UNIX(st.st_mtime);
121 memcpy(data, &aint, sizeof( aint ));
122 data += sizeof( aint );
127 (ad_getdate(ofork->of_ad, AD_DATE_MODIFY, &aint) < 0) ||
128 (AD_DATE_TO_UNIX(aint) < st.st_mtime))
129 aint = AD_DATE_FROM_UNIX(st.st_mtime);
130 memcpy(data, &aint, sizeof( aint ));
131 data += sizeof( aint );
136 (ad_getdate(ofork->of_ad, AD_DATE_BACKUP, &aint) < 0))
137 aint = AD_DATE_START;
138 memcpy(data, &aint, sizeof( aint ));
139 data += sizeof( aint );
144 (void *) ad_entry(ofork->of_ad, ADEID_FINDERI) :
145 (void *) ufinderi, 32);
147 memcmp( ad_entry( ofork->of_ad, ADEID_FINDERI ),
148 ufinderi, 8 ) == 0 ) {
149 memcpy(data, ufinderi, 8 );
150 if (( em = getextmap( ofork->of_name )) != NULL ) {
151 memcpy(data, em->em_type, sizeof( em->em_type ));
152 memcpy(data + 4, em->em_creator,
153 sizeof( em->em_creator ));
161 data += sizeof(u_int16_t);
165 memset(data, 0, sizeof(u_int16_t));
166 data += sizeof(u_int16_t);
171 * See file.c getfilparams() for why this is done this
174 #if AD_VERSION > AD_VERSION1
176 memcpy(&aint, ad_entry(ofork->of_ad, ADEID_DID), sizeof(aint));
180 if (!(aint = cnid_add(ofork->of_vol->v_db, &st,
181 ofork->of_dir->d_did,
182 upath, strlen(upath), aint))) {
187 aint = ( st.st_dev << 16 ) | ( st.st_ino & 0x0000ffff );
189 #if AD_VERSION > AD_VERSION1
192 memcpy(data, &aint, sizeof( aint ));
193 data += sizeof( aint );
197 aint = htonl( st.st_size );
198 memcpy(data, &aint, sizeof( aint ));
199 data += sizeof( aint );
204 aint = htonl( ad_getentrylen( ofork->of_ad, ADEID_RFORK ));
208 memcpy(data, &aint, sizeof( aint ));
209 data += sizeof( aint );
213 return( AFPERR_BITMAP );
220 ashort = htons( data - buf );
221 memcpy(nameoff, &ashort, sizeof( ashort ));
222 aint = strlen( ofork->of_name );
223 aint = ( aint > MACFILELEN ) ? MACFILELEN : aint;
225 memcpy(data, ofork->of_name, aint );
229 *buflen = data - buf;
233 int afp_openfork(obj, ibuf, ibuflen, rbuf, rbuflen )
236 int ibuflen, *rbuflen;
240 struct ofork *ofork, *opened;
241 struct adouble *adsame = NULL;
242 int buflen, ret, adflags, eid, lockop;
244 u_int16_t vid, bitmap, access, ofrefnum, attrbits = 0;
245 char fork, *path, *upath;
249 memcpy(&vid, ibuf, sizeof( vid ));
253 if (( vol = getvolbyvid( vid )) == NULL ) {
254 return( AFPERR_PARAM );
257 memcpy(&did, ibuf, sizeof( did ));
258 ibuf += sizeof( int );
260 if (( dir = dirsearch( vol, did )) == NULL ) {
261 return( AFPERR_NOOBJ );
264 memcpy(&bitmap, ibuf, sizeof( bitmap ));
265 bitmap = ntohs( bitmap );
266 ibuf += sizeof( bitmap );
267 memcpy(&access, ibuf, sizeof( access ));
268 access = ntohs( access );
269 ibuf += sizeof( access );
271 if ((vol->v_flags & AFPVOL_RO) && (access & OPENACC_WR)) {
275 if (( path = cname( vol, dir, &ibuf )) == NULL ) {
276 return( AFPERR_NOOBJ );
279 if ( fork == OPENFORK_DATA ) {
281 adflags = ADFLAGS_DF|ADFLAGS_HF;
284 adflags = ADFLAGS_HF;
287 /* XXX: this probably isn't the best way to do this. the already
288 open bits should really be set if the fork is opened by any
289 program, not just this one. however, that's problematic to do
290 if we can't write lock files somewhere. opened is also passed to
291 ad_open so that we can keep file locks together. */
292 if ((opened = of_findname(vol, curdir, path))) {
293 attrbits = ((opened->of_flags & AFPFORK_RSRC) ? ATTRBIT_ROPEN : 0) |
294 ((opened->of_flags & AFPFORK_DATA) ? ATTRBIT_DOPEN : 0);
295 adsame = opened->of_ad;
298 if (( ofork = of_alloc(vol, curdir, path, &ofrefnum, eid,
300 return( AFPERR_NFILE );
303 /* try opening in read-write mode with a fallback to read-only
304 * if we don't need write access. */
305 upath = mtoupath(vol, path);
307 if (ad_open(upath, adflags, O_RDWR, 0, ofork->of_ad) < 0) {
312 if (access & OPENACC_WR)
315 if (ad_open(upath, adflags, O_RDONLY, 0, ofork->of_ad) < 0) {
316 /* check for a read-only data fork */
317 if ((adflags != ADFLAGS_HF) &&
318 (ad_open(upath, ADFLAGS_DF, O_RDONLY, 0, ofork->of_ad) < 0))
321 adflags = ADFLAGS_DF;
328 /* see if client asked for the data fork */
329 if (fork == OPENFORK_DATA) {
330 if (((access & OPENACC_WR) &&
331 (ad_open(upath, ADFLAGS_DF, O_RDWR, 0, ofork->of_ad) < 0))
332 || (ad_open(upath, ADFLAGS_DF, O_RDONLY, 0,
333 ofork->of_ad) < 0)) {
336 adflags = ADFLAGS_DF;
338 } else if (stat(upath, &st) == 0) {
339 /* here's the deal. we only try to create the resource
340 * fork if the user wants to open it for write access. */
341 if ((access & OPENACC_WR) &&
342 (ad_open(upath, adflags, O_RDWR | O_CREAT,
343 0666, ofork->of_ad) < 0))
355 ret = AFPERR_BADTYPE;
359 syslog( LOG_ERR, "afp_openfork: ad_open: %m" );
366 if ((adflags & ADFLAGS_HF) &&
367 (ad_getoflags( ofork->of_ad, ADFLAGS_HF ) & O_CREAT)) {
368 ad_setentrylen( ofork->of_ad, ADEID_NAME, strlen( path ));
369 memcpy(ad_entry( ofork->of_ad, ADEID_NAME ), path,
370 ad_getentrylen( ofork->of_ad, ADEID_NAME ));
371 ad_flush( ofork->of_ad, adflags );
374 if (( ret = getforkparams(ofork, bitmap, rbuf + 2 * sizeof( u_int16_t ),
375 &buflen, attrbits )) != AFP_OK ) {
376 ad_close( ofork->of_ad, adflags );
380 *rbuflen = buflen + 2 * sizeof( u_int16_t );
381 bitmap = htons( bitmap );
382 memcpy(rbuf, &bitmap, sizeof( u_int16_t ));
383 rbuf += sizeof( u_int16_t );
386 * synchronization locks:
389 * 1) attempt a read lock to see if we have read or write
391 * 2) if that succeeds, set a write lock to correspond to the
392 * deny mode requested.
393 * 3) whenever a file is read/written, locks get set which
397 /* don't try to lock non-existent rforks. */
398 if ((eid == ADEID_DFORK) || (ad_hfileno(ofork->of_ad) != -1)) {
400 /* try to see if we have access. */
402 if (access & OPENACC_WR) {
403 ofork->of_flags |= AFPFORK_ACCWR;
404 ret = ad_lock(ofork->of_ad, eid, ADLOCK_RD | ADLOCK_FILELOCK,
405 AD_FILELOCK_WR, 1, ofrefnum);
408 if (!ret && (access & OPENACC_RD)) {
409 ofork->of_flags |= AFPFORK_ACCRD;
410 ret = ad_lock(ofork->of_ad, eid, ADLOCK_RD | ADLOCK_FILELOCK,
411 AD_FILELOCK_RD, 1, ofrefnum);
414 /* can we access the fork? */
416 ad_close( ofork->of_ad, adflags );
419 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
420 return (AFPERR_DENYCONF);
423 /* now try to set the deny lock. if the fork is open for read or
424 * write, a read lock will already have been set. otherwise, we upgrade
425 * our lock to a write lock.
427 * NOTE: we can't write lock a read-only file. on those, we just
428 * make sure that we have a read lock set. that way, we at least prevent
429 * someone else from really setting a deny read/write on the file. */
430 lockop = (ad_getoflags(ofork->of_ad, eid) & O_RDWR) ?
431 ADLOCK_WR : ADLOCK_RD;
432 ret = (access & OPENACC_DWR) ? ad_lock(ofork->of_ad, eid,
433 lockop | ADLOCK_FILELOCK |
434 ADLOCK_UPGRADE, AD_FILELOCK_WR, 1,
436 if (!ret && (access & OPENACC_DRD))
437 ret = ad_lock(ofork->of_ad, eid, lockop | ADLOCK_FILELOCK |
438 ADLOCK_UPGRADE, AD_FILELOCK_RD, 1, ofrefnum);
442 ad_close( ofork->of_ad, adflags );
445 case EAGAIN: /* return data anyway */
449 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
450 return( AFPERR_DENYCONF );
454 syslog( LOG_ERR, "afp_openfork: ad_lock: %m" );
455 return( AFPERR_PARAM );
460 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
466 return (access & OPENACC_WR) ? AFPERR_LOCK : AFPERR_ACCESS;
470 int afp_setforkparams(obj, ibuf, ibuflen, rbuf, rbuflen )
473 int ibuflen, *rbuflen;
477 u_int16_t ofrefnum, bitmap;
481 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
482 ibuf += sizeof( ofrefnum );
483 memcpy(&bitmap, ibuf, sizeof(bitmap));
484 bitmap = ntohs(bitmap);
485 ibuf += sizeof( bitmap );
486 memcpy(&size, ibuf, sizeof( size ));
487 size = ntohl( size );
490 if (( ofork = of_find( ofrefnum )) == NULL ) {
491 syslog( LOG_ERR, "afp_setforkparams: of_find: %m" );
492 return( AFPERR_PARAM );
495 if (ofork->of_vol->v_flags & AFPVOL_RO)
498 if ((ofork->of_flags & AFPFORK_ACCWR) == 0)
499 return AFPERR_ACCESS;
504 if ((bitmap == (1<<FILPBIT_DFLEN)) && (ofork->of_flags & AFPFORK_DATA)) {
505 err = ad_dtruncate( ofork->of_ad, size );
507 goto afp_setfork_err;
508 } else if ((bitmap == (1<<FILPBIT_RFLEN)) &&
509 (ofork->of_flags & AFPFORK_RSRC)) {
510 ad_refresh( ofork->of_ad );
511 err = ad_rtruncate(ofork->of_ad, size);
513 goto afp_setfork_err;
515 if (ad_flush( ofork->of_ad, ADFLAGS_HF ) < 0) {
516 syslog( LOG_ERR, "afp_setforkparams: ad_flush: %m" );
517 return( AFPERR_PARAM );
520 return AFPERR_BITMAP;
523 if ( flushfork( ofork ) < 0 ) {
524 syslog( LOG_ERR, "afp_setforkparams: flushfork: %m" );
539 return AFPERR_ACCESS;
550 /* for this to work correctly, we need to check for locks before each
551 * read and write. that's most easily handled by always doing an
552 * appropriate check before each ad_read/ad_write. other things
553 * that can change files like truncate are handled internally to those
556 #define ENDBIT(a) ((a) & 0x80)
557 #define UNLOCKBIT(a) ((a) & 0x01)
558 int afp_bytelock(obj, ibuf, ibuflen, rbuf, rbuflen )
561 int ibuflen, *rbuflen;
564 int32_t offset, length;
571 /* figure out parameters */
573 flags = *ibuf; /* first bit = endflag, lastbit = lockflag */
575 memcpy(&ofrefnum, ibuf, sizeof(ofrefnum));
576 ibuf += sizeof(ofrefnum);
578 if (( ofork = of_find( ofrefnum )) == NULL ) {
579 syslog( LOG_ERR, "afp_bytelock: of_find: %m" );
580 return( AFPERR_PARAM );
583 if ( ofork->of_flags & AFPFORK_DATA) {
585 } else if (ofork->of_flags & AFPFORK_RSRC) {
590 memcpy(&offset, ibuf, sizeof( offset ));
591 offset = ntohl(offset);
592 ibuf += sizeof(offset);
594 memcpy(&length, ibuf, sizeof( length ));
595 length = ntohl(length);
596 if (length == 0xFFFFFFFF)
597 length = BYTELOCK_MAX;
598 else if (length <= 0) {
600 } else if ((length >= AD_FILELOCK_BASE) &&
601 (ad_hfileno(ofork->of_ad) == -1))
605 offset += ad_size(ofork->of_ad, eid);
607 if (offset < 0) /* error if we have a negative offset */
610 /* if the file is a read-only file, we use read locks instead of
611 * write locks. that way, we can prevent anyone from initiating
613 if (ad_lock(ofork->of_ad, eid, UNLOCKBIT(flags) ? ADLOCK_CLR :
614 ((ad_getoflags(ofork->of_ad, eid) & O_RDWR) ?
615 ADLOCK_WR : ADLOCK_RD), offset, length,
616 ofork->of_refnum) < 0) {
620 return UNLOCKBIT(flags) ? AFPERR_NORANGE : AFPERR_LOCK;
626 return UNLOCKBIT(flags) ? AFPERR_NORANGE : AFPERR_RANGEOVR;
635 offset = htonl(offset);
636 memcpy(rbuf, &offset, sizeof( offset ));
637 *rbuflen = sizeof( offset );
643 static __inline__ int crlf( of )
648 if ( ad_hfileno( of->of_ad ) == -1 ||
649 memcmp( ufinderi, ad_entry( of->of_ad, ADEID_FINDERI ),
651 if (( em = getextmap( of->of_name )) == NULL ||
652 memcmp( "TEXT", em->em_type, sizeof( em->em_type )) == 0 ) {
658 if ( memcmp( ufinderi,
659 ad_entry( of->of_ad, ADEID_FINDERI ), 4 ) == 0 ) {
668 static __inline__ ssize_t read_file(struct ofork *ofork, int eid,
669 int offset, u_char nlmask,
670 u_char nlchar, char *rbuf,
671 int *rbuflen, const int xlate)
677 cc = ad_read(ofork->of_ad, eid, offset, rbuf, *rbuflen);
679 syslog( LOG_ERR, "afp_read: ad_read: %m" );
681 return( AFPERR_PARAM );
683 if ( cc < *rbuflen ) {
691 for ( p = rbuf, q = p + cc; p < q; ) {
692 if (( *p++ & nlmask ) == nlchar ) {
703 * If this file is of type TEXT, then swap \012 to \015.
706 for ( p = rbuf, q = p + cc; p < q; p++ ) {
707 if ( *p == '\012' ) {
709 } else if ( *p == '\015' ) {
718 return( AFPERR_EOF );
723 int afp_read(obj, ibuf, ibuflen, rbuf, rbuflen)
726 int ibuflen, *rbuflen;
730 int32_t offset, saveoff, reqcount;
731 int cc, err, eid, xlate = 0;
733 u_char nlmask, nlchar;
736 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
737 ibuf += sizeof( u_short );
739 if (( ofork = of_find( ofrefnum )) == NULL ) {
740 syslog( LOG_ERR, "afp_read: of_find: %m" );
745 if ((ofork->of_flags & AFPFORK_ACCRD) == 0) {
750 memcpy(&offset, ibuf, sizeof( offset ));
751 offset = ntohl( offset );
752 ibuf += sizeof( offset );
753 memcpy(&reqcount, ibuf, sizeof( reqcount ));
754 reqcount = ntohl( reqcount );
755 ibuf += sizeof( reqcount );
760 /* if we wanted to be picky, we could add in the following
761 * bit: if (afp_version == 11 && !(nlmask == 0xFF || !nlmask))
763 if (reqcount < 0 || offset < 0) {
768 if ( ofork->of_flags & AFPFORK_DATA) {
770 xlate = (ofork->of_vol->v_flags & AFPVOL_CRLF) ? crlf(ofork) : 0;
771 } else if (ofork->of_flags & AFPFORK_RSRC) {
773 } else { /* fork wasn't opened. this should never really happen. */
778 /* zero request count */
784 /* reqcount isn't always truthful. we need to deal with that. */
785 if ((size = ad_size(ofork->of_ad, eid)) == 0) {
791 if (ad_tmplock(ofork->of_ad, eid, ADLOCK_RD, saveoff, reqcount) < 0) {
796 #define min(a,b) ((a)<(b)?(a):(b))
797 *rbuflen = min( reqcount, *rbuflen );
798 err = read_file(ofork, eid, offset, nlmask, nlchar, rbuf, rbuflen,
803 /* dsi can stream requests. we can only do this if we're not checking
804 * for an end-of-line character. oh well. */
805 if ((obj->proto == AFPPROTO_DSI) && (*rbuflen < reqcount) && !nlmask) {
806 DSI *dsi = obj->handle;
808 /* subtract off the offset */
810 if (reqcount > size) {
815 if (obj->options.flags & OPTION_DEBUG) {
816 printf( "(read) reply: %d/%d, %d\n", *rbuflen,
817 reqcount, dsi->clientID);
818 bprint(rbuf, *rbuflen);
823 /* dsi_readinit() returns size of next read buffer. by this point,
824 * we know that we're sending some data. if we fail, something
825 * horrible happened. */
826 if ((*rbuflen = dsi_readinit(dsi, rbuf, *rbuflen, reqcount, err)) < 0)
829 /* due to the nature of afp packets, we have to exit if we get
830 an error. we can't do this with translation on. */
831 #ifdef HAVE_SENDFILE_READ
832 if (!(xlate || (obj->options.flags & OPTION_DEBUG))) {
833 if (ad_readfile(ofork->of_ad, eid, dsi->socket, offset,
834 dsi->datasize) < 0) {
838 syslog(LOG_ERR, "afp_read: ad_readfile: %m");
850 /* fill up our buffer. */
851 while (*rbuflen > 0) {
852 cc = read_file(ofork, eid, offset, nlmask, nlchar, rbuf,
858 if (obj->options.flags & OPTION_DEBUG) {
859 printf( "(read) reply: %d, %d\n", *rbuflen, dsi->clientID);
860 bprint(rbuf, *rbuflen);
863 /* dsi_read() also returns buffer size of next allocation */
864 cc = dsi_read(dsi, rbuf, *rbuflen); /* send it off */
873 syslog(LOG_ERR, "afp_read: %m");
875 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
880 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
888 int afp_flush(obj, ibuf, ibuflen, rbuf, rbuflen )
891 int ibuflen, *rbuflen;
899 memcpy(&vid, ibuf, sizeof(vid));
900 if (( vol = getvolbyvid( vid )) == NULL ) {
901 return( AFPERR_PARAM );
908 int afp_flushfork(obj, ibuf, ibuflen, rbuf, rbuflen )
911 int ibuflen, *rbuflen;
918 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
920 if (( ofork = of_find( ofrefnum )) == NULL ) {
921 syslog( LOG_ERR, "afp_flushfork: of_find: %m" );
922 return( AFPERR_PARAM );
925 if ( flushfork( ofork ) < 0 ) {
926 syslog( LOG_ERR, "afp_flushfork: %m" );
932 /* this is very similar to closefork */
933 int flushfork( ofork )
937 int len, err = 0, doflush = 0;
939 if ( ad_dfileno( ofork->of_ad ) != -1 &&
940 fsync( ad_dfileno( ofork->of_ad )) < 0 ) {
941 syslog( LOG_ERR, "flushfork: dfile(%d) %m",
942 ad_dfileno(ofork->of_ad) );
946 if ( ad_hfileno( ofork->of_ad ) != -1 ) {
947 if (ofork->of_flags & AFPFORK_RSRC) {
948 len = ad_getentrylen(ofork->of_ad, ADEID_RFORK);
949 ad_refresh(ofork->of_ad);
950 if (len != ad_getentrylen(ofork->of_ad, ADEID_RFORK)) {
951 ad_setentrylen(ofork->of_ad, ADEID_RFORK, len);
956 if ((ofork->of_flags & AFPFORK_DIRTY) &&
957 (gettimeofday(&tv, NULL) == 0)) {
958 ad_setdate(ofork->of_ad, AD_DATE_MODIFY|AD_DATE_UNIX, tv.tv_sec);
959 ofork->of_flags &= ~AFPFORK_DIRTY;
963 /* flush the header. */
964 if (doflush && (ad_flush(ofork->of_ad, ADFLAGS_HF) < 0))
967 if (fsync( ad_hfileno( ofork->of_ad )) < 0)
971 syslog( LOG_ERR, "flushfork: hfile(%d) %m",
972 ad_hfileno(ofork->of_ad) );
978 int afp_closefork(obj, ibuf, ibuflen, rbuf, rbuflen )
981 int ibuflen, *rbuflen;
985 int adflags, aint, doflush = 0;
990 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
992 if (( ofork = of_find( ofrefnum )) == NULL ) {
993 syslog( LOG_ERR, "afp_closefork: of_find: %m" );
994 return( AFPERR_PARAM );
998 if ((ofork->of_flags & AFPFORK_DATA) &&
999 (ad_dfileno( ofork->of_ad ) != -1)) {
1000 adflags |= ADFLAGS_DF;
1003 if ( ad_hfileno( ofork->of_ad ) != -1 ) {
1004 adflags |= ADFLAGS_HF;
1006 aint = ad_getentrylen( ofork->of_ad, ADEID_RFORK );
1007 ad_refresh( ofork->of_ad );
1008 if ((ofork->of_flags & AFPFORK_DIRTY) &&
1009 (gettimeofday(&tv, NULL) == 0)) {
1010 ad_setdate(ofork->of_ad, AD_DATE_MODIFY | AD_DATE_UNIX,
1016 * Only set the rfork's length if we're closing the rfork.
1018 if ((ofork->of_flags & AFPFORK_RSRC) && aint !=
1019 ad_getentrylen( ofork->of_ad, ADEID_RFORK )) {
1020 ad_setentrylen( ofork->of_ad, ADEID_RFORK, aint );
1024 ad_flush( ofork->of_ad, adflags );
1028 if ( ad_close( ofork->of_ad, adflags ) < 0 ) {
1029 syslog( LOG_ERR, "afp_closefork: ad_close: %m" );
1030 return( AFPERR_PARAM );
1033 of_dealloc( ofork );
1038 static __inline__ ssize_t write_file(struct ofork *ofork, int eid,
1039 off_t offset, char *rbuf,
1040 size_t rbuflen, const int xlate)
1046 * If this file is of type TEXT, swap \015 to \012.
1049 for ( p = rbuf, q = p + rbuflen; p < q; p++ ) {
1050 if ( *p == '\015' ) {
1052 } else if ( *p == '\012' ) {
1058 if (( cc = ad_write(ofork->of_ad, eid, offset, 0,
1059 rbuf, rbuflen)) < 0 ) {
1064 return( AFPERR_DFULL );
1066 syslog( LOG_ERR, "afp_write: ad_write: %m" );
1067 return( AFPERR_PARAM );
1074 /* FPWrite. NOTE: on an error, we always use afp_write_err as
1075 * the client may have sent us a bunch of data that's not reflected
1076 * in reqcount et al. */
1077 int afp_write(obj, ibuf, ibuflen, rbuf, rbuflen)
1080 int ibuflen, *rbuflen;
1082 struct ofork *ofork;
1083 int32_t offset, saveoff, reqcount;
1084 int endflag, eid, xlate = 0, err = AFP_OK;
1088 /* figure out parameters */
1090 endflag = ENDBIT(*ibuf);
1092 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1093 ibuf += sizeof( ofrefnum );
1094 memcpy(&offset, ibuf, sizeof( offset ));
1095 offset = ntohl( offset );
1096 ibuf += sizeof( offset );
1097 memcpy(&reqcount, ibuf, sizeof( reqcount ));
1098 reqcount = ntohl( reqcount );
1099 ibuf += sizeof( reqcount );
1101 if (( ofork = of_find( ofrefnum )) == NULL ) {
1102 syslog( LOG_ERR, "afp_write: of_find: %m" );
1107 if ((ofork->of_flags & AFPFORK_ACCWR) == 0) {
1108 err = AFPERR_ACCESS;
1113 writtenfork = ofork;
1116 if ( ofork->of_flags & AFPFORK_DATA) {
1118 xlate = (ofork->of_vol->v_flags & AFPVOL_CRLF) ? crlf(ofork) : 0;
1119 } else if (ofork->of_flags & AFPFORK_RSRC) {
1122 err = AFPERR_ACCESS; /* should never happen */
1127 offset += ad_size(ofork->of_ad, eid);
1129 /* handle bogus parameters */
1130 if (reqcount < 0 || offset < 0) {
1135 /* offset can overflow on 64-bit capable filesystems.
1136 * report disk full if that's going to happen. */
1137 if (offset + reqcount < 0) {
1142 if (!reqcount) { /* handle request counts of 0 */
1144 offset = htonl(offset);
1145 memcpy(rbuf, &offset, sizeof(offset));
1150 if (ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, saveoff,
1156 /* this is yucky, but dsi can stream i/o and asp can't */
1157 switch (obj->proto) {
1160 if (asp_wrtcont(obj->handle, rbuf, rbuflen) < 0) {
1162 syslog( LOG_ERR, "afp_write: asp_wrtcont: %m" );
1163 return( AFPERR_PARAM );
1166 if (obj->options.flags & OPTION_DEBUG) {
1167 printf("(write) len: %d\n", *rbuflen);
1168 bprint(rbuf, *rbuflen);
1171 if ((cc = write_file(ofork, eid, offset, rbuf, *rbuflen,
1174 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
1179 #endif /* no afp/asp */
1183 DSI *dsi = obj->handle;
1185 /* find out what we have already and write it out. */
1186 cc = dsi_writeinit(dsi, rbuf, *rbuflen);
1188 (cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
1189 dsi_writeflush(dsi);
1191 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
1196 #if 0 /*def HAVE_SENDFILE_WRITE*/
1197 if (!(xlate || obj->options.flags & OPTION_DEBUG)) {
1198 if ((cc = ad_writefile(ofork->of_ad, eid, dsi->socket,
1199 offset, dsi->datasize)) < 0) {
1207 syslog( LOG_ERR, "afp_write: ad_writefile: %m" );
1208 goto afp_write_loop;
1210 dsi_writeflush(dsi);
1212 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
1218 goto afp_write_done;
1222 /* loop until everything gets written. currently
1223 * dsi_write handles the end case by itself. */
1225 while ((cc = dsi_write(dsi, rbuf, *rbuflen))) {
1226 if ( obj->options.flags & OPTION_DEBUG ) {
1227 printf("(write) command cont'd: %d\n", cc);
1231 if ((cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
1232 dsi_writeflush(dsi);
1234 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
1245 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
1246 if ( ad_hfileno( ofork->of_ad ) != -1 )
1247 ofork->of_flags |= AFPFORK_DIRTY;
1249 offset = htonl( offset );
1250 #if defined(__GNUC__) && defined(HAVE_GCC_MEMCPY_BUG)
1251 bcopy(&offset, rbuf, sizeof(offset));
1253 memcpy(rbuf, &offset, sizeof(offset));
1255 *rbuflen = sizeof(offset);
1259 if (obj->proto == AFPPROTO_DSI) {
1260 dsi_writeinit(obj->handle, rbuf, *rbuflen);
1261 dsi_writeflush(obj->handle);
1264 *rbuflen = (err == AFP_OK) ? sizeof(offset) : 0;
1269 int afp_getforkparams(obj, ibuf, ibuflen, rbuf, rbuflen )
1272 int ibuflen, *rbuflen;
1274 struct ofork *ofork;
1276 u_int16_t ofrefnum, bitmap;
1279 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1280 ibuf += sizeof( ofrefnum );
1281 memcpy(&bitmap, ibuf, sizeof( bitmap ));
1282 bitmap = ntohs( bitmap );
1283 ibuf += sizeof( bitmap );
1286 if (( ofork = of_find( ofrefnum )) == NULL ) {
1287 syslog( LOG_ERR, "afp_getforkparams: of_find: %m" );
1288 return( AFPERR_PARAM );
1291 if (( ret = getforkparams( ofork, bitmap,
1292 rbuf + sizeof( u_short ), &buflen, 0 )) != AFP_OK ) {
1296 *rbuflen = buflen + sizeof( u_short );
1297 bitmap = htons( bitmap );
1298 memcpy(rbuf, &bitmap, sizeof( bitmap ));