X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=etc%2Fafpd%2Ffork.c;h=33aaf66d1c025b1be90da8170b05376a2f988d81;hb=b35812db1e932c31154b7da72c564dabe95fd03d;hp=ddc01fb31c2a7bd5ffea9391901d0e872b9d3573;hpb=63d8899d3bce4722a014f4566cbc9cde82e10225;p=netatalk.git diff --git a/etc/afpd/fork.c b/etc/afpd/fork.c index ddc01fb3..33aaf66d 100644 --- a/etc/afpd/fork.c +++ b/etc/afpd/fork.c @@ -1,5 +1,5 @@ /* - * $Id: fork.c,v 1.51 2003-03-15 01:34:35 didg Exp $ + * $Id: fork.c,v 1.73 2010-03-30 12:55:26 franklahm Exp $ * * Copyright (c) 1990,1993 Regents of The University of Michigan. * All Rights Reserved. See COPYRIGHT. @@ -10,55 +10,43 @@ #endif /* HAVE_CONFIG_H */ #include -#ifdef HAVE_UNISTD_H -#include -#endif /* HAVE_UNISTD_H */ -#ifdef HAVE_FCNTL_H -#include -#endif /* HAVE_FCNTL_H */ -#include + #include #include + +#include #include #include -#include -#include -#include #include -#include #include #include #include #include #include -#include #include -#ifdef CNID_DB #include -#endif +#include #include "fork.h" #include "file.h" -#include "globals.h" #include "directory.h" #include "desktop.h" #include "volume.h" -struct ofork *writtenfork; -extern int getmetadata(struct vol *vol, - u_int16_t bitmap, - struct path *path, struct dir *dir, char *buf, - int *buflen, struct adouble *adp, int attrbits ); - -static int getforkparams(ofork, bitmap, buf, buflen, attrbits ) -struct ofork *ofork; -u_int16_t bitmap; -char *buf; -int *buflen; -const u_int16_t attrbits; +#ifdef DEBUG1 +#define Debug(a) ((a)->options.flags & OPTION_DEBUG) +#else +#define Debug(a) (0) +#endif + +#ifdef AFS +struct ofork *writtenfork; +#endif + +static int getforkparams(struct ofork *ofork, u_int16_t bitmap, char *buf, size_t *buflen) { struct path path; struct stat *st; @@ -77,41 +65,41 @@ const u_int16_t attrbits; return( AFPERR_BITMAP ); } - if ( ad_hfileno( ofork->of_ad ) == -1 ) { + if ( ad_reso_fileno( ofork->of_ad ) == -1 ) { /* META ? */ adp = NULL; } else { adp = ofork->of_ad; } vol = ofork->of_vol; - dir = ofork->of_dir; + dir = dirlookup(vol, ofork->of_did); - if (NULL == (path.u_name = mtoupath(vol, ofork->of_name, utf8_encoding()))) { + if (NULL == (path.u_name = mtoupath(vol, of_name(ofork), dir->d_did, utf8_encoding()))) { return( AFPERR_MISC ); } - path.m_name = ofork->of_name; + path.m_name = of_name(ofork); + path.id = 0; st = &path.st; if ( bitmap & ( (1<of_ad ) == -1 ) { + if ( ad_data_fileno( ofork->of_ad ) <= 0 ) { + /* 0 is for symlink */ if (movecwd(vol, dir) < 0) return( AFPERR_NOOBJ ); - if ( stat( path.u_name, st ) < 0 ) + if ( lstat( path.u_name, st ) < 0 ) return( AFPERR_NOOBJ ); } else { - if ( fstat( ad_dfileno( ofork->of_ad ), st ) < 0 ) { + if ( fstat( ad_data_fileno( ofork->of_ad ), st ) < 0 ) { return( AFPERR_BITMAP ); } } } - return getmetadata(vol, bitmap, &path, dir, buf, buflen, adp, attrbits ); + return getmetadata(vol, bitmap, &path, dir, buf, buflen, adp ); } /* ---------------------------- */ -static off_t get_off_t(ibuf, is64) -char **ibuf; -int is64; +static off_t get_off_t(char **ibuf, int is64) { u_int32_t temp; off_t ret; @@ -133,10 +121,7 @@ int is64; } /* ---------------------- */ -static int set_off_t(offset, rbuf, is64) -off_t offset; -char *rbuf; -int is64; +static int set_off_t(off_t offset, char *rbuf, int is64) { u_int32_t temp; int ret; @@ -165,7 +150,7 @@ static int is_neg(int is64, off_t val) return 0; } -static __inline__ int sum_neg(int is64, off_t offset, off_t reqcount) +static int sum_neg(int is64, off_t offset, off_t reqcount) { if (is_neg(is64, offset +reqcount) ) return 1; @@ -174,18 +159,20 @@ static __inline__ int sum_neg(int is64, off_t offset, off_t reqcount) /* ------------------------- */ -static int setforkmode(struct adouble *adp, int eid, int ofrefnum, int what) +static int setforkmode(struct adouble *adp, int eid, int ofrefnum, off_t what) { return ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, what, 1, ofrefnum); } /* ------------------------- */ -static int getforkmode(struct adouble *adp, int eid, int what) +int getforkmode(struct adouble *adp, int eid, off_t what) { return ad_testlock(adp, eid, what); } +/* ------------------------- +*/ static int fork_setmode(struct adouble *adp, int eid, int access, int ofrefnum) { int ret; @@ -252,27 +239,23 @@ static int fork_setmode(struct adouble *adp, int eid, int access, int ofrefnum) return ret; } } - if ( access == (OPENACC_WR | OPENACC_RD | OPENACC_DWR | OPENACC_DRD)) { return ad_excl_lock(adp, eid); } - return 0; } /* ----------------------- */ -int afp_openfork(obj, ibuf, ibuflen, rbuf, rbuflen ) -AFPObj *obj; -char *ibuf, *rbuf; -int ibuflen, *rbuflen; +int afp_openfork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) { struct vol *vol; struct dir *dir; struct ofork *ofork, *opened; struct adouble *adsame = NULL; - int buflen, ret, adflags, eid; + size_t buflen; + int ret, adflags, eid; u_int32_t did; - u_int16_t vid, bitmap, access, ofrefnum, attrbits = 0; + u_int16_t vid, bitmap, access, ofrefnum; char fork, *path, *upath; struct stat *st; u_int16_t bshort; @@ -324,13 +307,20 @@ int ibuflen, *rbuflen; case EACCES: return (access & OPENACC_WR) ? AFPERR_LOCK : AFPERR_ACCESS; default: - LOG(log_error, logtype_afpd, "afp_openfork: ad_open: %s", strerror(errno) ); + LOG(log_error, logtype_afpd, "afp_openfork(%s): ad_open: %s", s_path->m_name, strerror(errno) ); return AFPERR_PARAM; } /* FIXME should we check it first ? */ upath = s_path->u_name; - if (check_access(upath, access ) < 0) { - return AFPERR_ACCESS; + if (!vol_unix_priv(vol)) { + if (check_access(upath, access ) < 0) { + return AFPERR_ACCESS; + } + } + else { + if (file_access(s_path, access ) < 0) { + return AFPERR_ACCESS; + } } st = &s_path->st; @@ -342,9 +332,6 @@ int ibuflen, *rbuflen; FIXME: add the fork we are opening? */ if ((opened = of_findname(s_path))) { - attrbits = ((opened->of_ad->ad_df.adf_refcount > 0) ? ATTRBIT_DOPEN : 0); - attrbits |= ((opened->of_ad->ad_hf.adf_refcount > opened->of_ad->ad_df.adf_refcount)? ATTRBIT_ROPEN : 0); - adsame = opened->of_ad; } @@ -398,7 +385,7 @@ int ibuflen, *rbuflen; goto openfork_err; break; default: - LOG(log_error, logtype_afpd, "afp_openfork: ad_open: %s", strerror(errno) ); + LOG(log_error, logtype_afpd, "afp_openfork(%s): ad_open: %s", s_path->m_name, strerror(errno) ); ret = AFPERR_PARAM; goto openfork_err; break; @@ -445,7 +432,8 @@ int ibuflen, *rbuflen; goto openfork_err; break; default: - LOG(log_error, logtype_afpd, "afp_openfork: ad_open: %s", strerror(errno) ); + LOG(log_error, logtype_afpd, "afp_openfork('%s/%s'): ad_open: errno: %i (%s)", + getcwdpath, s_path->m_name, errno, strerror(errno) ); goto openfork_err; break; } @@ -457,14 +445,13 @@ int ibuflen, *rbuflen; } if ((adflags & ADFLAGS_HF) && (ad_get_HF_flags( ofork->of_ad) & O_CREAT)) { - ad_setentrylen( ofork->of_ad, ADEID_NAME, strlen( path )); - memcpy(ad_entry( ofork->of_ad, ADEID_NAME ), path, - ad_getentrylen( ofork->of_ad, ADEID_NAME )); - ad_flush( ofork->of_ad, adflags ); + if (ad_setname(ofork->of_ad, path)) { + ad_flush( ofork->of_ad ); + } } if (( ret = getforkparams(ofork, bitmap, rbuf + 2 * sizeof( u_int16_t ), - &buflen, attrbits )) != AFP_OK ) { + &buflen )) != AFP_OK ) { ad_close( ofork->of_ad, adflags ); goto openfork_err; } @@ -477,7 +464,7 @@ int ibuflen, *rbuflen; /* check WriteInhibit bit if we have a ressource fork * the test is done here, after some Mac trafic capture */ - if (ad_hfileno(ofork->of_ad) != -1) { + if (ad_meta_fileno(ofork->of_ad) != -1) { /* META */ ad_getattr(ofork->of_ad, &bshort); if ((bshort & htons(ATTRBIT_NOWRITE)) && (access & OPENACC_WR)) { ad_close( ofork->of_ad, adflags ); @@ -493,7 +480,7 @@ int ibuflen, *rbuflen; */ /* don't try to lock non-existent rforks. */ - if ((eid == ADEID_DFORK) || (ad_hfileno(ofork->of_ad) != -1)) { + if ((eid == ADEID_DFORK) || (ad_meta_fileno(ofork->of_ad) != -1)) { /* META */ ret = fork_setmode(ofork->of_ad, eid, access, ofrefnum); /* can we access the fork? */ @@ -511,7 +498,7 @@ int ibuflen, *rbuflen; break; default: *rbuflen = 0; - LOG(log_error, logtype_afpd, "afp_openfork: ad_lock: %s", strerror(ret) ); + LOG(log_error, logtype_afpd, "afp_openfork(%s): ad_lock: %s", s_path->m_name, strerror(ret) ); return( AFPERR_PARAM ); } } @@ -532,10 +519,7 @@ openfork_err: return ret; } -int afp_setforkparams(obj, ibuf, ibuflen, rbuf, rbuflen ) -AFPObj *obj; -char *ibuf, *rbuf; -int ibuflen, *rbuflen; +int afp_setforkparams(AFPObj *obj _U_, char *ibuf, size_t ibuflen, char *rbuf _U_, size_t *rbuflen) { struct ofork *ofork; off_t size; @@ -556,7 +540,7 @@ int ibuflen, *rbuflen; *rbuflen = 0; if (NULL == ( ofork = of_find( ofrefnum )) ) { - LOG(log_error, logtype_afpd, "afp_setforkparams: of_find could not locate open fork refnum: %u", ofrefnum ); + LOG(log_error, logtype_afpd, "afp_setforkparams: of_find(%d) could not locate fork", ofrefnum ); return( AFPERR_PARAM ); } @@ -626,8 +610,8 @@ int ibuflen, *rbuflen; if (err < 0) goto afp_setfork_err; - if (ad_flush( ofork->of_ad, ADFLAGS_HF ) < 0) { - LOG(log_error, logtype_afpd, "afp_setforkparams: ad_flush: %s",strerror(errno) ); + if (ad_flush( ofork->of_ad ) < 0) { + LOG(log_error, logtype_afpd, "afp_setforkparams(%s): ad_flush: %s", of_name(ofork), strerror(errno) ); return AFPERR_PARAM; } } else @@ -635,7 +619,7 @@ int ibuflen, *rbuflen; #ifdef AFS if ( flushfork( ofork ) < 0 ) { - LOG(log_error, logtype_afpd, "afp_setforkparams: flushfork: %s", strerror(errno) ); + LOG(log_error, logtype_afpd, "afp_setforkparams(%s): flushfork: %s", of_name(ofork), strerror(errno) ); } #endif /* AFS */ @@ -654,6 +638,7 @@ afp_setfork_err: case EDQUOT: case EFBIG: case ENOSPC: + LOG(log_error, logtype_afpd, "afp_setforkparams: DISK FULL"); return AFPERR_DFULL; default: return AFPERR_PARAM; @@ -672,11 +657,7 @@ afp_setfork_err: /* ---------------------- */ -static int byte_lock(obj, ibuf, ibuflen, rbuf, rbuflen, is64 ) -AFPObj *obj; -char *ibuf, *rbuf; -int ibuflen, *rbuflen; -int is64; +static int byte_lock(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen, int is64) { struct ofork *ofork; off_t offset, length; @@ -695,7 +676,7 @@ int is64; ibuf += sizeof(ofrefnum); if (NULL == ( ofork = of_find( ofrefnum )) ) { - LOG(log_error, logtype_afpd, "afp_bytelock: of_find"); + LOG(log_error, logtype_afpd, "afp_bytelock: of_find(%d) could not locate fork", ofrefnum ); return( AFPERR_PARAM ); } @@ -714,7 +695,7 @@ int is64; length = BYTELOCK_MAX; else if (!length || is_neg(is64, length)) { return AFPERR_PARAM; - } else if ((length >= AD_FILELOCK_BASE) && -1 == (ad_hfileno(ofork->of_ad))) { + } else if ((length >= AD_FILELOCK_BASE) && -1 == (ad_reso_fileno(ofork->of_ad))) { /* HF ?*/ return AFPERR_LOCK; } @@ -755,19 +736,13 @@ int is64; } /* --------------------------- */ -int afp_bytelock(obj, ibuf, ibuflen, rbuf, rbuflen ) -AFPObj *obj; -char *ibuf, *rbuf; -int ibuflen, *rbuflen; +int afp_bytelock(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) { return byte_lock ( obj, ibuf, ibuflen, rbuf, rbuflen , 0); } /* --------------------------- */ -int afp_bytelock_ext(obj, ibuf, ibuflen, rbuf, rbuflen ) -AFPObj *obj; -char *ibuf, *rbuf; -int ibuflen, *rbuflen; +int afp_bytelock_ext(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) { return byte_lock ( obj, ibuf, ibuflen, rbuf, rbuflen , 1); } @@ -775,35 +750,29 @@ int ibuflen, *rbuflen; #undef UNLOCKBIT /* --------------------------- */ -static __inline__ int crlf( of ) -struct ofork *of; +static int crlf(struct ofork *of) { struct extmap *em; - if ( ad_hfileno( of->of_ad ) == -1 || - memcmp( ufinderi, ad_entry( of->of_ad, ADEID_FINDERI ), - 8) == 0 ) { - if (NULL == ( em = getextmap( of->of_name )) || - memcmp( "TEXT", em->em_type, sizeof( em->em_type )) == 0 ) { - return( 1 ); - } else { - return( 0 ); - } - } else { - if ( memcmp( ufinderi, - ad_entry( of->of_ad, ADEID_FINDERI ), 4 ) == 0 ) { - return( 1 ); - } else { - return( 0 ); - } + if ( ad_meta_fileno( of->of_ad ) == -1 || !memcmp( ufinderi, ad_entry( of->of_ad, ADEID_FINDERI),8)) { /* META */ + /* no resource fork or no finderinfo, use our files extension mapping */ + if (!( em = getextmap( of_name(of) )) || memcmp( "TEXT", em->em_type, sizeof( em->em_type ))) { + return 0; + } + /* file type is TEXT */ + return 1; + + } else if ( !memcmp( "TEXT", ad_entry( of->of_ad, ADEID_FINDERI ), 4 )) { + return 1; } + return 0; } -static __inline__ ssize_t read_file(struct ofork *ofork, int eid, +static ssize_t read_file(struct ofork *ofork, int eid, off_t offset, u_char nlmask, u_char nlchar, char *rbuf, - int *rbuflen, const int xlate) + size_t *rbuflen, const int xlate) { ssize_t cc; int eof = 0; @@ -811,11 +780,11 @@ static __inline__ ssize_t read_file(struct ofork *ofork, int eid, cc = ad_read(ofork->of_ad, eid, offset, rbuf, *rbuflen); if ( cc < 0 ) { - LOG(log_error, logtype_afpd, "afp_read: ad_read: %s", strerror(errno) ); + LOG(log_error, logtype_afpd, "afp_read(%s): ad_read: %s", of_name(ofork), strerror(errno) ); *rbuflen = 0; return( AFPERR_PARAM ); } - if ( cc < *rbuflen ) { + if ( (size_t)cc < *rbuflen ) { eof = 1; } @@ -868,25 +837,21 @@ static __inline__ ssize_t read_file(struct ofork *ofork, int eid, * * with dsi, should we check that reqcount < server quantum? */ -static int read_fork(obj, ibuf, ibuflen, rbuf, rbuflen, is64) -AFPObj *obj; -char *ibuf, *rbuf; -int ibuflen, *rbuflen; -int is64; +static int read_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen, int is64) { struct ofork *ofork; - off_t size; off_t offset, saveoff, reqcount, savereqcount; - int cc, err, eid, xlate = 0; + ssize_t cc, err; + int eid, xlate = 0; u_int16_t ofrefnum; u_char nlmask, nlchar; - + ibuf += 2; memcpy(&ofrefnum, ibuf, sizeof( ofrefnum )); ibuf += sizeof( u_short ); if (NULL == ( ofork = of_find( ofrefnum )) ) { - LOG(log_error, logtype_afpd, "afp_read: of_find"); + LOG(log_error, logtype_afpd, "afp_read: of_find(%d) could not locate fork", ofrefnum ); err = AFPERR_PARAM; goto afp_read_err; } @@ -929,13 +894,8 @@ int is64; goto afp_read_err; } - /* reqcount isn't always truthful. we need to deal with that. */ - size = ad_size(ofork->of_ad, eid); - - if (offset >= size) { - err = AFPERR_EOF; - goto afp_read_err; - } + LOG(log_debug, logtype_afpd, "afp_read(name: \"%s\", offset: %jd, reqcount: %jd)", + of_name(ofork), (intmax_t)offset, (intmax_t)reqcount); savereqcount = reqcount; saveoff = offset; @@ -944,23 +904,24 @@ int is64; goto afp_read_err; } -#define min(a,b) ((a)<(b)?(a):(b)) - *rbuflen = min( reqcount, *rbuflen ); - err = read_file(ofork, eid, offset, nlmask, nlchar, rbuf, rbuflen, - xlate); + *rbuflen = MIN(reqcount, *rbuflen); + LOG(log_debug, logtype_afpd, "afp_read(name: \"%s\", offset: %jd, reqcount: %jd): reading %jd bytes from file", + of_name(ofork), (intmax_t)offset, (intmax_t)reqcount, (intmax_t)*rbuflen); + err = read_file(ofork, eid, offset, nlmask, nlchar, rbuf, rbuflen, xlate); if (err < 0) goto afp_read_done; + LOG(log_debug, logtype_afpd, "afp_read(name: \"%s\", offset: %jd, reqcount: %jd): got %jd bytes from file", + of_name(ofork), (intmax_t)offset, (intmax_t)reqcount, (intmax_t)*rbuflen); /* dsi can stream requests. we can only do this if we're not checking * for an end-of-line character. oh well. */ if ((obj->proto == AFPPROTO_DSI) && (*rbuflen < reqcount) && !nlmask) { - DSI *dsi = obj->handle; + DSI *dsi = obj->handle; + off_t size; + + /* reqcount isn't always truthful. we need to deal with that. */ + size = ad_size(ofork->of_ad, eid); - if (obj->options.flags & OPTION_DEBUG) { - printf( "(read) reply: %d/%d, %d\n", *rbuflen, - (int) reqcount, dsi->clientID); - bprint(rbuf, *rbuflen); - } /* subtract off the offset */ size -= offset; if (reqcount > size) { @@ -973,19 +934,22 @@ int is64; /* dsi_readinit() returns size of next read buffer. by this point, * we know that we're sending some data. if we fail, something * horrible happened. */ - if ((*rbuflen = dsi_readinit(dsi, rbuf, *rbuflen, reqcount, err)) < 0) + if ((cc = dsi_readinit(dsi, rbuf, *rbuflen, reqcount, err)) < 0) goto afp_read_exit; - + *rbuflen = cc; /* due to the nature of afp packets, we have to exit if we get an error. we can't do this with translation on. */ -#ifdef HAVE_SENDFILE_READ - if (!(xlate || (obj->options.flags & OPTION_DEBUG))) { - if (ad_readfile(ofork->of_ad, eid, dsi->socket, offset, - dsi->datasize) < 0) { - if (errno == EINVAL) +#ifdef WITH_SENDFILE + if (!(xlate || Debug(obj) )) { + int fd; + + fd = ad_readfile_init(ofork->of_ad, eid, &offset, 0); + + if (dsi_stream_read_file(dsi, fd, offset, dsi->datasize) < 0) { + if (errno == EINVAL || errno == ENOSYS) goto afp_read_loop; else { - LOG(log_error, logtype_afpd, "afp_read: ad_readfile: %s", strerror(errno)); + LOG(log_error, logtype_afpd, "afp_read(%s): ad_readfile: %s", of_name(ofork), strerror(errno)); goto afp_read_exit; } } @@ -995,21 +959,15 @@ int is64; } afp_read_loop: -#endif /* HAVE_SENDFILE_READ */ +#endif /* fill up our buffer. */ while (*rbuflen > 0) { - cc = read_file(ofork, eid, offset, nlmask, nlchar, rbuf, - rbuflen, xlate); + cc = read_file(ofork, eid, offset, nlmask, nlchar, rbuf,rbuflen, xlate); if (cc < 0) goto afp_read_exit; offset += *rbuflen; - if (obj->options.flags & OPTION_DEBUG) { - printf( "(read) reply: %d, %d\n", *rbuflen, dsi->clientID); - bprint(rbuf, *rbuflen); - } - /* dsi_read() also returns buffer size of next allocation */ cc = dsi_read(dsi, rbuf, *rbuflen); /* send it off */ if (cc < 0) @@ -1020,10 +978,10 @@ afp_read_loop: goto afp_read_done; afp_read_exit: - LOG(log_error, logtype_afpd, "afp_read: %s", strerror(errno)); + LOG(log_error, logtype_afpd, "afp_read(%s): %s", of_name(ofork), strerror(errno)); dsi_readdone(dsi); ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount,ofork->of_refnum); - obj->exit(1); + obj->exit(EXITERR_CLNT); } afp_read_done: @@ -1036,28 +994,19 @@ afp_read_err: } /* ---------------------- */ -int afp_read(obj, ibuf, ibuflen, rbuf, rbuflen) -AFPObj *obj; -char *ibuf, *rbuf; -int ibuflen, *rbuflen; +int afp_read(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) { return read_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 0); } /* ---------------------- */ -int afp_read_ext(obj, ibuf, ibuflen, rbuf, rbuflen) -AFPObj *obj; -char *ibuf, *rbuf; -int ibuflen, *rbuflen; +int afp_read_ext(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) { return read_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 1); } /* ---------------------- */ -int afp_flush(obj, ibuf, ibuflen, rbuf, rbuflen ) -AFPObj *obj; -char *ibuf, *rbuf; -int ibuflen, *rbuflen; +int afp_flush(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) { struct vol *vol; u_int16_t vid; @@ -1074,10 +1023,7 @@ int ibuflen, *rbuflen; return( AFP_OK ); } -int afp_flushfork(obj, ibuf, ibuflen, rbuf, rbuflen ) -AFPObj *obj; -char *ibuf, *rbuf; -int ibuflen, *rbuflen; +int afp_flushfork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) { struct ofork *ofork; u_int16_t ofrefnum; @@ -1087,34 +1033,63 @@ int ibuflen, *rbuflen; memcpy(&ofrefnum, ibuf, sizeof( ofrefnum )); if (NULL == ( ofork = of_find( ofrefnum )) ) { - LOG(log_error, logtype_afpd, "afp_flushfork: of_find"); + LOG(log_error, logtype_afpd, "afp_flushfork: of_find(%d) could not locate fork", ofrefnum ); + return( AFPERR_PARAM ); + } + + if ( flushfork( ofork ) < 0 ) { + LOG(log_error, logtype_afpd, "afp_flushfork(%s): %s", of_name(ofork), strerror(errno) ); + } + + return( AFP_OK ); +} + +/* + FIXME + There is a lot to tell about fsync, fdatasync, F_FULLFSYNC. + fsync(2) on OSX is implemented differently than on other platforms. + see: http://mirror.linux.org.au/pub/linux.conf.au/2007/video/talks/278.pdf. + */ +int afp_syncfork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +{ + struct ofork *ofork; + u_int16_t ofrefnum; + + *rbuflen = 0; + ibuf += 2; + + memcpy(&ofrefnum, ibuf, sizeof(ofrefnum)); + ibuf += sizeof( ofrefnum ); + + if (NULL == ( ofork = of_find( ofrefnum )) ) { + LOG(log_error, logtype_afpd, "afpd_syncfork: of_find(%d) could not locate fork", ofrefnum ); return( AFPERR_PARAM ); } if ( flushfork( ofork ) < 0 ) { - LOG(log_error, logtype_afpd, "afp_flushfork: %s", strerror(errno) ); + LOG(log_error, logtype_afpd, "flushfork(%s): %s", of_name(ofork), strerror(errno) ); + return AFPERR_MISC; } return( AFP_OK ); } /* this is very similar to closefork */ -int flushfork( ofork ) -struct ofork *ofork; +int flushfork(struct ofork *ofork) { struct timeval tv; int err = 0, doflush = 0; - if ( ad_dfileno( ofork->of_ad ) != -1 && - fsync( ad_dfileno( ofork->of_ad )) < 0 ) { - LOG(log_error, logtype_afpd, "flushfork: dfile(%d) %s", - ad_dfileno(ofork->of_ad), strerror(errno) ); + if ( ad_data_fileno( ofork->of_ad ) != -1 && + fsync( ad_data_fileno( ofork->of_ad )) < 0 ) { + LOG(log_error, logtype_afpd, "flushfork(%s): dfile(%d) %s", + of_name(ofork), ad_data_fileno(ofork->of_ad), strerror(errno) ); err = -1; } - if ( ad_hfileno( ofork->of_ad ) != -1 && - (ofork->of_flags & AFPFORK_RSRC)) { + if ( ad_reso_fileno( ofork->of_ad ) != -1 && /* HF */ + (ofork->of_flags & AFPFORK_RSRC)) { /* read in the rfork length */ ad_refresh(ofork->of_ad); @@ -1127,28 +1102,23 @@ struct ofork *ofork; } /* flush the header */ - if (doflush && ad_flush(ofork->of_ad, ADFLAGS_HF) < 0) + if (doflush && ad_flush(ofork->of_ad) < 0) err = -1; - if (fsync( ad_hfileno( ofork->of_ad )) < 0) + if (fsync( ad_reso_fileno( ofork->of_ad )) < 0) err = -1; if (err < 0) - LOG(log_error, logtype_afpd, "flushfork: hfile(%d) %s", - ad_hfileno(ofork->of_ad), strerror(errno) ); + LOG(log_error, logtype_afpd, "flushfork(%s): hfile(%d) %s", + of_name(ofork), ad_reso_fileno(ofork->of_ad), strerror(errno) ); } return( err ); } -int afp_closefork(obj, ibuf, ibuflen, rbuf, rbuflen ) -AFPObj *obj; -char *ibuf, *rbuf; -int ibuflen, *rbuflen; +int afp_closefork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) { struct ofork *ofork; - struct timeval tv; - int adflags, doflush = 0; u_int16_t ofrefnum; *rbuflen = 0; @@ -1156,42 +1126,19 @@ int ibuflen, *rbuflen; memcpy(&ofrefnum, ibuf, sizeof( ofrefnum )); if (NULL == ( ofork = of_find( ofrefnum )) ) { - LOG(log_error, logtype_afpd, "afp_closefork: of_find"); + LOG(log_error, logtype_afpd, "afp_closefork: of_find(%d) could not locate fork", ofrefnum ); return( AFPERR_PARAM ); } - - adflags = 0; - if ((ofork->of_flags & AFPFORK_DATA) && (ad_dfileno( ofork->of_ad ) != -1)) { - adflags |= ADFLAGS_DF; - } - if ( (ofork->of_flags & AFPFORK_OPEN) && ad_hfileno( ofork->of_ad ) != -1 ) { - adflags |= ADFLAGS_HF; - /* - * Only set the rfork's length if we're closing the rfork. - */ - if ((ofork->of_flags & AFPFORK_RSRC)) { - ad_refresh( ofork->of_ad ); - if ((ofork->of_flags & AFPFORK_DIRTY) && !gettimeofday(&tv, NULL)) { - ad_setdate(ofork->of_ad, AD_DATE_MODIFY | AD_DATE_UNIX,tv.tv_sec); - doflush++; - } - if ( doflush ) { - ad_flush( ofork->of_ad, adflags ); - } - } - } - - if ( ad_close( ofork->of_ad, adflags ) < 0 ) { - LOG(log_error, logtype_afpd, "afp_closefork: ad_close: %s", strerror(errno) ); + if ( of_closefork( ofork ) < 0 ) { + LOG(log_error, logtype_afpd, "afp_closefork(%s): of_closefork: %s", of_name(ofork), strerror(errno) ); return( AFPERR_PARAM ); } - of_dealloc( ofork ); return( AFP_OK ); } -static __inline__ ssize_t write_file(struct ofork *ofork, int eid, +static ssize_t write_file(struct ofork *ofork, int eid, off_t offset, char *rbuf, size_t rbuflen, const int xlate) { @@ -1217,9 +1164,12 @@ static __inline__ ssize_t write_file(struct ofork *ofork, int eid, case EDQUOT : case EFBIG : case ENOSPC : + LOG(log_error, logtype_afpd, "write_file: DISK FULL"); return( AFPERR_DFULL ); + case EACCES: + return AFPERR_ACCESS; default : - LOG(log_error, logtype_afpd, "afp_write: ad_write: %s", strerror(errno) ); + LOG(log_error, logtype_afpd, "afp_write(%s): ad_write: %s", of_name(ofork), strerror(errno) ); return( AFPERR_PARAM ); } } @@ -1231,14 +1181,10 @@ static __inline__ ssize_t write_file(struct ofork *ofork, int eid, /* FPWrite. NOTE: on an error, we always use afp_write_err as * the client may have sent us a bunch of data that's not reflected * in reqcount et al. */ -static int write_fork(obj, ibuf, ibuflen, rbuf, rbuflen, is64) -AFPObj *obj; -char *ibuf, *rbuf; -int ibuflen, *rbuflen; -int is64; +static int write_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen, int is64) { struct ofork *ofork; - off_t offset, saveoff, reqcount; + off_t offset, saveoff, reqcount, oldsize, newsize; int endflag, eid, xlate = 0, err = AFP_OK; u_int16_t ofrefnum; ssize_t cc; @@ -1254,7 +1200,7 @@ int is64; reqcount = get_off_t(&ibuf, is64); if (NULL == ( ofork = of_find( ofrefnum )) ) { - LOG(log_error, logtype_afpd, "afp_write: of_find"); + LOG(log_error, logtype_afpd, "afp_write: of_find(%d) could not locate fork", ofrefnum ); err = AFPERR_PARAM; goto afp_write_err; } @@ -1278,8 +1224,9 @@ int is64; goto afp_write_err; } + oldsize = ad_size(ofork->of_ad, eid); if (endflag) - offset += ad_size(ofork->of_ad, eid); + offset += oldsize; /* handle bogus parameters */ if (reqcount < 0 || offset < 0) { @@ -1287,9 +1234,12 @@ int is64; goto afp_write_err; } + newsize = ((offset + reqcount) > oldsize) ? (offset + reqcount) : oldsize; + /* offset can overflow on 64-bit capable filesystems. * report disk full if that's going to happen. */ if (sum_neg(is64, offset, reqcount)) { + LOG(log_error, logtype_afpd, "write_fork: DISK FULL"); err = AFPERR_DFULL; goto afp_write_err; } @@ -1317,11 +1267,12 @@ int is64; return( AFPERR_PARAM ); } +#ifdef DEBUG1 if (obj->options.flags & OPTION_DEBUG) { printf("(write) len: %d\n", *rbuflen); bprint(rbuf, *rbuflen); } - +#endif if ((cc = write_file(ofork, eid, offset, rbuf, *rbuflen, xlate)) < 0) { *rbuflen = 0; @@ -1338,8 +1289,7 @@ int is64; /* find out what we have already and write it out. */ cc = dsi_writeinit(dsi, rbuf, *rbuflen); - if (!cc || - (cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) { + if (!cc || (cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) { dsi_writeflush(dsi); *rbuflen = 0; ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum); @@ -1376,11 +1326,6 @@ int is64; /* loop until everything gets written. currently * dsi_write handles the end case by itself. */ while ((cc = dsi_write(dsi, rbuf, *rbuflen))) { - if ( obj->options.flags & OPTION_DEBUG ) { - printf("(write) command cont'd: %d\n", cc); - bprint(rbuf, cc); - } - if ((cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) { dsi_writeflush(dsi); *rbuflen = 0; @@ -1395,9 +1340,15 @@ int is64; } ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum); - if ( ad_hfileno( ofork->of_ad ) != -1 ) + if ( ad_meta_fileno( ofork->of_ad ) != -1 ) /* META */ ofork->of_flags |= AFPFORK_DIRTY; + /* we have modified any fork, remember until close_fork */ + ofork->of_flags |= AFPFORK_MODIFIED; + + /* update write count */ + ofork->of_vol->v_appended += (newsize > oldsize) ? (newsize - oldsize) : 0; + *rbuflen = set_off_t (offset, rbuf, is64); return( AFP_OK ); @@ -1406,16 +1357,14 @@ afp_write_err: dsi_writeinit(obj->handle, rbuf, *rbuflen); dsi_writeflush(obj->handle); } - - *rbuflen = (err == AFP_OK) ? sizeof(offset) : 0; + if (err != AFP_OK) { + *rbuflen = 0; + } return err; } /* ---------------------------- */ -int afp_write(obj, ibuf, ibuflen, rbuf, rbuflen) -AFPObj *obj; -char *ibuf, *rbuf; -int ibuflen, *rbuflen; +int afp_write(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) { return write_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 0); } @@ -1423,25 +1372,18 @@ int ibuflen, *rbuflen; /* ---------------------------- * FIXME need to deal with SIGXFSZ signal */ -int afp_write_ext(obj, ibuf, ibuflen, rbuf, rbuflen) -AFPObj *obj; -char *ibuf, *rbuf; -int ibuflen, *rbuflen; +int afp_write_ext(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) { return write_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 1); } /* ---------------------------- */ -int afp_getforkparams(obj, ibuf, ibuflen, rbuf, rbuflen ) -AFPObj *obj; -char *ibuf, *rbuf; -int ibuflen, *rbuflen; +int afp_getforkparams(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) { struct ofork *ofork; - int buflen, ret; + int ret; u_int16_t ofrefnum, bitmap; - u_int16_t attrbits = 0; - + size_t buflen; ibuf += 2; memcpy(&ofrefnum, ibuf, sizeof( ofrefnum )); ibuf += sizeof( ofrefnum ); @@ -1451,21 +1393,19 @@ int ibuflen, *rbuflen; *rbuflen = 0; if (NULL == ( ofork = of_find( ofrefnum )) ) { - LOG(log_error, logtype_afpd, "afp_getforkparams: of_find"); + LOG(log_error, logtype_afpd, "afp_getforkparams: of_find(%d) could not locate fork", ofrefnum ); return( AFPERR_PARAM ); } - attrbits = ((ofork->of_ad->ad_df.adf_refcount > 0) ? ATTRBIT_DOPEN : 0); - attrbits |= ((ofork->of_ad->ad_hf.adf_refcount > ofork->of_ad->ad_df.adf_refcount) ? ATTRBIT_ROPEN : 0); - if ( ad_hfileno( ofork->of_ad ) != -1 ) { + if ( ad_meta_fileno( ofork->of_ad ) != -1 ) { /* META */ if ( ad_refresh( ofork->of_ad ) < 0 ) { - LOG(log_error, logtype_afpd, "getforkparams: ad_refresh: %s", strerror(errno) ); + LOG(log_error, logtype_afpd, "getforkparams(%s): ad_refresh: %s", of_name(ofork), strerror(errno) ); return( AFPERR_PARAM ); } } if (AFP_OK != ( ret = getforkparams( ofork, bitmap, - rbuf + sizeof( u_short ), &buflen, attrbits ))) { + rbuf + sizeof( u_short ), &buflen ))) { return( ret ); }