/*
- * $Id: fork.c,v 1.32 2002-08-21 05:21:38 didg Exp $
+ * $Id: fork.c,v 1.51.2.2.2.10.2.6 2008-11-25 15:16:33 didg Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
#endif /* HAVE_CONFIG_H */
#include <stdio.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif /* HAVE_FCNTL_H */
+
#include <dirent.h>
#include <string.h>
#include <errno.h>
+
+#include <atalk/adouble.h>
#include <atalk/logger.h>
#include <sys/param.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/time.h>
#include <sys/socket.h>
-#include <netatalk/endian.h>
#include <netatalk/at.h>
#include <atalk/dsi.h>
#include <atalk/atp.h>
#include <atalk/asp.h>
#include <atalk/afp.h>
-#include <atalk/adouble.h>
+
#include <atalk/util.h>
-#ifdef CNID_DB
#include <atalk/cnid.h>
-#endif
#include "fork.h"
#include "file.h"
#include "desktop.h"
#include "volume.h"
-#define BYTELOCK_MAX 0x7FFFFFFFU
+#ifdef DEBUG1
+#define Debug(a) ((a)->options.flags & OPTION_DEBUG)
+#else
+#define Debug(a) (0)
+#endif
struct ofork *writtenfork;
extern int getmetadata(struct vol *vol,
u_int16_t bitmap,
- char *path, struct dir *dir, struct stat *st,
- char *buf, int *buflen, struct adouble *adp, int attrbits );
+ 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;
int *buflen;
const u_int16_t attrbits;
{
-#ifndef USE_LASTDID
- struct stat lst, *lstp;
-#endif /* !USE_LASTDID */
- struct stat st;
- char *upath;
- u_int32_t aint;
+ struct path path;
+ struct stat *st;
struct adouble *adp;
struct dir *dir;
struct vol *vol;
+
+ /* can only get the length of the opened fork */
+ if ( ( (bitmap & ((1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN)))
+ && (ofork->of_flags & AFPFORK_RSRC))
+ ||
+ ( (bitmap & ((1<<FILPBIT_RFLEN) | (1<<FILPBIT_EXTRFLEN)))
+ && (ofork->of_flags & AFPFORK_DATA))) {
+ return( AFPERR_BITMAP );
+ }
+
if ( ad_hfileno( ofork->of_ad ) == -1 ) {
adp = NULL;
} else {
- aint = ad_getentrylen( ofork->of_ad, ADEID_RFORK );
- if ( ad_refresh( ofork->of_ad ) < 0 ) {
- LOG(log_error, logtype_afpd, "getforkparams: ad_refresh: %s", strerror(errno) );
- return( AFPERR_PARAM );
- }
- /* See afp_closefork() for why this is bad */
- ad_setentrylen( ofork->of_ad, ADEID_RFORK, aint );
adp = ofork->of_ad;
}
- /* can only get the length of the opened fork */
- if (((bitmap & (1<<FILPBIT_DFLEN)) && (ofork->of_flags & AFPFORK_RSRC)) ||
- ((bitmap & (1<<FILPBIT_RFLEN)) && (ofork->of_flags & AFPFORK_DATA))) {
- return( AFPERR_BITMAP );
- }
+ vol = ofork->of_vol;
+ dir = ofork->of_dir;
- if ( bitmap & ( 1<<FILPBIT_DFLEN | 1<<FILPBIT_FNUM |
- (1 << FILPBIT_CDATE) | (1 << FILPBIT_MDATE) |
- (1 << FILPBIT_BDATE))) {
- upath = mtoupath(ofork->of_vol, ofork->of_name);
+ if (NULL == (path.u_name = mtoupath(vol, of_name(ofork), dir->d_did, utf8_encoding()))) {
+ return( AFPERR_MISC );
+ }
+ path.m_name = of_name(ofork);
+ st = &path.st;
+ if ( bitmap & ( (1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN) |
+ (1<<FILPBIT_FNUM) | (1 << FILPBIT_CDATE) |
+ (1 << FILPBIT_MDATE) | (1 << FILPBIT_BDATE))) {
if ( ad_dfileno( ofork->of_ad ) == -1 ) {
- if ( stat( upath, &st ) < 0 )
+ if (movecwd(vol, dir) < 0)
+ return( AFPERR_NOOBJ );
+ if ( stat( path.u_name, st ) < 0 )
return( AFPERR_NOOBJ );
} else {
- if ( fstat( ad_dfileno( ofork->of_ad ), &st ) < 0 ) {
+ if ( fstat( ad_dfileno( ofork->of_ad ), st ) < 0 ) {
return( AFPERR_BITMAP );
}
}
}
- dir = ofork->of_dir;
- vol = ofork->of_vol;
- return getmetadata(vol, bitmap, ofork->of_name, dir, &st, buf, buflen, adp, attrbits );
+ return getmetadata(vol, bitmap, &path, dir, buf, buflen, adp, attrbits );
}
-/* -------------------------
+/* ---------------------------- */
+static off_t get_off_t(ibuf, is64)
+char **ibuf;
+int is64;
+{
+ u_int32_t temp;
+ off_t ret;
+
+ ret = 0;
+ memcpy(&temp, *ibuf, sizeof( temp ));
+ ret = ntohl(temp); /* ntohl is unsigned */
+ *ibuf += sizeof(temp);
+
+ if (is64) {
+ memcpy(&temp, *ibuf, sizeof( temp ));
+ *ibuf += sizeof(temp);
+ ret = ntohl(temp)| (ret << 32);
+ }
+ else {
+ ret = (int)ret; /* sign extend */
+ }
+ return ret;
+}
+
+/* ---------------------- */
+static int set_off_t(offset, rbuf, is64)
+off_t offset;
+char *rbuf;
+int is64;
+{
+ u_int32_t temp;
+ int ret;
+
+ ret = 0;
+ if (is64) {
+ temp = htonl(offset >> 32);
+ memcpy(rbuf, &temp, sizeof( temp ));
+ rbuf += sizeof(temp);
+ ret = sizeof( temp );
+ offset &= 0xffffffff;
+ }
+ temp = htonl(offset);
+ memcpy(rbuf, &temp, sizeof( temp ));
+ ret += sizeof( temp );
+
+ return ret;
+}
+
+/* ------------------------
*/
-#define SHARE 0
-#define EXCL 1
-static int setforkmode(struct adouble *adp, int eid, int ofrefnum, int what, int mode)
+static int is_neg(int is64, off_t val)
{
- int lockmode;
- int lockop;
-
- /* NOTE: we can't write lock a read-only file. on those, we just
- * make sure that we have a read lock set. that way, we at least prevent
- * someone else from really setting a deny read/write on the file.
- */
- lockmode = (ad_getoflags(adp, eid) & O_RDWR) ?ADLOCK_WR : ADLOCK_RD;
- lockop = (mode == EXCL)?lockmode:ADLOCK_RD;
-
- return ad_lock(adp, eid, lockop | ADLOCK_FILELOCK | ADLOCK_UPGRADE,
- what, 1, ofrefnum);
+ if (val < 0 || (sizeof(off_t) == 8 && !is64 && (val & 0x80000000U)))
+ return 1;
+ return 0;
+}
+
+static int sum_neg(int is64, off_t offset, off_t reqcount)
+{
+ if (is_neg(is64, offset +reqcount) )
+ return 1;
+ return 0;
}
/* -------------------------
*/
-extern int ad_testlock(struct adouble *adp, int eid, int off);
+static int setforkmode(struct adouble *adp, int eid, int ofrefnum, int 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, int what)
{
return ad_testlock(adp, eid, what);
}
-/* --------------------------
- a lot of races, some can be remove. but I try first to get the semantic right
+/* -------------------------
*/
-#ifdef USE_FLOCK_LOCKS
-#error sorry, for now configure --with-flock-locks is broken...
-#endif
-
-static int afp_setmode(struct adouble *adp, int eid, int access, int ofrefnum)
+static int fork_setmode(struct adouble *adp, int eid, int access, int ofrefnum)
{
int ret;
int readset;
int writeset;
int denyreadset;
int denywriteset;
- int mode;
if (! (access & (OPENACC_WR | OPENACC_RD | OPENACC_DWR | OPENACC_DRD))) {
- return setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_NONE, SHARE);
+ return setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_NONE);
}
if ((access & (OPENACC_RD | OPENACC_DRD))) {
/* boolean logic is not enough, because getforkmode is not always telling the
* true
*/
- mode = ((access & OPENACC_DRD))?EXCL: SHARE;
if ((access & OPENACC_RD)) {
- ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_RD, mode);
+ ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_RD);
if (ret)
return ret;
}
if ((access & OPENACC_DRD)) {
- ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_DENY_RD, SHARE);
+ ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_DENY_RD);
if (ret)
return ret;
}
errno = EACCES;
return -1;
}
- mode = ((access & OPENACC_DWR))?EXCL: SHARE;
if ((access & OPENACC_WR)) {
- ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_WR, mode);
+ ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_WR);
if (ret)
return ret;
}
if ((access & OPENACC_DWR)) {
- ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_DENY_WR, SHARE);
+ ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_DENY_WR);
if (ret)
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;
+AFPObj *obj _U_;
char *ibuf, *rbuf;
-int ibuflen, *rbuflen;
+int ibuflen _U_, *rbuflen;
{
struct vol *vol;
struct dir *dir;
struct ofork *ofork, *opened;
struct adouble *adsame = NULL;
- int buflen, ret, adflags, eid, lockop;
+ int buflen, ret, adflags, eid;
u_int32_t did;
u_int16_t vid, bitmap, access, ofrefnum, attrbits = 0;
char fork, *path, *upath;
- u_int16_t bshort;
-
+ struct stat *st;
+ u_int16_t bshort;
+ struct path *s_path;
+
ibuf++;
fork = *ibuf++;
memcpy(&vid, ibuf, sizeof( vid ));
ibuf += sizeof(vid);
*rbuflen = 0;
- if (( vol = getvolbyvid( vid )) == NULL ) {
+ if (NULL == ( vol = getvolbyvid( vid ))) {
return( AFPERR_PARAM );
}
memcpy(&did, ibuf, sizeof( did ));
ibuf += sizeof( int );
- if (( dir = dirsearch( vol, did )) == NULL ) {
- return( AFPERR_NOOBJ );
+ if (NULL == ( dir = dirlookup( vol, did ))) {
+ return afp_errno;
}
memcpy(&bitmap, ibuf, sizeof( bitmap ));
return AFPERR_VLOCK;
}
- if (( path = cname( vol, dir, &ibuf )) == NULL ) {
- return( AFPERR_NOOBJ );
+ if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
+ return get_afp_errno(AFPERR_PARAM);
}
- if ( fork == OPENFORK_DATA ) {
- eid = ADEID_DFORK;
- adflags = ADFLAGS_DF|ADFLAGS_HF;
- } else {
- eid = ADEID_RFORK;
- adflags = ADFLAGS_HF;
+ if (*s_path->m_name == '\0') {
+ /* it's a dir ! */
+ return AFPERR_BADTYPE;
+ }
+
+ /* stat() data fork st is set because it's not a dir */
+ switch ( s_path->st_errno ) {
+ case 0:
+ break;
+ case ENOENT:
+ return AFPERR_NOOBJ;
+ case EACCES:
+ return (access & OPENACC_WR) ? AFPERR_LOCK : AFPERR_ACCESS;
+ default:
+ 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 (!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;
/* XXX: this probably isn't the best way to do this. the already
open bits should really be set if the fork is opened by any
program, not just this one. however, that's problematic to do
ad_open so that we can keep file locks together.
FIXME: add the fork we are opening?
*/
- if ((opened = of_findname(vol, curdir, path))) {
+ 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;
}
+ if ( fork == OPENFORK_DATA ) {
+ eid = ADEID_DFORK;
+ adflags = ADFLAGS_DF|ADFLAGS_HF;
+ } else {
+ eid = ADEID_RFORK;
+ adflags = ADFLAGS_HF;
+ }
+
+ path = s_path->m_name;
if (( ofork = of_alloc(vol, curdir, path, &ofrefnum, eid,
- adsame)) == NULL ) {
+ adsame, st)) == NULL ) {
return( AFPERR_NFILE );
}
+
+ ret = AFPERR_NOOBJ;
if (access & OPENACC_WR) {
/* try opening in read-write mode */
- upath = mtoupath(vol, path);
- ret = AFPERR_NOOBJ;
if (ad_open(upath, adflags, O_RDWR, 0, ofork->of_ad) < 0) {
switch ( errno ) {
case EROFS:
ret = AFPERR_VLOCK;
case EACCES:
goto openfork_err;
-
break;
case ENOENT:
- {
- struct stat st;
-
- /* see if client asked for the data fork */
- if (fork == OPENFORK_DATA) {
- if (ad_open(upath, ADFLAGS_DF, O_RDWR, 0, ofork->of_ad) < 0) {
- goto openfork_err;
- }
- adflags = ADFLAGS_DF;
-
- } else if (stat(upath, &st) == 0) {
- /* here's the deal. we only try to create the resource
- * fork if the user wants to open it for write acess. */
- if (ad_open(upath, adflags, O_RDWR | O_CREAT, 0666, ofork->of_ad) < 0)
- goto openfork_err;
- } else
+ if (fork == OPENFORK_DATA) {
+ /* try to open only the data fork */
+ if (ad_open(upath, ADFLAGS_DF, O_RDWR, 0, ofork->of_ad) < 0) {
goto openfork_err;
+ }
+ adflags = ADFLAGS_DF;
+ }
+ else {
+ /* here's the deal. we only try to create the resource
+ * fork if the user wants to open it for write acess. */
+ if (ad_open(upath, adflags, O_RDWR | O_CREAT, 0666, ofork->of_ad) < 0)
+ goto openfork_err;
+ ofork->of_flags |= AFPFORK_OPEN;
}
break;
case EMFILE :
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;
}
}
+ else {
+ /* the ressource fork is open too */
+ ofork->of_flags |= AFPFORK_OPEN;
+ }
} else {
/* try opening in read-only mode */
- upath = mtoupath(vol, path);
ret = AFPERR_NOOBJ;
if (ad_open(upath, adflags, O_RDONLY, 0, ofork->of_ad) < 0) {
switch ( errno ) {
case EROFS:
ret = AFPERR_VLOCK;
case EACCES:
- /* check for a read-only data fork */
- if ((adflags != ADFLAGS_HF) &&
- (ad_open(upath, ADFLAGS_DF, O_RDONLY, 0, ofork->of_ad) < 0))
- goto openfork_err;
-
- adflags = ADFLAGS_DF;
+ goto openfork_err;
break;
case ENOENT:
- {
- struct stat st;
-
- /* see if client asked for the data fork */
- if (fork == OPENFORK_DATA) {
- if (ad_open(upath, ADFLAGS_DF, O_RDONLY, 0, ofork->of_ad) < 0) {
- goto openfork_err;
- }
- adflags = ADFLAGS_DF;
-
- } else if (stat(upath, &st) != 0) {
+ /* see if client asked for a read only data fork */
+ if (fork == OPENFORK_DATA) {
+ if (ad_open(upath, ADFLAGS_DF, O_RDONLY, 0, ofork->of_ad) < 0) {
goto openfork_err;
}
+ adflags = ADFLAGS_DF;
}
+ /* else we don't set AFPFORK_OPEN because there's no ressource fork file
+ * We need to check AFPFORK_OPEN in afp_closefork(). eg fork open read-only
+ * then create in open read-write.
+ * FIXME , it doesn't play well with byte locking example:
+ * ressource fork open read only
+ * locking set on it (no effect, there's no file!)
+ * ressource fork open read write now
+ */
break;
case EMFILE :
case ENFILE :
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) );
goto openfork_err;
break;
}
}
+ else {
+ /* the ressource fork is open too */
+ ofork->of_flags |= AFPFORK_OPEN;
+ }
}
- if ((adflags & ADFLAGS_HF) &&
- (ad_getoflags( ofork->of_ad, ADFLAGS_HF ) & 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 ((adflags & ADFLAGS_HF) && (ad_get_HF_flags( ofork->of_ad) & O_CREAT)) {
+ if (ad_setname(ofork->of_ad, path)) {
+ ad_flush( ofork->of_ad, adflags );
+ }
}
if (( ret = getforkparams(ofork, bitmap, rbuf + 2 * sizeof( u_int16_t ),
memcpy(rbuf, &bitmap, sizeof( u_int16_t ));
rbuf += sizeof( u_int16_t );
- /* check WriteInhibit bit, the test is done here, after some Mac trafic capture */
- ad_getattr(ofork->of_ad, &bshort);
- if ((bshort & htons(ATTRBIT_NOWRITE)) && (access & OPENACC_WR)) {
- ad_close( ofork->of_ad, adflags );
- of_dealloc( ofork );
- ofrefnum = 0;
- memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
- return(AFPERR_OLOCK);
+ /* 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) {
+ ad_getattr(ofork->of_ad, &bshort);
+ if ((bshort & htons(ATTRBIT_NOWRITE)) && (access & OPENACC_WR)) {
+ ad_close( ofork->of_ad, adflags );
+ of_dealloc( ofork );
+ ofrefnum = 0;
+ memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
+ return(AFPERR_OLOCK);
+ }
}
/*
/* don't try to lock non-existent rforks. */
if ((eid == ADEID_DFORK) || (ad_hfileno(ofork->of_ad) != -1)) {
- ret = afp_setmode(ofork->of_ad, eid, access, ofrefnum);
+ ret = fork_setmode(ofork->of_ad, eid, access, ofrefnum);
/* can we access the fork? */
if (ret < 0) {
ret = errno;
break;
default:
*rbuflen = 0;
- LOG(log_error, logtype_afpd, "afp_openfork: ad_lock: %s", strerror(errno) );
+ LOG(log_error, logtype_afpd, "afp_openfork(%s): ad_lock: %s", s_path->m_name, strerror(ret) );
return( AFPERR_PARAM );
}
}
if ((access & OPENACC_WR))
ofork->of_flags |= AFPFORK_ACCWR;
- if ((access & OPENACC_RD))
- ofork->of_flags |= AFPFORK_ACCRD;
}
+ /* the file may be open read only without ressource fork */
+ if ((access & OPENACC_RD))
+ ofork->of_flags |= AFPFORK_ACCRD;
memcpy(rbuf, &ofrefnum, sizeof(ofrefnum));
return( AFP_OK );
}
int afp_setforkparams(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj *obj;
-char *ibuf, *rbuf;
-int ibuflen, *rbuflen;
+AFPObj *obj _U_;
+char *ibuf, *rbuf _U_;
+int ibuflen, *rbuflen;
{
struct ofork *ofork;
- int32_t size;
+ off_t size;
u_int16_t ofrefnum, bitmap;
int err;
-
+ int is64;
+ int eid;
+ off_t st_size;
+
ibuf += 2;
+
memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
ibuf += sizeof( ofrefnum );
+
memcpy(&bitmap, ibuf, sizeof(bitmap));
bitmap = ntohs(bitmap);
ibuf += sizeof( bitmap );
- memcpy(&size, ibuf, sizeof( size ));
- size = ntohl( size );
*rbuflen = 0;
- if (( ofork = of_find( ofrefnum )) == NULL ) {
- LOG(log_error, logtype_afpd, "afp_setforkparams: of_find could not locate open fork refnum: %u", ofrefnum );
+ if (NULL == ( ofork = of_find( ofrefnum )) ) {
+ LOG(log_error, logtype_afpd, "afp_setforkparams: of_find(%d) could not locate fork", ofrefnum );
return( AFPERR_PARAM );
}
if ((ofork->of_flags & AFPFORK_ACCWR) == 0)
return AFPERR_ACCESS;
- if (size < 0)
+ if ( ofork->of_flags & AFPFORK_DATA) {
+ eid = ADEID_DFORK;
+ } else if (ofork->of_flags & AFPFORK_RSRC) {
+ eid = ADEID_RFORK;
+ } else
return AFPERR_PARAM;
- if ((bitmap == (1<<FILPBIT_DFLEN)) && (ofork->of_flags & AFPFORK_DATA)) {
+ if ( ( (bitmap & ( (1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN) ))
+ && eid == ADEID_RFORK
+ ) ||
+ ( (bitmap & ( (1<<FILPBIT_RFLEN) | (1<<FILPBIT_EXTRFLEN) ))
+ && eid == ADEID_DFORK)) {
+ return AFPERR_BITMAP;
+ }
+
+ is64 = 0;
+ if ((bitmap & ( (1<<FILPBIT_EXTDFLEN) | (1<<FILPBIT_EXTRFLEN) ))) {
+ if (afp_version >= 30) {
+ is64 = 4;
+ }
+ else
+ return AFPERR_BITMAP;
+ }
+
+ if (ibuflen < 2+ sizeof(ofrefnum) + sizeof(bitmap) + is64 +4)
+ return AFPERR_PARAM ;
+
+ size = get_off_t(&ibuf, is64);
+
+ if (size < 0)
+ return AFPERR_PARAM; /* Some MacOS don't return an error they just don't change the size! */
+
+
+ if (bitmap == (1<<FILPBIT_DFLEN) || bitmap == (1<<FILPBIT_EXTDFLEN)) {
+ st_size = ad_size(ofork->of_ad, eid);
+ err = -2;
+ if (st_size > size &&
+ ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, size, st_size -size, ofork->of_refnum) < 0)
+ goto afp_setfork_err;
+
err = ad_dtruncate( ofork->of_ad, size );
+ if (st_size > size)
+ ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, size, st_size -size, ofork->of_refnum);
if (err < 0)
goto afp_setfork_err;
- } else if ((bitmap == (1<<FILPBIT_RFLEN)) &&
- (ofork->of_flags & AFPFORK_RSRC)) {
+ } else if (bitmap == (1<<FILPBIT_RFLEN) || bitmap == (1<<FILPBIT_EXTRFLEN)) {
ad_refresh( ofork->of_ad );
+
+ st_size = ad_size(ofork->of_ad, eid);
+ err = -2;
+ if (st_size > size &&
+ ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, size, st_size -size, ofork->of_refnum) < 0) {
+ goto afp_setfork_err;
+ }
err = ad_rtruncate(ofork->of_ad, size);
+ if (st_size > size)
+ ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, size, st_size -size, ofork->of_refnum);
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) );
- return( AFPERR_PARAM );
+ LOG(log_error, logtype_afpd, "afp_setforkparams(%s): ad_flush: %s", of_name(ofork), strerror(errno) );
+ return AFPERR_PARAM;
}
} else
return AFPERR_BITMAP;
#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 */
*/
#define ENDBIT(a) ((a) & 0x80)
#define UNLOCKBIT(a) ((a) & 0x01)
-int afp_bytelock(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj *obj;
+
+
+/* ---------------------- */
+static int byte_lock(obj, ibuf, ibuflen, rbuf, rbuflen, is64 )
+AFPObj *obj _U_;
char *ibuf, *rbuf;
-int ibuflen, *rbuflen;
+int ibuflen _U_, *rbuflen;
+int is64;
{
struct ofork *ofork;
- int32_t offset, length;
+ off_t offset, length;
int eid;
u_int16_t ofrefnum;
u_int8_t flags;
-
+ int lockop;
+
*rbuflen = 0;
/* figure out parameters */
memcpy(&ofrefnum, ibuf, sizeof(ofrefnum));
ibuf += sizeof(ofrefnum);
- if (( ofork = of_find( ofrefnum )) == NULL ) {
- LOG(log_error, logtype_afpd, "afp_bytelock: of_find");
+ if (NULL == ( ofork = of_find( ofrefnum )) ) {
+ LOG(log_error, logtype_afpd, "afp_bytelock: of_find(%d) could not locate fork", ofrefnum );
return( AFPERR_PARAM );
}
} else
return AFPERR_PARAM;
- memcpy(&offset, ibuf, sizeof( offset ));
- offset = ntohl(offset);
- ibuf += sizeof(offset);
+ offset = get_off_t(&ibuf, is64);
+ length = get_off_t(&ibuf, is64);
- memcpy(&length, ibuf, sizeof( length ));
- length = ntohl(length);
- if (length == 0xFFFFFFFF)
+ /* FIXME AD_FILELOCK test is surely wrong */
+ if (length == -1)
length = BYTELOCK_MAX;
- else if (length <= 0) {
- return AFPERR_PARAM;
- } else if ((length >= AD_FILELOCK_BASE) &&
- (ad_hfileno(ofork->of_ad) == -1))
+ else if (!length || is_neg(is64, length)) {
+ return AFPERR_PARAM;
+ } else if ((length >= AD_FILELOCK_BASE) && -1 == (ad_hfileno(ofork->of_ad))) {
return AFPERR_LOCK;
+ }
- if (ENDBIT(flags))
+ if (ENDBIT(flags)) {
offset += ad_size(ofork->of_ad, eid);
-
+ /* FIXME what do we do if file size > 2 GB and
+ it's not byte_lock_ext?
+ */
+ }
if (offset < 0) /* error if we have a negative offset */
return AFPERR_PARAM;
/* if the file is a read-only file, we use read locks instead of
* write locks. that way, we can prevent anyone from initiating
* a write lock. */
- if (ad_lock(ofork->of_ad, eid, UNLOCKBIT(flags) ? ADLOCK_CLR :
- ((ad_getoflags(ofork->of_ad, eid) & O_RDWR) ?
- ADLOCK_WR : ADLOCK_RD), offset, length,
+ lockop = UNLOCKBIT(flags) ? ADLOCK_CLR : ADLOCK_WR;
+ if (ad_lock(ofork->of_ad, eid, lockop, offset, length,
ofork->of_refnum) < 0) {
switch (errno) {
case EACCES:
break;
}
}
-
- offset = htonl(offset);
- memcpy(rbuf, &offset, sizeof( offset ));
- *rbuflen = sizeof( offset );
+ *rbuflen = set_off_t (offset, rbuf, is64);
return( AFP_OK );
}
-#undef UNLOCKBIT
+/* --------------------------- */
+int afp_bytelock(obj, ibuf, ibuflen, rbuf, rbuflen )
+AFPObj *obj;
+char *ibuf, *rbuf;
+int ibuflen, *rbuflen;
+{
+ return byte_lock ( obj, ibuf, ibuflen, rbuf, rbuflen , 0);
+}
-static __inline__ int crlf( of )
+/* --------------------------- */
+int afp_bytelock_ext(obj, ibuf, ibuflen, rbuf, rbuflen )
+AFPObj *obj;
+char *ibuf, *rbuf;
+int ibuflen, *rbuflen;
+{
+ return byte_lock ( obj, ibuf, ibuflen, rbuf, rbuflen , 1);
+}
+
+#undef UNLOCKBIT
+
+/* --------------------------- */
+static int crlf( of )
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 (( em = getextmap( of->of_name )) == NULL ||
- 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_hfileno( of->of_ad ) == -1 || !memcmp( ufinderi, ad_entry( of->of_ad, ADEID_FINDERI),8)) {
+ /* 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,
- int offset, u_char nlmask,
+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)
{
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 );
}
*
* with dsi, should we check that reqcount < server quantum?
*/
-int afp_read(obj, ibuf, ibuflen, rbuf, rbuflen)
-AFPObj *obj;
+static int read_fork(obj, ibuf, ibuflen, rbuf, rbuflen, is64)
+AFPObj *obj;
char *ibuf, *rbuf;
-int ibuflen, *rbuflen;
+int ibuflen _U_, *rbuflen;
+int is64;
{
struct ofork *ofork;
- off_t size;
- int32_t offset, saveoff, reqcount, savereqcount;
+ off_t offset, saveoff, reqcount, savereqcount;
int cc, err, eid, xlate = 0;
u_int16_t ofrefnum;
u_char nlmask, nlchar;
-
+
ibuf += 2;
memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
ibuf += sizeof( u_short );
- if (( ofork = of_find( ofrefnum )) == NULL ) {
- LOG(log_error, logtype_afpd, "afp_read: of_find");
+ if (NULL == ( ofork = of_find( ofrefnum )) ) {
+ LOG(log_error, logtype_afpd, "afp_read: of_find(%d) could not locate fork", ofrefnum );
err = AFPERR_PARAM;
goto afp_read_err;
}
err = AFPERR_ACCESS;
goto afp_read_err;
}
+ offset = get_off_t(&ibuf, is64);
+ reqcount = get_off_t(&ibuf, is64);
- memcpy(&offset, ibuf, sizeof( offset ));
- offset = ntohl( offset );
- ibuf += sizeof( offset );
- memcpy(&reqcount, ibuf, sizeof( reqcount ));
- reqcount = ntohl( reqcount );
- ibuf += sizeof( reqcount );
-
- nlmask = *ibuf++;
- nlchar = *ibuf++;
-
+ if (is64) {
+ nlmask = nlchar = 0;
+ }
+ else {
+ nlmask = *ibuf++;
+ nlchar = *ibuf++;
+ }
/* if we wanted to be picky, we could add in the following
* bit: if (afp_version == 11 && !(nlmask == 0xFF || !nlmask))
*/
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;
- }
-
savereqcount = reqcount;
saveoff = offset;
- if (ad_tmplock(ofork->of_ad, eid, ADLOCK_RD, saveoff, savereqcount) < 0) {
+ if (ad_tmplock(ofork->of_ad, eid, ADLOCK_RD, saveoff, savereqcount,ofork->of_refnum) < 0) {
err = AFPERR_LOCK;
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);
+ err = read_file(ofork, eid, offset, nlmask, nlchar, rbuf, rbuflen, xlate);
if (err < 0)
goto afp_read_done;
/* 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;
+ int non_blocking = 0;
+#ifdef DEBUG1
if (obj->options.flags & OPTION_DEBUG) {
- printf( "(read) reply: %d/%d, %d\n", *rbuflen,
- reqcount, dsi->clientID);
+ printf( "(read) reply: %d/%d, %d\n", *rbuflen,(int) reqcount, dsi->clientID);
bprint(rbuf, *rbuflen);
}
+#endif
+ /* reqcount isn't always truthful. we need to deal with that. */
+ size = ad_size(ofork->of_ad, eid);
+
/* subtract off the offset */
size -= offset;
if (reqcount > size) {
/* 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)
+#if 0 /* ifdef WITH_SENDFILE */
+ /* FIXME with OS X deadlock partial workaround we can't use sendfile */
+ if (!(xlate || Debug(obj) )) {
+ if (ad_readfile(ofork->of_ad, eid, dsi->socket, 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;
}
}
}
afp_read_loop:
-#endif /* HAVE_SENDFILE_READ */
+#endif
+ /* fill up our buffer. */
+ if (*rbuflen) {
+ /* set to non blocking mode */
+ non_blocking = 1;
+ dsi_block(dsi, 1);
+ }
/* 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;
+#ifdef DEBUG1
if (obj->options.flags & OPTION_DEBUG) {
printf( "(read) reply: %d, %d\n", *rbuflen, dsi->clientID);
bprint(rbuf, *rbuflen);
}
-
+#endif
/* dsi_read() also returns buffer size of next allocation */
cc = dsi_read(dsi, rbuf, *rbuflen); /* send it off */
if (cc < 0)
goto afp_read_exit;
*rbuflen = cc;
}
+ if (non_blocking) {
+ /* set back to blocking mode */
+ dsi_block(dsi, 0);
+ }
dsi_readdone(dsi);
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);
- obj->exit(1);
+ ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount,ofork->of_refnum);
+ obj->exit(EXITERR_CLNT);
}
afp_read_done:
- ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount);
+ ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount,ofork->of_refnum);
return err;
afp_read_err:
return err;
}
-int afp_flush(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj *obj;
+/* ---------------------- */
+int afp_read(obj, ibuf, ibuflen, rbuf, rbuflen)
+AFPObj *obj;
+char *ibuf, *rbuf;
+int ibuflen, *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 ibuflen, *rbuflen;
+{
+ return read_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 1);
+}
+
+/* ---------------------- */
+int afp_flush(obj, ibuf, ibuflen, rbuf, rbuflen )
+AFPObj *obj _U_;
+char *ibuf, *rbuf _U_;
+int ibuflen _U_, *rbuflen;
{
struct vol *vol;
u_int16_t vid;
ibuf += 2;
memcpy(&vid, ibuf, sizeof(vid));
- if (( vol = getvolbyvid( vid )) == NULL ) {
+ if (NULL == ( vol = getvolbyvid( vid )) ) {
return( AFPERR_PARAM );
}
}
int afp_flushfork(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj *obj;
-char *ibuf, *rbuf;
-int ibuflen, *rbuflen;
+AFPObj *obj _U_;
+char *ibuf, *rbuf _U_;
+int ibuflen _U_, *rbuflen;
{
struct ofork *ofork;
u_int16_t ofrefnum;
ibuf += 2;
memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
- if (( ofork = of_find( ofrefnum )) == NULL ) {
- LOG(log_error, logtype_afpd, "afp_flushfork: of_find");
+ if (NULL == ( ofork = of_find( ofrefnum )) ) {
+ 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", strerror(errno) );
+ LOG(log_error, logtype_afpd, "afp_flushfork(%s): %s", of_name(ofork), strerror(errno) );
}
return( AFP_OK );
struct ofork *ofork;
{
struct timeval tv;
- int len, err = 0, doflush = 0;
+
+ 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) );
+ LOG(log_error, logtype_afpd, "flushfork(%s): dfile(%d) %s",
+ of_name(ofork), ad_dfileno(ofork->of_ad), strerror(errno) );
err = -1;
}
- if ( ad_hfileno( ofork->of_ad ) != -1 ) {
+ if ( ad_hfileno( ofork->of_ad ) != -1 &&
+ (ofork->of_flags & AFPFORK_RSRC)) {
/* read in the rfork length */
- len = ad_getentrylen(ofork->of_ad, ADEID_RFORK);
ad_refresh(ofork->of_ad);
/* set the date if we're dirty */
- if ((ofork->of_flags & AFPFORK_DIRTY) &&
- (gettimeofday(&tv, NULL) == 0)) {
+ if ((ofork->of_flags & AFPFORK_DIRTY) && !gettimeofday(&tv, NULL)) {
ad_setdate(ofork->of_ad, AD_DATE_MODIFY|AD_DATE_UNIX, tv.tv_sec);
ofork->of_flags &= ~AFPFORK_DIRTY;
doflush++;
}
- /* if we're actually flushing this fork, make sure to set the
- * length. otherwise, just use the stored length */
- if ((ofork->of_flags & AFPFORK_RSRC) &&
- (len != ad_getentrylen(ofork->of_ad, ADEID_RFORK))) {
- ad_setentrylen(ofork->of_ad, ADEID_RFORK, len);
- doflush++;
- }
-
-
- /* flush the header (if it is a resource fork) */
- if (ofork->of_flags & AFPFORK_RSRC)
- if (doflush && (ad_flush(ofork->of_ad, ADFLAGS_HF) < 0))
+ /* flush the header */
+ if (doflush && ad_flush(ofork->of_ad, ADFLAGS_HF) < 0)
err = -1;
if (fsync( ad_hfileno( 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_hfileno(ofork->of_ad), strerror(errno) );
}
return( err );
}
int afp_closefork(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj *obj;
-char *ibuf, *rbuf;
-int ibuflen, *rbuflen;
+AFPObj *obj _U_;
+char *ibuf, *rbuf _U_;
+int ibuflen _U_, *rbuflen;
{
struct ofork *ofork;
struct timeval tv;
- int adflags, aint, doflush = 0;
+ int adflags, doflush = 0;
u_int16_t ofrefnum;
+ int ret;
+
*rbuflen = 0;
ibuf += 2;
memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
- if (( ofork = of_find( ofrefnum )) == NULL ) {
- LOG(log_error, logtype_afpd, "afp_closefork: of_find");
+ if (NULL == ( ofork = of_find( ofrefnum )) ) {
+ 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_DATA) && (ad_dfileno( ofork->of_ad ) != -1)) {
+ adflags |= ADFLAGS_DF;
}
-
- if ( ad_hfileno( ofork->of_ad ) != -1 ) {
+ if ( (ofork->of_flags & AFPFORK_OPEN) && ad_hfileno( ofork->of_ad ) != -1 ) {
adflags |= ADFLAGS_HF;
-
- aint = ad_getentrylen( ofork->of_ad, ADEID_RFORK );
- ad_refresh( ofork->of_ad );
- if ((ofork->of_flags & AFPFORK_DIRTY) &&
- (gettimeofday(&tv, NULL) == 0)) {
- ad_setdate(ofork->of_ad, AD_DATE_MODIFY | AD_DATE_UNIX,
- tv.tv_sec);
- doflush++;
- }
-
/*
* Only set the rfork's length if we're closing the rfork.
*/
- if ((ofork->of_flags & AFPFORK_RSRC) && aint !=
- ad_getentrylen( ofork->of_ad, ADEID_RFORK )) {
- ad_setentrylen( ofork->of_ad, ADEID_RFORK, aint );
- doflush++;
- }
- if ( doflush ) {
- ad_flush( ofork->of_ad, adflags );
+ 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 );
+ }
}
}
-
+ ret = AFP_OK;
if ( ad_close( ofork->of_ad, adflags ) < 0 ) {
- LOG(log_error, logtype_afpd, "afp_closefork: ad_close: %s", strerror(errno) );
- return( AFPERR_PARAM );
+ LOG(log_error, logtype_afpd, "afp_closefork(%s): ad_close: %s", of_name(ofork), strerror(errno) );
+ ret = AFPERR_PARAM;
}
of_dealloc( ofork );
- return( AFP_OK );
+ return ret;
}
-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)
{
case ENOSPC :
return( AFPERR_DFULL );
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 );
}
}
return cc;
}
+
/* 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. */
-int afp_write(obj, ibuf, ibuflen, rbuf, rbuflen)
+static int write_fork(obj, ibuf, ibuflen, rbuf, rbuflen, is64)
AFPObj *obj;
char *ibuf, *rbuf;
-int ibuflen, *rbuflen;
+int ibuflen _U_, *rbuflen;
+int is64;
{
struct ofork *ofork;
- int32_t offset, saveoff, reqcount;
+ off_t offset, saveoff, reqcount;
int endflag, eid, xlate = 0, err = AFP_OK;
u_int16_t ofrefnum;
ssize_t cc;
ibuf++;
memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
ibuf += sizeof( ofrefnum );
- memcpy(&offset, ibuf, sizeof( offset ));
- offset = ntohl( offset );
- ibuf += sizeof( offset );
- memcpy(&reqcount, ibuf, sizeof( reqcount ));
- reqcount = ntohl( reqcount );
- ibuf += sizeof( reqcount );
-
- if (( ofork = of_find( ofrefnum )) == NULL ) {
- LOG(log_error, logtype_afpd, "afp_write: of_find");
+
+ offset = get_off_t(&ibuf, is64);
+ reqcount = get_off_t(&ibuf, is64);
+
+ if (NULL == ( ofork = of_find( ofrefnum )) ) {
+ LOG(log_error, logtype_afpd, "afp_write: of_find(%d) could not locate fork", ofrefnum );
err = AFPERR_PARAM;
goto afp_write_err;
}
/* offset can overflow on 64-bit capable filesystems.
* report disk full if that's going to happen. */
- if (offset + reqcount < 0) {
+ if (sum_neg(is64, offset, reqcount)) {
err = AFPERR_DFULL;
goto afp_write_err;
}
if (!reqcount) { /* handle request counts of 0 */
err = AFP_OK;
- offset = htonl(offset);
- memcpy(rbuf, &offset, sizeof(offset));
+ *rbuflen = set_off_t (offset, rbuf, is64);
goto afp_write_err;
}
saveoff = offset;
if (ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, saveoff,
- reqcount) < 0) {
+ reqcount, ofork->of_refnum) < 0) {
err = AFPERR_LOCK;
goto afp_write_err;
}
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;
- ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
+ ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum);
return cc;
}
offset += cc;
/* 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);
+ ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum);
return cc;
}
offset += cc;
dsi_writeflush(dsi);
*rbuflen = 0;
ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
- reqcount);
+ reqcount, ofork->of_refnum);
return cc;
}
/* loop until everything gets written. currently
* dsi_write handles the end case by itself. */
while ((cc = dsi_write(dsi, rbuf, *rbuflen))) {
+#ifdef DEBUG1
if ( obj->options.flags & OPTION_DEBUG ) {
printf("(write) command cont'd: %d\n", cc);
bprint(rbuf, cc);
}
-
+#endif
if ((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);
+ reqcount, ofork->of_refnum);
return cc;
}
offset += cc;
break;
}
- ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount);
+ ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum);
if ( ad_hfileno( ofork->of_ad ) != -1 )
ofork->of_flags |= AFPFORK_DIRTY;
- offset = htonl( offset );
-#if defined(__GNUC__) && defined(HAVE_GCC_MEMCPY_BUG)
- bcopy(&offset, rbuf, sizeof(offset));
-#else /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */
- memcpy(rbuf, &offset, sizeof(offset));
-#endif /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */
- *rbuflen = sizeof(offset);
+ *rbuflen = set_off_t (offset, rbuf, is64);
return( AFP_OK );
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;
+{
+ return write_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 0);
+}
+
+/* ----------------------------
+ * FIXME need to deal with SIGXFSZ signal
+*/
+int afp_write_ext(obj, ibuf, ibuflen, rbuf, rbuflen)
+AFPObj *obj;
+char *ibuf, *rbuf;
+int ibuflen, *rbuflen;
+{
+ return write_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 1);
+}
+/* ---------------------------- */
int afp_getforkparams(obj, ibuf, ibuflen, rbuf, rbuflen )
-AFPObj *obj;
+AFPObj *obj _U_;
char *ibuf, *rbuf;
-int ibuflen, *rbuflen;
+int ibuflen _U_, *rbuflen;
{
struct ofork *ofork;
int buflen, ret;
ibuf += sizeof( bitmap );
*rbuflen = 0;
- if (( ofork = of_find( ofrefnum )) == NULL ) {
- LOG(log_error, logtype_afpd, "afp_getforkparams: of_find");
+ if (NULL == ( ofork = of_find( ofrefnum )) ) {
+ 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 (( ret = getforkparams( ofork, bitmap,
- rbuf + sizeof( u_short ), &buflen, attrbits )) != AFP_OK ) {
+ if ( ad_hfileno( ofork->of_ad ) != -1 ) {
+ if ( ad_refresh( ofork->of_ad ) < 0 ) {
+ 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 ))) {
return( ret );
}