X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=etc%2Fafpd%2Ffork.c;h=f7d9f82a839fb2412c3b514bf3df3e5fa06e0826;hb=4054f4b3c85ecab060dafd46c0d3632cadbb5803;hp=d43ea1600f959f6b1f601c3db099dc1388e523c5;hpb=ac3ff5227a21f223c17d57b31419f695b19857d8;p=netatalk.git diff --git a/etc/afpd/fork.c b/etc/afpd/fork.c index d43ea160..f7d9f82a 100644 --- a/etc/afpd/fork.c +++ b/etc/afpd/fork.c @@ -1,5 +1,5 @@ /* - * $Id: fork.c,v 1.59 2009-02-25 22:41:03 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. @@ -11,7 +11,6 @@ #include -#include #include #include @@ -44,17 +43,11 @@ #define Debug(a) (0) #endif -struct ofork *writtenfork; -extern int getmetadata(struct vol *vol, - u_int16_t bitmap, - struct path *path, struct dir *dir, char *buf, - int *buflen, struct adouble *adp); - -static int getforkparams(ofork, bitmap, buf, buflen ) -struct ofork *ofork; -u_int16_t bitmap; -char *buf; -int *buflen; +#ifdef AFS +struct ofork *writtenfork; +#endif + +static int getforkparams(struct ofork *ofork, u_int16_t bitmap, char *buf, size_t *buflen) { struct path path; struct stat *st; @@ -80,20 +73,22 @@ int *buflen; } 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 ) { @@ -105,9 +100,7 @@ int *buflen; } /* ---------------------------- */ -static off_t get_off_t(ibuf, is64) -char **ibuf; -int is64; +static off_t get_off_t(char **ibuf, int is64) { u_int32_t temp; off_t ret; @@ -129,10 +122,7 @@ int is64; } /* ---------------------- */ -static int set_off_t(offset, rbuf, is64) -off_t offset; -char *rbuf; -int is64; +static int set_off_t(off_t offset, char *rbuf, int is64) { u_int32_t temp; int ret; @@ -257,16 +247,14 @@ static int fork_setmode(struct adouble *adp, int eid, int access, int ofrefnum) } /* ----------------------- */ -int afp_openfork(obj, ibuf, ibuflen, rbuf, rbuflen ) -AFPObj *obj _U_; -char *ibuf, *rbuf; -int ibuflen _U_, *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; @@ -445,7 +433,8 @@ int ibuflen _U_, *rbuflen; 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; } @@ -531,10 +520,7 @@ openfork_err: return ret; } -int afp_setforkparams(obj, ibuf, ibuflen, rbuf, rbuflen ) -AFPObj *obj _U_; -char *ibuf, *rbuf _U_; -int ibuflen, *rbuflen; +int afp_setforkparams(AFPObj *obj _U_, char *ibuf, size_t ibuflen, char *rbuf _U_, size_t *rbuflen) { struct ofork *ofork; off_t size; @@ -671,11 +657,7 @@ afp_setfork_err: /* ---------------------- */ -static int byte_lock(obj, ibuf, ibuflen, rbuf, rbuflen, is64 ) -AFPObj *obj _U_; -char *ibuf, *rbuf; -int ibuflen _U_, *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; @@ -754,19 +736,13 @@ int is64; } /* --------------------------- */ -int afp_bytelock(obj, ibuf, ibuflen, rbuf, rbuflen ) -AFPObj *obj; -char *ibuf, *rbuf; -int ibuflen, *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(obj, ibuf, ibuflen, rbuf, rbuflen ) -AFPObj *obj; -char *ibuf, *rbuf; -int ibuflen, *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); } @@ -774,8 +750,7 @@ int ibuflen, *rbuflen; #undef UNLOCKBIT /* --------------------------- */ -static int crlf( of ) -struct ofork *of; +static int crlf(struct ofork *of) { struct extmap *em; @@ -797,7 +772,7 @@ struct ofork *of; 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; @@ -809,7 +784,7 @@ static ssize_t read_file(struct ofork *ofork, int eid, *rbuflen = 0; return( AFPERR_PARAM ); } - if ( cc < *rbuflen ) { + if ( (size_t)cc < *rbuflen ) { eof = 1; } @@ -862,15 +837,12 @@ static ssize_t read_file(struct ofork *ofork, int eid, * * with dsi, should we check that reqcount < server quantum? */ -static int read_fork(obj, ibuf, ibuflen, rbuf, rbuflen, is64) -AFPObj *obj; -char *ibuf, *rbuf; -int ibuflen _U_, *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; @@ -940,14 +912,7 @@ int is64; 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); @@ -963,15 +928,17 @@ int is64; /* 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 { @@ -987,12 +954,6 @@ int is64; 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); @@ -1012,10 +973,6 @@ afp_read_loop: 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; @@ -1036,28 +993,19 @@ afp_read_err: } /* ---------------------- */ -int afp_read(obj, ibuf, ibuflen, rbuf, rbuflen) -AFPObj *obj; -char *ibuf, *rbuf; -int ibuflen, *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(obj, ibuf, ibuflen, rbuf, rbuflen) -AFPObj *obj; -char *ibuf, *rbuf; -int ibuflen, *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(obj, ibuf, ibuflen, rbuf, rbuflen ) -AFPObj *obj _U_; -char *ibuf, *rbuf _U_; -int ibuflen _U_, *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; @@ -1074,10 +1022,7 @@ int ibuflen _U_, *rbuflen; return( AFP_OK ); } -int afp_flushfork(obj, ibuf, ibuflen, rbuf, rbuflen ) -AFPObj *obj _U_; -char *ibuf, *rbuf _U_; -int ibuflen _U_, *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; @@ -1104,10 +1049,7 @@ int ibuflen _U_, *rbuflen; 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(obj, ibuf, ibuflen, rbuf, rbuflen ) - AFPObj *obj; - char *ibuf, *rbuf _U_; - int ibuflen _U_, *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; @@ -1118,7 +1060,7 @@ int afp_syncfork(obj, ibuf, ibuflen, rbuf, rbuflen ) memcpy(&ofrefnum, ibuf, sizeof(ofrefnum)); ibuf += sizeof( ofrefnum ); - if (NULL == ( ofork == of_find( ofrefnum )) ) { + if (NULL == ( ofork = of_find( ofrefnum )) ) { LOG(log_error, logtype_afpd, "afpd_syncfork: of_find(%d) could not locate fork", ofrefnum ); return( AFPERR_PARAM ); } @@ -1131,10 +1073,8 @@ int afp_syncfork(obj, ibuf, ibuflen, rbuf, rbuflen ) return( AFP_OK ); } - /* this is very similar to closefork */ -int flushfork( ofork ) -struct ofork *ofork; +int flushfork(struct ofork *ofork) { struct timeval tv; @@ -1175,10 +1115,7 @@ struct ofork *ofork; return( err ); } -int afp_closefork(obj, ibuf, ibuflen, rbuf, rbuflen ) -AFPObj *obj _U_; -char *ibuf, *rbuf _U_; -int ibuflen _U_, *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; @@ -1227,6 +1164,8 @@ static ssize_t write_file(struct ofork *ofork, int eid, 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 ); @@ -1240,11 +1179,7 @@ static ssize_t write_file(struct ofork *ofork, int eid, /* 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(obj, ibuf, ibuflen, rbuf, rbuflen, is64) -AFPObj *obj; -char *ibuf, *rbuf; -int ibuflen _U_, *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; @@ -1385,12 +1320,6 @@ int is64; /* 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; @@ -1408,6 +1337,9 @@ int is64; 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; + *rbuflen = set_off_t (offset, rbuf, is64); return( AFP_OK ); @@ -1423,10 +1355,7 @@ afp_write_err: } /* ---------------------------- */ -int afp_write(obj, ibuf, ibuflen, rbuf, rbuflen) -AFPObj *obj; -char *ibuf, *rbuf; -int ibuflen, *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); } @@ -1434,24 +1363,18 @@ int ibuflen, *rbuflen; /* ---------------------------- * FIXME need to deal with SIGXFSZ signal */ -int afp_write_ext(obj, ibuf, ibuflen, rbuf, rbuflen) -AFPObj *obj; -char *ibuf, *rbuf; -int ibuflen, *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(obj, ibuf, ibuflen, rbuf, rbuflen ) -AFPObj *obj _U_; -char *ibuf, *rbuf; -int ibuflen _U_, *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 );