/*
- * $Id: fork.c,v 1.68 2009-10-25 06:12:51 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.
#include <stdio.h>
-#include <dirent.h>
#include <string.h>
#include <errno.h>
#include <atalk/atp.h>
#include <atalk/asp.h>
#include <atalk/afp.h>
-
#include <atalk/util.h>
#include <atalk/cnid.h>
+#include <atalk/globals.h>
#include "fork.h"
#include "file.h"
-#include "globals.h"
#include "directory.h"
#include "desktop.h"
#include "volume.h"
}
vol = ofork->of_vol;
- dir = ofork->of_dir;
+ dir = dirlookup(vol, ofork->of_did);
if (NULL == (path.u_name = mtoupath(vol, of_name(ofork), dir->d_did, utf8_encoding()))) {
return( AFPERR_MISC );
}
path.m_name = of_name(ofork);
+ path.id = 0;
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_data_fileno( ofork->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_data_fileno( ofork->of_ad ), st ) < 0 ) {
/* -------------------------
*/
-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);
}
/* -------------------------
*/
-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);
}
goto openfork_err;
break;
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'): ad_open: errno: %i (%s)",
+ getcwdpath, s_path->m_name, errno, strerror(errno) );
goto openfork_err;
break;
}
case EDQUOT:
case EFBIG:
case ENOSPC:
+ LOG(log_error, logtype_afpd, "afp_setforkparams: DISK FULL");
return AFPERR_DFULL;
default:
return AFPERR_PARAM;
int eid, xlate = 0;
u_int16_t ofrefnum;
u_char nlmask, nlchar;
-
+
ibuf += 2;
memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
ibuf += sizeof( u_short );
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. */
*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. */
-#if 0 /* ifdef WITH_SENDFILE */
- /* FIXME with OS X deadlock partial workaround we can't use sendfile */
+#ifdef WITH_SENDFILE
if (!(xlate || Debug(obj) )) {
- if (ad_readfile(ofork->of_ad, eid, dsi->socket, offset, dsi->datasize) < 0) {
+ 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 {
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)
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(%s): ad_write: %s", of_name(ofork), strerror(errno) );
return( AFPERR_PARAM );
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;
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)) {
+ LOG(log_error, logtype_afpd, "write_fork: DISK FULL");
err = AFPERR_DFULL;
goto afp_write_err;
}
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 );