#include <sys/socket.h>
#include <inttypes.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/logger.h>
#include <atalk/util.h>
#include <atalk/cnid.h>
#include <atalk/bstradd.h>
+#include <atalk/globals.h>
#include "fork.h"
#include "file.h"
-#include "globals.h"
#include "directory.h"
#include "desktop.h"
#include "volume.h"
-#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)
+static int getforkparams(struct ofork *ofork, uint16_t bitmap, char *buf, size_t *buflen)
{
struct path path;
struct stat *st;
return getmetadata(vol, bitmap, &path, dir, buf, buflen, adp );
}
-/* ---------------------------- */
static off_t get_off_t(char **ibuf, int is64)
{
- u_int32_t temp;
+ uint32_t temp;
off_t ret;
ret = 0;
return ret;
}
-/* ---------------------- */
static int set_off_t(off_t offset, char *rbuf, int is64)
{
- u_int32_t temp;
+ uint32_t temp;
int ret;
ret = 0;
return ret;
}
-/* ------------------------
- */
static int is_neg(int is64, off_t val)
{
if (val < 0 || (sizeof(off_t) == 8 && !is64 && (val & 0x80000000U)))
return 0;
}
-/* -------------------------
- */
-static int setforkmode(struct adouble *adp, int eid, int ofrefnum, int what)
-{
- return ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, what, 1, ofrefnum);
-}
-
-/* -------------------------
- */
-int getforkmode(struct adouble *adp, int eid, int what)
-{
- return ad_testlock(adp, eid, what);
-}
-
-/* -------------------------
- */
static int fork_setmode(struct adouble *adp, int eid, int access, int ofrefnum)
{
int ret;
int denywriteset;
if (! (access & (OPENACC_WR | OPENACC_RD | OPENACC_DWR | OPENACC_DRD))) {
- return setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_NONE);
+ return ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_OPEN_NONE, 1, ofrefnum);
}
if ((access & (OPENACC_RD | OPENACC_DRD))) {
- if ((readset = getforkmode(adp, eid, AD_FILELOCK_OPEN_RD)) <0)
+ if ((readset = ad_testlock(adp, eid, AD_FILELOCK_OPEN_RD)) <0)
return readset;
- if ((denyreadset = getforkmode(adp, eid, AD_FILELOCK_DENY_RD)) <0)
+ if ((denyreadset = ad_testlock(adp, eid, AD_FILELOCK_DENY_RD)) <0)
return denyreadset;
if ((access & OPENACC_RD) && denyreadset) {
* true
*/
if ((access & OPENACC_RD)) {
- ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_RD);
+ ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_OPEN_RD, 1, ofrefnum);
if (ret)
return ret;
}
if ((access & OPENACC_DRD)) {
- ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_DENY_RD);
+ ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_DENY_RD, 1, ofrefnum);
if (ret)
return ret;
}
}
/* ------------same for writing -------------- */
if ((access & (OPENACC_WR | OPENACC_DWR))) {
- if ((writeset = getforkmode(adp, eid, AD_FILELOCK_OPEN_WR)) <0)
+ if ((writeset = ad_testlock(adp, eid, AD_FILELOCK_OPEN_WR)) <0)
return writeset;
- if ((denywriteset = getforkmode(adp, eid, AD_FILELOCK_DENY_WR)) <0)
+ if ((denywriteset = ad_testlock(adp, eid, AD_FILELOCK_DENY_WR)) <0)
return denywriteset;
if ((access & OPENACC_WR) && denywriteset) {
return -1;
}
if ((access & OPENACC_WR)) {
- ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_WR);
+ ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_OPEN_WR, 1, ofrefnum);
if (ret)
return ret;
}
if ((access & OPENACC_DWR)) {
- ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_DENY_WR);
+ ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_DENY_WR, 1, ofrefnum);
if (ret)
return ret;
}
return AFPERR_BADTYPE;
}
- LOG(log_debug, logtype_afpd,
- "afp_openfork(\"%s\", fork: %s)",
- abspath(s_path->u_name),
- (fork & OPENFORK_DATA) ? "d" : "r");
+ LOG(log_debug, logtype_afpd, "afp_openfork(\"%s\", %s)",
+ fullpathname(s_path->u_name), (fork & OPENFORK_RSCS) ? "RSRC" : "DATA");
/* stat() data fork st is set because it's not a dir */
switch ( s_path->st_errno ) {
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) );
+ LOG(log_error, logtype_afpd, "afp_openfork(%s): %s", s_path->m_name, strerror(errno));
return AFPERR_PARAM;
}
/* FIXME should we check it first ? */
if ( fork == OPENFORK_DATA ) {
eid = ADEID_DFORK;
- adflags = ADFLAGS_DF | ADFLAGS_HF;
+ adflags = ADFLAGS_DF | ADFLAGS_HF ;
} else {
eid = ADEID_RFORK;
adflags = ADFLAGS_RF | ADFLAGS_HF;
ret = AFPERR_NOOBJ;
if (access & OPENACC_WR) {
/* try opening in read-write mode */
- if (ad_open(upath, adflags, O_RDWR, 0, ofork->of_ad) < 0) {
+ if (ad_open(ofork->of_ad, upath,
+ adflags | ADFLAGS_RDWR | ADFLAGS_SETSHRMD) < 0) {
switch ( errno ) {
case EROFS:
ret = AFPERR_VLOCK;
case ENOENT:
if (fork == OPENFORK_DATA) {
/* try to open only the data fork */
- if (ad_open(upath, ADFLAGS_DF, O_RDWR, 0, ofork->of_ad) < 0) {
+ if (ad_open(ofork->of_ad, upath,
+ ADFLAGS_DF | ADFLAGS_RDWR | ADFLAGS_SETSHRMD) < 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)
+ if (ad_open(ofork->of_ad, upath,
+ adflags | ADFLAGS_RDWR | ADFLAGS_SETSHRMD | ADFLAGS_CREATE, 0666) < 0)
goto openfork_err;
ofork->of_flags |= AFPFORK_OPEN;
}
} else {
/* try opening in read-only mode */
ret = AFPERR_NOOBJ;
- if (ad_open(upath, adflags, O_RDONLY, 0, ofork->of_ad) < 0) {
+ /* we need w access for setting deny mode fcntl excl lock */
+ if (ad_open(ofork->of_ad, upath, adflags | ADFLAGS_RDONLY | ADFLAGS_SETSHRMD) < 0) {
switch ( errno ) {
case EROFS:
ret = AFPERR_VLOCK;
+ goto openfork_err;
case EACCES:
goto openfork_err;
- break;
case ENOENT:
/* 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) {
+ if (ad_open(ofork->of_ad, upath, ADFLAGS_DF | ADFLAGS_RDONLY | ADFLAGS_SETSHRMD) < 0) {
goto openfork_err;
}
adflags = ADFLAGS_DF;
break;
default:
LOG(log_error, logtype_afpd, "afp_openfork(\"%s\"): %s",
- abspath(s_path->m_name), strerror(errno) );
+ fullpathname(s_path->m_name), strerror(errno) );
goto openfork_err;
break;
}
}
}
- if ((adflags & ADFLAGS_HF) && (ad_get_HF_flags( ofork->of_ad) & O_CREAT)) {
+ if ((adflags & ADFLAGS_RF) && (ad_get_RF_flags( ofork->of_ad) & O_CREAT)) {
if (ad_setname(ofork->of_ad, path)) {
ad_flush( ofork->of_ad );
}
}
- if (( ret = getforkparams(ofork, bitmap, rbuf + 2 * sizeof( u_int16_t ),
- &buflen )) != AFP_OK ) {
+ if ((ret = getforkparams(ofork, bitmap, rbuf + 2 * sizeof(int16_t), &buflen)) != AFP_OK) {
ad_close( ofork->of_ad, adflags );
goto openfork_err;
}
- *rbuflen = buflen + 2 * sizeof( u_int16_t );
+ *rbuflen = buflen + 2 * sizeof( uint16_t );
bitmap = htons( bitmap );
- memcpy(rbuf, &bitmap, sizeof( u_int16_t ));
- rbuf += sizeof( u_int16_t );
+ memcpy(rbuf, &bitmap, sizeof( uint16_t ));
+ rbuf += sizeof( uint16_t );
/* check WriteInhibit bit if we have a ressource fork
* the test is done here, after some Mac trafic capture
{
struct ofork *ofork;
off_t size;
- u_int16_t ofrefnum, bitmap;
+ uint16_t ofrefnum, bitmap;
int err;
int is64;
int eid;
struct ofork *ofork;
off_t offset, length;
int eid;
- u_int16_t ofrefnum;
- u_int8_t flags;
+ uint16_t ofrefnum;
+ uint8_t flags;
int lockop;
*rbuflen = 0;
off_t offset, saveoff, reqcount, savereqcount;
ssize_t cc, err;
int eid, xlate = 0;
- u_int16_t ofrefnum;
+ uint16_t ofrefnum;
u_char nlmask, nlchar;
ibuf += 2;
reqcount = get_off_t(&ibuf, is64);
LOG(log_debug, logtype_afpd,
- "afp_read(\"%s\", off: %" PRIu64 ", size: %" PRIu64 ", fork: %s)",
- cfrombstr(ofork->of_ad->ad_fullpath), offset, reqcount,
- (ofork->of_flags & AFPFORK_DATA) ? "d" : "r");
+ "afp_read(off: %" PRIu64 ", size: %" PRIu64 ", fork: %s)", offset, reqcount,
+ (ofork->of_flags & AFPFORK_DATA) ? "d" : "r");
if (is64) {
nlmask = nlchar = 0;
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;
if (ad_tmplock(ofork->of_ad, eid, ADLOCK_RD, saveoff, savereqcount,ofork->of_refnum) < 0) {
goto afp_read_err;
}
-#define min(a,b) ((a)<(b)?(a):(b))
- *rbuflen = min( reqcount, *rbuflen );
+ *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. */
/* 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 WITH_SENDFILE
- if (!(xlate || Debug(obj) )) {
+ if (!(xlate)) {
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;
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)
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;
+ uint16_t vid;
*rbuflen = 0;
ibuf += 2;
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;
+ uint16_t ofrefnum;
*rbuflen = 0;
ibuf += 2;
return( AFPERR_PARAM );
}
- LOG(log_debug, logtype_afpd,
- "afp_flushfork(\"%s\", fork: %s)",
- cfrombstr(ofork->of_ad->ad_fullpath),
+ LOG(log_debug, logtype_afpd, "afp_flushfork(fork: %s)",
(ofork->of_flags & AFPFORK_DATA) ? "d" : "r");
if ( flushfork( ofork ) < 0 ) {
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;
+ uint16_t ofrefnum;
*rbuflen = 0;
ibuf += 2;
return( AFPERR_PARAM );
}
- LOG(log_debug, logtype_afpd,
- "afp_syncfork(\"%s\", fork: %s)",
- cfrombstr(ofork->of_ad->ad_fullpath),
+ LOG(log_debug, logtype_afpd, "afp_syncfork(fork: %s)",
(ofork->of_flags & AFPFORK_DATA) ? "d" : "r");
if ( flushfork( ofork ) < 0 ) {
int afp_closefork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
{
struct ofork *ofork;
- u_int16_t ofrefnum;
+ uint16_t ofrefnum;
*rbuflen = 0;
ibuf += 2;
return( AFPERR_PARAM );
}
- LOG(log_debug, logtype_afpd,
- "afp_closefork(\"%s\", fork: %s)",
- cfrombstr(ofork->of_ad->ad_fullpath),
+ LOG(log_debug, logtype_afpd, "afp_closefork(fork: %s)",
(ofork->of_flags & AFPFORK_DATA) ? "d" : "r");
if ( of_closefork( ofork ) < 0 ) {
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;
+ uint16_t ofrefnum;
ssize_t cc;
/* figure out parameters */
goto afp_write_err;
}
- LOG(log_debug, logtype_afpd,
- "afp_write(\"%s\", off: %" PRIu64 ", size: %" PRIu64 ", fork: %s)",
- cfrombstr(ofork->of_ad->ad_fullpath), offset, reqcount,
- (ofork->of_flags & AFPFORK_DATA) ? "d" : "r");
+ LOG(log_debug, logtype_afpd, "afp_write(off: %" PRIu64 ", size: %" PRIu64 ", fork: %s)",
+ offset, reqcount, (ofork->of_flags & AFPFORK_DATA) ? "d" : "r");
if ((ofork->of_flags & AFPFORK_ACCWR) == 0) {
err = AFPERR_ACCESS;
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) {
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)) {
/* this is yucky, but dsi can stream i/o and asp can't */
switch (obj->proto) {
-#ifndef NO_DDP
- case AFPPROTO_ASP:
- if (asp_wrtcont(obj->handle, rbuf, rbuflen) < 0) {
- *rbuflen = 0;
- LOG(log_error, logtype_afpd, "afp_write: asp_wrtcont: %s", strerror(errno) );
- 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, ofork->of_refnum);
- return cc;
- }
- offset += cc;
- break;
-#endif /* no afp/asp */
-
case AFPPROTO_DSI:
{
DSI *dsi = obj->handle;
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 );
{
struct ofork *ofork;
int ret;
- u_int16_t ofrefnum, bitmap;
+ uint16_t ofrefnum, bitmap;
size_t buflen;
ibuf += 2;
memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));