2 * $Id: fork.c,v 1.51.2.2.2.8 2004-03-11 16:16:41 didg Exp $
4 * Copyright (c) 1990,1993 Regents of The University of Michigan.
5 * All Rights Reserved. See COPYRIGHT.
10 #endif /* HAVE_CONFIG_H */
18 #include <atalk/adouble.h>
19 #include <atalk/logger.h>
21 #include <sys/param.h>
22 #include <sys/socket.h>
24 #include <netatalk/at.h>
26 #include <atalk/dsi.h>
27 #include <atalk/atp.h>
28 #include <atalk/asp.h>
29 #include <atalk/afp.h>
31 #include <atalk/util.h>
32 #include <atalk/cnid.h>
37 #include "directory.h"
42 #define Debug(a) ((a)->options.flags & OPTION_DEBUG)
47 struct ofork *writtenfork;
48 extern int getmetadata(struct vol *vol,
50 struct path *path, struct dir *dir, char *buf,
51 int *buflen, struct adouble *adp, int attrbits );
53 static int getforkparams(ofork, bitmap, buf, buflen, attrbits )
58 const u_int16_t attrbits;
68 /* can only get the length of the opened fork */
69 if ( ( (bitmap & ((1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN)))
70 && (ofork->of_flags & AFPFORK_RSRC))
72 ( (bitmap & ((1<<FILPBIT_RFLEN) | (1<<FILPBIT_EXTRFLEN)))
73 && (ofork->of_flags & AFPFORK_DATA))) {
74 return( AFPERR_BITMAP );
77 if ( ad_hfileno( ofork->of_ad ) == -1 ) {
86 if (NULL == (path.u_name = mtoupath(vol, ofork->of_name, dir->d_did, utf8_encoding()))) {
87 return( AFPERR_MISC );
89 path.m_name = ofork->of_name;
91 if ( bitmap & ( (1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN) |
92 (1<<FILPBIT_FNUM) | (1 << FILPBIT_CDATE) |
93 (1 << FILPBIT_MDATE) | (1 << FILPBIT_BDATE))) {
94 if ( ad_dfileno( ofork->of_ad ) == -1 ) {
95 if (movecwd(vol, dir) < 0)
96 return( AFPERR_NOOBJ );
97 if ( stat( path.u_name, st ) < 0 )
98 return( AFPERR_NOOBJ );
100 if ( fstat( ad_dfileno( ofork->of_ad ), st ) < 0 ) {
101 return( AFPERR_BITMAP );
105 return getmetadata(vol, bitmap, &path, dir, buf, buflen, adp, attrbits );
108 /* ---------------------------- */
109 static off_t get_off_t(ibuf, is64)
117 memcpy(&temp, *ibuf, sizeof( temp ));
118 ret = ntohl(temp); /* ntohl is unsigned */
119 *ibuf += sizeof(temp);
122 memcpy(&temp, *ibuf, sizeof( temp ));
123 *ibuf += sizeof(temp);
124 ret = ntohl(temp)| (ret << 32);
127 ret = (int)ret; /* sign extend */
132 /* ---------------------- */
133 static int set_off_t(offset, rbuf, is64)
143 temp = htonl(offset >> 32);
144 memcpy(rbuf, &temp, sizeof( temp ));
145 rbuf += sizeof(temp);
146 ret = sizeof( temp );
147 offset &= 0xffffffff;
149 temp = htonl(offset);
150 memcpy(rbuf, &temp, sizeof( temp ));
151 ret += sizeof( temp );
156 /* ------------------------
158 static int is_neg(int is64, off_t val)
160 if (val < 0 || (sizeof(off_t) == 8 && !is64 && (val & 0x80000000U)))
165 static __inline__ int sum_neg(int is64, off_t offset, off_t reqcount)
167 if (is_neg(is64, offset +reqcount) )
172 /* -------------------------
174 static int setforkmode(struct adouble *adp, int eid, int ofrefnum, int what)
176 return ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, what, 1, ofrefnum);
179 /* -------------------------
181 static int getforkmode(struct adouble *adp, int eid, int what)
183 return ad_testlock(adp, eid, what);
186 static int fork_setmode(struct adouble *adp, int eid, int access, int ofrefnum)
194 if (! (access & (OPENACC_WR | OPENACC_RD | OPENACC_DWR | OPENACC_DRD))) {
195 return setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_NONE);
198 if ((access & (OPENACC_RD | OPENACC_DRD))) {
199 if ((readset = getforkmode(adp, eid, AD_FILELOCK_OPEN_RD)) <0)
201 if ((denyreadset = getforkmode(adp, eid, AD_FILELOCK_DENY_RD)) <0)
204 if ((access & OPENACC_RD) && denyreadset) {
208 if ((access & OPENACC_DRD) && readset) {
212 /* boolean logic is not enough, because getforkmode is not always telling the
215 if ((access & OPENACC_RD)) {
216 ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_RD);
220 if ((access & OPENACC_DRD)) {
221 ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_DENY_RD);
226 /* ------------same for writing -------------- */
227 if ((access & (OPENACC_WR | OPENACC_DWR))) {
228 if ((writeset = getforkmode(adp, eid, AD_FILELOCK_OPEN_WR)) <0)
230 if ((denywriteset = getforkmode(adp, eid, AD_FILELOCK_DENY_WR)) <0)
233 if ((access & OPENACC_WR) && denywriteset) {
237 if ((access & OPENACC_DWR) && writeset) {
241 if ((access & OPENACC_WR)) {
242 ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_WR);
246 if ((access & OPENACC_DWR)) {
247 ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_DENY_WR);
252 if ( access == (OPENACC_WR | OPENACC_RD | OPENACC_DWR | OPENACC_DRD)) {
253 return ad_excl_lock(adp, eid);
258 /* ----------------------- */
259 int afp_openfork(obj, ibuf, ibuflen, rbuf, rbuflen )
262 int ibuflen, *rbuflen;
266 struct ofork *ofork, *opened;
267 struct adouble *adsame = NULL;
268 int buflen, ret, adflags, eid;
270 u_int16_t vid, bitmap, access, ofrefnum, attrbits = 0;
271 char fork, *path, *upath;
278 memcpy(&vid, ibuf, sizeof( vid ));
282 if (NULL == ( vol = getvolbyvid( vid ))) {
283 return( AFPERR_PARAM );
286 memcpy(&did, ibuf, sizeof( did ));
287 ibuf += sizeof( int );
289 if (NULL == ( dir = dirlookup( vol, did ))) {
293 memcpy(&bitmap, ibuf, sizeof( bitmap ));
294 bitmap = ntohs( bitmap );
295 ibuf += sizeof( bitmap );
296 memcpy(&access, ibuf, sizeof( access ));
297 access = ntohs( access );
298 ibuf += sizeof( access );
300 if ((vol->v_flags & AFPVOL_RO) && (access & OPENACC_WR)) {
304 if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
305 return get_afp_errno(AFPERR_PARAM);
308 if (*s_path->m_name == '\0') {
310 return AFPERR_BADTYPE;
313 /* stat() data fork st is set because it's not a dir */
314 switch ( s_path->st_errno ) {
320 return (access & OPENACC_WR) ? AFPERR_LOCK : AFPERR_ACCESS;
322 LOG(log_error, logtype_afpd, "afp_openfork: ad_open: %s", strerror(errno) );
325 /* FIXME should we check it first ? */
326 upath = s_path->u_name;
327 if (!vol_unix_priv(vol)) {
328 if (check_access(upath, access ) < 0) {
329 return AFPERR_ACCESS;
333 if (file_access(s_path, access ) < 0) {
334 return AFPERR_ACCESS;
339 /* XXX: this probably isn't the best way to do this. the already
340 open bits should really be set if the fork is opened by any
341 program, not just this one. however, that's problematic to do
342 if we can't write lock files somewhere. opened is also passed to
343 ad_open so that we can keep file locks together.
344 FIXME: add the fork we are opening?
346 if ((opened = of_findname(s_path))) {
347 attrbits = ((opened->of_ad->ad_df.adf_refcount > 0) ? ATTRBIT_DOPEN : 0);
348 attrbits |= ((opened->of_ad->ad_hf.adf_refcount > opened->of_ad->ad_df.adf_refcount)? ATTRBIT_ROPEN : 0);
350 adsame = opened->of_ad;
353 if ( fork == OPENFORK_DATA ) {
355 adflags = ADFLAGS_DF|ADFLAGS_HF;
358 adflags = ADFLAGS_HF;
361 path = s_path->m_name;
362 if (( ofork = of_alloc(vol, curdir, path, &ofrefnum, eid,
363 adsame, st)) == NULL ) {
364 return( AFPERR_NFILE );
368 if (access & OPENACC_WR) {
369 /* try opening in read-write mode */
370 if (ad_open(upath, adflags, O_RDWR, 0, ofork->of_ad) < 0) {
378 if (fork == OPENFORK_DATA) {
379 /* try to open only the data fork */
380 if (ad_open(upath, ADFLAGS_DF, O_RDWR, 0, ofork->of_ad) < 0) {
383 adflags = ADFLAGS_DF;
386 /* here's the deal. we only try to create the resource
387 * fork if the user wants to open it for write acess. */
388 if (ad_open(upath, adflags, O_RDWR | O_CREAT, 0666, ofork->of_ad) < 0)
390 ofork->of_flags |= AFPFORK_OPEN;
399 ret = AFPERR_BADTYPE;
403 LOG(log_error, logtype_afpd, "afp_openfork: ad_open: %s", strerror(errno) );
410 /* the ressource fork is open too */
411 ofork->of_flags |= AFPFORK_OPEN;
414 /* try opening in read-only mode */
416 if (ad_open(upath, adflags, O_RDONLY, 0, ofork->of_ad) < 0) {
424 /* see if client asked for a read only data fork */
425 if (fork == OPENFORK_DATA) {
426 if (ad_open(upath, ADFLAGS_DF, O_RDONLY, 0, ofork->of_ad) < 0) {
429 adflags = ADFLAGS_DF;
431 /* else we don't set AFPFORK_OPEN because there's no ressource fork file
432 * We need to check AFPFORK_OPEN in afp_closefork(). eg fork open read-only
433 * then create in open read-write.
434 * FIXME , it doesn't play well with byte locking example:
435 * ressource fork open read only
436 * locking set on it (no effect, there's no file!)
437 * ressource fork open read write now
446 ret = AFPERR_BADTYPE;
450 LOG(log_error, logtype_afpd, "afp_openfork: ad_open: %s", strerror(errno) );
456 /* the ressource fork is open too */
457 ofork->of_flags |= AFPFORK_OPEN;
461 if ((adflags & ADFLAGS_HF) && (ad_get_HF_flags( ofork->of_ad) & O_CREAT)) {
462 if (ad_setname(ofork->of_ad, path)) {
463 ad_flush( ofork->of_ad, adflags );
467 if (( ret = getforkparams(ofork, bitmap, rbuf + 2 * sizeof( u_int16_t ),
468 &buflen, attrbits )) != AFP_OK ) {
469 ad_close( ofork->of_ad, adflags );
473 *rbuflen = buflen + 2 * sizeof( u_int16_t );
474 bitmap = htons( bitmap );
475 memcpy(rbuf, &bitmap, sizeof( u_int16_t ));
476 rbuf += sizeof( u_int16_t );
478 /* check WriteInhibit bit if we have a ressource fork
479 * the test is done here, after some Mac trafic capture
481 if (ad_hfileno(ofork->of_ad) != -1) {
482 ad_getattr(ofork->of_ad, &bshort);
483 if ((bshort & htons(ATTRBIT_NOWRITE)) && (access & OPENACC_WR)) {
484 ad_close( ofork->of_ad, adflags );
487 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
488 return(AFPERR_OLOCK);
493 * synchronization locks:
496 /* don't try to lock non-existent rforks. */
497 if ((eid == ADEID_DFORK) || (ad_hfileno(ofork->of_ad) != -1)) {
499 ret = fork_setmode(ofork->of_ad, eid, access, ofrefnum);
500 /* can we access the fork? */
503 ad_close( ofork->of_ad, adflags );
506 case EAGAIN: /* return data anyway */
510 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
511 return( AFPERR_DENYCONF );
515 LOG(log_error, logtype_afpd, "afp_openfork: ad_lock: %s", strerror(ret) );
516 return( AFPERR_PARAM );
519 if ((access & OPENACC_WR))
520 ofork->of_flags |= AFPFORK_ACCWR;
522 /* the file may be open read only without ressource fork */
523 if ((access & OPENACC_RD))
524 ofork->of_flags |= AFPFORK_ACCRD;
526 memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
532 return (access & OPENACC_WR) ? AFPERR_LOCK : AFPERR_ACCESS;
536 int afp_setforkparams(obj, ibuf, ibuflen, rbuf, rbuflen )
539 int ibuflen, *rbuflen;
543 u_int16_t ofrefnum, bitmap;
551 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
552 ibuf += sizeof( ofrefnum );
554 memcpy(&bitmap, ibuf, sizeof(bitmap));
555 bitmap = ntohs(bitmap);
556 ibuf += sizeof( bitmap );
559 if (NULL == ( ofork = of_find( ofrefnum )) ) {
560 LOG(log_error, logtype_afpd, "afp_setforkparams: of_find could not locate open fork refnum: %u", ofrefnum );
561 return( AFPERR_PARAM );
564 if (ofork->of_vol->v_flags & AFPVOL_RO)
567 if ((ofork->of_flags & AFPFORK_ACCWR) == 0)
568 return AFPERR_ACCESS;
570 if ( ofork->of_flags & AFPFORK_DATA) {
572 } else if (ofork->of_flags & AFPFORK_RSRC) {
577 if ( ( (bitmap & ( (1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN) ))
578 && eid == ADEID_RFORK
580 ( (bitmap & ( (1<<FILPBIT_RFLEN) | (1<<FILPBIT_EXTRFLEN) ))
581 && eid == ADEID_DFORK)) {
582 return AFPERR_BITMAP;
586 if ((bitmap & ( (1<<FILPBIT_EXTDFLEN) | (1<<FILPBIT_EXTRFLEN) ))) {
587 if (afp_version >= 30) {
591 return AFPERR_BITMAP;
594 if (ibuflen < 2+ sizeof(ofrefnum) + sizeof(bitmap) + is64 +4)
595 return AFPERR_PARAM ;
597 size = get_off_t(&ibuf, is64);
600 return AFPERR_PARAM; /* Some MacOS don't return an error they just don't change the size! */
603 if (bitmap == (1<<FILPBIT_DFLEN) || bitmap == (1<<FILPBIT_EXTDFLEN)) {
604 st_size = ad_size(ofork->of_ad, eid);
606 if (st_size > size &&
607 ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, size, st_size -size, ofork->of_refnum) < 0)
608 goto afp_setfork_err;
610 err = ad_dtruncate( ofork->of_ad, size );
612 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, size, st_size -size, ofork->of_refnum);
614 goto afp_setfork_err;
615 } else if (bitmap == (1<<FILPBIT_RFLEN) || bitmap == (1<<FILPBIT_EXTRFLEN)) {
616 ad_refresh( ofork->of_ad );
618 st_size = ad_size(ofork->of_ad, eid);
620 if (st_size > size &&
621 ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, size, st_size -size, ofork->of_refnum) < 0) {
622 goto afp_setfork_err;
624 err = ad_rtruncate(ofork->of_ad, size);
626 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, size, st_size -size, ofork->of_refnum);
628 goto afp_setfork_err;
630 if (ad_flush( ofork->of_ad, ADFLAGS_HF ) < 0) {
631 LOG(log_error, logtype_afpd, "afp_setforkparams: ad_flush: %s",strerror(errno) );
635 return AFPERR_BITMAP;
638 if ( flushfork( ofork ) < 0 ) {
639 LOG(log_error, logtype_afpd, "afp_setforkparams: flushfork: %s", strerror(errno) );
654 return AFPERR_ACCESS;
665 /* for this to work correctly, we need to check for locks before each
666 * read and write. that's most easily handled by always doing an
667 * appropriate check before each ad_read/ad_write. other things
668 * that can change files like truncate are handled internally to those
671 #define ENDBIT(a) ((a) & 0x80)
672 #define UNLOCKBIT(a) ((a) & 0x01)
675 /* ---------------------- */
676 static int byte_lock(obj, ibuf, ibuflen, rbuf, rbuflen, is64 )
679 int ibuflen, *rbuflen;
683 off_t offset, length;
691 /* figure out parameters */
693 flags = *ibuf; /* first bit = endflag, lastbit = lockflag */
695 memcpy(&ofrefnum, ibuf, sizeof(ofrefnum));
696 ibuf += sizeof(ofrefnum);
698 if (NULL == ( ofork = of_find( ofrefnum )) ) {
699 LOG(log_error, logtype_afpd, "afp_bytelock: of_find");
700 return( AFPERR_PARAM );
703 if ( ofork->of_flags & AFPFORK_DATA) {
705 } else if (ofork->of_flags & AFPFORK_RSRC) {
710 offset = get_off_t(&ibuf, is64);
711 length = get_off_t(&ibuf, is64);
713 /* FIXME AD_FILELOCK test is surely wrong */
715 length = BYTELOCK_MAX;
716 else if (!length || is_neg(is64, length)) {
718 } else if ((length >= AD_FILELOCK_BASE) && -1 == (ad_hfileno(ofork->of_ad))) {
723 offset += ad_size(ofork->of_ad, eid);
724 /* FIXME what do we do if file size > 2 GB and
725 it's not byte_lock_ext?
728 if (offset < 0) /* error if we have a negative offset */
731 /* if the file is a read-only file, we use read locks instead of
732 * write locks. that way, we can prevent anyone from initiating
734 lockop = UNLOCKBIT(flags) ? ADLOCK_CLR : ADLOCK_WR;
735 if (ad_lock(ofork->of_ad, eid, lockop, offset, length,
736 ofork->of_refnum) < 0) {
740 return UNLOCKBIT(flags) ? AFPERR_NORANGE : AFPERR_LOCK;
746 return UNLOCKBIT(flags) ? AFPERR_NORANGE : AFPERR_RANGEOVR;
754 *rbuflen = set_off_t (offset, rbuf, is64);
758 /* --------------------------- */
759 int afp_bytelock(obj, ibuf, ibuflen, rbuf, rbuflen )
762 int ibuflen, *rbuflen;
764 return byte_lock ( obj, ibuf, ibuflen, rbuf, rbuflen , 0);
767 /* --------------------------- */
768 int afp_bytelock_ext(obj, ibuf, ibuflen, rbuf, rbuflen )
771 int ibuflen, *rbuflen;
773 return byte_lock ( obj, ibuf, ibuflen, rbuf, rbuflen , 1);
778 /* --------------------------- */
779 static __inline__ int crlf( of )
784 if ( ad_hfileno( of->of_ad ) == -1 ||
785 memcmp( ufinderi, ad_entry( of->of_ad, ADEID_FINDERI ),
787 if (NULL == ( em = getextmap( of->of_name )) ||
788 memcmp( "TEXT", em->em_type, sizeof( em->em_type )) == 0 ) {
794 if ( memcmp( ufinderi,
795 ad_entry( of->of_ad, ADEID_FINDERI ), 4 ) == 0 ) {
804 static __inline__ ssize_t read_file(struct ofork *ofork, int eid,
805 off_t offset, u_char nlmask,
806 u_char nlchar, char *rbuf,
807 int *rbuflen, const int xlate)
813 cc = ad_read(ofork->of_ad, eid, offset, rbuf, *rbuflen);
815 LOG(log_error, logtype_afpd, "afp_read: ad_read: %s", strerror(errno) );
817 return( AFPERR_PARAM );
819 if ( cc < *rbuflen ) {
827 for ( p = rbuf, q = p + cc; p < q; ) {
828 if (( *p++ & nlmask ) == nlchar ) {
839 * If this file is of type TEXT, then swap \012 to \015.
842 for ( p = rbuf, q = p + cc; p < q; p++ ) {
843 if ( *p == '\012' ) {
845 } else if ( *p == '\015' ) {
854 return( AFPERR_EOF );
859 /* -----------------------------
860 * with ddp, afp_read can return fewer bytes than in reqcount
861 * so return EOF only if read actually past end of file not
862 * if offset +reqcount > size of file
864 * getfork size ==> 10430
865 * read fork offset 0 size 10752 ???? ==> 4264 bytes (without EOF)
866 * read fork offset 4264 size 6128 ==> 4264 (without EOF)
867 * read fork offset 9248 size 1508 ==> 1182 (EOF)
868 * 10752 is a bug in Mac 7.5.x finder
870 * with dsi, should we check that reqcount < server quantum?
872 static int read_fork(obj, ibuf, ibuflen, rbuf, rbuflen, is64)
875 int ibuflen, *rbuflen;
880 off_t offset, saveoff, reqcount, savereqcount;
881 int cc, err, eid, xlate = 0;
883 u_char nlmask, nlchar;
884 int non_blocking = 0;
887 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
888 ibuf += sizeof( u_short );
890 if (NULL == ( ofork = of_find( ofrefnum )) ) {
891 LOG(log_error, logtype_afpd, "afp_read: of_find");
896 if ((ofork->of_flags & AFPFORK_ACCRD) == 0) {
900 offset = get_off_t(&ibuf, is64);
901 reqcount = get_off_t(&ibuf, is64);
910 /* if we wanted to be picky, we could add in the following
911 * bit: if (afp_version == 11 && !(nlmask == 0xFF || !nlmask))
913 if (reqcount < 0 || offset < 0) {
918 if ( ofork->of_flags & AFPFORK_DATA) {
920 xlate = (ofork->of_vol->v_flags & AFPVOL_CRLF) ? crlf(ofork) : 0;
921 } else if (ofork->of_flags & AFPFORK_RSRC) {
923 } else { /* fork wasn't opened. this should never really happen. */
928 /* zero request count */
934 /* reqcount isn't always truthful. we need to deal with that. */
935 size = ad_size(ofork->of_ad, eid);
937 if (offset >= size) {
942 savereqcount = reqcount;
944 if (ad_tmplock(ofork->of_ad, eid, ADLOCK_RD, saveoff, savereqcount,ofork->of_refnum) < 0) {
949 #define min(a,b) ((a)<(b)?(a):(b))
950 *rbuflen = min( reqcount, *rbuflen );
951 err = read_file(ofork, eid, offset, nlmask, nlchar, rbuf, rbuflen, xlate);
955 /* dsi can stream requests. we can only do this if we're not checking
956 * for an end-of-line character. oh well. */
957 if ((obj->proto == AFPPROTO_DSI) && (*rbuflen < reqcount) && !nlmask) {
958 DSI *dsi = obj->handle;
961 if (obj->options.flags & OPTION_DEBUG) {
962 printf( "(read) reply: %d/%d, %d\n", *rbuflen,(int) reqcount, dsi->clientID);
963 bprint(rbuf, *rbuflen);
966 /* subtract off the offset */
968 if (reqcount > size) {
975 /* dsi_readinit() returns size of next read buffer. by this point,
976 * we know that we're sending some data. if we fail, something
977 * horrible happened. */
978 if ((*rbuflen = dsi_readinit(dsi, rbuf, *rbuflen, reqcount, err)) < 0)
981 /* due to the nature of afp packets, we have to exit if we get
982 an error. we can't do this with translation on. */
983 #if 0 /* idef WITH_SENDFILE */
984 /* FIXME with OS X deadlock partial workaround we can't use sendfile */
985 if (!(xlate || Debug(obj) )) {
986 if (ad_readfile(ofork->of_ad, eid, dsi->socket, offset, dsi->datasize) < 0) {
987 if (errno == EINVAL || errno == ENOSYS)
990 LOG(log_error, logtype_afpd, "afp_read: ad_readfile: %s", strerror(errno));
1002 /* fill up our buffer. */
1004 /* set to non blocking mode */
1008 /* fill up our buffer. */
1009 while (*rbuflen > 0) {
1010 cc = read_file(ofork, eid, offset, nlmask, nlchar, rbuf,rbuflen, xlate);
1016 if (obj->options.flags & OPTION_DEBUG) {
1017 printf( "(read) reply: %d, %d\n", *rbuflen, dsi->clientID);
1018 bprint(rbuf, *rbuflen);
1021 /* dsi_read() also returns buffer size of next allocation */
1022 cc = dsi_read(dsi, rbuf, *rbuflen); /* send it off */
1031 LOG(log_error, logtype_afpd, "afp_read: %s", strerror(errno));
1033 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount,ofork->of_refnum);
1039 DSI *dsi = obj->handle;
1040 /* set back to blocking mode */
1043 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount,ofork->of_refnum);
1051 /* ---------------------- */
1052 int afp_read(obj, ibuf, ibuflen, rbuf, rbuflen)
1055 int ibuflen, *rbuflen;
1057 return read_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 0);
1060 /* ---------------------- */
1061 int afp_read_ext(obj, ibuf, ibuflen, rbuf, rbuflen)
1064 int ibuflen, *rbuflen;
1066 return read_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 1);
1069 /* ---------------------- */
1070 int afp_flush(obj, ibuf, ibuflen, rbuf, rbuflen )
1073 int ibuflen, *rbuflen;
1081 memcpy(&vid, ibuf, sizeof(vid));
1082 if (NULL == ( vol = getvolbyvid( vid )) ) {
1083 return( AFPERR_PARAM );
1090 int afp_flushfork(obj, ibuf, ibuflen, rbuf, rbuflen )
1093 int ibuflen, *rbuflen;
1095 struct ofork *ofork;
1100 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1102 if (NULL == ( ofork = of_find( ofrefnum )) ) {
1103 LOG(log_error, logtype_afpd, "afp_flushfork: of_find");
1104 return( AFPERR_PARAM );
1107 if ( flushfork( ofork ) < 0 ) {
1108 LOG(log_error, logtype_afpd, "afp_flushfork: %s", strerror(errno) );
1114 /* this is very similar to closefork */
1115 int flushfork( ofork )
1116 struct ofork *ofork;
1120 int err = 0, doflush = 0;
1122 if ( ad_dfileno( ofork->of_ad ) != -1 &&
1123 fsync( ad_dfileno( ofork->of_ad )) < 0 ) {
1124 LOG(log_error, logtype_afpd, "flushfork: dfile(%d) %s",
1125 ad_dfileno(ofork->of_ad), strerror(errno) );
1129 if ( ad_hfileno( ofork->of_ad ) != -1 &&
1130 (ofork->of_flags & AFPFORK_RSRC)) {
1132 /* read in the rfork length */
1133 ad_refresh(ofork->of_ad);
1135 /* set the date if we're dirty */
1136 if ((ofork->of_flags & AFPFORK_DIRTY) && !gettimeofday(&tv, NULL)) {
1137 ad_setdate(ofork->of_ad, AD_DATE_MODIFY|AD_DATE_UNIX, tv.tv_sec);
1138 ofork->of_flags &= ~AFPFORK_DIRTY;
1142 /* flush the header */
1143 if (doflush && ad_flush(ofork->of_ad, ADFLAGS_HF) < 0)
1146 if (fsync( ad_hfileno( ofork->of_ad )) < 0)
1150 LOG(log_error, logtype_afpd, "flushfork: hfile(%d) %s",
1151 ad_hfileno(ofork->of_ad), strerror(errno) );
1157 int afp_closefork(obj, ibuf, ibuflen, rbuf, rbuflen )
1160 int ibuflen, *rbuflen;
1162 struct ofork *ofork;
1164 int adflags, doflush = 0;
1169 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1171 if (NULL == ( ofork = of_find( ofrefnum )) ) {
1172 LOG(log_error, logtype_afpd, "afp_closefork: of_find");
1173 return( AFPERR_PARAM );
1177 if ((ofork->of_flags & AFPFORK_DATA) && (ad_dfileno( ofork->of_ad ) != -1)) {
1178 adflags |= ADFLAGS_DF;
1180 if ( (ofork->of_flags & AFPFORK_OPEN) && ad_hfileno( ofork->of_ad ) != -1 ) {
1181 adflags |= ADFLAGS_HF;
1183 * Only set the rfork's length if we're closing the rfork.
1185 if ((ofork->of_flags & AFPFORK_RSRC)) {
1186 ad_refresh( ofork->of_ad );
1187 if ((ofork->of_flags & AFPFORK_DIRTY) && !gettimeofday(&tv, NULL)) {
1188 ad_setdate(ofork->of_ad, AD_DATE_MODIFY | AD_DATE_UNIX,tv.tv_sec);
1192 ad_flush( ofork->of_ad, adflags );
1197 if ( ad_close( ofork->of_ad, adflags ) < 0 ) {
1198 LOG(log_error, logtype_afpd, "afp_closefork: ad_close: %s", strerror(errno) );
1199 return( AFPERR_PARAM );
1202 of_dealloc( ofork );
1207 static __inline__ ssize_t write_file(struct ofork *ofork, int eid,
1208 off_t offset, char *rbuf,
1209 size_t rbuflen, const int xlate)
1215 * If this file is of type TEXT, swap \015 to \012.
1218 for ( p = rbuf, q = p + rbuflen; p < q; p++ ) {
1219 if ( *p == '\015' ) {
1221 } else if ( *p == '\012' ) {
1227 if (( cc = ad_write(ofork->of_ad, eid, offset, 0,
1228 rbuf, rbuflen)) < 0 ) {
1233 return( AFPERR_DFULL );
1235 LOG(log_error, logtype_afpd, "afp_write: ad_write: %s", strerror(errno) );
1236 return( AFPERR_PARAM );
1244 /* FPWrite. NOTE: on an error, we always use afp_write_err as
1245 * the client may have sent us a bunch of data that's not reflected
1246 * in reqcount et al. */
1247 static int write_fork(obj, ibuf, ibuflen, rbuf, rbuflen, is64)
1250 int ibuflen, *rbuflen;
1253 struct ofork *ofork;
1254 off_t offset, saveoff, reqcount;
1255 int endflag, eid, xlate = 0, err = AFP_OK;
1259 /* figure out parameters */
1261 endflag = ENDBIT(*ibuf);
1263 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1264 ibuf += sizeof( ofrefnum );
1266 offset = get_off_t(&ibuf, is64);
1267 reqcount = get_off_t(&ibuf, is64);
1269 if (NULL == ( ofork = of_find( ofrefnum )) ) {
1270 LOG(log_error, logtype_afpd, "afp_write: of_find");
1275 if ((ofork->of_flags & AFPFORK_ACCWR) == 0) {
1276 err = AFPERR_ACCESS;
1281 writtenfork = ofork;
1284 if ( ofork->of_flags & AFPFORK_DATA) {
1286 xlate = (ofork->of_vol->v_flags & AFPVOL_CRLF) ? crlf(ofork) : 0;
1287 } else if (ofork->of_flags & AFPFORK_RSRC) {
1290 err = AFPERR_ACCESS; /* should never happen */
1295 offset += ad_size(ofork->of_ad, eid);
1297 /* handle bogus parameters */
1298 if (reqcount < 0 || offset < 0) {
1303 /* offset can overflow on 64-bit capable filesystems.
1304 * report disk full if that's going to happen. */
1305 if (sum_neg(is64, offset, reqcount)) {
1310 if (!reqcount) { /* handle request counts of 0 */
1312 *rbuflen = set_off_t (offset, rbuf, is64);
1317 if (ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, saveoff,
1318 reqcount, ofork->of_refnum) < 0) {
1323 /* this is yucky, but dsi can stream i/o and asp can't */
1324 switch (obj->proto) {
1327 if (asp_wrtcont(obj->handle, rbuf, rbuflen) < 0) {
1329 LOG(log_error, logtype_afpd, "afp_write: asp_wrtcont: %s", strerror(errno) );
1330 return( AFPERR_PARAM );
1334 if (obj->options.flags & OPTION_DEBUG) {
1335 printf("(write) len: %d\n", *rbuflen);
1336 bprint(rbuf, *rbuflen);
1339 if ((cc = write_file(ofork, eid, offset, rbuf, *rbuflen,
1342 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum);
1347 #endif /* no afp/asp */
1351 DSI *dsi = obj->handle;
1353 /* find out what we have already and write it out. */
1354 cc = dsi_writeinit(dsi, rbuf, *rbuflen);
1355 if (!cc || (cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
1356 dsi_writeflush(dsi);
1358 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum);
1363 #if 0 /*def HAVE_SENDFILE_WRITE*/
1364 if (!(xlate || obj->options.flags & OPTION_DEBUG)) {
1365 if ((cc = ad_writefile(ofork->of_ad, eid, dsi->socket,
1366 offset, dsi->datasize)) < 0) {
1374 LOG(log_error, logtype_afpd, "afp_write: ad_writefile: %s", strerror(errno) );
1375 goto afp_write_loop;
1377 dsi_writeflush(dsi);
1379 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
1380 reqcount, ofork->of_refnum);
1385 goto afp_write_done;
1387 #endif /* 0, was HAVE_SENDFILE_WRITE */
1389 /* loop until everything gets written. currently
1390 * dsi_write handles the end case by itself. */
1391 while ((cc = dsi_write(dsi, rbuf, *rbuflen))) {
1393 if ( obj->options.flags & OPTION_DEBUG ) {
1394 printf("(write) command cont'd: %d\n", cc);
1398 if ((cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
1399 dsi_writeflush(dsi);
1401 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
1402 reqcount, ofork->of_refnum);
1411 ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum);
1412 if ( ad_hfileno( ofork->of_ad ) != -1 )
1413 ofork->of_flags |= AFPFORK_DIRTY;
1415 *rbuflen = set_off_t (offset, rbuf, is64);
1419 if (obj->proto == AFPPROTO_DSI) {
1420 dsi_writeinit(obj->handle, rbuf, *rbuflen);
1421 dsi_writeflush(obj->handle);
1423 if (err != AFP_OK) {
1429 /* ---------------------------- */
1430 int afp_write(obj, ibuf, ibuflen, rbuf, rbuflen)
1433 int ibuflen, *rbuflen;
1435 return write_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 0);
1438 /* ----------------------------
1439 * FIXME need to deal with SIGXFSZ signal
1441 int afp_write_ext(obj, ibuf, ibuflen, rbuf, rbuflen)
1444 int ibuflen, *rbuflen;
1446 return write_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 1);
1449 /* ---------------------------- */
1450 int afp_getforkparams(obj, ibuf, ibuflen, rbuf, rbuflen )
1453 int ibuflen, *rbuflen;
1455 struct ofork *ofork;
1457 u_int16_t ofrefnum, bitmap;
1458 u_int16_t attrbits = 0;
1461 memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
1462 ibuf += sizeof( ofrefnum );
1463 memcpy(&bitmap, ibuf, sizeof( bitmap ));
1464 bitmap = ntohs( bitmap );
1465 ibuf += sizeof( bitmap );
1468 if (NULL == ( ofork = of_find( ofrefnum )) ) {
1469 LOG(log_error, logtype_afpd, "afp_getforkparams: of_find");
1470 return( AFPERR_PARAM );
1472 attrbits = ((ofork->of_ad->ad_df.adf_refcount > 0) ? ATTRBIT_DOPEN : 0);
1473 attrbits |= ((ofork->of_ad->ad_hf.adf_refcount > ofork->of_ad->ad_df.adf_refcount) ? ATTRBIT_ROPEN : 0);
1475 if ( ad_hfileno( ofork->of_ad ) != -1 ) {
1476 if ( ad_refresh( ofork->of_ad ) < 0 ) {
1477 LOG(log_error, logtype_afpd, "getforkparams: ad_refresh: %s", strerror(errno) );
1478 return( AFPERR_PARAM );
1482 if (AFP_OK != ( ret = getforkparams( ofork, bitmap,
1483 rbuf + sizeof( u_short ), &buflen, attrbits ))) {
1487 *rbuflen = buflen + sizeof( u_short );
1488 bitmap = htons( bitmap );
1489 memcpy(rbuf, &bitmap, sizeof( bitmap ));