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 ) {
948 /* read in the rfork length */
949 len = ad_getentrylen(ofork->of_ad, ADEID_RFORK);
950 ad_refresh(ofork->of_ad);
952 /* set the date if we're dirty */
953 if ((ofork->of_flags & AFPFORK_DIRTY) &&
954 (gettimeofday(&tv, NULL) == 0)) {
955 ad_setdate(ofork->of_ad, AD_DATE_MODIFY|AD_DATE_UNIX, tv.tv_sec);
956 ofork->of_flags &= ~AFPFORK_DIRTY;
960 /* if we're actually flushing this fork, make sure to set the
961 * length. otherwise, just use the stored length */
962 if ((ofork->of_flags & AFPFORK_RSRC) &&
963 (len != ad_getentrylen(ofork->of_ad, ADEID_RFORK))) {
964 ad_setentrylen(ofork->of_ad, ADEID_RFORK, len);
969 /* flush the header. */
970 if (doflush && (ad_flush(ofork->of_ad, ADFLAGS_HF) < 0))
973 if (fsync( ad_hfileno( ofork->of_ad )) < 0)
977 syslog( LOG_ERR, "flushfork: hfile(%d) %m",
978 ad_hfileno(ofork->of_ad) );
984 int afp_closefork(obj, ibuf, ibuflen, rbuf, rbuflen )
987 int ibuflen, *rbuflen;
991 int adflags, aint, doflush = 0;
996 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
998 if (( ofork = of_find( ofrefnum )) == NULL ) {
999 syslog( LOG_ERR, "afp_closefork: of_find: %m" );
1000 return( AFPERR_PARAM );
1004 if ((ofork->of_flags & AFPFORK_DATA) &&
1005 (ad_dfileno( ofork->of_ad ) != -1)) {
1006 adflags |= ADFLAGS_DF;
1009 if ( ad_hfileno( ofork->of_ad ) != -1 ) {
1010 adflags |= ADFLAGS_HF;
1012 aint = ad_getentrylen( ofork->of_ad, ADEID_RFORK );
1013 ad_refresh( ofork->of_ad );
1014 if ((ofork->of_flags & AFPFORK_DIRTY) &&
1015 (gettimeofday(&tv, NULL) == 0)) {
1016 ad_setdate(ofork->of_ad, AD_DATE_MODIFY | AD_DATE_UNIX,
1022 * Only set the rfork's length if we're closing the rfork.
1024 if ((ofork->of_flags & AFPFORK_RSRC) && aint !=
1025 ad_getentrylen( ofork->of_ad, ADEID_RFORK )) {
1026 ad_setentrylen( ofork->of_ad, ADEID_RFORK, aint );
1030 ad_flush( ofork->of_ad, adflags );
1034 if ( ad_close( ofork->of_ad, adflags ) < 0 ) {
1035 syslog( LOG_ERR, "afp_closefork: ad_close: %m" );
1036 return( AFPERR_PARAM );
1039 of_dealloc( ofork );
1044 static __inline__ ssize_t write_file(struct ofork *ofork, int eid,
1045 off_t offset, char *rbuf,
1046 size_t rbuflen, const int xlate)
1052 * If this file is of type TEXT, swap \015 to \012.
1055 for ( p = rbuf, q = p + rbuflen; p < q; p++ ) {
1056 if ( *p == '\015' ) {
1058 } else if ( *p == '\012' ) {
1064 if (( cc = ad_write(ofork->of_ad, eid, offset, 0,
1065 rbuf, rbuflen)) < 0 ) {
1070 return( AFPERR_DFULL );
1072 syslog( LOG_ERR, "afp_write: ad_write: %m" );
1073 return( AFPERR_PARAM );
1080 /* FPWrite. NOTE: on an error, we always use afp_write_err as
1081 * the client may have sent us a bunch of data that's not reflected
1082 * in reqcount et al. */
1083 int afp_write(obj, ibuf, ibuflen, rbuf, rbuflen)
1086 int ibuflen, *rbuflen;
1088 struct ofork *ofork;
1089 int32_t offset, saveoff, reqcount;
1090 int endflag, eid, xlate = 0, err = AFP_OK;
1094 /* figure out parameters */
1096 endflag = ENDBIT(*ibuf);
1098 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1099 ibuf += sizeof( ofrefnum );
1100 memcpy(&offset, ibuf, sizeof( offset ));
1101 offset = ntohl( offset );
1102 ibuf += sizeof( offset );
1103 memcpy(&reqcount, ibuf, sizeof( reqcount ));
1104 reqcount = ntohl( reqcount );
1105 ibuf += sizeof( reqcount );
1107 if (( ofork = of_find( ofrefnum )) == NULL ) {
1108 syslog( LOG_ERR, "afp_write: of_find: %m" );
1113 if ((ofork->of_flags & AFPFORK_ACCWR) == 0) {
1114 err = AFPERR_ACCESS;
1119 writtenfork = ofork;
1122 if ( ofork->of_flags & AFPFORK_DATA) {
1124 xlate = (ofork->of_vol->v_flags & AFPVOL_CRLF) ? crlf(ofork) : 0;
1125 } else if (ofork->of_flags & AFPFORK_RSRC) {
1128 err = AFPERR_ACCESS; /* should never happen */
1133 offset += ad_size(ofork->of_ad, eid);
1135 /* handle bogus parameters */
1136 if (reqcount < 0 || offset < 0) {
1141 /* offset can overflow on 64-bit capable filesystems.
1142 * report disk full if that's going to happen. */
1143 if (offset + reqcount < 0) {
1148 if (!reqcount) { /* handle request counts of 0 */
1150 offset = htonl(offset);
1151 memcpy(rbuf, &offset, sizeof(offset));
1156 if (ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, saveoff,
1162 /* this is yucky, but dsi can stream i/o and asp can't */
1163 switch (obj->proto) {
1166 if (asp_wrtcont(obj->handle, rbuf, rbuflen) < 0) {
1168 syslog( LOG_ERR, "afp_write: asp_wrtcont: %m" );
1169 return( AFPERR_PARAM );
1172 if (obj->options.flags & OPTION_DEBUG) {
1173 printf("(write) len: %d\n", *rbuflen);
1174 bprint(rbuf, *rbuflen);
1177 if ((cc = write_file(ofork, eid, offset, rbuf, *rbuflen,
1180 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
1185 #endif /* no afp/asp */
1189 DSI *dsi = obj->handle;
1191 /* find out what we have already and write it out. */
1192 cc = dsi_writeinit(dsi, rbuf, *rbuflen);
1194 (cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
1195 dsi_writeflush(dsi);
1197 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
1202 #if 0 /*def HAVE_SENDFILE_WRITE*/
1203 if (!(xlate || obj->options.flags & OPTION_DEBUG)) {
1204 if ((cc = ad_writefile(ofork->of_ad, eid, dsi->socket,
1205 offset, dsi->datasize)) < 0) {
1213 syslog( LOG_ERR, "afp_write: ad_writefile: %m" );
1214 goto afp_write_loop;
1216 dsi_writeflush(dsi);
1218 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
1224 goto afp_write_done;
1228 /* loop until everything gets written. currently
1229 * dsi_write handles the end case by itself. */
1231 while ((cc = dsi_write(dsi, rbuf, *rbuflen))) {
1232 if ( obj->options.flags & OPTION_DEBUG ) {
1233 printf("(write) command cont'd: %d\n", cc);
1237 if ((cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
1238 dsi_writeflush(dsi);
1240 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
1251 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
1252 if ( ad_hfileno( ofork->of_ad ) != -1 )
1253 ofork->of_flags |= AFPFORK_DIRTY;
1255 offset = htonl( offset );
1256 #if defined(__GNUC__) && defined(HAVE_GCC_MEMCPY_BUG)
1257 bcopy(&offset, rbuf, sizeof(offset));
1259 memcpy(rbuf, &offset, sizeof(offset));
1261 *rbuflen = sizeof(offset);
1265 if (obj->proto == AFPPROTO_DSI) {
1266 dsi_writeinit(obj->handle, rbuf, *rbuflen);
1267 dsi_writeflush(obj->handle);
1270 *rbuflen = (err == AFP_OK) ? sizeof(offset) : 0;
1275 int afp_getforkparams(obj, ibuf, ibuflen, rbuf, rbuflen )
1278 int ibuflen, *rbuflen;
1280 struct ofork *ofork;
1282 u_int16_t ofrefnum, bitmap;
1285 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1286 ibuf += sizeof( ofrefnum );
1287 memcpy(&bitmap, ibuf, sizeof( bitmap ));
1288 bitmap = ntohs( bitmap );
1289 ibuf += sizeof( bitmap );
1292 if (( ofork = of_find( ofrefnum )) == NULL ) {
1293 syslog( LOG_ERR, "afp_getforkparams: of_find: %m" );
1294 return( AFPERR_PARAM );
1297 if (( ret = getforkparams( ofork, bitmap,
1298 rbuf + sizeof( u_short ), &buflen, 0 )) != AFP_OK ) {
1302 *rbuflen = buflen + sizeof( u_short );
1303 bitmap = htons( bitmap );
1304 memcpy(rbuf, &bitmap, sizeof( bitmap ));