diff --git a/ChangeLog b/ChangeLog index c498ba7..6f3c65d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,29 @@ +Version NEXT + use srandomdev for seeding of client seq. number generator + make dirlister smarter - save one RTT per each directory listings + Locking uses unsigned int sized key, not unsigned short + Locking type can be specified by ./configure --with-locking= + Lock prefix can be specified by ./configure --with-lockprefix= + All 5 locking subsystems synced against fsplib and fspclient code base + Do not use CC_STAT when doing directory listing -- performace gain. + This saves 1 RTT per directory listing. + clients: do not send CC_BYE to the server on exit if we can keep server + key for next invocation. Saves 1 RTT. + !! Major client utils speedup: Directory listings are now 3 RTT + times faster. + fmvcmd added to merged client + new command fbye(1). Sends CC_BYE to the server and possibly removes + cached session key. + fbye added to merged client + PROTOCOL: Add note about client key multiplexing + we have incorrectly recovered requested size of reply packet sent + by client + !! LARGE PACKET SUPPORT !! FSP can be quite Faaaast now. + fver -l displays maximum packet size supported by client + fsp_env.7: added info about larger packets + send_file function renamed to serve_file for avoiding name clash + on AIX. + Version 2.8.1b22 - 20 Dec 2004 fixed sf bug 1060594: fspd: owner can't rename files fixed sf bug 1060558: fpro 'l' sets 'm' flag instead (dairiki) diff --git a/TODO b/TODO index 910094e..6fdccb9 100644 --- a/TODO +++ b/TODO @@ -34,16 +34,11 @@ we should retune retry algoritm for better support lines with higher add more detailed stats from retry alg. :low: fver and others add support new syntax fsp://host:port/file -flscmd should not to do stat before directory listing. -directory listing should not need to get 0 sized block. Needs total code - rewrite. :long-term goals: drop this library and use libfsp instead LOCKING -better support for persistent keys - do not send cc_bye ? this should - be probably configurable CLIENTS :high: diff --git a/bsd_src/ls.c b/bsd_src/ls.c index f11e835..4e8795f 100644 --- a/bsd_src/ls.c +++ b/bsd_src/ls.c @@ -213,6 +213,7 @@ static void doargs (int argc, char ** argv) struct stat sb; char top[2*1024 + 1], **av, *av2[2]; unsigned long blocks; + RDIR * dl; /* * walk through the operands, building separate arrays of LS @@ -220,6 +221,8 @@ static void doargs (int argc, char ** argv) */ dstats = rstats = NULL; dirmax = regmax = 0; + /* disable use of new CC_STAT command for performance reasons */ + statworks = 0; for (dircnt = regcnt = 0; *argv; ++argv) { if(!(av = glob(*argv))) { @@ -229,13 +232,12 @@ static void doargs (int argc, char ** argv) } for( ; *av; av++) { - /* TODO: this stat call should be avoided for performance speedups */ - /* Better is turn it to get_dirblk or something like this */ if (util_stat(*av, &sb)) { perror(*av); if (errno == ENOENT) continue; ls_bad(1); } + if ((S_ISDIR(sb.st_mode)) && !f_listdir) { if(dirmax == dircnt) { dirmax += 10; diff --git a/client/lib.c b/client/lib.c index 77e0370..424fe17 100644 --- a/client/lib.c +++ b/client/lib.c @@ -167,8 +167,7 @@ UBUF *client_interact (unsigned char cmd, unsigned long pos, myseq = (myseq + 0x0004) & 0xfffc; /* seq for next request */ key = BB_READ2(rbuf.bb_key); /* key for next request */ - if(rbuf.cmd != CC_BYE) - client_set_key(key); + client_set_key(key); if(client_intr_state == 2) { if(!key_persists) client_done(); @@ -201,6 +200,9 @@ static RETSIGTYPE client_intr (int signum) void init_client (const char * host, unsigned short port, unsigned short myport) { busy_delay = idle_delay = target_delay; +#ifdef HAVE_SRANDOMDEV + srandomdev(); +#endif myseq = random(); if((myfd = _x_udp(env_listen_on,&myport)) == -1) { @@ -217,10 +219,16 @@ void init_client (const char * host, unsigned short port, unsigned short myport) signal(SIGINT,client_intr); } -int client_done (void) +void client_finish(void) { (void) client_interact(CC_BYE, 0L, 0, (unsigned char *)NULLP, 0, (unsigned char *)NULLP); client_destroy_key(); +} + +int client_done (void) +{ + if(!key_persists) + client_finish(); return(0); } diff --git a/client/lock.c b/client/lock.c index 1ff2167..736d248 100644 --- a/client/lock.c +++ b/client/lock.c @@ -16,8 +16,8 @@ #include "c_extern.h" #include "my-string.h" -#ifndef NOLOCKING -static char key_string[sizeof(KEY_PREFIX)+32]; +#ifndef FSP_NOLOCKING +static char key_string[sizeof(FSP_KEY_PREFIX)+32]; static char code_str[] = "0123456789:_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; @@ -28,7 +28,7 @@ static void make_key_string( unsigned long server_addr, unsigned long v1, v2; char *p; - strcpy(key_string,KEY_PREFIX); + strcpy(key_string,FSP_KEY_PREFIX); for(p = key_string; *p; p++) ; v1 = server_addr; @@ -50,15 +50,15 @@ static void make_key_string( unsigned long server_addr, /********************************************************************/ /******* For those systems that has flock function call *************/ /********************************************************************/ -#ifdef USE_FLOCK +#ifdef FSP_USE_FLOCK #include int key_persists = 1; static unsigned int lock_fd; -static unsigned short okey; +static unsigned int okey; -unsigned short client_get_key PROTO0((void)) +unsigned short client_get_key (void) { if(flock(lock_fd,LOCK_EX) == -1) { perror("flock"); @@ -74,8 +74,10 @@ unsigned short client_get_key PROTO0((void)) return(okey); } -void client_set_key PROTO1(unsigned short, key) +void client_set_key (unsigned short nkey) { + unsigned int key; + key=nkey; if(write(lock_fd,&key,sizeof(key)) == -1) { perror("write"); exit(1); @@ -90,11 +92,11 @@ void client_set_key PROTO1(unsigned short, key) } } -void client_init_key PROTO3(unsigned long, server_addr, - unsigned long, server_port, - unsigned short, key) +void client_init_key (unsigned long server_addr, + unsigned long server_port, + unsigned short key) { - unsigned long omask; + mode_t omask; okey = key; make_key_string(server_addr,server_port); @@ -113,7 +115,7 @@ void client_destroy_key(void) /********************************************************************/ /******* For those systems that has lockf function call *************/ /********************************************************************/ -#ifdef USE_LOCKF +#ifdef FSP_USE_LOCKF #ifdef HAVE_UNISTD_H #include @@ -121,9 +123,9 @@ void client_destroy_key(void) int key_persists = 1; static unsigned int lock_fd; -static unsigned short okey; +static unsigned int okey; -unsigned short client_get_key PROTO0((void)) +unsigned short client_get_key (void) { if(lockf(lock_fd,F_LOCK,sizeof(okey)) == -1) { perror("lockf"); @@ -140,8 +142,10 @@ unsigned short client_get_key PROTO0((void)) return(okey); } -void client_set_key PROTO1(unsigned short, key) +void client_set_key (unsigned short nkey) { + unsigned int key; + key=nkey; if(write(lock_fd,&key,sizeof(key)) == -1) { perror("write"); exit(1); @@ -156,11 +160,11 @@ void client_set_key PROTO1(unsigned short, key) } } -void client_init_key PROTO3(unsigned long, server_addr, - unsigned long, server_port, - unsigned short, key) +void client_init_key (unsigned long server_addr, + unsigned long server_port, + unsigned short key) { - unsigned long omask; + mode_t omask; okey = key; make_key_string(server_addr,server_port); @@ -173,13 +177,12 @@ void client_init_key PROTO3(unsigned long, server_addr, void client_destroy_key(void) { (void)close(lock_fd); - unlink(key_string); } #endif /********************************************************************/ /******* For those systems that has SysV shared memory + lockf ******/ /********************************************************************/ -#ifdef USE_SHAREMEM_AND_LOCKF +#ifdef FSP_USE_SHAREMEM_AND_LOCKF #ifdef HAVE_UNISTD_H #include @@ -187,8 +190,8 @@ void client_destroy_key(void) #include #include -int key_persists = 0; -static unsigned short *share_key; +int key_persists = 1; +static unsigned int *share_key; static unsigned int lock_fd; static int lock_shm; @@ -214,7 +217,7 @@ void client_init_key (unsigned long server_addr, unsigned long server_port, unsigned short key) { - unsigned long omask; + mode_t omask; key_t lock_key; make_key_string(server_addr,server_port); @@ -227,11 +230,11 @@ void client_init_key (unsigned long server_addr, perror("ftok"); exit(1); } - if((lock_shm = shmget(lock_key,sizeof(short),IPC_CREAT|0666)) == -1) { + if((lock_shm = shmget(lock_key,2*sizeof(unsigned int),IPC_CREAT|0666)) == -1) { perror("shmget"); exit(1); } - if(!(share_key = (unsigned short *) shmat(lock_shm,(char*)0,0))) { + if(!(share_key = (unsigned int *) shmat(lock_shm,(char*)0,0))) { perror("shmat"); exit(1); } @@ -245,13 +248,12 @@ void client_destroy_key(void) perror("shmdt"); } shmctl(lock_shm,IPC_RMID,NULL); - unlink(key_string); } #endif /********************************************************************/ /******* For those who does not want to use locking *****************/ /********************************************************************/ -#ifdef NOLOCKING +#ifdef FSP_NOLOCKING int key_persists = 0; static unsigned short okey; @@ -281,7 +283,7 @@ void client_destroy_key(void) /********************************************************************/ /******* For those systems that has SysV shared memory + semop ******/ /********************************************************************/ -#ifdef USE_SHAREMEM_AND_SEMOP +#ifdef FSP_USE_SHAREMEM_AND_SEMOP #ifdef HAVE_UNISTD_H #include @@ -301,7 +303,7 @@ union semun #endif int key_persists = 1; -static unsigned short *share_key; +static unsigned int *share_key; static int lock_shm; static int lock_sem; @@ -339,7 +341,7 @@ void client_init_key (unsigned long server_addr, unsigned long server_port, unsigned short key) { - unsigned long omask; + mode_t omask; key_t lock_key; int fd; union semun sun; @@ -356,11 +358,11 @@ void client_init_key (unsigned long server_addr, perror("ftok"); exit(1); } - if((lock_shm = shmget(lock_key,sizeof(short),IPC_CREAT|0666)) == -1) { + if((lock_shm = shmget(lock_key,2*sizeof(unsigned int),IPC_CREAT|0666)) == -1) { perror("shmget"); exit(1); } - if(!(share_key = (unsigned short *) shmat(lock_shm,(char*)0,0))) { + if(!(share_key = (unsigned int *) shmat(lock_shm,(char*)0,0))) { perror("shmat"); exit(1); } diff --git a/client/util.c b/client/util.c index b1b5b97..63cda09 100644 --- a/client/util.c +++ b/client/util.c @@ -26,6 +26,7 @@ const char *env_listen_on; unsigned int env_timeout; unsigned short client_buf_len; unsigned short client_net_len; +int statworks=1; #define TWOGIGS 0x7fffffffUL #define FOURGIGS 0xffffffffUL @@ -145,16 +146,19 @@ char *util_getwd (char * p) static RDIRENT **get_dir_blk (char * path) { RDIRENT **dp; - char *p1, *p2, *fpath, buf[2*UBUF_SPACE]; + char *p1, *p2, *fpath, buf[NBSIZE]; unsigned long pos; int cnt, k, len, rem, acc, at_eof, rlen; + unsigned short dirblocksize; UBUF *ub; fpath = util_abs_path(path); + + dirblocksize = 0; for(pos = 0, at_eof = acc = cnt = 0; ; ) { - while((acc < UBUF_SPACE) && !at_eof) + while((acc < UBUF_MAXSPACE) && !at_eof) { ub = client_interact(CC_GET_DIR,pos, strlen(fpath), (unsigned char *)fpath+1, 2, @@ -168,13 +172,17 @@ static RDIRENT **get_dir_blk (char * path) } rlen = BB_READ2(ub->bb_len); - if(rlen < RDHSIZE) at_eof = 1; + if(dirblocksize == 0 ) + dirblocksize = rlen; + else + if (rlen < dirblocksize) at_eof = 1; + /* if(rlen < RDHSIZE) at_eof = 1; */ for(p1 = ub->buf, p2 = buf + acc, k = rlen; k--; ) *p2++ = *p1++; acc += rlen; pos += rlen; } - if(acc >= UBUF_SPACE) len = UBUF_SPACE; + if(acc >= UBUF_MAXSPACE) len = UBUF_MAXSPACE; else len = acc; for(p2 = buf, rem = len, k = 0; ; k++) { @@ -218,12 +226,12 @@ static RDIRENT **get_dir_blk (char * path) } } - if(acc < UBUF_SPACE) { + if(acc < UBUF_MAXSPACE) { dp[cnt] = 0; free(fpath); return(dp); } - for(p1 = buf + UBUF_SPACE, p2 = buf, k = (acc -= UBUF_SPACE); k--;) + for(p1 = buf + UBUF_MAXSPACE, p2 = buf, k = (acc -= UBUF_MAXSPACE); k--;) *p2++ = *p1++; } free(fpath); @@ -243,7 +251,7 @@ static int util_download_main (char * path, char * fpath, FILE * fp, if(client_trace && (udp_sent_time != sent_time)) { sent_time = udp_sent_time; - if(client_buf_len == UBUF_SPACE) fprintf(stderr,"\r%luk ",1+(pos>>10)); + if(client_buf_len >= UBUF_SPACE) fprintf(stderr,"\r%luk ",1+(pos>>10)); else fprintf(stderr,"\r%lu ", pos); fflush(stderr); } @@ -332,7 +340,7 @@ int util_upload (char * path, FILE * fp, time_t stamp) { unsigned long pos; unsigned bytes, first, tmax, sent_time; - char *fpath, buf[UBUF_SPACE]; + char *fpath, buf[UBUF_MAXSPACE]; UBUF *ub; time_t t = time(NULL); char *dpath,*p1,*p2; @@ -396,7 +404,7 @@ int util_upload (char * path, FILE * fp, time_t stamp) if(client_trace && (udp_sent_time != sent_time)) { sent_time = udp_sent_time; - if(client_buf_len == UBUF_SPACE) + if(client_buf_len >= UBUF_SPACE) fprintf(stderr,"\r%luk ",1+(pos>>10)); else fprintf(stderr,"\r%lu ", pos ); fflush(stderr); @@ -460,7 +468,7 @@ static void util_get_env (void) if( (p = getenv("FSP_BUF_SIZE")) ) client_buf_len = atoi(p); else client_buf_len = UBUF_SPACE; - if(client_buf_len > UBUF_SPACE) client_buf_len = UBUF_SPACE; + if(client_buf_len > UBUF_MAXSPACE) client_buf_len = UBUF_MAXSPACE; client_net_len = htons(client_buf_len); if( (p = getenv("FSP_DELAY")) ) target_delay = atol(p); @@ -553,11 +561,10 @@ void util_junk_password(char *path) if(pos != NULL) /* terminate them! */ *pos='\0'; -} +} int util_stat (char * path, struct stat * sbuf) { - static int statworks=1; RDIR *drp; RDIRENT **dep; DDLIST *ddp; diff --git a/clients/.cvsignore b/clients/.cvsignore index 45b424f..a7ed9d0 100644 --- a/clients/.cvsignore +++ b/clients/.cvsignore @@ -20,3 +20,4 @@ fver .deps fspprof.c fmvcmd +fbye diff --git a/clients/Makefile.am b/clients/Makefile.am index abcbc53..5deafd6 100644 --- a/clients/Makefile.am +++ b/clients/Makefile.am @@ -2,7 +2,7 @@ bin_PROGRAMS=fcatcmd fcdcmd fducmd ffindcmd fgetcmd fgrabcmd fhostcmd \ flscmd fmkdir fprocmd fput frmcmd frmdircmd fver fspmerge \ - fstatcmd fmvcmd + fstatcmd fmvcmd fbye LDADD=-L../common -L../bsd_src -L../client -lclient -lcommon -lbsdfsp $(EX_LIBS) @@ -16,7 +16,7 @@ fhostcmd_LDADD=$(LDADD) fspmerge_LDADD=fcatcmd_m.o fcdcmd_m.o fducmd_m.o ffindcmd_m.o fgetcmd_m.o \ fgrabcmd_m.o fhostcmd_m.o flscmd_m.o fmkdir_m.o fprocmd_m.o \ fput_m.o frmcmd_m.o frmdircmd_m.o fver_m.o fmvcmd_m.o \ - fstatcmd_m.o $(LDADD) + fstatcmd_m.o fbye_m.o $(LDADD) fgetcmd_CFLAGS:=-DCOMMAND_GET @@ -87,4 +87,7 @@ fmvcmd_m.o: @echo '#include "fmvcmd.c"' > fmvcmd_m.c ${COMPILE} -Dmain=fmvcmd_main -c fmvcmd_m.c @rm -f fmvcmd_m.c - +fbye_m.o: + @echo '#include "fbye.c"' > fbye_m.c + ${COMPILE} -Dmain=fbye_main -c fbye_m.c + @rm -f fbye_m.c diff --git a/clients/fbye.c b/clients/fbye.c new file mode 100644 index 0000000..293b88b --- /dev/null +++ b/clients/fbye.c @@ -0,0 +1,26 @@ + /*********************************************************************\ + * Copyright (c) 2004 by Radim Kolar (hsn@cybermail.net) * + * * + * You may copy or modify this file in any manner you wish, provided * + * that this notice is always included, and that you hold the author * + * harmless for any loss or damage resulting from the installation or * + * use of this software. * + \*********************************************************************/ + +#include "tweak.h" +#include "client_def.h" +#include "c_extern.h" +#include "merge.h" +#include +#ifdef STDC_HEADERS +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif + +int main (int argc, char ** argv) +{ + env_client(); + client_finish(); +} diff --git a/clients/fver.c b/clients/fver.c index 2389133..9d8ce9d 100644 --- a/clients/fver.c +++ b/clients/fver.c @@ -82,25 +82,26 @@ int main (int argc, char ** argv) } else { printf("Local FSP version: %s\n\n",PACKAGE_VERSION); + printf("Max. packet size supported by client: %d\n",UBUF_MAXSPACE); printf("System startup file: %s\n",FSPRC); printf("Local startup file: %s\n",FSPPROF); printf("Locking method is: "); -#if defined(USE_SHAREMEM_AND_LOCKF) +#if defined(FSP_USE_SHAREMEM_AND_LOCKF) printf("SHAREMEM_AND_LOCKF"); -#elif defined(USE_FLOCK) +#elif defined(FSP_USE_FLOCK) printf("FLOCK"); -#elif defined(USE_LOCKF) +#elif defined(FSP_USE_LOCKF) printf("LOCKF"); -#elif defined(NOLOCKING) +#elif defined(FSP_NOLOCKING) printf("None"); -#elif defined(USE_SHAREMEM_AND_SEMOP) +#elif defined(FSP_USE_SHAREMEM_AND_SEMOP) printf("SHAREMEM_AND_SEMOP"); #else #error "We do not have any locking method defined!" #endif printf("\n"); -#ifndef NOLOCKING - printf("Lock prefix is: %s\n",KEY_PREFIX); +#ifndef FSP_NOLOCKING + printf("Lock prefix is: %s\n",FSP_KEY_PREFIX); #endif printf("Timestamping supported: "); #ifdef HAVE_UTIME_H diff --git a/clients/merge.c b/clients/merge.c index d4e4046..b7e48dd 100644 --- a/clients/merge.c +++ b/clients/merge.c @@ -39,6 +39,7 @@ int main (int argc, char ** argv) else if(!strcmp(q,"fhostcmd")) fhostcmd_main(argc,argv); else if(!strcmp(q,"ffindcmd")) ffindcmd_main(argc,argv); else if(!strcmp(q,"fstatcmd")) fstatcmd_main(argc,argv); + else if(!strcmp(q,"fmvcmd")) fmvcmd_main(argc,argv); else { fprintf(stderr,"Unknown FSP client command: %s\n",q); exit(1); diff --git a/clients/merge.h b/clients/merge.h index 248a4c0..3daffcc 100644 --- a/clients/merge.h +++ b/clients/merge.h @@ -26,3 +26,4 @@ int fhostcmd_main (int argc, char ** argv); int ffindcmd_main (int argc, char ** argv); int fstatcmd_main (int argc, char ** argv); int fmvcmd_main (int argc, char ** argv); +int fbye_main (int argc, char ** argv); diff --git a/configure.ac b/configure.ac index 782c362..83ba389 100644 --- a/configure.ac +++ b/configure.ac @@ -1,10 +1,12 @@ dnl Process this file with autoconf to produce a working configure script. dnl tested with autoconf 2.57 -AC_INIT(fsp,2.8.1b22,hsn@netmag.cz) +AC_INIT(fsp,2.8.1b23,hsn@netmag.cz) AC_CONFIG_SRCDIR(server/main.c) AM_INIT_AUTOMAKE([dist-bzip2]) AM_MAINTAINER_MODE AC_CONFIG_HEADERS(include/config.h) +AC_ARG_WITH(lockprefix,AS_HELP_STRING([--with-lockprefix=path],[Set lock prefix path to (default /tmp/.FSPL)])) +AC_ARG_WITH([locking],AS_HELP_STRING([--with-locking=none/semop/shmget/lockf/flock],[Set client locking type (default autodetected)])) AC_CANONICAL_HOST AC_MSG_CHECKING([if bulding for DYNIX/ptx]) dnl check for dynix/ptx @@ -71,7 +73,7 @@ then -Wmissing-noreturn -pedantic \ -Wlong-long -Wundef -Winline \ -Wno-unused-parameter \ - -Wunreachable-code -Wconversion + -Wconversion# -Wunreachable-code do if $CC $i $ac_cv_prog_gcc_flags -c configure-dummy.c >/dev/null 2>&1 then ac_cv_prog_gcc_flags="$ac_cv_prog_gcc_flags $i" @@ -122,13 +124,13 @@ AC_CHECK_TYPE(nlink_t, ,AC_DEFINE(nlink_t, int,[declare nlink_t as int if not fo AC_CHECK_TYPE(rlim_t, ,AC_DEFINE(rlim_t, [unsigned int],[declare rlim_t as unsigned int if not found in ]),[#include ]) AC_TYPE_SIGNAL AC_FUNC_CLOSEDIR_VOID -AC_CHECK_FUNCS(random strdup bcopy flock lockf getrlimit fork setsid semop) +AC_CHECK_FUNCS(random srandomdev strdup bcopy flock lockf getrlimit fork setsid semop) AC_CHECK_TYPE(union semun, ,AC_DEFINE(_SEM_SEMUN_UNDEFINED,1,[Define if you do not have semun in sys/sem.h]), [#include #include #include ]) -AC_CACHE_CHECK(for working shmget ,fsp_cv_func_shmget, +AC_CACHE_CHECK(for working shmget ,ac_cv_func_shmget, [LOCKPATH="conftestlock" AC_TRY_RUN([ #include @@ -153,10 +155,10 @@ main() { else shmctl(sh, IPC_RMID, &foo); } close(fd); - exit(rv); }],fsp_cv_func_shmget="yes",fsp_cv_func_shmget="no") + exit(rv); }],ac_cv_func_shmget="yes",ac_cv_func_shmget="no") rm -f $LOCKPATH conftest.c ]) -if test "x$fsp_cv_func_shmget" = "xyes"; then +if test "x$ac_cv_func_shmget" = "xyes"; then AC_DEFINE(HAVE_SHMEM,1,[Define the following if you have working shared memory]) fi AC_CHECK_MEMBER(struct dirent.d_ino,AC_DEFINE(HAVE_D_INO,1,[define if you have d_ino in struct dirent]), AC_CHECK_MEMBER(struct direct.d_ino,AC_DEFINE(HAVE_D_INO,1,[do you have d_ino in struct direct]), ,[ @@ -216,5 +218,34 @@ main() { fsp_cv_sys_reliable_signals="yes",fsp_cv_sys_reliable_signals="no")]) if test "x$fsp_cv_sys_reliable_signals" = "xyes"; then AC_DEFINE(RELIABLE_SIGNALS,1,[undefine If your signal handlers don't reinstall automatically]) fi + +#Parse user locking choice +if test "x$with_locking" = "xno" -o "x$with_locking" = "xnone" ; then +AC_DEFINE(FSP_NOLOCKING,1,[Define if you do not want to use any locking]) +AC_MSG_NOTICE(locking disabled by user) +elif test "x$with_locking" = "xlockf" -a "x$ac_cv_func_lockf" = "xyes"; then + AC_DEFINE(FSP_USE_LOCKF,1,[Define for lockf style locking]) +elif test "x$with_locking" = "xsemop" -a "x$ac_cv_func_semop" = "xyes" -a "x$ac_cv_func_shmget" = "xyes";then + AC_DEFINE(FSP_USE_SHAREMEM_AND_SEMOP,1,[Define for sharemem+semop locking]) +elif test "x$with_locking" = "xshmget" -a "x$ac_cv_func_shmget" = "xyes" -a "x$ac_cv_func_lockf" = "xyes"; then + AC_DEFINE(FSP_USE_SHAREMEM_AND_LOCKF,1,[Define for lockf locking]) +elif test "x$with_locking" = "xflock" -a "x$ac_cv_func_flock" = "xyes"; then + AC_DEFINE(FSP_USE_FLOCK,1,[Define for flock style locks]) +#Autodetect locking +elif test "x$ac_cv_func_semop" = "xyes" -a "x$ac_cv_func_shmget" = "xyes"; then + AC_DEFINE(FSP_USE_SHAREMEM_AND_SEMOP,1) +elif test "x$ac_cv_func_shmget" = "xyes" -a "x$ac_cv_func_lockf" = "xyes"; then + AC_DEFINE(FSP_USE_SHAREMEM_AND_LOCKF,1) +elif test "x$ac_cv_func_lockf" = "xyes"; then AC_DEFINE(FSP_USE_LOCKF,1) +elif "x$ac_cv_func_flock" = "xyes"; then AC_DEFINE(FSP_USE_FLOCK,1) +else +AC_DEFINE(FSP_NOLOCKING,1) +AC_MSG_NOTICE([no suitable locking method detected]) +fi + +#locking prefix +if test "x$with_lockprefix" != "xno" -a "x$with_lockprefix" != "xyes" -a "x$with_lockprefix" != "x" ; then + AC_DEFINE_UNQUOTED(FSP_KEY_PREFIX,"$with_lockprefix",[Key locking prefix]) +fi AC_CONFIG_FILES(Makefile bsd_src/Makefile common/Makefile client/Makefile server/Makefile clients/Makefile man/Makefile include/Makefile contrib/Makefile doc/Makefile tests/Makefile) AC_OUTPUT diff --git a/doc/HISTORY b/doc/HISTORY index 357824b..ceda1ab 100644 --- a/doc/HISTORY +++ b/doc/HISTORY @@ -410,7 +410,7 @@ Version 2.6 -- July 6, 1992 5) fver now will take an optional argument. If none is supplied, it prints the version string of the server. - If one is supplied, it prints the versioin string of + If one is supplied, it prints the version string of the client FSP software. Version 2.5 -- April 8, 1992 diff --git a/doc/PROTOCOL b/doc/PROTOCOL index 75f1bab..a94a516 100644 --- a/doc/PROTOCOL +++ b/doc/PROTOCOL @@ -2,8 +2,8 @@ OFFICIAL PROTOCOL DEFINITION FSP v2 - Document version 0.16 - Last updated 15 Dec 2004 + Document version 0.17 + Last updated 25 Dec 2004 Also known as File Slurping Protocol, @@ -143,6 +143,12 @@ Client's message to server contain a KEY value that is the same as the KEY value of the previous message received from the server. KEY is chosen random by server. +Server uses one KEY per client network address. If multiple fsp clients +on the same host wants access same fsp server at the same time, they +must implement some local method of key exchange. If they don't server +will serve only one client from host, because other clients do not +have valid key. + TIMEOUTS 1. Resend @@ -224,6 +230,12 @@ CC_VERSION is recommended. Bit 5 - accept xtra data flag is set only by fspd 2.8.1 b21 or newer. + Note + + Some fsp servers do not responds to this command, + because this command is used by FSP scanners and + servers do not wishes to be detected. + CC_ERR 0x40 - error response from server If you want to get a error from server, send diff --git a/fspd.conf b/fspd.conf index 666d51c..ab7f0eb 100644 --- a/fspd.conf +++ b/fspd.conf @@ -22,9 +22,18 @@ port 21 # The 'packetsize' sets maximal data size which will send FSPD in one packet. # FSP definition allows up to 1024 bytes of data (default value) and it is a # recommended to use this value unless there is a reason to use a smaller one. -# If your fsp site eats too much bandwidth try smaller value. -# !!! If you change this value you must delete all prebuilded directory -# listings == .FSP_CONTENT files !!! +# If your fsp site eats too much bandwidth try smaller value. +# +# You could try larger values. Almost all networks today works with 1300 +# and most with 1400. Larger values are possible, but FSP packet will be +# split into 2 or more IP packets which lowers reliability of file +# transfers. +# +# Packets > 1024 bytes are never send out unless client requests them. +# +# !!! If you change this value in 64-1024 range you must delete all +# prebuilded directory listings stored in .FSP_CONTENT files !!! + # packetsize 768 # The 'conf' command allows a global file to read local files so that diff --git a/include/c_extern.h b/include/c_extern.h index b1a012c..1f90c05 100644 --- a/include/c_extern.h +++ b/include/c_extern.h @@ -9,6 +9,7 @@ UBUF *client_interact (unsigned char, unsigned long, unsigned int, unsigned const char *); void init_client (const char *, unsigned short, unsigned short); int client_done (void); +void client_finish(void); /* lock.c */ extern int key_persists; @@ -21,6 +22,7 @@ void client_init_key (unsigned long, unsigned long, /* util.c */ extern const char *env_dir,*env_passwd,*env_local_dir,*env_port,*env_myport,*env_host,*env_listen_on; extern unsigned int env_timeout; +extern int statworks; extern unsigned short client_buf_len,client_net_len; char *util_abs_path (const char *); void util_junk_password(char *path); diff --git a/include/client_conf.h b/include/client_conf.h index 5842d69..73906c4 100644 --- a/include/client_conf.h +++ b/include/client_conf.h @@ -26,33 +26,19 @@ ****************************************************************************/ #define HOST_LOOKUP 1 -/**************************************************************************** - * The following code tries to set the file locking mechanism to the one * - * best suited for your system. This should only be changed if the auto * - * configuration code fails and it doesn't compile. That sort of bug * - * should also be immediately reported to the maintainers listed in the * - * INFO file * - ****************************************************************************/ -#define KEY_PREFIX "/tmp/.FSPL" +/* Key lock prefix, works best on local filesystem */ +#ifndef FSP_KEY_PREFIX +# define FSP_KEY_PREFIX "/tmp/.FSPL" +#endif -/* find the best locking method, defines one of USE_SHAREMEM_AND_LOCKF, - * USE_FLOCK,USE_LOCKF,NOLOCKING */ -#if defined(HAVE_SHMEM) && defined(HAVE_SEMOP) - #define USE_SHAREMEM_AND_SEMOP 1 -#else - #if defined(HAVE_SHMEM) && defined(HAVE_LOCKF) - #define USE_SHAREMEM_AND_LOCKF 1 - #else - #ifdef HAVE_LOCKF - #define USE_LOCKF 1 - #else - #ifdef HAVE_FLOCK - #define USE_FLOCK 1 - #else - #define NOLOCKING 1 - #endif - #endif - #endif -#endif /* locking story */ +/* check if we have at least one lock type configured */ +#ifdef FSP_USE_SHAREMEM_AND_SEMOP +#elif defined(FSP_NOLOCKING) +#elif defined(FSP_USE_LOCKF) +#elif defined(FSP_USE_FLOCK) +#elif defined(FSP_USE_SHAREMEM_AND_LOCKF) +#else +# error "Locking type is not configured" +#endif #endif /* _FSP_CLIENT_CONF_H_ */ diff --git a/include/common_def.h b/include/common_def.h index c18ac5e..45a59b2 100644 --- a/include/common_def.h +++ b/include/common_def.h @@ -81,7 +81,10 @@ ****************************************************************************/ #define UBUF_HSIZE 12 /* 12 bytes for the header */ -#define UBUF_SPACE 1024 /* maximum payload. */ +#define UBUF_SPACE 1024 /* maximum standard payload. */ +#define UBUF_MAXSPACE 2800 /* maximum payload supported by server */ + +#define NBSIZE (UBUF_MAXSPACE+UBUF_SPACE) typedef struct UBUF { unsigned char cmd; /* message code. */ unsigned char sum; /* message checksum. */ @@ -90,7 +93,7 @@ typedef struct UBUF { unsigned char cmd; /* message code. */ unsigned char bb_len[2]; /* number of bytes in buf 1. */ unsigned char bb_pos[4]; /* location in the file. */ - char buf[UBUF_SPACE]; + char buf[UBUF_MAXSPACE]; } UBUF; /* definition of cmds */ diff --git a/include/s_extern.h b/include/s_extern.h index 359132c..5fad1dc 100644 --- a/include/s_extern.h +++ b/include/s_extern.h @@ -73,8 +73,8 @@ RETSIGTYPE server_interrupt (int signum); RETSIGTYPE server_dump (int signum); int server_loop (int fd,time_t timeout); int server_reply (struct sockaddr_in *, UBUF *, unsigned int, unsigned int); -void send_file (struct sockaddr_in *, UBUF *, FILE *, unsigned int, - char *); +void serve_file (struct sockaddr_in *, UBUF *, FILE *, unsigned int, + unsigned char *); /* acl.c, security code */ void load_access_rights (DIRINFO *di); diff --git a/include/server_def.h b/include/server_def.h index b2b91a6..f1cf1fd 100644 --- a/include/server_def.h +++ b/include/server_def.h @@ -13,7 +13,6 @@ #include "common_def.h" #include "server_conf.h" -#define NBSIZE (2*sizeof(UBUF)) /**************************************************************************** * HTAB is structure for storing client information for one client machine. diff --git a/man/Makefile.am b/man/Makefile.am index 4037448..e583673 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -3,6 +3,6 @@ man_MANS= fcat.1 fcatcmd.1 fcd.1 fcdcmd.1 fdu.1 fducmd.1 ffind.1 ffindcmd.1 \ fget.1 fgetcmd.1 fgrab.1 fgrabcmd.1 fhost.1 fhostcmd.1 fls.1 \ flscmd.1 fmkdir.1 fpro.1 fprocmd.1 fput.1 frm.1 frmcmd.1 frmdir.1 \ frmdircmd.1 fsp_prof.5 fspd.1 fver.1 fstatcmd.1 fspscan.1 \ - fsp_env.7 + fsp_env.7 fbye.1 EXTRA_DIST=$(man_MANS) diff --git a/man/fsp_env.7 b/man/fsp_env.7 index 6716c68..b771674 100644 --- a/man/fsp_env.7 +++ b/man/fsp_env.7 @@ -33,7 +33,9 @@ provided a correct password. There are 2 access levels: public and owner. .TP .B FSP_BUF_SIZE Prefered size of server reply. Default is 1024 which is also maximum -allowed value. You can lower that value if you want to get smaller +allowed value by all servers. Some servers can accept larger packets and +you will get some extra speed with them. +You can lower that value if you want to get smaller packets from server. .TP .B FSP_DIR diff --git a/man/fspd.1 b/man/fspd.1 index 573d65d..32d28c8 100644 --- a/man/fspd.1 +++ b/man/fspd.1 @@ -2,7 +2,7 @@ .SH NAME fspd, in.fspd \- File Service Protocol (FSP) server .SH SYNOPSIS -.B fspd [-f configfile] [-p port] [-i] [-v|-V] [-t timeout] [-X] [-d directory] [-F ] [-T temporary directory] [-l logfile] [-P pidlogname] [-b bandwidth] +.B fspd [-f configfile] [-p port] [-i] [-v|-V] [-t timeout] [-X] [-d directory] [-F ] [-T temporary directory] [-l logfile] [-P pidlogname] [-b bandwidth] [-s packetsize] .SH DESCRIPTION .B fspd is the server for an anonymous-ftp style archive called FSP. The main @@ -78,6 +78,13 @@ Enable bandwidth limiting. Limit output to .I bandwidth bytes per second. +.PD 0 +.TP 20 +.B -s packetsize +Sets maximum allowed packet size or prefered packet size. Server must +support packets up to 1024, but may prefer to send smaller packets. +It may accept packets over 1024 bytes. Default value is 1024 bytes. + .LP .SH FILES .PD 0 diff --git a/server/conf.c b/server/conf.c index e43e107..d5bfddf 100644 --- a/server/conf.c +++ b/server/conf.c @@ -186,7 +186,14 @@ static void read_configuration (const char * name) } else if(strcasecmp(p, "packetsize") == 0) { packetsize = atoi(q); - if(packetsize <= 64 || packetsize > UBUF_SPACE ) packetsize = UBUF_SPACE; + if(packetsize == 0) + packetsize = UBUF_SPACE; + else + if(packetsize < 64 ) + packetsize = 64; + else + if(packetsize > UBUF_MAXSPACE ) + packetsize = UBUF_MAXSPACE; } else if(strcasecmp(p, "filecache") == 0) { fp_cache_limit = atoi(q); diff --git a/server/file.c b/server/file.c index d441a0f..a12941b 100644 --- a/server/file.c +++ b/server/file.c @@ -409,10 +409,11 @@ static void build_dir_listing (DIRLISTING * dl,const char *directory) struct stat sb; /* stat data of record */ register char *s; /* pointer to filename */ size_t nlen; /* filename length including zero terminator */ - char buffer[UBUF_SPACE]; /* buffer for building packet */ + char buffer[UBUF_SPACE]; /* buffer for building dirblock packet */ char name[NBSIZE]; /* buffer for stat name */ int namelen; /* directory name length */ unsigned int bufpos; /* current write pos. in buffer */ + unsigned int dirblocksize; /* init pointers */ dl->listing=NULL; @@ -423,13 +424,17 @@ static void build_dir_listing (DIRLISTING * dl,const char *directory) fprintf(stderr,"Can't open dir during listing initialization\n"); return; } - - memset(buffer,0,packetsize); /* clear memory on the stack */ + /* do not build longer directory blocks than 1024 bytes */ + if(packetsize > UBUF_SPACE) + dirblocksize=UBUF_SPACE; + else + dirblocksize = packetsize; + memset(buffer,0,dirblocksize); /* clear memory on the stack */ strcpy(name,directory); namelen=strlen(directory); name[namelen++]='/'; /* add directory separator to name */ - for(rem = packetsize; (dp = readdir(dir_f)); ) { + for(rem = dirblocksize; (dp = readdir(dir_f)); ) { if (dp->d_ino == 0) continue; s = dp->d_name; @@ -448,12 +453,12 @@ static void build_dir_listing (DIRLISTING * dl,const char *directory) /* fill rest of buffer with '*' */ memset(buffer+bufpos,RDTYPE_SKIP,rem); /* append this buffer */ - if(append_dir_listing(dl,buffer,packetsize)) + if(append_dir_listing(dl,buffer,dirblocksize)) { closedir(dir_f); return; } - rem = packetsize; + rem = dirblocksize; bufpos = 0; } @@ -481,7 +486,7 @@ static void build_dir_listing (DIRLISTING * dl,const char *directory) /* no, make a new packet */ memset(buffer+bufpos,RDTYPE_SKIP,rem); /* append this buffer */ - if(append_dir_listing(dl,buffer,packetsize)) + if(append_dir_listing(dl,buffer,dirblocksize)) return; bufpos = 0; diff --git a/server/main.c b/server/main.c index d996dbc..1918db9 100644 --- a/server/main.c +++ b/server/main.c @@ -43,9 +43,9 @@ static void display_version (void) static void arg_err (void) { #ifndef LAMERPACK - fputs("Usage: fspd [-f configfile] [-d directory] [-v|-V] [-i] [-F] [-p port] [-X] [-t timeout] [-T temporary directory] [-l logfile] [-P pidlogname] [-b bytes/sec]\n", stderr); + fputs("Usage: fspd [-f configfile] [-d directory] [-v|-V] [-i] [-F] [-p port] [-X] [-t inetd timeout] [-T temporary directory] [-l logfile] [-P pidlogname] [-b bytes/sec] [-s packetsize]\n", stderr); #else - fputs("Usage: fspd [-d directory] [-p port] [-T temporary directory] [-l logfile] [-b bytes/sec]\n", stderr); + fputs("Usage: fspd [-d directory] [-p port] [-T temporary directory] [-l logfile] [-b bytes/sec] [-s packetsize]\n", stderr); #endif } @@ -74,6 +74,15 @@ static void check_required_vars (void) rnd=(random())/(double)RAND_MAX; udp_port=rnd*(65535-1024)+1024; } + if(packetsize > UBUF_MAXSPACE) + packetsize = UBUF_MAXSPACE; + else + if (packetsize == 0) + packetsize = UBUF_SPACE; + else + if(packetsize < 64) + packetsize = 64; + if(!home_dir) { #ifdef LAMERPACK home_dir = strdup("/"); @@ -139,9 +148,9 @@ int main (int argc, char ** argv) inetd_mode = !strcasecmp(&argv[0][strlen(argv[0])-7],"in.fspd"); while( (opt=getopt(argc,argv, #ifndef LAMERPACK - "h?Xd:f:vVip:t:FT:l:P:b:" + "h?Xd:f:vVip:t:FT:l:P:b:s:" #else - "d:p:T:l:b:h?" + "d:p:T:l:b:h?s:" #endif ))!=EOF) { @@ -178,6 +187,9 @@ int main (int argc, char ** argv) case 'p': udp_port = atoi (optarg); break; + case 's': + packetsize = atoi (optarg); + break; case 'b': maxthcallowed = atoi (optarg); break; @@ -215,10 +227,12 @@ int main (int argc, char ** argv) if(dbug) { display_version(); fprintf(stderr,"listening on port %d\n",udp_port); + fprintf(stderr,"FSP payload size %d bytes\n",packetsize); } #ifdef LAMERPACK display_version(); fprintf(stderr,"rocking on port %d\n",udp_port); + fprintf(stderr,"FSP payload size %d bytes\n",packetsize); #endif } diff --git a/server/server.c b/server/server.c index 19b73eb..419b54a 100644 --- a/server/server.c +++ b/server/server.c @@ -376,8 +376,8 @@ return(0); * message buffer. ****************************************************************************/ -void send_file (struct sockaddr_in * from, UBUF * ub, FILE * fp, - unsigned int has_len, char * lp) +void serve_file (struct sockaddr_in * from, UBUF * ub, FILE * fp, + unsigned int has_len, unsigned char * lp) { size_t bytes; unsigned len; @@ -386,7 +386,11 @@ void send_file (struct sockaddr_in * from, UBUF * ub, FILE * fp, if(has_len == 2) { /* recover length field if it exists */ len=lp[0] << 8; len = len + lp[1]; - if(len > packetsize || len <= 0) len = packetsize; + if(len > packetsize ) + len = packetsize; + else + if(len <= 0) + len = UBUF_SPACE; } else len = packetsize; /* use default if it doesn't exist */ pos = BB_READ4(ub->bb_pos); @@ -541,16 +545,22 @@ static void server_process_packet (unsigned bytes, UBUF * ub, int old, return; } /* copy directory listing to client buffer */ - if(pos>=dl->listing_size) l1=0; + if(pos>=dl->listing_size) + l1=0; else { + /* limit directory blocks to 1k max */ + if(packetsize>UBUF_SPACE) + l2=UBUF_SPACE; + else + l2=packetsize; l1=dl->listing_size-pos; - if(l1>packetsize) l1=packetsize; + if(l1>l2) l1=l2; memcpy( ub->buf, dl->listing+pos, l1); } - if( (l1>0) && (pos % packetsize != 0) ) + if( (l1>0) && (pos % l2 != 0) ) { - send_error(from,ub,"Invalid seek offset"); + send_error(from,ub,"Invalid directory seek offset"); } else { @@ -582,7 +592,7 @@ static void server_process_packet (unsigned bytes, UBUF * ub, int old, ACTIONINFO(L_GETFILE,(" (%d)",sd.st_size)); xferlog('o',pp.fullp,sd.st_size,inetstr); } - send_file(from,ub,fp,l2,s2); + serve_file(from,ub,fp,l2,s2); if (!pos) ACTIONOK(L_GETFILE); return; case CC_DEL_FILE: @@ -827,7 +837,7 @@ static void server_process_packet (unsigned bytes, UBUF * ub, int old, send_error(from, ub, pe) ; return; } - send_file(from,ub,fp,l2,s2); + serve_file(from,ub,fp,l2,s2); fclose(fp); if (!pos) ACTIONOK(L_GRABFILE); return;