2 * $Id: fork.c,v 1.11.2.3 2002-02-07 23:56:58 srittau Exp $
4 * Copyright (c) 1990,1993 Regents of The University of Michigan.
5 * All Rights Reserved. See COPYRIGHT.
10 #endif /* HAVE_CONFIG_H */
15 #endif /* HAVE_UNISTD_H */
18 #endif /* HAVE_FCNTL_H */
24 #include <sys/param.h>
26 #include <sys/types.h>
28 #include <sys/socket.h>
30 #include <netatalk/endian.h>
31 #include <netatalk/at.h>
33 #include <atalk/dsi.h>
34 #include <atalk/atp.h>
35 #include <atalk/asp.h>
36 #include <atalk/afp.h>
37 #include <atalk/adouble.h>
38 #include <atalk/util.h>
40 #include <atalk/cnid.h>
46 #include "directory.h"
50 #define BYTELOCK_MAX 0x7FFFFFFFU
52 struct ofork *writtenfork;
54 static int getforkparams(ofork, bitmap, buf, buflen, attrbits )
59 const u_int16_t attrbits;
62 struct stat hst, lst, *lstp;
63 #else /* USE_LASTDID */
68 char *data, *nameoff = NULL, *upath;
69 int bit = 0, isad = 1;
73 if ( ad_hfileno( ofork->of_ad ) == -1 ) {
76 aint = ad_getentrylen( ofork->of_ad, ADEID_RFORK );
77 if ( ad_refresh( ofork->of_ad ) < 0 ) {
78 syslog( LOG_ERR, "getforkparams: ad_refresh: %s", strerror(errno) );
79 return( AFPERR_PARAM );
81 /* See afp_closefork() for why this is bad */
82 ad_setentrylen( ofork->of_ad, ADEID_RFORK, aint );
85 /* can only get the length of the opened fork */
86 if (((bitmap & (1<<FILPBIT_DFLEN)) && (ofork->of_flags & AFPFORK_RSRC)) ||
87 ((bitmap & (1<<FILPBIT_RFLEN)) && (ofork->of_flags & AFPFORK_DATA))) {
88 return( AFPERR_BITMAP );
91 if ( bitmap & ( 1<<FILPBIT_DFLEN | 1<<FILPBIT_FNUM |
92 (1 << FILPBIT_CDATE) | (1 << FILPBIT_MDATE) |
93 (1 << FILPBIT_BDATE))) {
94 upath = mtoupath(ofork->of_vol, ofork->of_name);
95 if ( ad_dfileno( ofork->of_ad ) == -1 ) {
96 if ( stat( upath, &st ) < 0 )
97 return( AFPERR_NOOBJ );
99 if ( fstat( ad_dfileno( ofork->of_ad ), &st ) < 0 ) {
100 return( AFPERR_BITMAP );
106 while ( bitmap != 0 ) {
107 while (( bitmap & 1 ) == 0 ) {
115 ad_getattr(ofork->of_ad, &ashort);
120 ashort = htons(ntohs(ashort) | attrbits);
121 memcpy(data, &ashort, sizeof( ashort ));
122 data += sizeof( ashort );
126 memcpy(data, &ofork->of_dir->d_did, sizeof( aint ));
127 data += sizeof( aint );
132 (ad_getdate(ofork->of_ad, AD_DATE_CREATE, &aint) < 0))
133 aint = AD_DATE_FROM_UNIX(st.st_mtime);
134 memcpy(data, &aint, sizeof( aint ));
135 data += sizeof( aint );
140 (ad_getdate(ofork->of_ad, AD_DATE_MODIFY, &aint) < 0) ||
141 (AD_DATE_TO_UNIX(aint) < st.st_mtime))
142 aint = AD_DATE_FROM_UNIX(st.st_mtime);
143 memcpy(data, &aint, sizeof( aint ));
144 data += sizeof( aint );
149 (ad_getdate(ofork->of_ad, AD_DATE_BACKUP, &aint) < 0))
150 aint = AD_DATE_START;
151 memcpy(data, &aint, sizeof( aint ));
152 data += sizeof( aint );
157 (void *) ad_entry(ofork->of_ad, ADEID_FINDERI) :
158 (void *) ufinderi, 32);
160 memcmp( ad_entry( ofork->of_ad, ADEID_FINDERI ),
161 ufinderi, 8 ) == 0 ) {
162 memcpy(data, ufinderi, 8 );
163 if (( em = getextmap( ofork->of_name )) != NULL ) {
164 memcpy(data, em->em_type, sizeof( em->em_type ));
165 memcpy(data + 4, em->em_creator,
166 sizeof( em->em_creator ));
174 data += sizeof(u_int16_t);
178 memset(data, 0, sizeof(u_int16_t));
179 data += sizeof(u_int16_t);
184 #if AD_VERSION > AD_VERSION1
185 /* look in AD v2 header */
187 memcpy(&aint, ad_entry(ofork->of_ad, ADEID_DID), sizeof(aint));
188 #endif /* AD_VERSION > AD_VERSION1 */
191 aint = cnid_add(ofork->of_vol->v_db, &st,
192 ofork->of_dir->d_did,
193 upath, strlen(upath), aint);
198 aint = htonl(( st.st_dev << 16 ) | ( st.st_ino & 0x0000ffff ));
199 #else /* USE_LASTDID */
200 lstp = lstat(upath, &lst) < 0 ? &st : &lst;
202 aint = htonl( afpd_st_cnid ( lstp ) );
204 aint = htonl(CNID(lstp, 1));
205 #endif /* DID_MTAB */
206 #endif /* USE_LASTDID */
209 memcpy(data, &aint, sizeof( aint ));
210 data += sizeof( aint );
214 aint = htonl( st.st_size );
215 memcpy(data, &aint, sizeof( aint ));
216 data += sizeof( aint );
221 aint = htonl( ad_getentrylen( ofork->of_ad, ADEID_RFORK ));
225 memcpy(data, &aint, sizeof( aint ));
226 data += sizeof( aint );
230 return( AFPERR_BITMAP );
237 ashort = htons( data - buf );
238 memcpy(nameoff, &ashort, sizeof( ashort ));
239 aint = strlen( ofork->of_name );
240 aint = ( aint > MACFILELEN ) ? MACFILELEN : aint;
242 memcpy(data, ofork->of_name, aint );
246 *buflen = data - buf;
250 int afp_openfork(obj, ibuf, ibuflen, rbuf, rbuflen )
253 int ibuflen, *rbuflen;
257 struct ofork *ofork, *opened;
258 struct adouble *adsame = NULL;
259 int buflen, ret, adflags, eid, lockop;
261 u_int16_t vid, bitmap, access, ofrefnum, attrbits = 0;
262 char fork, *path, *upath;
266 memcpy(&vid, ibuf, sizeof( vid ));
270 if (( vol = getvolbyvid( vid )) == NULL ) {
271 return( AFPERR_PARAM );
274 memcpy(&did, ibuf, sizeof( did ));
275 ibuf += sizeof( int );
277 if (( dir = dirsearch( vol, did )) == NULL ) {
278 return( AFPERR_NOOBJ );
281 memcpy(&bitmap, ibuf, sizeof( bitmap ));
282 bitmap = ntohs( bitmap );
283 ibuf += sizeof( bitmap );
284 memcpy(&access, ibuf, sizeof( access ));
285 access = ntohs( access );
286 ibuf += sizeof( access );
288 if ((vol->v_flags & AFPVOL_RO) && (access & OPENACC_WR)) {
292 if (( path = cname( vol, dir, &ibuf )) == NULL ) {
293 return( AFPERR_NOOBJ );
296 if ( fork == OPENFORK_DATA ) {
298 adflags = ADFLAGS_DF|ADFLAGS_HF;
301 adflags = ADFLAGS_HF;
304 /* XXX: this probably isn't the best way to do this. the already
305 open bits should really be set if the fork is opened by any
306 program, not just this one. however, that's problematic to do
307 if we can't write lock files somewhere. opened is also passed to
308 ad_open so that we can keep file locks together. */
309 if ((opened = of_findname(vol, curdir, path))) {
310 attrbits = ((opened->of_flags & AFPFORK_RSRC) ? ATTRBIT_ROPEN : 0) |
311 ((opened->of_flags & AFPFORK_DATA) ? ATTRBIT_DOPEN : 0);
312 adsame = opened->of_ad;
315 if (( ofork = of_alloc(vol, curdir, path, &ofrefnum, eid,
317 return( AFPERR_NFILE );
319 if (access & OPENACC_WR) {
320 /* try opening in read-write mode */
321 upath = mtoupath(vol, path);
323 if (ad_open(upath, adflags, O_RDWR, 0, ofork->of_ad) < 0) {
335 /* see if client asked for the data fork */
336 if (fork == OPENFORK_DATA) {
337 if (ad_open(upath, ADFLAGS_DF, O_RDWR, 0, ofork->of_ad) < 0) {
340 adflags = ADFLAGS_DF;
342 } else if (stat(upath, &st) == 0) {
343 /* here's the deal. we only try to create the resource
344 * fork if the user wants to open it for write acess. */
345 if (ad_open(upath, adflags, O_RDWR | O_CREAT, 0666, ofork->of_ad) < 0)
357 ret = AFPERR_BADTYPE;
361 syslog( LOG_ERR, "afp_openfork: ad_open: %s", strerror(errno) );
368 /* try opening in read-only mode */
369 upath = mtoupath(vol, path);
371 if (ad_open(upath, adflags, O_RDONLY, 0, ofork->of_ad) < 0) {
376 /* check for a read-only data fork */
377 if ((adflags != ADFLAGS_HF) &&
378 (ad_open(upath, ADFLAGS_DF, O_RDONLY, 0, ofork->of_ad) < 0))
381 adflags = ADFLAGS_DF;
387 /* see if client asked for the data fork */
388 if (fork == OPENFORK_DATA) {
389 if (ad_open(upath, ADFLAGS_DF, O_RDONLY, 0, ofork->of_ad) < 0) {
392 adflags = ADFLAGS_DF;
394 } else if (stat(upath, &st) != 0) {
405 ret = AFPERR_BADTYPE;
409 syslog( LOG_ERR, "afp_openfork: ad_open: %s", strerror(errno) );
416 if ((adflags & ADFLAGS_HF) &&
417 (ad_getoflags( ofork->of_ad, ADFLAGS_HF ) & O_CREAT)) {
418 ad_setentrylen( ofork->of_ad, ADEID_NAME, strlen( path ));
419 memcpy(ad_entry( ofork->of_ad, ADEID_NAME ), path,
420 ad_getentrylen( ofork->of_ad, ADEID_NAME ));
421 ad_flush( ofork->of_ad, adflags );
424 if (( ret = getforkparams(ofork, bitmap, rbuf + 2 * sizeof( u_int16_t ),
425 &buflen, attrbits )) != AFP_OK ) {
426 ad_close( ofork->of_ad, adflags );
430 *rbuflen = buflen + 2 * sizeof( u_int16_t );
431 bitmap = htons( bitmap );
432 memcpy(rbuf, &bitmap, sizeof( u_int16_t ));
433 rbuf += sizeof( u_int16_t );
436 * synchronization locks:
439 * 1) attempt a read lock to see if we have read or write
441 * 2) if that succeeds, set a write lock to correspond to the
442 * deny mode requested.
443 * 3) whenever a file is read/written, locks get set which
447 /* don't try to lock non-existent rforks. */
448 if ((eid == ADEID_DFORK) || (ad_hfileno(ofork->of_ad) != -1)) {
450 /* try to see if we have access. */
452 if (access & OPENACC_WR) {
453 ofork->of_flags |= AFPFORK_ACCWR;
454 ret = ad_lock(ofork->of_ad, eid, ADLOCK_RD | ADLOCK_FILELOCK,
455 AD_FILELOCK_WR, 1, ofrefnum);
458 if (!ret && (access & OPENACC_RD)) {
459 ofork->of_flags |= AFPFORK_ACCRD;
460 ret = ad_lock(ofork->of_ad, eid, ADLOCK_RD | ADLOCK_FILELOCK,
461 AD_FILELOCK_RD, 1, ofrefnum);
464 /* can we access the fork? */
466 ad_close( ofork->of_ad, adflags );
469 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
470 return (AFPERR_DENYCONF);
473 /* now try to set the deny lock. if the fork is open for read or
474 * write, a read lock will already have been set. otherwise, we upgrade
475 * our lock to a write lock.
477 * NOTE: we can't write lock a read-only file. on those, we just
478 * make sure that we have a read lock set. that way, we at least prevent
479 * someone else from really setting a deny read/write on the file. */
480 lockop = (ad_getoflags(ofork->of_ad, eid) & O_RDWR) ?
481 ADLOCK_WR : ADLOCK_RD;
482 ret = (access & OPENACC_DWR) ? ad_lock(ofork->of_ad, eid,
483 lockop | ADLOCK_FILELOCK |
484 ADLOCK_UPGRADE, AD_FILELOCK_WR, 1,
486 if (!ret && (access & OPENACC_DRD))
487 ret = ad_lock(ofork->of_ad, eid, lockop | ADLOCK_FILELOCK |
488 ADLOCK_UPGRADE, AD_FILELOCK_RD, 1, ofrefnum);
492 ad_close( ofork->of_ad, adflags );
495 case EAGAIN: /* return data anyway */
499 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
500 return( AFPERR_DENYCONF );
504 syslog( LOG_ERR, "afp_openfork: ad_lock: %s", strerror(errno) );
505 return( AFPERR_PARAM );
510 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
516 return (access & OPENACC_WR) ? AFPERR_LOCK : AFPERR_ACCESS;
520 int afp_setforkparams(obj, ibuf, ibuflen, rbuf, rbuflen )
523 int ibuflen, *rbuflen;
527 u_int16_t ofrefnum, bitmap;
531 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
532 ibuf += sizeof( ofrefnum );
533 memcpy(&bitmap, ibuf, sizeof(bitmap));
534 bitmap = ntohs(bitmap);
535 ibuf += sizeof( bitmap );
536 memcpy(&size, ibuf, sizeof( size ));
537 size = ntohl( size );
540 if (( ofork = of_find( ofrefnum )) == NULL ) {
541 syslog( LOG_ERR, "afp_setforkparams: of_find: %s", strerror(errno) );
542 return( AFPERR_PARAM );
545 if (ofork->of_vol->v_flags & AFPVOL_RO)
548 if ((ofork->of_flags & AFPFORK_ACCWR) == 0)
549 return AFPERR_ACCESS;
554 if ((bitmap == (1<<FILPBIT_DFLEN)) && (ofork->of_flags & AFPFORK_DATA)) {
555 err = ad_dtruncate( ofork->of_ad, size );
557 goto afp_setfork_err;
558 } else if ((bitmap == (1<<FILPBIT_RFLEN)) &&
559 (ofork->of_flags & AFPFORK_RSRC)) {
560 ad_refresh( ofork->of_ad );
561 err = ad_rtruncate(ofork->of_ad, size);
563 goto afp_setfork_err;
565 if (ad_flush( ofork->of_ad, ADFLAGS_HF ) < 0) {
566 syslog( LOG_ERR, "afp_setforkparams: ad_flush: %s",
568 return( AFPERR_PARAM );
571 return AFPERR_BITMAP;
574 if ( flushfork( ofork ) < 0 ) {
575 syslog( LOG_ERR, "afp_setforkparams: flushfork: %s", strerror(errno) );
590 return AFPERR_ACCESS;
601 /* for this to work correctly, we need to check for locks before each
602 * read and write. that's most easily handled by always doing an
603 * appropriate check before each ad_read/ad_write. other things
604 * that can change files like truncate are handled internally to those
607 #define ENDBIT(a) ((a) & 0x80)
608 #define UNLOCKBIT(a) ((a) & 0x01)
609 int afp_bytelock(obj, ibuf, ibuflen, rbuf, rbuflen )
612 int ibuflen, *rbuflen;
615 int32_t offset, length;
622 /* figure out parameters */
624 flags = *ibuf; /* first bit = endflag, lastbit = lockflag */
626 memcpy(&ofrefnum, ibuf, sizeof(ofrefnum));
627 ibuf += sizeof(ofrefnum);
629 if (( ofork = of_find( ofrefnum )) == NULL ) {
630 syslog( LOG_ERR, "afp_bytelock: of_find: %s", strerror(errno) );
631 return( AFPERR_PARAM );
634 if ( ofork->of_flags & AFPFORK_DATA) {
636 } else if (ofork->of_flags & AFPFORK_RSRC) {
641 memcpy(&offset, ibuf, sizeof( offset ));
642 offset = ntohl(offset);
643 ibuf += sizeof(offset);
645 memcpy(&length, ibuf, sizeof( length ));
646 length = ntohl(length);
647 if (length == 0xFFFFFFFF)
648 length = BYTELOCK_MAX;
649 else if (length <= 0) {
651 } else if ((length >= AD_FILELOCK_BASE) &&
652 (ad_hfileno(ofork->of_ad) == -1))
656 offset += ad_size(ofork->of_ad, eid);
658 if (offset < 0) /* error if we have a negative offset */
661 /* if the file is a read-only file, we use read locks instead of
662 * write locks. that way, we can prevent anyone from initiating
664 if (ad_lock(ofork->of_ad, eid, UNLOCKBIT(flags) ? ADLOCK_CLR :
665 ((ad_getoflags(ofork->of_ad, eid) & O_RDWR) ?
666 ADLOCK_WR : ADLOCK_RD), offset, length,
667 ofork->of_refnum) < 0) {
671 return UNLOCKBIT(flags) ? AFPERR_NORANGE : AFPERR_LOCK;
677 return UNLOCKBIT(flags) ? AFPERR_NORANGE : AFPERR_RANGEOVR;
686 offset = htonl(offset);
687 memcpy(rbuf, &offset, sizeof( offset ));
688 *rbuflen = sizeof( offset );
694 static __inline__ int crlf( of )
699 if ( ad_hfileno( of->of_ad ) == -1 ||
700 memcmp( ufinderi, ad_entry( of->of_ad, ADEID_FINDERI ),
702 if (( em = getextmap( of->of_name )) == NULL ||
703 memcmp( "TEXT", em->em_type, sizeof( em->em_type )) == 0 ) {
709 if ( memcmp( ufinderi,
710 ad_entry( of->of_ad, ADEID_FINDERI ), 4 ) == 0 ) {
719 static __inline__ ssize_t read_file(struct ofork *ofork, int eid,
720 int offset, u_char nlmask,
721 u_char nlchar, char *rbuf,
722 int *rbuflen, const int xlate)
728 cc = ad_read(ofork->of_ad, eid, offset, rbuf, *rbuflen);
730 syslog( LOG_ERR, "afp_read: ad_read: %s", strerror(errno) );
732 return( AFPERR_PARAM );
734 if ( cc < *rbuflen ) {
742 for ( p = rbuf, q = p + cc; p < q; ) {
743 if (( *p++ & nlmask ) == nlchar ) {
754 * If this file is of type TEXT, then swap \012 to \015.
757 for ( p = rbuf, q = p + cc; p < q; p++ ) {
758 if ( *p == '\012' ) {
760 } else if ( *p == '\015' ) {
769 return( AFPERR_EOF );
774 int afp_read(obj, ibuf, ibuflen, rbuf, rbuflen)
777 int ibuflen, *rbuflen;
781 int32_t offset, saveoff, reqcount, savereqcount;
782 int cc, err, saveerr, eid, xlate = 0;
784 u_char nlmask, nlchar;
787 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
788 ibuf += sizeof( u_short );
790 if (( ofork = of_find( ofrefnum )) == NULL ) {
791 syslog( LOG_ERR, "afp_read: of_find: %s", strerror(errno) );
796 if ((ofork->of_flags & AFPFORK_ACCRD) == 0) {
801 memcpy(&offset, ibuf, sizeof( offset ));
802 offset = ntohl( offset );
803 ibuf += sizeof( offset );
804 memcpy(&reqcount, ibuf, sizeof( reqcount ));
805 reqcount = ntohl( reqcount );
806 ibuf += sizeof( reqcount );
811 /* if we wanted to be picky, we could add in the following
812 * bit: if (afp_version == 11 && !(nlmask == 0xFF || !nlmask))
814 if (reqcount < 0 || offset < 0) {
819 if ( ofork->of_flags & AFPFORK_DATA) {
821 xlate = (ofork->of_vol->v_flags & AFPVOL_CRLF) ? crlf(ofork) : 0;
822 } else if (ofork->of_flags & AFPFORK_RSRC) {
824 } else { /* fork wasn't opened. this should never really happen. */
829 /* zero request count */
835 /* reqcount isn't always truthful. we need to deal with that. */
836 size = ad_size(ofork->of_ad, eid);
838 if (offset >= size) {
843 /* subtract off the offset */
845 savereqcount = reqcount;
846 if (reqcount > size) {
852 /* if EOF lock on the old reqcount, some prg may need it */
853 if (ad_tmplock(ofork->of_ad, eid, ADLOCK_RD, saveoff, savereqcount) < 0) {
858 #define min(a,b) ((a)<(b)?(a):(b))
859 *rbuflen = min( reqcount, *rbuflen );
861 err = read_file(ofork, eid, offset, nlmask, nlchar, rbuf, rbuflen,
869 /* dsi can stream requests. we can only do this if we're not checking
870 * for an end-of-line character. oh well. */
871 if ((obj->proto == AFPPROTO_DSI) && (*rbuflen < reqcount) && !nlmask) {
872 DSI *dsi = obj->handle;
874 if (obj->options.flags & OPTION_DEBUG) {
875 printf( "(read) reply: %d/%d, %d\n", *rbuflen,
876 reqcount, dsi->clientID);
877 bprint(rbuf, *rbuflen);
882 /* dsi_readinit() returns size of next read buffer. by this point,
883 * we know that we're sending some data. if we fail, something
884 * horrible happened. */
885 if ((*rbuflen = dsi_readinit(dsi, rbuf, *rbuflen, reqcount, err)) < 0)
888 /* due to the nature of afp packets, we have to exit if we get
889 an error. we can't do this with translation on. */
890 #ifdef HAVE_SENDFILE_READ
891 if (!(xlate || (obj->options.flags & OPTION_DEBUG))) {
892 if (ad_readfile(ofork->of_ad, eid, dsi->socket, offset,
893 dsi->datasize) < 0) {
897 syslog(LOG_ERR, "afp_read: ad_readfile: %s", strerror(errno));
907 #endif /* HAVE_SENDFILE_READ */
909 /* fill up our buffer. */
910 while (*rbuflen > 0) {
911 cc = read_file(ofork, eid, offset, nlmask, nlchar, rbuf,
917 if (obj->options.flags & OPTION_DEBUG) {
918 printf( "(read) reply: %d, %d\n", *rbuflen, dsi->clientID);
919 bprint(rbuf, *rbuflen);
922 /* dsi_read() also returns buffer size of next allocation */
923 cc = dsi_read(dsi, rbuf, *rbuflen); /* send it off */
932 syslog(LOG_ERR, "afp_read: %s", strerror(errno));
934 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount);
939 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount);
947 int afp_flush(obj, ibuf, ibuflen, rbuf, rbuflen )
950 int ibuflen, *rbuflen;
958 memcpy(&vid, ibuf, sizeof(vid));
959 if (( vol = getvolbyvid( vid )) == NULL ) {
960 return( AFPERR_PARAM );
967 int afp_flushfork(obj, ibuf, ibuflen, rbuf, rbuflen )
970 int ibuflen, *rbuflen;
977 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
979 if (( ofork = of_find( ofrefnum )) == NULL ) {
980 syslog( LOG_ERR, "afp_flushfork: of_find: %s", strerror(errno) );
981 return( AFPERR_PARAM );
984 if ( flushfork( ofork ) < 0 ) {
985 syslog( LOG_ERR, "afp_flushfork: %s", strerror(errno) );
991 /* this is very similar to closefork */
992 int flushfork( ofork )
996 int len, err = 0, doflush = 0;
998 if ( ad_dfileno( ofork->of_ad ) != -1 &&
999 fsync( ad_dfileno( ofork->of_ad )) < 0 ) {
1000 syslog( LOG_ERR, "flushfork: dfile(%d) %s",
1001 ad_dfileno(ofork->of_ad), strerror(errno) );
1005 if ( ad_hfileno( ofork->of_ad ) != -1 ) {
1007 /* read in the rfork length */
1008 len = ad_getentrylen(ofork->of_ad, ADEID_RFORK);
1009 ad_refresh(ofork->of_ad);
1011 /* set the date if we're dirty */
1012 if ((ofork->of_flags & AFPFORK_DIRTY) &&
1013 (gettimeofday(&tv, NULL) == 0)) {
1014 ad_setdate(ofork->of_ad, AD_DATE_MODIFY|AD_DATE_UNIX, tv.tv_sec);
1015 ofork->of_flags &= ~AFPFORK_DIRTY;
1019 /* if we're actually flushing this fork, make sure to set the
1020 * length. otherwise, just use the stored length */
1021 if ((ofork->of_flags & AFPFORK_RSRC) &&
1022 (len != ad_getentrylen(ofork->of_ad, ADEID_RFORK))) {
1023 ad_setentrylen(ofork->of_ad, ADEID_RFORK, len);
1028 /* flush the header (if it is a resource fork) */
1029 if (ofork->of_flags & AFPFORK_RSRC)
1030 if (doflush && (ad_flush(ofork->of_ad, ADFLAGS_HF) < 0))
1033 if (fsync( ad_hfileno( ofork->of_ad )) < 0)
1037 syslog( LOG_ERR, "flushfork: hfile(%d) %s",
1038 ad_hfileno(ofork->of_ad), strerror(errno) );
1044 int afp_closefork(obj, ibuf, ibuflen, rbuf, rbuflen )
1047 int ibuflen, *rbuflen;
1049 struct ofork *ofork;
1051 int adflags, aint, doflush = 0;
1056 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1058 if (( ofork = of_find( ofrefnum )) == NULL ) {
1059 syslog( LOG_ERR, "afp_closefork: of_find: %s", strerror(errno) );
1060 return( AFPERR_PARAM );
1064 if ((ofork->of_flags & AFPFORK_DATA) &&
1065 (ad_dfileno( ofork->of_ad ) != -1)) {
1066 adflags |= ADFLAGS_DF;
1069 if ( ad_hfileno( ofork->of_ad ) != -1 ) {
1070 adflags |= ADFLAGS_HF;
1072 aint = ad_getentrylen( ofork->of_ad, ADEID_RFORK );
1073 ad_refresh( ofork->of_ad );
1074 if ((ofork->of_flags & AFPFORK_DIRTY) &&
1075 (gettimeofday(&tv, NULL) == 0)) {
1076 ad_setdate(ofork->of_ad, AD_DATE_MODIFY | AD_DATE_UNIX,
1082 * Only set the rfork's length if we're closing the rfork.
1084 if ((ofork->of_flags & AFPFORK_RSRC) && aint !=
1085 ad_getentrylen( ofork->of_ad, ADEID_RFORK )) {
1086 ad_setentrylen( ofork->of_ad, ADEID_RFORK, aint );
1090 ad_flush( ofork->of_ad, adflags );
1094 if ( ad_close( ofork->of_ad, adflags ) < 0 ) {
1095 syslog( LOG_ERR, "afp_closefork: ad_close: %s", strerror(errno) );
1096 return( AFPERR_PARAM );
1099 of_dealloc( ofork );
1104 static __inline__ ssize_t write_file(struct ofork *ofork, int eid,
1105 off_t offset, char *rbuf,
1106 size_t rbuflen, const int xlate)
1112 * If this file is of type TEXT, swap \015 to \012.
1115 for ( p = rbuf, q = p + rbuflen; p < q; p++ ) {
1116 if ( *p == '\015' ) {
1118 } else if ( *p == '\012' ) {
1124 if (( cc = ad_write(ofork->of_ad, eid, offset, 0,
1125 rbuf, rbuflen)) < 0 ) {
1130 return( AFPERR_DFULL );
1132 syslog( LOG_ERR, "afp_write: ad_write: %s", strerror(errno) );
1133 return( AFPERR_PARAM );
1140 /* FPWrite. NOTE: on an error, we always use afp_write_err as
1141 * the client may have sent us a bunch of data that's not reflected
1142 * in reqcount et al. */
1143 int afp_write(obj, ibuf, ibuflen, rbuf, rbuflen)
1146 int ibuflen, *rbuflen;
1148 struct ofork *ofork;
1149 int32_t offset, saveoff, reqcount;
1150 int endflag, eid, xlate = 0, err = AFP_OK;
1154 /* figure out parameters */
1156 endflag = ENDBIT(*ibuf);
1158 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1159 ibuf += sizeof( ofrefnum );
1160 memcpy(&offset, ibuf, sizeof( offset ));
1161 offset = ntohl( offset );
1162 ibuf += sizeof( offset );
1163 memcpy(&reqcount, ibuf, sizeof( reqcount ));
1164 reqcount = ntohl( reqcount );
1165 ibuf += sizeof( reqcount );
1167 if (( ofork = of_find( ofrefnum )) == NULL ) {
1168 syslog( LOG_ERR, "afp_write: of_find: %s", strerror(errno) );
1173 if ((ofork->of_flags & AFPFORK_ACCWR) == 0) {
1174 err = AFPERR_ACCESS;
1179 writtenfork = ofork;
1182 if ( ofork->of_flags & AFPFORK_DATA) {
1184 xlate = (ofork->of_vol->v_flags & AFPVOL_CRLF) ? crlf(ofork) : 0;
1185 } else if (ofork->of_flags & AFPFORK_RSRC) {
1188 err = AFPERR_ACCESS; /* should never happen */
1193 offset += ad_size(ofork->of_ad, eid);
1195 /* handle bogus parameters */
1196 if (reqcount < 0 || offset < 0) {
1201 /* offset can overflow on 64-bit capable filesystems.
1202 * report disk full if that's going to happen. */
1203 if (offset + reqcount < 0) {
1208 if (!reqcount) { /* handle request counts of 0 */
1210 offset = htonl(offset);
1211 memcpy(rbuf, &offset, sizeof(offset));
1216 if (ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, saveoff,
1222 /* this is yucky, but dsi can stream i/o and asp can't */
1223 switch (obj->proto) {
1226 if (asp_wrtcont(obj->handle, rbuf, rbuflen) < 0) {
1228 syslog( LOG_ERR, "afp_write: asp_wrtcont: %s", strerror(errno) );
1229 return( AFPERR_PARAM );
1232 if (obj->options.flags & OPTION_DEBUG) {
1233 printf("(write) len: %d\n", *rbuflen);
1234 bprint(rbuf, *rbuflen);
1237 if ((cc = write_file(ofork, eid, offset, rbuf, *rbuflen,
1240 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
1245 #endif /* no afp/asp */
1249 DSI *dsi = obj->handle;
1251 /* find out what we have already and write it out. */
1252 cc = dsi_writeinit(dsi, rbuf, *rbuflen);
1254 (cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
1255 dsi_writeflush(dsi);
1257 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
1262 #if 0 /*def HAVE_SENDFILE_WRITE*/
1263 if (!(xlate || obj->options.flags & OPTION_DEBUG)) {
1264 if ((cc = ad_writefile(ofork->of_ad, eid, dsi->socket,
1265 offset, dsi->datasize)) < 0) {
1273 syslog( LOG_ERR, "afp_write: ad_writefile: %s", strerror(errno) );
1274 goto afp_write_loop;
1276 dsi_writeflush(dsi);
1278 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
1284 goto afp_write_done;
1286 #endif /* 0, was HAVE_SENDFILE_WRITE */
1288 /* loop until everything gets written. currently
1289 * dsi_write handles the end case by itself. */
1291 while ((cc = dsi_write(dsi, rbuf, *rbuflen))) {
1292 if ( obj->options.flags & OPTION_DEBUG ) {
1293 printf("(write) command cont'd: %d\n", cc);
1297 if ((cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
1298 dsi_writeflush(dsi);
1300 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
1311 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
1312 if ( ad_hfileno( ofork->of_ad ) != -1 )
1313 ofork->of_flags |= AFPFORK_DIRTY;
1315 offset = htonl( offset );
1316 #if defined(__GNUC__) && defined(HAVE_GCC_MEMCPY_BUG)
1317 bcopy(&offset, rbuf, sizeof(offset));
1318 #else /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */
1319 memcpy(rbuf, &offset, sizeof(offset));
1320 #endif /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */
1321 *rbuflen = sizeof(offset);
1325 if (obj->proto == AFPPROTO_DSI) {
1326 dsi_writeinit(obj->handle, rbuf, *rbuflen);
1327 dsi_writeflush(obj->handle);
1330 *rbuflen = (err == AFP_OK) ? sizeof(offset) : 0;
1335 int afp_getforkparams(obj, ibuf, ibuflen, rbuf, rbuflen )
1338 int ibuflen, *rbuflen;
1340 struct ofork *ofork;
1342 u_int16_t ofrefnum, bitmap;
1345 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1346 ibuf += sizeof( ofrefnum );
1347 memcpy(&bitmap, ibuf, sizeof( bitmap ));
1348 bitmap = ntohs( bitmap );
1349 ibuf += sizeof( bitmap );
1352 if (( ofork = of_find( ofrefnum )) == NULL ) {
1353 syslog( LOG_ERR, "afp_getforkparams: of_find: %s", strerror(errno) );
1354 return( AFPERR_PARAM );
1357 if (( ret = getforkparams( ofork, bitmap,
1358 rbuf + sizeof( u_short ), &buflen, 0 )) != AFP_OK ) {
1362 *rbuflen = buflen + sizeof( u_short );
1363 bitmap = htons( bitmap );
1364 memcpy(rbuf, &bitmap, sizeof( bitmap ));