/*
- * $Id: fork.c,v 1.64 2009-10-14 01:38:28 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"
struct ofork *writtenfork;
#endif
-static int getforkparams(struct ofork *ofork, u_int16_t bitmap, char *buf, int *buflen)
+static int getforkparams(struct ofork *ofork, u_int16_t bitmap, char *buf, size_t *buflen)
{
struct path path;
struct stat *st;
}
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 ) {
}
/* ----------------------- */
-int afp_openfork(AFPObj *obj _U_, char *ibuf, int ibuflen _U_, char *rbuf, int *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;
char fork, *path, *upath;
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;
}
return ret;
}
-int afp_setforkparams(AFPObj *obj _U_, char *ibuf, int ibuflen, char *rbuf _U_, int *rbuflen)
+int afp_setforkparams(AFPObj *obj _U_, char *ibuf, size_t ibuflen, char *rbuf _U_, size_t *rbuflen)
{
struct ofork *ofork;
off_t size;
/* ---------------------- */
-static int byte_lock(AFPObj *obj _U_, char *ibuf, int ibuflen _U_, char *rbuf, int *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;
}
/* --------------------------- */
-int afp_bytelock(AFPObj *obj, char *ibuf, int ibuflen, char *rbuf, int *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(AFPObj *obj, char *ibuf, int ibuflen, char *rbuf, int *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);
}
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;
*rbuflen = 0;
return( AFPERR_PARAM );
}
- if ( cc < *rbuflen ) {
+ if ( (size_t)cc < *rbuflen ) {
eof = 1;
}
*
* with dsi, should we check that reqcount < server quantum?
*/
-static int read_fork(AFPObj *obj, char *ibuf, int ibuflen _U_, char *rbuf, int *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 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;
if ((obj->proto == AFPPROTO_DSI) && (*rbuflen < reqcount) && !nlmask) {
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,(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);
/* 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. */
-#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 {
afp_read_loop:
#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);
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;
}
/* ---------------------- */
-int afp_read(AFPObj *obj, char *ibuf, int ibuflen, char *rbuf, int *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(AFPObj *obj, char *ibuf, int ibuflen, char *rbuf, int *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(AFPObj *obj _U_, char *ibuf, int ibuflen _U_, char *rbuf _U_, int *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;
return( AFP_OK );
}
-int afp_flushfork(AFPObj *obj _U_, char *ibuf, int ibuflen _U_, char *rbuf _U_, int *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;
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, int ibuflen _U_, char *rbuf _U_, int *rbuflen)
+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;
return( err );
}
-int afp_closefork(AFPObj *obj _U_, char *ibuf, int ibuflen _U_, char *rbuf _U_, int *rbuflen)
+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;
case EFBIG :
case ENOSPC :
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 );
/* 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(AFPObj *obj, char *ibuf, int ibuflen _U_, char *rbuf, int *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;
/* 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;
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_written += reqcount;
+
*rbuflen = set_off_t (offset, rbuf, is64);
return( AFP_OK );
}
/* ---------------------------- */
-int afp_write(AFPObj *obj, char *ibuf, int ibuflen, char *rbuf, int *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);
}
/* ----------------------------
* FIXME need to deal with SIGXFSZ signal
*/
-int afp_write_ext(AFPObj *obj, char *ibuf, int ibuflen, char *rbuf, int *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(AFPObj *obj _U_, char *ibuf, int ibuflen _U_, char *rbuf, int *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;
-
+ size_t buflen;
ibuf += 2;
memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
ibuf += sizeof( ofrefnum );