X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=etc%2Fafpd%2Ffork.c;h=33aaf66d1c025b1be90da8170b05376a2f988d81;hb=b35812db1e932c31154b7da72c564dabe95fd03d;hp=57b3268ea8726d0d8cb7bb1d80ad8ead3d73693f;hpb=f758a8c097b044293fa2fe58f8a7fcc2d8909b55;p=netatalk.git diff --git a/etc/afpd/fork.c b/etc/afpd/fork.c index 57b3268e..33aaf66d 100644 --- a/etc/afpd/fork.c +++ b/etc/afpd/fork.c @@ -1,5 +1,5 @@ /* - * $Id: fork.c,v 1.67 2009-10-22 12:35:38 franklahm 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. @@ -11,7 +11,6 @@ #include -#include #include #include @@ -27,13 +26,12 @@ #include #include #include - #include #include +#include #include "fork.h" #include "file.h" -#include "globals.h" #include "directory.h" #include "desktop.h" #include "volume.h" @@ -74,20 +72,22 @@ static int getforkparams(struct ofork *ofork, u_int16_t bitmap, char *buf, size_ } 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<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 ) { @@ -159,14 +159,14 @@ static 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); } /* ------------------------- */ -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); } @@ -432,7 +432,8 @@ int afp_openfork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, si 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; } @@ -637,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; @@ -843,7 +845,7 @@ static int read_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, si int eid, xlate = 0; u_int16_t ofrefnum; u_char nlmask, nlchar; - + ibuf += 2; memcpy(&ofrefnum, ibuf, sizeof( ofrefnum )); ibuf += sizeof( u_short ); @@ -892,6 +894,9 @@ static int read_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, si 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) { @@ -899,18 +904,20 @@ static int read_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, si 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. */ if ((obj->proto == AFPPROTO_DSI) && (*rbuflen < reqcount) && !nlmask) { DSI *dsi = obj->handle; off_t size; - int non_blocking = 0; /* reqcount isn't always truthful. we need to deal with that. */ size = ad_size(ofork->of_ad, eid); @@ -932,10 +939,13 @@ static int read_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, si *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 { @@ -951,12 +961,6 @@ static int read_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, si 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); @@ -964,22 +968,12 @@ 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) 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; @@ -1170,7 +1164,10 @@ static 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(%s): ad_write: %s", of_name(ofork), strerror(errno) ); return( AFPERR_PARAM ); @@ -1187,7 +1184,7 @@ static ssize_t write_file(struct ofork *ofork, int eid, 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; @@ -1227,8 +1224,9 @@ static int write_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, s 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) { @@ -1236,9 +1234,12 @@ static int write_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, s 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; } @@ -1342,6 +1343,12 @@ static int write_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, s 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 );