From 8390634da0b93d329a2bb0eb8777a5f0ec301d48 Mon Sep 17 00:00:00 2001 From: hsn <> Date: Sat, 23 Oct 2004 13:52:12 +0000 Subject: [PATCH] autogen added --- BETA.README | 34 ++-- COPYRIGHT | 2 +- ChangeLog | 450 +++++++++++++++++++++++------------------- INFO | 78 +++++--- MACHINES | 5 +- TODO | 26 ++- autogen.sh | 32 +++ bsd_src/find.c | 2 +- bsd_src/function.c | 66 +++---- bsd_src/glob.c | 2 +- bsd_src/ls.c | 22 +-- bsd_src/operator.c | 36 ++-- bsd_src/option.c | 8 +- bsd_src/print.c | 40 ++-- bsd_src/util.c | 4 +- client/lib.c | 114 +++++++---- client/lock.c | 58 ++++-- client/util.c | 222 +++++++++++---------- clients/fcatcmd.c | 10 +- clients/fcdcmd.c | 6 +- clients/fducmd.c | 16 +- clients/ffindcmd.c | 18 +- clients/fgetcmd.c | 56 +++--- clients/fhostcmd.c | 24 +-- clients/flscmd.c | 6 +- clients/fmkdir.c | 12 +- clients/fprocmd.c | 20 +- clients/fput.c | 14 +- clients/frmcmd.c | 14 +- clients/frmdircmd.c | 14 +- clients/fspprof.l | 8 +- clients/fstatcmd.c | 24 +-- clients/fver.c | 9 +- clients/merge.c | 2 +- clients/printpro.c | 6 +- common/random.c | 24 +-- common/udp_io.c | 34 ++-- configure.ac | 2 +- contrib/fspscan.c | 34 ++-- contrib/fspscan.h | 4 +- doc/PROTOCOL | 159 ++++++++++----- fspd.conf | 22 ++- include/c_extern.h | 13 +- include/client_def.h | 2 +- include/common_def.h | 8 +- include/proto.h | 2 +- include/server_conf.h | 6 +- include/server_def.h | 6 +- include/tweak.h | 2 +- man/Makefile.am | 5 +- man/fsp_env.7 | 6 +- man/fspd.1 | 20 +- man/fver.1 | 4 +- server/Makefile.am | 2 +- server/acl.c | 22 +-- server/conf.c | 15 +- server/fifocache.c | 30 +-- server/file.c | 217 +++++++++++--------- server/filecache.c | 2 +- server/host.c | 22 +-- server/iprange.c | 62 +++--- server/log.c | 2 +- server/main.c | 64 +++--- server/path.c | 28 +-- server/pidfile.c | 15 +- server/pidfile.h | 4 +- server/random.c | 16 +- server/server.c | 85 ++++---- tests/cachecheck.c | 2 +- tests/mklargefile.c | 6 +- tests/parsecheck.c | 8 +- tests/randomcheck.c | 12 +- 72 files changed, 1388 insertions(+), 1039 deletions(-) create mode 100755 autogen.sh diff --git a/BETA.README b/BETA.README index 808d13e..5db5adf 100644 --- a/BETA.README +++ b/BETA.README @@ -2,16 +2,28 @@ This is a BETA release, as such it's not guaranteed to work perfectly any problems let me know, they'll be sorted out in the next Beta release. At the point at which people stop complaining the non-beta release will be let out. -You can get beta version from CVS on sf.net there are tagged fsp-281-bXX. +You can get beta versions from CVS on sf.net there are tagged fsp-281-bXX. +checkouting HEAD it always best. FSP Development Battle plan: ============================ -* for next 2.8 Stable version (will be called 2.8.2) + +2.8.2 - Next Stable version after 10 years or so +- get out this version as soon as possible. 2.8.1b3 and lower are buggy. - add FSP Rename command - add FSP Info command -- go out this version as soon as possible. 2.8.1b3 and lower are buggy. +- resolve symlink support problem. This maybe breaks compatibility + with older software versions. +- security: symlink to FILE can escape from FSP root directory. +- fix Sven's Slowaris 8 compile problem +- local bind address FSP_LOCALIP for clients +- bind-ip-address for server +- normalize return error codes of all clients +- server can be run multiple times on the same port, how to check? + on freebsd this works okay. needs re-testing on linux. +- fspd: add special defence against rapid/double fire clients (burst command in fspclient) + * for next point Stable version 2.8.3 -- add native symbolic link support - add FSP change password command - add FSP command for changing owners - add FSP command for listing directory owners @@ -33,17 +45,9 @@ release and ultimately into the final release. ----------------------------------------------------------------------------- -This version is fully backwards compatible with 2.7.1 and 2.8.1 both from the -client and the server viewpoints. Bar one thing, the reversed IP problem with -restricted host lists has now been fixed, so if you've deliberately reversed -the IP numbers in that list to get around the bug you should now put them back -in the correct order again. - -Another point worth noting is that the next release will go to ANSI-C. If you -have a problem with this then now is the time to let me know. I don't forsee -any portability problems since I would expect that ANSI-C compliant compilers -are available for all platforms by now. This move will aid both maintenance and -any future use of C++ for Application Programming Interfaces. +This version is not quite fully backwards compatible with 2.7.1 and 2.8.1 from +the client and the server viewpoints. See file PROTOCOL for minor changes +in wire-protocol. If you successfully build this distribution on a machine/OS/compiler combination which isn't listed in the MACHINES file then please drop me a line diff --git a/COPYRIGHT b/COPYRIGHT index 22c3cb4..0895735 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -1,5 +1,5 @@ Authors: - Radim Kolar (Current FSP maintainer) + Radim Kolar (Current FSP maintainer) Andrew Doherty Michael Fischbein Cimarron D. Taylor diff --git a/ChangeLog b/ChangeLog index 9aa99c0..fe71d4e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,49 +1,91 @@ Version - not yet released Added pidfile.[c|h] from FreeBSD and modified it to fit in (hoaxter) - Added pidfile support, config option is 'pidlogname', the option - is required to start fspd, hope that's ok for most people (hoaxter) - Replaced . file information from INSTALL with a hint to man 1 fspd (hoaxter) - + Added pidfile support, config option is 'pidlogname' (hoaxter) + Replaced .file information from INSTALL with a hint to man 1 fspd (hoaxter) + PROTOCOL: Added security section, fixed method of computing of checksums fspd: unlink filecache.c from build + conf: commented dangerours settings for win32 platform which can + cause data loss when fspd.conf is reused on win32 without editing. + Defaults are detected at build time. + fspd: allow to run without pidfile set. + added autogen.sh for regenerating of autoconf on FreeBSD which needs + to set some env. variables unless --enable-maintainer-mode do + not works. + do not free pidfile name on failure + changelog reformated: each entry begins with tab/not spaces. + continuation line has 2 chars leading space + removed trailing spaces from all sources and headers + tests: run random test 2000 times by default + random generator switched to simple2. Better results on both + freebsd and linux systems. + added maximum supported packet size to output of CC_VER command + fspd: -b command line switch for bandwidth limiting + PROTOCOL: Added compatibility section to some commands + Default timeout increased from 180 to 360 seconds. + clients: apply delay timeout also when starting transfer + clients: added env. variable FSP_MAXDELAY for fine-tuning resends + DEFAULT_MAXDELAY added to source code + FSP_TIMEOUT is total number of seconds, not retry count. + clients: try to resend packet on less fatal error (network down or so) + remove clients lock files after sending BYE. code merged from fspclient. + threre is an race condition: After client unlinks lock file and other + clients still runs new client will create new lock file which will + not share secret key with other clients. New client can't communicate + with server until other clients terminates. + man: we did not install fsp_env.7 manpage + allow home directory not starting with / + allow uploads only on file border + up/down speed is in B/s, not b/s. + client tracing improved: + H - not enough bytes for header + C - wrong checksum + S - wrong seq. number + T - truncated + R - First resend + I - Idle resend + client: use random starting seq. number - better for avoiding + seq. number clash with another client + fixed compiler warning on BB_READ4(const char *); + Version 2.8.1b19 - 11 Jan 2004 sven has added fspget URL command to setup.sh. fixed case for mklargefile.py in tests/Makefile.am added --enable-debug switch to configure for enabling extra - debuging code in client library + debuging code in client library fsp/fifocache.c changed malloc.h to stdlib.h -> allow compile on - freebsd + freebsd do not use ${RM} in clients/Makefile.am -> allow compile with bsd make Version 2.8.1b18 - 25 Nov 24 2003 - This is MINIMUM REQUIRED VERSION for applications which are using - javafsp library, only download machine atm. Javafsp library will - be released shortly as separate package. - PROTOCOL updated. Made rules about breaking directory header on - packet boundary more clear. Previous text was from fspd code comment - and was bad. + This is MINIMUM REQUIRED VERSION for applications which are using + javafsp library, only download machine atm. Javafsp library will + be released shortly as separate package. + PROTOCOL updated. Made rules about breaking directory header on + packet boundary more clear. Previous text was from fspd code comment + and was bad. fixed tests/mklargefile.py log uploads to wuftpd logfile also PROTOCOL file updated. Added required commands section. PROTOCOL file updated. Added recommended delay management section. default delay in clients adjusted from 1.5 to 1.34 sec as recommended - in PROTOCOL + in PROTOCOL support for MIN_DELAY, MAX_DELAY and DEFAULT_DELAY in source path parsing moved to separate file server/path.c new test tool parsecheck for testing server path parser reworked parse path: separate error messages for high bit chars, - control chars + control chars MAJOR BUGFIX: path with trailing / or starting / is now parsed correctly pathes with dot after slash are now detected at parse level (side - effect of prev. fix, fixed security prob) + effect of prev. fix, fixed security prob) tests moved from server/ into tests/ directory removed special test case for root directory in path.c -> use more - general alg. instead. This fixed "/" dir. + general alg. instead. This fixed "/" dir. parsecheck turned into test suite with hard coded test results parsecheck added to 'make check' support for multiple \n in filename - in future there will be - used for symlinks. + used for symlinks. random generator changed to one recommended by Jiann-Ming Su. new test program tests/randomcheck.c - tests random number generators. - + Version 2.8.1b17 -- 17 Nov 2003 Allow filenames with spaces inside check for fork() and setsid() in configure.ac @@ -63,31 +105,31 @@ Version 2.8.1b16 -- 8 Nov 2003 fixed memory leak in client/util.c:get_dir_blk fixed memory leak in client/util.c:open_dir fixed error from 2.8.1b15 in util_stat which brokes recursive - directory listings + directory listings do not delete partial file on FSP timeout in fgetcmd Version 2.8.1b15 -- 15 Oct 2003 - Sven writes manpage for fspscan.1 + Sven writes manpage for fspscan.1 junked concept of private directory, now directory has flag - +g - public can get files + +g - public can get files dir_priv -> dir_get fprocmd flags changed +p -> -g (incompatible change in protocol) fgetprocmd works in private directories. There are no more - private. + private. .FSP_PRIVATE -> .FSP_NO_GET for avoiding user confusion because - i have axed marking directories as private in beta6 + i have axed marking directories as private in beta6 fixed off-by-one error in getpro cmd fsetpro cmd shows command syntax on error fspd: do not save readme files to disk (avoids truncation them - to 1k) + to 1k) fspd: fixed reply for makedir command (size of reply block was - not included) - fspd: getdirlisting checks for seek offsets (do not allow send partial - packets of dir listings) - Done item from my 1997 fsp wishlist: check 4 rights before + not included) + fspd: getdirlisting checks for seek offsets (do not allow send partial + packets of dir listings) + Done item from my 1997 fsp wishlist: check 4 rights before uploading! fver command can be disabled on server -- protection against FSP - detectors. + detectors. fspscan: end port -e switch configure.ac add check for compiler warning options removed multiple definition of process from bsd_src/find.c and @@ -104,7 +146,7 @@ Version 2.8.1b15 -- 15 Oct 2003 fsp_prof: made `fsp` in `fsp port` optional fsp_prof: made `fsp` in `fsp directory' optional fhostcmd has now parser written in flex, should be less brain - damaged and more stable + damaged and more stable fhostcmd: searching can now match full hostname or alias, not a subpart of hostname or alias. fhostcmd: added -? switch @@ -116,33 +158,33 @@ Version 2.8.1b15 -- 15 Oct 2003 do not use echo -e when building fspmerge client updated manpages for fhostcmd.1 and fsp_prof.5 fspd: really reuse cached directory listings. Forgot to update - mtime after loading and they were loaded for every dirlisting - packet. - client library: do not use CC_STAT when building a directory listing. - fix in beta14 do not fixed the problem when working in non root - directory. + mtime after loading and they were loaded for every dirlisting + packet. + client library: do not use CC_STAT when building a directory listing. + fix in beta14 do not fixed the problem when working in non root + directory. Version 2.8.1b14 -- 22 Sep 2003 - Sven fixed bash shell script + Sven fixed bash shell script fspd: list files over 4GB as 4GB in directory listings fspd: do not allow seeking over 2GB when OS is not LFS friendly fspd: print command names instead of numbers in debug mode added new program fspscan.c to package. Well known fsp port scanner - made in 1992. Paranoid people calls this program fsp exploit. + made in 1992. Paranoid people calls this program fsp exploit. added new SGML FSP FAQ made by Sven fspd: debug messages are printed to stderr PROTOCOL: added talking about timeouts fcatcmd: removed debug messages - !!dirlist cache hit ratio is bad - something overwrites that!! - !!only happens when compiled without EFENCE?? - fixed by fifocache malloc -> calloc + !!dirlist cache hit ratio is bad - something overwrites that!! + !!only happens when compiled without EFENCE?? + fixed by fifocache malloc -> calloc fspd: return 'is a directory' when trying to download directory - client library: do not use CC_STAT when building a directory listing - PLEASE!!! It is S l o w. Fixed: Performance of flscmd -l is now - back to the normal speed. EnJoy! + client library: do not use CC_STAT when building a directory listing + PLEASE!!! It is S l o w. Fixed: Performance of flscmd -l is now + back to the normal speed. EnJoy! fstatcmd: print dates in ISO format, avoid tabs in output fspd: support for long local directory names > 1024 but < 2048 - fixed SECURITY prob: stat can stat any file (even out of FSP root!) + fixed SECURITY prob: stat can stat any file (even out of FSP root!) added support for fstat to both shell scripts fifocache.c support for memory profiler functions fifocache.c supports nice memory stats @@ -150,19 +192,19 @@ Version 2.8.1b14 -- 22 Sep 2003 cache stats are dumped to dumpfile also on SIGUSR1 Version 2.8.1b13 -- 10 Sep 2003 - fver: reports if timestamping is supported + fver: reports if timestamping is supported CC_VER: now reports fspd + version + \n Hanno Hecker help us port shell script from CSH to BASH large file support activated in configure example.conf -> fspd.conf added contrib/mklargefile.c program for creating a large file with - hole + hole fver -l reports max file size supported and LFS mode server detects i/o errors when uploading (out of diskspace) 4GB-1 files should work from server p. of view if LFS is on fspd -F runs in foreground, for broken startup scripts random port for fspd (-p 65535) important for keeping lamers out of - your warez site. + your warez site. changed exit codes for server, for easy debuging manual page for fspd updated - exit codes added PROTOCOL: added support for timestamping on uploads @@ -170,8 +212,8 @@ Version 2.8.1b13 -- 10 Sep 2003 fspd: -T switch for setting temporary directory for uploads fput.c: added support for timestamping uploads fcdcmd supports new permisions also - fput - made timestamping optional -p option - correct stats dumping - now dumpfile is used (really) + fput - made timestamping optional -p option + correct stats dumping - now dumpfile is used (really) inetd mode now works! updated INFO document moved faq, history and protocol to a new doc subdirectory @@ -181,17 +223,17 @@ Version 2.8.1b12 -- 3 Sep 2003 port setting in config file works manual page for fprocmd updated fstatcmd now uses remote wildcard expansion like rest of fsp - merged fgetcmd and fgrabcmd commands + merged fgetcmd and fgrabcmd commands merged patch Geoffrey T. Dairiki. Server records new keyid from client - when serving session timeout. + when serving session timeout. updated Bash version of CSH setup script, but still do not works NEW FEATURE: fget/fgrab can now set file timestamps to remote date - When I have first used FSP in 1996 - I wanted this option. + When I have first used FSP in 1996 - I wanted this option. Cygwin has now different builtin defaults modified man page for fgetcmd - after 10 years! same goes for - fgrabcmd - default mode of fget/grab changed to unique fnames. Should I - change it to noclober + fgrabcmd + default mode of fget/grab changed to unique fnames. Should I + change it to noclober? fget/grab has now -h help Version 2.8.1b11 -- 27 Aug 2003 @@ -200,7 +242,7 @@ Version 2.8.1b11 -- 27 Aug 2003 stat type log switch new command FSP_STAT (not tested) some code cleanup in client/ and common/ directories, warnings - removed. + removed. PROTOCOL definition updated (stat and rename commands added) auto_del.csh script added to server directory (untested) return only file or directory objects in dir listing and stat command. @@ -208,8 +250,8 @@ Version 2.8.1b11 -- 27 Aug 2003 server has -? and -h options new command fstatcmd (no manpage yet) fixed main arg count in merged fsp client - client library now uses a new command FSP_STAT if server supports it - fprocmd without args displays directory name instead of . + client library now uses a new command FSP_STAT if server supports it + fprocmd without args displays directory name instead of . fprocmd now supports 2.8.1bXX extented access rights Version 2.8.1b10 -- 21 Jul 2003 @@ -217,155 +259,155 @@ Version 2.8.1b10 -- 21 Jul 2003 removed -Wconversion from debug gcc switches MAJOR BUGFIX: can CD to more than 1 level deep changes init order in server/main.c so we can see error messages - during server startup - + during server startup + Version 2.8.1b9 -- 19 Jul 2003 - missing tmpdir switches fspd to read-only mode (really!) - daemonize is on by default - added port to default cnf file for fspd - check for -lefence in configure script - check for sys/syslimits.h - needed for cygwin - default port is 21 in conf.c - FIXED BUG when server root != file system root - Now compiles and runs on cygwin - do not use -1 exit code in server/main.c - server now tries to create tmpdirectory on startup - fspd: allow command line overide even when -f is used - + missing tmpdir switches fspd to read-only mode (really!) + daemonize is on by default + added port to default cnf file for fspd + check for -lefence in configure script + check for sys/syslimits.h - needed for cygwin + default port is 21 in conf.c + FIXED BUG when server root != file system root + Now compiles and runs on cygwin + do not use -1 exit code in server/main.c + server now tries to create tmpdirectory on startup + fspd: allow command line overide even when -f is used + Version 2.8.1b8 -- 17 Jul 2003 - new cfg switch: setgid - use /dev/random for seeding a random number generator - new cfg switches: umask and serverumask (octal value). Umask - for creating server files - fixed compilation on GCC < 3.0 - fixed check for maintainer_mode in server/Makefile.am and - clients/Makefile.am - fhostcmd: check for $SHELL if we have csh-like shell - fhostcmd: options -c or -b to force C or Bourne shell syntax - server tables dump signal changed from alarm -> sigusr1 - new cfg switch: dumpname for dumping runtime stats - clean server shutdown on sigint, sigterm - new cfg switch: grabcommand on/off - env. vars removed from individual manual pages and moved to a New - manpage fsp_env 7. - updated PROTOCOL definition of FSP. Fixed some bugs, added method - of packet checksum. - updated example configuration file for server - removed all prints when debug is not on - updated FILES section in fspd manpage + new cfg switch: setgid + use /dev/random for seeding a random number generator + new cfg switches: umask and serverumask (octal value). Umask + for creating server files + fixed compilation on GCC < 3.0 + fixed check for maintainer_mode in server/Makefile.am and + clients/Makefile.am + fhostcmd: check for $SHELL if we have csh-like shell + fhostcmd: options -c or -b to force C or Bourne shell syntax + server tables dump signal changed from alarm -> sigusr1 + new cfg switch: dumpname for dumping runtime stats + clean server shutdown on sigint, sigterm + new cfg switch: grabcommand on/off + env. vars removed from individual manual pages and moved to a New + manpage fsp_env 7. + updated PROTOCOL definition of FSP. Fixed some bugs, added method + of packet checksum. + updated example configuration file for server + removed all prints when debug is not on + updated FILES section in fspd manpage Version 2.8.1b7 -- 13 Jul 2003 - do not sent zero length blocks if client asks for them - filecache.c nuked - new cfg statement tmpdir for placing files during upload - all server code (except host.c) rewriting complete. + do not sent zero length blocks if client asks for them + filecache.c nuked + new cfg statement tmpdir for placing files during upload + all server code (except host.c) rewriting complete. Version 2.8.1b6 -- 2 Jul 2003 - configuration file was not closed after reading (found by valgrind) - link against Eletric Fence only in maintainer mode - compile server/cachecheck only in maintainer mode - removed long files check and support for code. FSP has maximum path - about 1024; it is no need to check if file can be longer than 14 chars - use config.guess for guessing OS type. - simplified configure.ac - up to date BETA.README - MACHINES file lives again - allow files starting with \ in directory listing - directory content is builded correctly on systems with pragma pack > 1 - fixed another bug in generating of directory listing which violates FSP - protocol definiton (but worked in current code anyway) - use extern only in header files - key was not initialised when using shmem locking method - default timeout for clients changed from 4 to 180 sec. - removed option -r from fcatcmd - init socket data in udp io and avoid using sin there (gcc builtin) - server debug option changed from -d to -X - server argument -d directory -> sets root directory - server now runs also without configuration file! - keys generated by server are now 16bit random, not 8bit random - directory_cache nuked - it was uneffective and it has a file - descriptor leak! - new cfg. use_prebuild_dirlists (load/save) content file - new directory memory based cache engine works! - new directory .FSP_CONTENT load/save engine works - clear buffer before generating a directory listing (no information - leak) - fixed buffer overflow (exploitable if file uploads was allowed). - new cfg keyword statcache - size of dirstatcache - new cfg keyword statcache_timeout - (sec) - new cfg keyword use_access_files - boolean - fixed bug when home directory was symlinked to somewhere - removed remote FSP support from PPATH. It was never used in code. - new cfg use_directory_mtime - boolean. For windows set it to NO. - !!! NEW DIRECTORY STATE ENGINE CACHE !!! - new .FSP_PASSWORD access file - new .FSP_OWNER owner file (not yet implemented) - resend of BYE command is also accepted, why not? - no memory leaks in new code. Last leaks are in code which is going - to be rewrited - !!! MAJOR PERFORMANCE SPEEDUP. Need only 1 syscal to serve a - packet (if everything is cached). - do not list special files as directories - added file COPYRIGHT - speedup when loading access files - min delay for clients was increased from 0.5s to 1.5s (packets - was are just thrown out by server for <3sec reply). Performance - tested on our WireLess network. Today only 65% packets loss! - new configuration option homedir_restricted for following symlinks - out of home_directory - if $test in configure changed to x$test - ip range and IP parsing function moved out of host.c to iprange.c - host type must be specified (in config or in owner file) - renamed cfg. bufsize -> packetsize - use packetsize when generatin a directory listing. -> max packet size - management moved from user cfg. to server cfg. - added support for readme files to new dirstat engine - public directory list flag changed from negative to positive - new cfg option permit_passwordless_owners - NEW SECURITY ENGINE implemented - fixed infinite loop in client library if server sends directory - in smaller blocks than expected. - removed buffer overflow in log code (remote exploitable of course) - added new log switch 'readonly' - fixed security hole in grab command - rewrite log in packet processing (more readable) - corrected handling of public rights in private directories - detect if cached directory listings are out of date + configuration file was not closed after reading (found by valgrind) + link against Eletric Fence only in maintainer mode + compile server/cachecheck only in maintainer mode + removed long files check and support for code. FSP has maximum path + about 1024; it is no need to check if file can be longer than 14 chars + use config.guess for guessing OS type. + simplified configure.ac + up to date BETA.README + MACHINES file lives again + allow files starting with \ in directory listing + directory content is builded correctly on systems with pragma pack > 1 + fixed another bug in generating of directory listing which violates FSP + protocol definiton (but worked in current code anyway) + use extern only in header files + key was not initialised when using shmem locking method + default timeout for clients changed from 4 to 180 sec. + removed option -r from fcatcmd + init socket data in udp io and avoid using sin there (gcc builtin) + server debug option changed from -d to -X + server argument -d directory -> sets root directory + server now runs also without configuration file! + keys generated by server are now 16bit random, not 8bit random + directory_cache nuked - it was uneffective and it has a file + descriptor leak! + new cfg. use_prebuild_dirlists (load/save) content file + new directory memory based cache engine works! + new directory .FSP_CONTENT load/save engine works + clear buffer before generating a directory listing (no information + leak) + fixed buffer overflow (exploitable if file uploads was allowed). + new cfg keyword statcache - size of dirstatcache + new cfg keyword statcache_timeout - (sec) + new cfg keyword use_access_files - boolean + fixed bug when home directory was symlinked to somewhere + removed remote FSP support from PPATH. It was never used in code. + new cfg use_directory_mtime - boolean. For windows set it to NO. + !!! NEW DIRECTORY STATE ENGINE CACHE !!! + new .FSP_PASSWORD access file + new .FSP_OWNER owner file (not yet implemented) + resend of BYE command is also accepted, why not? + no memory leaks in new code. Last leaks are in code which is going + to be rewrited + !!! MAJOR PERFORMANCE SPEEDUP. Need only 1 syscal to serve a + packet (if everything is cached). + do not list special files as directories + added file COPYRIGHT + speedup when loading access files + min delay for clients was increased from 0.5s to 1.5s (packets + was are just thrown out by server for <3sec reply). Performance + tested on our WireLess network. Today only 65% packets loss! + new configuration option homedir_restricted for following symlinks + out of home_directory + if $test in configure changed to x$test + ip range and IP parsing function moved out of host.c to iprange.c + host type must be specified (in config or in owner file) + renamed cfg. bufsize -> packetsize + use packetsize when generatin a directory listing. -> max packet size + management moved from user cfg. to server cfg. + added support for readme files to new dirstat engine + public directory list flag changed from negative to positive + new cfg option permit_passwordless_owners + NEW SECURITY ENGINE implemented + fixed infinite loop in client library if server sends directory + in smaller blocks than expected. + removed buffer overflow in log code (remote exploitable of course) + added new log switch 'readonly' + fixed security hole in grab command + rewrite log in packet processing (more readable) + corrected handling of public rights in private directories + detect if cached directory listings are out of date Version 2.8.1b5 -- 25 June 2003 - configure.ac upgaded to autoconf 2.57 and cleaned - added missing include headers to source code - vms code nuked from rest of headers - prefix is now used when finding configuration file - check for max. number of open files and adjust open handle cache - removed long file limit hack for FAT/VMS filesystems. Nonstandard and - unsecure. - removed include/version.h - use autoconf instead - added -V server option (display version) - do not use dircache as upload cache. Uploads now works even without - dircache - turn off cachedir when it do not exists - better init of random number generator. It should be really random. - fixed use of prebuild directory content and dircache - turn of logging if no log file is set - clean cache directory on startup - merged security patch from Debian package fsp_2.81.b3-4, i have - fixed this problem in 2.8.1b4; but Debian code looks better. - removed non standard NEED_ from configure.ac, use HAVE_ - fver displays locking method and used config. files. - give lockf locking method priority over flock method - fgetcmd and fgrabcmd now understands -c continue download - fixed check for in.fspd - we have called check_required_vars twice - display copyright in fspd -V - INFO document updated, fixed spelling errors, added section - FSP today - added -t option for fspd; specifes timeout for inetd mode (or - when debug is on for normal more also) + configure.ac upgaded to autoconf 2.57 and cleaned + added missing include headers to source code + vms code nuked from rest of headers + prefix is now used when finding configuration file + check for max. number of open files and adjust open handle cache + removed long file limit hack for FAT/VMS filesystems. Nonstandard and + unsecure. + removed include/version.h - use autoconf instead + added -V server option (display version) + do not use dircache as upload cache. Uploads now works even without + dircache + turn off cachedir when it do not exists + better init of random number generator. It should be really random. + fixed use of prebuild directory content and dircache + turn off logging if no log file is set + clean cache directory on startup + merged security patch from Debian package fsp_2.81.b3-4, i have + fixed this problem in 2.8.1b4; but Debian code looks better. + removed non standard NEED_ from configure.ac, use HAVE_ + fver displays locking method and used config. files. + give lockf locking method priority over flock method + fgetcmd and fgrabcmd now understands -c continue download + fixed check for in.fspd + we have called check_required_vars twice + display copyright in fspd -V + INFO document updated, fixed spelling errors, added section + FSP today + added -t option for fspd; specifes timeout for inetd mode (or + when debug is on for normal more also) Version 2.8.1b4 -- 30 March, 2001 ------------------------------------------------------------------------- -New maintainer: Radim Kolar hsn/at/cybermail.net now maintains FSP codebase. +New maintainer: Radim Kolar hsn/at/netmag.cz now maintains FSP codebase. ------------------------------------------------------------------------- 1) Eliminated a lot of warnings when compiling with -Wall. 2) Moved to autoconf 2.12. Replaced old m4 macros with Autoconf's. @@ -381,11 +423,11 @@ New maintainer: Radim Kolar hsn/at/cybermail.net now maintains FSP codebase. 8) Server has now configurable timeouts, maximal packetsize, directory and file handles caches. 9) REMOVED VMS part vms/ and vms_src/. Is was out of date. - 10) Removed file MACHINES. It was out of date. After my changes in - autoconf, it may not compile on non-Linux systems. - 11) Implemented a check for reliable signals in the configure script. - 12) Return type of signal handler is detected in configure script. - 13) ANSI prototypes are now used, if host compiler supports them. - 14) When server is running in read-only mode, server send this - information to clients, instead generic "Permission denied". - 15) Access checking and uploading was fixed. Now works. + 10) Removed file MACHINES. It was out of date. After my changes in + autoconf, it may not compile on non-Linux systems. + 11) Implemented a check for reliable signals in the configure script. + 12) Return type of signal handler is detected in configure script. + 13) ANSI prototypes are now used, if host compiler supports them. + 14) When server is running in read-only mode, server send this + information to clients, instead generic "Permission denied". + 15) Access checking and uploading was fixed. Now works. diff --git a/INFO b/INFO index d5c822b..f9ea402 100644 --- a/INFO +++ b/INFO @@ -9,40 +9,74 @@ and FSP software was not maintained... FSP today + Written by Radim Kolar - FSP uses UDP datagrams and it is reliable even when there is high - number of packet loss. It is usable on WiFi network with 60% packet - loss. + Protocol related + + FSP uses UDP datagrams and it is reliable even when there is + high number of packet loss. It is usable on WiFi network with + 60% packet loss. - Unlike TCP, FSP has a fast restart when line comes up. + FSP can very quickly addapt to changing line condition. This + is excelent for wireless packet networks. FSP needs about 6 + RTT to retune itself after receiving condition goes worse. + And unlike TCP based protocols, FSP has a fast restart when + line improves - It do not needs any RTT; FSP goes immediatly + to maximum possible speed. + + Maximum FSP speed is by design lower than maximum speed of TCP + based protocols because it has only 1 packet in the network. + TCP protocol has about 3 packets. Design of FSP protocol + makes impossible to send more than 1 packet into network. + This is nice method for bandwidth protection. - FSP server do not sends any data out unless is asked for. This - solves problem with transfering duplicate data when using - TCP protocol on overloaded lines. About 30% are dupes, thrown - out by client. + FSP server do not sends any data out unless is asked for. This + solves problem with transfering duplicate data when using TCP + protocol on overloaded lines. About 30% are dupes, thrown out + by client. Note: TCP stacks from BSD family has this dupe + ratio much lower. - UDP ports are not often port scanned today. Nobody notice that - you are running a server. + Embedded devices - FSP uses UDP which is unnoticed by many firewalls. FSP server - runs on 21 port by default, if you move it to port 53 (dns) - even strictly configured firewall can be worked around. + FSP protocol is very easy to implement; client core has about + one page of C code. It is ideal for embedded devices for + file-transfer tasks, like firmware downloading. Because of its + simplicity, there is a little chance to writing buggy + implementation. - You want to run anonymous archive and want to keep lamers out. + FSP is also good for remote booting. It is simplier than TFTP + and supports directory listings. - You want to share something without ruining your valueable bandwidth. + FSP protocol can be used as wire-protocol even without using + any layer 2 stuff. It operates in degraded mode with extra + features disabled. - You have overloaded archive site. - - You do want to share large data files (movies, ISO images) on - slow (or you do not want to waste valuable bandwidth) lines. - Ideal for sharing files on modem lines. + Internet operation + + UDP ports are not often port scanned today, only one exception + is scanning for Windows/Samba file sharing service. Nobody + will notice that you are running a fsp server. + + FSP uses UDP which is unnoticed by many firewalls. FSP server + runs on 21 port by default, if you move it to port 53 (dns) + even strictly configured firewall can be worked around. + + You want to run anonymous archive and want to keep lamers out. + + You want to share something without ruining your valueable + bandwidth. + + You have overloaded archive site. + + You do want to share large data files (movies, ISO images) on + slow (or you do not want to waste valuable bandwidth) lines. + Ideal for sharing files on modem lines. FSP daemon is a very light server. - + What is the purpose of FSP (V2.8.1): - + Written by A.J.Doherty@reading.ac.uk FSP is a set of programs that implements a public-access archive diff --git a/MACHINES b/MACHINES index 51d6db3..f5e7931 100644 --- a/MACHINES +++ b/MACHINES @@ -3,7 +3,7 @@ successfully compiled out of the box using configure script. If you get it to compile on an architecture/compiler combination other than one listed here, PLEASE SEND ME DETAILS of the fsp version, the type of machine, the OS, the compiler used and C library used; As well as what changes (if any) were needed -to for a clean compile. My email address is hsn/at/cybermail.net. Thanks +to for a clean compile. My email address is hsn/at/sendmail.cz. Thanks for your cooperation. FSP Version CPU OS Compiler C library @@ -14,4 +14,5 @@ FSP Version CPU OS Compiler C library 2.8.1 Beta 14 i386 Debian/testing-unstable 2.8.1 Beta 14 i386 RedHat 7.3 2.8.1 Beta 14 i386 Conectiva Linux 9 -2.8.1 Beta 19 i386 FreeBSD 5.x gcc-3.3 +2.8.1 Beta 19 i386 FreeBSD 5.2 gcc-3.3 +2.8.1 Beta 19 i386 FreeBSD 5.3 gcc-3.4 diff --git a/TODO b/TODO index 45b6419..4095d67 100644 --- a/TODO +++ b/TODO @@ -6,31 +6,36 @@ show loosers online (finfo command) and server statz rename command password change command -TESTING NEEDED: +TESTSUITE NEEDED: Write a simple FSP protocol testing tool Write a test suite using testing tool test for remote buffer overflows -Test new command rename /when implemented/ Test if >2GB files but <4GB works correctly with and without --disable-largefile +Test new command rename /when implemented/ SECURITY BUGS: symlink to FILE can escape from FSP root directory. OLD known problem. PROTOCOL-RELATED BUGS: +none known PORTING Sven's Slowaris 8 compile problem +not builds on freebsd 4 and non intel platforms? NEEDS IMPROVMENT: Client LIBRARY +:high: local bind address FSP_LOCALIP -remove stale lock files if not needed, port code from fspclient. -FSP_TIMEOUT should be total number of seconds, not delay between retrys. +we should retune retry algoritm for better support lines with higher + packed loss. +add more detailed stats from retry alg. :low: fver and others add support new syntax fsp://host:port/file add sem locking method, possible? flscmd does stat before directory listing, why? +:long-term goals: :better to write a new code instead fixing old crap =convert to multi threaded= make setup from env a separate function @@ -42,17 +47,21 @@ write new clients for new commands - fsprencmd fpasswd finfo :low: add support for more sane fsplist file format (as used by warez ppl) to fhostcmd +it looks like +#FSP Sites list +genie.lut.ac.uk 21 genie / # small UK site + clients do not freeing memory allocated from glob() FUTURE FEATURES FOR SERVER: -:high: -can be run multiple times on the same port, how to check? +:high: required for 2.8.2 final +can be run multiple times on the same port, how to check? + Currently looks fine on bsd. write RENAME FSP command bind-ip-address for server (and client via FSP_LOCAL_IP) report number of clients connected, size of hostable in new command CC_INFO command special defence against rapid/double fire clients (burst command in fspclient) -common log format - replace custom fspd log :midle:may not be in 2.8.2 Native Supports for symbolic links (needed for mirroring Debian) @@ -73,7 +82,7 @@ PERFORMANCE: host hashtable shrinking sometimes stat cache pro FSP_STAT a ostatni background time() alarm() caller -Current performance 1925648b/s +Current performance 1925648B/s MAN: update FAQ - urgent!! @@ -96,3 +105,4 @@ LARGEFILES64 how to turn them on: Cygwin: #define __LARGE64_FILES fopen64,ftello64,fseeko64 _off64_t glibc 2.3: #define _LARGEFILE64_SOURCE off64_t native: _FILE_OFFSETS_BITS = 32 / 64 then use off_t +FreeBSD: in 5.X always enabled, in 4.X not supported. diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..4897f2c --- /dev/null +++ b/autogen.sh @@ -0,0 +1,32 @@ +#! /bin/sh -e +# This scripts rebuilds configure files using autoconf tools. +# Supports both FreeBSD and Linux installations. No copyrights +# script is public domain. +# +# I am not big fan of autotools stuff, but other solutions +# like scons are worse (harder to maintain). +# +# Radim Kolar +# +# TODO: add linux support (sven?) +# add detection of automake19 and use it instead of +# automake18 +# +rm -f configure configure.lineno config.log config.status +rm -f aclocal.m4 +#rm -fr autom4te.cache +rm -f Makefile "Makefile.in" +echo "Generating configure and friends..." +if [ `uname -s` = 'FreeBSD' ]; then + echo "* FreeBSD detected" + echo "* Using autoconf 2.59 + automake 1.8" + #Use autoconf 2.59 + automake 1.8 pair + ACLOCAL=aclocal18; export ACLOCAL + AUTOMAKE=automake18; export AUTOMAKE + AUTOHEADER=autoheader259; export AUTOHEADER + AUTOCONF=autoconf259; export AUTOCONF + autoreconf259 -v +fi +echo "Now running configure $@" +./configure $@ +echo "done." diff --git a/bsd_src/find.c b/bsd_src/find.c index 6c60ac4..65619ee 100644 --- a/bsd_src/find.c +++ b/bsd_src/find.c @@ -68,7 +68,7 @@ void find_formplan PROTO1(char **, argv) tail = new; } } - + if (!isoutput) { new = c_print(); if (plan == NULL) tail = plan = new; diff --git a/bsd_src/function.c b/bsd_src/function.c index 0d466b0..a6ce30b 100644 --- a/bsd_src/function.c +++ b/bsd_src/function.c @@ -71,8 +71,8 @@ # include # endif #endif - -#ifdef HAVE_SYS_WAIT_H + +#ifdef HAVE_SYS_WAIT_H #include #endif #ifndef WEXITSTATUS @@ -111,7 +111,7 @@ static PLAN *palloc (t, f) PLAN *new; new = (PLAN *) malloc(sizeof(PLAN)); - + if ( new ) { new->type = t; new->eval = f; @@ -135,7 +135,7 @@ static long find_parsenum PROTO4(PLAN *, plan, const char *, option, char *, str { long value; char *endchar; /* pointer to character ending conversion */ - + /* determine comparison from leading + or - */ switch(*str) { case '+': @@ -150,7 +150,7 @@ static long find_parsenum PROTO4(PLAN *, plan, const char *, option, char *, str plan->flags = FIND_EQUAL; break; } - + /* * convert the string with strtol(). Note, if strtol() returns zero * and endchar points to the beginning of the string we know we have @@ -183,7 +183,7 @@ static int find_time PROTO3(PLAN *, plan, struct stat *, sbuf, char *, path) COMPARE((now - sbuf->st_atime + SECSPERDAY - 1) / SECSPERDAY, plan->t_data); } - + PLAN * c_time PROTO1(char *, arg) { PLAN *new; @@ -234,9 +234,9 @@ static int queryuser PROTO1(char **, argv) fflush(stderr); first = ch = getchar(); - for (nl = 0;;) + for (nl = 0;;) { - if (ch == '\n') + if (ch == '\n') { nl = 1; break; @@ -304,7 +304,7 @@ static char *emalloc_ffind PROTO1(unsigned int, len) perror("malloc"); exit(1); } - + /* * c_exec -- * build three parallel arrays, one with pointers to the strings passed @@ -319,7 +319,7 @@ PLAN *c_exec PROTO2(char ***, argvp, int, isok) register char **argv, **ap, *p; isoutput = 1; - + new = palloc(N_EXEC, find_exec); new->flags = isok; @@ -389,7 +389,7 @@ static void printlong_ffind PROTO2(char *, name, struct stat *, sb) printf("%s", name); putchar('\n'); } - + /* * -ls functions -- * @@ -400,7 +400,7 @@ static int find_ls PROTO3(PLAN *, plan, struct stat *, sbuf, char *, path) printlong_ffind(path, sbuf); return(1); } - + PLAN *c_ls PROTO0((void)) { isoutput = 1; @@ -422,7 +422,7 @@ static int find_name PROTO3(PLAN *, plan, struct stat *, sbuf, char *, path) if (*name == '/') name++; return(fnmatch(plan->c_data, name)); } - + PLAN *c_name PROTO1(char *, pattern) { PLAN *new; @@ -431,7 +431,7 @@ PLAN *c_name PROTO1(char *, pattern) new->c_data = pattern; return(new); } - + /* * -newer file functions -- * @@ -443,12 +443,12 @@ static int find_newer PROTO3(PLAN *, plan, struct stat *, sbuf, char *, path) { return(sbuf->st_mtime > plan->t_data); } - + PLAN *c_newer PROTO1(char *, filename) { PLAN *new; struct stat sb; - + if (stat(filename, &sb)) { perror("stat"); exit(1); @@ -457,7 +457,7 @@ PLAN *c_newer PROTO1(char *, filename) new->t_data = sb.st_mtime; return(new); } - + /* * -print functions -- * @@ -469,14 +469,14 @@ static int find_print PROTO3(PLAN *, plan, struct stat *, sbuf, char *, path) (void)printf("%s\n", path); return(1); } - + PLAN *c_print PROTO0((void)) { isoutput = 1; return(palloc(N_PRINT, find_print)); } - + /* * -prune functions -- * @@ -487,12 +487,12 @@ static int find_prune PROTO3(PLAN *, plan, struct stat *, sbuf, char *, path) process = -1; return(1); } - + PLAN *c_prune PROTO0((void)) { return(palloc(N_PRUNE, find_prune)); } - + /* * -size n[c] functions -- * @@ -510,18 +510,18 @@ static int find_size PROTO3(PLAN *, plan, struct stat *, sbuf, char *, path) size = divsize ? ((sbuf->st_size + FIND_SIZE - 1)/FIND_SIZE) : sbuf->st_size; COMPARE(size, plan->o_data); } - + PLAN *c_size PROTO1(char *, arg) { PLAN *new; char endch='c'; - + new = palloc(N_SIZE, find_size); new->o_data = find_parsenum(new, "-size", arg, &endch); if (endch == 'c') divsize = 0; return(new); } - + /* * -type c functions -- * @@ -532,12 +532,12 @@ static int find_type PROTO3(PLAN *, plan, struct stat *, sbuf, char *, path) { return((sbuf->st_mode & S_IFMT) == plan->m_data); } - + PLAN *c_type PROTO1(char *, typestring) { PLAN *new; mode_t mask; - + switch (typestring[0]) { case 'd': mask = S_IFDIR; @@ -549,12 +549,12 @@ PLAN *c_type PROTO1(char *, typestring) fprintf(stderr,"-type: unknown type"); exit(1); } - + new = palloc(N_TYPE, find_type); new->m_data = mask; return(new); } - + /* * ( expression ) functions -- * @@ -568,7 +568,7 @@ int find_expr PROTO3(PLAN *, plan, struct stat *, sbuf, char *, path) for(p=plan->p_data[0]; p && (state=(p->eval)(p, sbuf, path)); p=p->next); return(state); } - + /* * N_OPENPAREN and N_CLOSEPAREN nodes are temporary place markers. They are * eliminated during phase 2 of find_formplan() --- the '(' node is converted @@ -578,12 +578,12 @@ PLAN *c_openparen PROTO0((void)) { return(palloc(N_OPENPAREN, (int (*)())-1)); } - + PLAN *c_closeparen PROTO0((void)) { return(palloc(N_CLOSEPAREN, (int (*)())-1)); } - + /* * ! expression functions -- @@ -598,12 +598,12 @@ static int find_not PROTO3(PLAN *, plan, struct stat *, sbuf, char *, path) for(p=plan->p_data[0]; p && (state=(p->eval)(p, sbuf, path)); p=p->next); return(!state); } - + PLAN *c_not PROTO0((void)) { return(palloc(N_NOT, find_not)); } - + /* * expression -o expression functions -- * diff --git a/bsd_src/glob.c b/bsd_src/glob.c index 4dec543..03e15ef 100644 --- a/bsd_src/glob.c +++ b/bsd_src/glob.c @@ -425,7 +425,7 @@ static void rscan(t, f) #ifdef PROTOTYPES if (f == (charfunc) tglob) #else - if (f == tglob) + if (f == tglob) #endif { if (*p == '~') gflag |= 2; diff --git a/bsd_src/ls.c b/bsd_src/ls.c index bc0430f..e62c15e 100644 --- a/bsd_src/ls.c +++ b/bsd_src/ls.c @@ -82,7 +82,7 @@ static int tabdir PROTO2(LS *, lp, LS **, s_stats) struct rdirent *dp; unsigned long blocks; LS *stats; - + if (!(dirp = util_opendir("."))) { perror(lp->name); return(0); @@ -118,25 +118,25 @@ static int tabdir PROTO2(LS *, lp, LS **, s_stats) continue; } stats[cnt].name = dp->d_name; - + /* * get the inode from the directory, so the -f flag * works right. */ stats[cnt].lstat.st_ino = dp->d_fileno; - + /* save name length for -C format */ stats[cnt].len = dp->d_namlen; - + /* calculate number of blocks if -l/-s formats */ if (f_longform || f_size) blocks += (stats[cnt].lstat.st_size+1023)/1024; - + /* save max length if -C format */ if (f_column && maxlen < (int)dp->d_namlen) maxlen = dp->d_namlen; ++cnt; } (void)util_closedir(dirp); - + if (cnt) { stats[0].lstat.st_btotal = blocks; stats[0].lstat.st_maxlen = maxlen; @@ -187,12 +187,12 @@ static void displaydir PROTO2(LS *, stats, register int, num) printfcn(stats, num); - if (f_recursive) + if (f_recursive) { savedpath = endofpath; - for (lp = stats; num--; ++lp) + for (lp = stats; num--; ++lp) { - if (!(S_ISDIR(lp->lstat.st_mode))) + if (!(S_ISDIR(lp->lstat.st_mode))) continue; p = lp->name; if (p[0] == '.' && (!p[1] || (p[1] == '.' && !p[2]))) continue; @@ -227,7 +227,7 @@ static void doargs PROTO2(int, argc, char **, argv) av2[0] = *argv; av2[1] = 0; } - + for( ; *av; av++) { if (util_stat(*av, &sb)) { perror(*av); @@ -421,7 +421,7 @@ void fls_main PROTO2(int, argc, char **, argv) if (!f_timesort) sortfcn = revnamecmp; else if (f_accesstime) sortfcn = revacccmp; else if (f_statustime) sortfcn = revstatcmp; - else sortfcn = revmodcmp; /* use modification time */ + else sortfcn = revmodcmp; /* use modification time */ } else { if (!f_timesort) sortfcn = namecmp; else if (f_accesstime) sortfcn = acccmp; diff --git a/bsd_src/operator.c b/bsd_src/operator.c index a35a26a..3acaca2 100644 --- a/bsd_src/operator.c +++ b/bsd_src/operator.c @@ -47,10 +47,10 @@ * yanknode -- * destructively removes the top from the plan */ -static PLAN *yanknode PROTO1(PLAN **, planp) +static PLAN *yanknode PROTO1(PLAN **, planp) { PLAN *node; /* top node removed from the plan */ - + if ((node = (*planp)) == NULL) return(NULL); (*planp) = (*planp)->next; node->next = NULL; @@ -63,16 +63,16 @@ static PLAN *yanknode PROTO1(PLAN **, planp) * paren_squish. In comments below, an expression is either a * simple node or a N_EXPR node containing a list of simple nodes. */ -static PLAN *yankexpr PROTO1(PLAN **, planp) +static PLAN *yankexpr PROTO1(PLAN **, planp) { register PLAN *next; /* temp node holding subexpression results */ PLAN *node; /* pointer to returned node or expression */ PLAN *tail; /* pointer to tail of subplan */ PLAN *subplan; /* pointer to head of ( ) expression */ - + /* first pull the top node from the plan */ if ((node = yanknode(planp)) == NULL) return(NULL); - + /* * If the node is an '(' then we recursively slurp up expressions * until we find its associated ')'. If it's a closing paren we @@ -120,9 +120,9 @@ PLAN *paren_squish PROTO1(PLAN *, plan) register PLAN *expr; /* pointer to next expression */ register PLAN *tail; /* pointer to tail of result plan */ PLAN *result; /* pointer to head of result plan */ - + result = tail = NULL; - + /* * the basic idea is to have yankexpr do all our work and just * collect it's results together. @@ -136,7 +136,7 @@ PLAN *paren_squish PROTO1(PLAN *, plan) fprintf(stderr,"): no beginning '('"); exit(1); } - + /* add the expression to our result plan */ if (result == NULL) tail = result = expr; else { @@ -158,16 +158,16 @@ PLAN *not_squish PROTO1(PLAN *, plan) register PLAN *node; /* temporary node used in N_NOT processing */ register PLAN *tail; /* pointer to tail of result plan */ PLAN *result; /* pointer to head of result plan */ - + tail = result = next = NULL; - + while ((next = yanknode(&plan)) != NULL) { /* * if we encounter a ( expression ) then look for nots in * the expr subplan. */ if (next->type == N_EXPR) next->p_data[0] = not_squish(next->p_data[0]); - + /* * if we encounter a not, then snag the next node and place * it in the not's subplan. As an optimization we compress @@ -175,7 +175,7 @@ PLAN *not_squish PROTO1(PLAN *, plan) */ if (next->type == N_NOT) { int notlevel = 1; - + node = yanknode(&plan); while (node->type == N_NOT) { ++notlevel; @@ -192,7 +192,7 @@ PLAN *not_squish PROTO1(PLAN *, plan) if (notlevel % 2 != 1) next = node; else next->p_data[0] = node; } - + /* add the node to our result plan */ if (result == NULL) tail = result = next; else { @@ -213,19 +213,19 @@ PLAN *or_squish PROTO1(PLAN *, plan) register PLAN *next; /* next node being processed */ register PLAN *tail; /* pointer to tail of result plan */ PLAN *result; /* pointer to head of result plan */ - + tail = result = next = NULL; - + while ((next = yanknode(&plan)) != NULL) { /* * if we encounter a ( expression ) then look for or's in * the expr subplan. */ if (next->type == N_EXPR) next->p_data[0] = or_squish(next->p_data[0]); - + /* if we encounter a not then look for not's in the subplan */ if (next->type == N_NOT) next->p_data[0] = or_squish(next->p_data[0]); - + /* * if we encounter an or, then place our collected plan in the * or's first subplan and then recursively collect the @@ -244,7 +244,7 @@ PLAN *or_squish PROTO1(PLAN *, plan) } return(next); } - + /* add the node to our result plan */ if (result == NULL) tail = result = next; else { diff --git a/bsd_src/option.c b/bsd_src/option.c index cc192d6..46f84d2 100644 --- a/bsd_src/option.c +++ b/bsd_src/option.c @@ -80,9 +80,9 @@ PLAN *find_create PROTO1(char ***, argvp) register OPTION *p; PLAN *new; char **argv; - + argv = *argvp; - + if ((p = option(*argv)) == NULL) { (void)fprintf(stderr, "find: unknown option %s.\n", *argv); exit(1); @@ -93,7 +93,7 @@ PLAN *find_create PROTO1(char ***, argvp) *--argv); exit(1); } - + switch(p->flags) { case O_NONE: new = NULL; @@ -120,7 +120,7 @@ static int typecompare PROTO2(const void *, a, const void *, b) OPTION *option PROTO1(char *, name) { OPTION tmp; - + tmp.name = name; return((OPTION *)bsearch(&tmp, options, sizeof(options)/sizeof(OPTION), sizeof(OPTION), typecompare)); diff --git a/bsd_src/print.c b/bsd_src/print.c index 5e42a57..f4041b4 100644 --- a/bsd_src/print.c +++ b/bsd_src/print.c @@ -21,9 +21,9 @@ */ #include "tweak.h" - + #include - + #include #include #ifdef HAVE_UNISTD_H @@ -43,11 +43,11 @@ # include # endif #endif -#include "my-string.h" +#include "my-string.h" #include "ls.h" - + #define BLK(A) (((A)+1023)/1024) - + static int printtype PROTO1(mode_t, mode) { switch(mode & S_IFMT) { @@ -65,23 +65,23 @@ static int printtype PROTO1(mode_t, mode) static int printaname PROTO1(LS *, lp) { int chcnt; - + chcnt = 0; - + if (f_inode) { printf("%5lu ", (unsigned long)lp->lstat.st_ino); chcnt += 6; } - + if (f_size) { printf("%4ld ", (long)BLK(lp->lstat.st_size)); chcnt += 5; } - + printf("%s", lp->name); chcnt += strlen(lp->name); - + if (f_type) chcnt += printtype(lp->lstat.st_mode); - + return(chcnt); } @@ -97,10 +97,10 @@ static void printtime PROTO1(time_t, ftime) { int i; char *longstring; - + longstring = (char *)ctime((long *)&ftime); for (i = 4; i < 11; ++i) (void)putchar(longstring[i]); - + #define SIXMONTHS ((365 / 2) * 24 * 60 * 60) if (ftime + SIXMONTHS > time((time_t *)NULL)) @@ -115,13 +115,13 @@ static void printtime PROTO1(time_t, ftime) void printlong PROTO2(LS *, stats, int, num) { const char *modep; - + if (f_total) (void)printf("total %lu\n",(unsigned long) stats[0].lstat.st_btotal); for (; num--; ++stats) { if (f_inode) printf("%6lu ", (unsigned long)stats->lstat.st_ino); if (f_size ) printf("%4lu ", (unsigned long)BLK(stats->lstat.st_size)); modep = ((S_IFDIR & stats->lstat.st_mode)) ? "drwxrwxrwx" : "-rw-rw-rw-" ; - + (void)printf("%s %3u %-*s ", modep, stats->lstat.st_nlink, 8, "nobody"); if (f_group) printf("%-*s ", 8, "nobody"); else printf("%8lu ", (unsigned long)stats->lstat.st_size); @@ -137,27 +137,27 @@ void printlong PROTO2(LS *, stats, int, num) #define TAB 8 extern int termwidth; - + void printcol PROTO2(LS *, stats, int, num) { register int base, chcnt, cnt, col, colwidth; int endcol, numcols, numrows, row; - + colwidth = stats[0].lstat.st_maxlen; if (f_inode) colwidth += 6; if (f_size) colwidth += 5; if (f_type) colwidth += 1; - + colwidth = (colwidth + TAB) & ~(TAB - 1); if (termwidth < 2 * colwidth) { printscol(stats, num); return; } - + numcols = termwidth / colwidth; numrows = num / numcols; if (num % numcols) ++numrows; - + if (f_size && f_total) printf("total %lu\n", (unsigned long)stats[0].lstat.st_btotal); for (row = 0; row < numrows; ++row) { endcol = colwidth; diff --git a/bsd_src/util.c b/bsd_src/util.c index 78df144..f55d544 100644 --- a/bsd_src/util.c +++ b/bsd_src/util.c @@ -34,7 +34,7 @@ void prcopy PROTO3(char *, src, char *, dest, int, len) { register int ch; - + while(len--) { ch = *src++; *dest++ = isprint(ch) ? ch : '?'; @@ -50,7 +50,7 @@ void nomem PROTO0((void)) char *emalloc PROTO1(int, size) { char *retval; - + if (!(retval = malloc(size))) nomem(); return(retval); } diff --git a/client/lib.c b/client/lib.c index 2d38bfd..2dd0e82 100644 --- a/client/lib.c +++ b/client/lib.c @@ -1,4 +1,5 @@ /*********************************************************************\ + * Copyright (c) 2004 by Radim Kolar * * Copyright (c) 1991 by Wen-King Su (wen-king@vlsi.cs.caltech.edu) * * * * You may copy or modify this file in any manner you wish, provided * @@ -26,7 +27,9 @@ static unsigned short key; int client_trace = 0; int client_intr_state = 0; -unsigned long target_delay = DEFAULT_DELAY; /* expected max delay */ +unsigned long target_delay = DEFAULT_DELAY; /* expected max delay from server on good connection */ + +unsigned long target_maxdelay = DEFAULT_MAXDELAY; /* max resend timer */ unsigned long busy_delay = DEFAULT_DELAY; /* busy retransmit timer */ unsigned long idle_delay = DEFAULT_DELAY; /* idle retransmit timer */ unsigned long udp_sent_time; @@ -41,8 +44,10 @@ UBUF *client_interact PROTO6(unsigned char, cmd, unsigned long, pos, unsigned char *s, *t, *d, seq0, seq1; unsigned u, n, sum, mlen, rlen; fd_set mask; - int retval, bytes, retry_send, retry_recv; + int retval, retry_send, retry_recv; + socklen_t bytes; unsigned long w_delay; + unsigned long total_delay; FD_ZERO(&mask); sbuf.cmd = cmd; @@ -53,24 +58,27 @@ UBUF *client_interact PROTO6(unsigned char, cmd, unsigned long, pos, BB_WRITE2(sbuf.bb_len,l1); BB_WRITE4(sbuf.bb_pos,pos); - + client_intr_state = 1; - + total_delay = 0; + w_delay = 0; + for(u = l1, d = (unsigned char *) sbuf.buf; u--; *d++ = *p1++); for(u = l2; u--; *d++ = *p2++); mlen = d - (unsigned char *) &sbuf; - + key = client_get_key(); - + for(retry_send = 0; ; retry_send++) { + total_delay += w_delay; BB_WRITE2(sbuf.bb_key,key); sbuf.bb_seq[0] = seq0 = (myseq >> 8) & 0xff; sbuf.bb_seq[1] = seq1 = (myseq & 0xfc) | (retry_send & 0x0003); sbuf.sum = 0; - + for(t = (unsigned char *) &sbuf, sum = n = mlen; n--; sum += *t++); sbuf.sum = sum + (sum >> 8); - + switch(retry_send) { /* adaptive retry delay adjustments */ case 0: busy_delay = (target_delay+(busy_delay<<3)-busy_delay)>>3; @@ -79,58 +87,89 @@ UBUF *client_interact PROTO6(unsigned char, cmd, unsigned long, pos, case 1: busy_delay = busy_delay * 3 / 2; w_delay = busy_delay; - if(client_trace) write(2,"R",1); + if(client_trace) write(2,"R",1); break; - + default: #ifdef CLIENT_TIMEOUT - if (!pos && retry_send >= env_timeout ) { + if (total_delay/1000 >= env_timeout ) { fprintf(stderr, "\rRemote server not responding.\n"); exit(1); } #endif - if(idle_delay < 3*60*1000) idle_delay = idle_delay * 3 / 2; + idle_delay = idle_delay * 3 / 2; + if (idle_delay > target_maxdelay) idle_delay = target_maxdelay; w_delay = idle_delay; if(client_trace) write(2,"I",1); break; } - + if(sendto(myfd,(const char*)&sbuf,mlen,0,(struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) { - perror("sendto"); - exit(1); + switch(errno) { + case ENOBUFS: + case EHOSTUNREACH: + case ECONNREFUSED: + case EHOSTDOWN: + case ENETDOWN: + case EPIPE: + /* try to resend packet */ + continue; + default: + perror("sendto"); + exit(1); + } } udp_sent_time = time((time_t *) 0); FD_SET(myfd,&mask); - + for(retry_recv = 0; ; retry_recv++) { - if(retry_recv && client_trace) write(2,"E",1); retval = _x_select(&mask, w_delay); if((retval == -1) && (errno == EINTR)) continue; if(retval == 1) { /* an incoming message is waiting */ bytes = sizeof(from); if((bytes = recvfrom(myfd,(char*)&rbuf,sizeof(rbuf),0, (struct sockaddr *)&from, &bytes)) < UBUF_HSIZE) + { + /* too enough bytes for header */ + if (client_trace) write(2,"H",1); continue; - + } + + rlen = BB_READ2(rbuf.bb_len); + + if( (rlen+UBUF_HSIZE) > bytes) + { + /* truncated. */ + if (client_trace) write(2,"T",1); + continue; + } + s = (unsigned char *) &rbuf; d = s + bytes; u = rbuf.sum; rbuf.sum = 0; for(t = s, sum = 0; t < d; sum += *t++); sum = (sum + (sum >> 8)) & 0xff; - if(sum != u) continue; /* wrong check sum */ - - rlen = BB_READ2(rbuf.bb_len); - + if(sum != u) + { + /* wrong check sum */ + if (client_trace) write(2,"C",1); + continue; + } + if( (rbuf.bb_seq[0] ^ seq0) || - ((rbuf.bb_seq[1] ^ seq1)&0xfc)) continue; /* wrong seq # */ - if((int) (rlen+UBUF_HSIZE) > bytes) continue; /* truncated. */ - + ((rbuf.bb_seq[1] ^ seq1)&0xfc)) + { + /* wrong seq # */ + if (client_trace) write(2,"S",1); + continue; + } myseq = (myseq + 0x0004) & 0xfffc; /* seq for next request */ key = BB_READ2(rbuf.bb_key); /* key for next request */ - - client_set_key(key); - + + if(rbuf.cmd != CC_BYE) + client_set_key(key); + if(client_intr_state == 2) { if(!key_persists) client_done(); exit(1); @@ -139,9 +178,9 @@ UBUF *client_interact PROTO6(unsigned char, cmd, unsigned long, pos, #ifdef DEBUG printf("rbuf.cmd = %u\n",rbuf.cmd); #endif - + return(&rbuf); - + } else break; /* go back to re-transmit buffer again */ } } @@ -154,25 +193,26 @@ static RETSIGTYPE client_intr PROTO1(int, signum) case 1: client_intr_state = 2; break; case 2: exit(3); } -#ifndef RELIABLE_SIGNALS +#ifndef RELIABLE_SIGNALS signal(SIGINT,client_intr); -#endif +#endif } void init_client PROTO3(const char *, host, unsigned short, port, unsigned short, myport) { busy_delay = idle_delay = target_delay; - + myseq = random(); + if((myfd = _x_udp(&myport)) == -1) { perror("socket open"); exit(1); } - + if(_x_adr(host,port,&server_addr) == -1) { perror("server addr"); exit(1); - } - + } + client_init_key(server_addr.sin_addr.s_addr,port,getpid()); signal(SIGINT,client_intr); } @@ -181,6 +221,6 @@ int client_done PROTO0((void)) { (void) client_interact(CC_BYE, 0L, 0, (unsigned char *)NULLP, 0, (unsigned char *)NULLP); + client_destroy_key(); return(0); } - diff --git a/client/lock.c b/client/lock.c index 862048f..ff1f402 100644 --- a/client/lock.c +++ b/client/lock.c @@ -17,21 +17,21 @@ #ifndef NOLOCKING static char key_string[sizeof(KEY_PREFIX)+32]; - + static char code_str[] = - "0123456789:_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - + "0123456789:_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + static void make_key_string PROTO2(unsigned long, server_addr, unsigned long, server_port) { unsigned long v1, v2; char *p; - + strcpy(key_string,KEY_PREFIX); for(p = key_string; *p; p++); v1 = server_addr; v2 = server_port; - + *p++ = code_str[v1 & 0x3f]; v1 >>= 6; *p++ = code_str[v1 & 0x3f]; v1 >>= 6; *p++ = code_str[v1 & 0x3f]; v1 >>= 6; @@ -94,14 +94,19 @@ void client_init_key PROTO3(unsigned long, server_addr, { unsigned long omask; okey = key; - + make_key_string(server_addr,server_port); - + omask = umask(0); lock_fd = open(key_string,O_RDWR|O_CREAT,0666); umask(omask); } +void client_destroy_key(void) +{ + (void)close(lock_fd); + unlink(key_string); +} #endif /********************************************************************/ /******* For those systems that has lockf function call *************/ @@ -155,14 +160,19 @@ void client_init_key PROTO3(unsigned long, server_addr, { unsigned long omask; okey = key; - + make_key_string(server_addr,server_port); - + omask = umask(0); lock_fd = open(key_string,O_RDWR|O_CREAT,0666); umask(omask); } +void client_destroy_key(void) +{ + (void)close(lock_fd); + unlink(key_string); +} #endif /********************************************************************/ /******* For those systems that has SysV shared memory + lockf ******/ @@ -178,6 +188,7 @@ void client_init_key PROTO3(unsigned long, server_addr, int key_persists = 0; static unsigned short *share_key; static unsigned int lock_fd; +static int lock_shm; unsigned short client_get_key PROTO0((void)) { @@ -203,14 +214,13 @@ void client_init_key PROTO3(unsigned long, server_addr, { unsigned long omask; key_t lock_key; - int lock_shm; - + make_key_string(server_addr,server_port); - + omask = umask(0); lock_fd = open(key_string,O_RDWR|O_CREAT,0666); umask(omask); - + if((lock_key = ftok(key_string,238)) == -1) { perror("ftok"); exit(1); @@ -226,6 +236,21 @@ void client_init_key PROTO3(unsigned long, server_addr, *share_key = key; } +void client_destroy_key(void) +{ + (void)close(lock_fd); + if (shmdt((char *)share_key) < 0) + { + perror("shmdt"); + exit(1); + } + if (shmctl(lock_shm,IPC_RMID,NULL) < 0) + { + perror("shmctl"); + exit(1); + } + unlink(key_string); +} #endif /********************************************************************/ /******* For those who does not want to use locking *****************/ @@ -252,4 +277,11 @@ void client_init_key PROTO3(unsigned long, server_addr, okey = key; } +void client_destroy_key(void) +{ + return; +} #endif +/********************************************************************/ +/********************************************************************/ +/********************************************************************/ diff --git a/client/util.c b/client/util.c index 1fbc88d..d822023 100644 --- a/client/util.c +++ b/client/util.c @@ -22,7 +22,7 @@ const char *env_myport; const char *env_host; const char *env_port; const char *env_local_dir; -int env_timeout; +unsigned int env_timeout; unsigned short client_buf_len; unsigned short client_net_len; @@ -33,10 +33,10 @@ unsigned short client_net_len; char *util_abs_path PROTO1(const char *, s2) { char *path, *s, *d, *t; - + if(!env_dir) env_dir = ""; if(!s2) s2 = ""; - + if(*s2 == '/') { path = malloc(strlen(s2)+2+strlen(env_passwd)+1); sprintf(path,"/%s",s2); @@ -44,7 +44,7 @@ char *util_abs_path PROTO1(const char *, s2) path = malloc(strlen(env_dir)+strlen(s2)+3+strlen(env_passwd)+1); sprintf(path,"/%s/%s",env_dir,s2); } - + for(t = path; *t; ) { if(t[0] == '/') { while(t[1] == '/') for(d = t, (s = t+1); (*d++ = *s++); ); @@ -82,7 +82,7 @@ char *util_abs_path PROTO1(const char *, s2) } if(t[-1] == '/' && (t[1] == '/' || t[1] == 0)) { s = t + 1; /* point to either slash or nul */ - for(d = t-1; (*d++ = *s++); ); + for(d = t-1; (*d++ = *s++); ); t--; continue; } @@ -97,7 +97,7 @@ static int util_split_path PROTO4(char *, path, char **, p1, char **, p2, { char *s; static char junk; - + *p1 = "/"; if(*path == '/') { *p2 = path; @@ -106,7 +106,7 @@ static int util_split_path PROTO4(char *, path, char **, p1, char **, p2, *p2 = &junk; *p3 = path; } - + for(s = *p3; *s; s++) { if(*s == '/') { *p1 = path; @@ -114,7 +114,7 @@ static int util_split_path PROTO4(char *, path, char **, p1, char **, p2, *p3 = s+1; } } - + if (**p3 == '\0') *p3 = "."; return(1); } @@ -133,17 +133,17 @@ static RDIRENT **get_dir_blk PROTO1(char *, path) unsigned long pos; int cnt, k, len, rem, acc, at_eof, rlen; UBUF *ub; - + fpath = util_abs_path(path); - - for(pos = 0, at_eof = acc = cnt = 0; ; ) + + for(pos = 0, at_eof = acc = cnt = 0; ; ) { - while((acc < UBUF_SPACE) && !at_eof) + while((acc < UBUF_SPACE) && !at_eof) { ub = client_interact(CC_GET_DIR,pos, strlen(fpath), (unsigned char *)fpath+1, 2, (unsigned char *)&client_net_len); - + if(ub->cmd == CC_ERR) { fprintf(stderr,"%s: %s\n",path, ub->buf); free(fpath); @@ -157,10 +157,10 @@ static RDIRENT **get_dir_blk PROTO1(char *, path) acc += rlen; pos += rlen; } - + if(acc >= UBUF_SPACE) len = UBUF_SPACE; else len = acc; - + for(p2 = buf, rem = len, k = 0; ; k++) { if(rem < RDHSIZE) break; if(((RDIRENT *) p2)->type == RDTYPE_SKIP) break; @@ -172,17 +172,17 @@ static RDIRENT **get_dir_blk PROTO1(char *, path) rem--; } } - + p1 = malloc(p2-buf); if(cnt) dp = (RDIRENT **) realloc(dp,(cnt+k+1)*sizeof(RDIRENT *)); else dp = (RDIRENT **) malloc((cnt+k+1)*sizeof(RDIRENT *)); - + if(!p1 || !dp) { fputs("directory reading out of memory\n",stderr); free(fpath); return((RDIRENT **) 0); } - + for(p2 = buf, rem = len; ; cnt++) { if(rem < RDHSIZE) break; if(((RDIRENT *) p2)->type == RDTYPE_SKIP) break; @@ -192,7 +192,7 @@ static RDIRENT **get_dir_blk PROTO1(char *, path) return(dp); } dp[cnt] = (RDIRENT *) p1; - + for(k = RDHSIZE, rem -= (RDHSIZE+1); k--; *p1++ = *p2++); while( (*p1++ = *p2++) ) rem--; while((p2 - buf) & 3) { @@ -201,7 +201,7 @@ static RDIRENT **get_dir_blk PROTO1(char *, path) rem--; } } - + if(acc < UBUF_SPACE) { dp[cnt] = 0; free(fpath); @@ -215,28 +215,28 @@ static RDIRENT **get_dir_blk PROTO1(char *, path) static int util_download_main PROTO5(char *, path, char *, fpath, FILE *, fp, unsigned long, start_from, int, cmd) -{ +{ unsigned long pos, started_from = start_from, downloaded; unsigned tmax, wrote, sent_time, rlen; UBUF *ub; time_t t = time(NULL); - - for(tmax = 1, pos = start_from, sent_time = 0; ;) { + + for(tmax = 1, pos = start_from, sent_time = 0; ;) { ub = client_interact(cmd,pos,strlen(fpath),(unsigned char *)fpath+1, 2, (unsigned char *)&client_net_len); - + 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)); else fprintf(stderr,"\r%lu ", pos); fflush(stderr); } - - if(ub->cmd == CC_ERR) { + + if(ub->cmd == CC_ERR) { fprintf(stderr,"downloading %s: %s\n",path,ub->buf); - return(-1); + return(-1); } - + rlen = BB_READ2(ub->bb_len); wrote = fwrite(ub->buf,1,rlen,fp); /* check for long integer pos overflow */ @@ -244,34 +244,34 @@ static int util_download_main PROTO5(char *, path, char *, fpath, FILE *, fp, if(pos+bytes>FOURGIGS) break; #else - if(pos+wrote>10), path, downloaded/t); + fprintf(stderr,"\r%luk : %s [%ldB/s] \n", 1+(pos>>10), path, downloaded/t); fflush(stderr); } - + return(0); } int util_download PROTO3(char *, path, FILE *, fp, unsigned long, start_from) -{ +{ int code, len; char *fpath; - + fpath = util_abs_path(path); if(*env_passwd) { strcat(fpath, "\n"); @@ -284,11 +284,11 @@ int util_download PROTO3(char *, path, FILE *, fp, unsigned long, start_from) } int util_grab_file PROTO3(char *, path, FILE *, fp, unsigned long, start_from) -{ +{ int code, len; char *fpath; UBUF *ub; - + fpath = util_abs_path(path); if(*env_passwd) { strcat(fpath, "\n"); @@ -300,20 +300,20 @@ int util_grab_file PROTO3(char *, path, FILE *, fp, unsigned long, start_from) free(fpath); return(code); } - + ub = client_interact(CC_GRAB_DONE, 0L, len, (unsigned char *)fpath+1, 0, - (unsigned char *)NULLP); - + (unsigned char *)NULLP); + if(ub->cmd == CC_ERR) { fprintf(stderr,"Warning, unexpected grab error: %s\n",ub->buf); } - + free(fpath); return(code); } int util_upload PROTO3(char *, path, FILE *, fp, time_t , stamp) -{ +{ unsigned long pos; unsigned bytes, first, tmax, sent_time; char *fpath, buf[UBUF_SPACE]; @@ -322,21 +322,21 @@ int util_upload PROTO3(char *, path, FILE *, fp, time_t , stamp) char *dpath,*p1,*p2; unsigned char flags; struct stat sb; - + fpath = util_abs_path(path); util_split_path(fpath,&dpath,&p1,&p2); *p1='\0'; - + /* check if we have enough rights to create file */ ub = client_interact(CC_GET_PRO,0, strlen(dpath), (unsigned char *)dpath+1, 0, (unsigned char *)NULLP); free(fpath); fpath = util_abs_path(path); - if(ub->cmd == CC_ERR) - { + if(ub->cmd == CC_ERR) + { fprintf(stderr,"uploading %s: %s\n",path,ub->buf); free(fpath); - return(1); + return(1); } /* extract flags from server reply */ bytes = BB_READ2(ub->bb_len); @@ -346,13 +346,13 @@ int util_upload PROTO3(char *, path, FILE *, fp, time_t , stamp) /* flags are in the reply */ flags = *(ub->buf+bytes); /* check for required flags */ - if(! (flags & DIR_OWNER)) + if(! (flags & DIR_OWNER)) { if( ! (flags & DIR_ADD)) { fprintf(stderr,"No permission for adding files.\n"); free(fpath); - return(1); + return(1); } } else { @@ -366,18 +366,18 @@ int util_upload PROTO3(char *, path, FILE *, fp, time_t , stamp) { fprintf(stderr,"No permission for overwriting: %s\n",fpath); free(fpath); - return(1); + return(1); } } } - - for(tmax = 1, sent_time = 0, pos = 0, first = 1; ; first = 0) - { - if((bytes = fread(buf,1,client_buf_len,fp)) || first) + + for(tmax = 1, sent_time = 0, pos = 0, first = 1; ; first = 0) + { + if((bytes = fread(buf,1,client_buf_len,fp)) || first) { ub = client_interact(CC_UP_LOAD,pos, bytes, (unsigned char *)buf, 0, (unsigned char *)NULLP); - if(client_trace && (udp_sent_time != sent_time)) + if(client_trace && (udp_sent_time != sent_time)) { sent_time = udp_sent_time; if(client_buf_len == UBUF_SPACE) @@ -389,16 +389,16 @@ int util_upload PROTO3(char *, path, FILE *, fp, time_t , stamp) else { BB_WRITE4(buf,stamp); - ub = client_interact(CC_INSTALL,pos,strlen(fpath), + ub = client_interact(CC_INSTALL,pos,strlen(fpath), (unsigned char *)fpath+1, stamp==0?0:4, (unsigned char *)buf); } - if(ub->cmd == CC_ERR) { + if(ub->cmd == CC_ERR) { fprintf(stderr,"uploading %s: %s\n",path,ub->buf); free(fpath); - return(1); - } - + return(1); + } + if(!bytes && !first) break; #if SIZEOF_LONG > 4 if(pos+bytes>FOURGIGS) @@ -409,12 +409,12 @@ int util_upload PROTO3(char *, path, FILE *, fp, time_t , stamp) #endif pos += bytes; } - + t = time(NULL) - t; if(t == 0) t = 1; - if(client_trace) + if(client_trace) { - fprintf(stderr,"\r%luk : %s [%ldb/s] \n", 1+(pos>>10), path, pos/t); + fprintf(stderr,"\r%luk : %s [%ldB/s] \n", 1+(pos>>10), path, pos/t); fflush(stderr); } free(fpath); @@ -424,7 +424,7 @@ int util_upload PROTO3(char *, path, FILE *, fp, time_t , stamp) static void util_get_env PROTO0((void)) { char *p; - + if(!(env_host = getenv("FSP_HOST"))) { fputs("No FSP_HOST specified.\n",stderr); exit(1); @@ -442,17 +442,21 @@ static void util_get_env PROTO0((void)) client_trace = !!getenv("FSP_TRACE"); 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_SPACE) client_buf_len = UBUF_SPACE; client_net_len = htons(client_buf_len); - + if( (p = getenv("FSP_DELAY")) ) target_delay = atol(p); if(target_delay < MIN_DELAY) target_delay = MIN_DELAY; if(target_delay > MAX_DELAY) target_delay = MAX_DELAY; + if( (p = getenv("FSP_MAXDELAY")) ) target_maxdelay = atol(p); + if(target_maxdelay < target_delay) target_maxdelay = target_delay; + if(target_maxdelay > MAX_DELAY) target_maxdelay = MAX_DELAY; + if(!(env_local_dir = getenv("FSP_LOCAL_DIR"))) env_local_dir="."; - - if(!(p = getenv("FSP_TIMEOUT"))) env_timeout = 180; + + if(!(p = getenv("FSP_TIMEOUT"))) env_timeout = DEFAULT_TIMEOUT; else env_timeout = atol(p); } @@ -471,12 +475,12 @@ RDIR *util_opendir PROTO1(char *, path) RDIRENT **dep; DDLIST *ddp; RDIR *rdirp; - + fpath = util_abs_path(path); - + for(ddp = ddroot; ddp; ddp = ddp->next) if(!strcmp(ddp->path,fpath)) break; - + if(!ddp) { if(!(dep = get_dir_blk(fpath))) { @@ -490,9 +494,9 @@ RDIR *util_opendir PROTO1(char *, path) ddp->next = ddroot; ddroot = ddp; } else free(fpath); - + ddp->ref_cnt++; - + rdirp = (RDIR *) malloc(sizeof(RDIR)); rdirp->ddp = ddp; rdirp->dep = ddp->dep_root; @@ -509,17 +513,17 @@ rdirent *util_readdir PROTO1(RDIR *, rdirp) { static rdirent rde; RDIRENT **dep; - + dep = rdirp->dep; - + if(!*dep) return((rdirent *) 0); - + rde.d_fileno = 10; rde.d_rcdlen = 10; rde.d_namlen = strlen((*dep)->name); rde.d_name = (*dep)->name; rdirp->dep = dep+1; - + return(&rde); } @@ -533,10 +537,10 @@ int util_stat PROTO2(char *, path, struct stat *, sbuf) UBUF *ub; char *fpath,*fpath2, *ppath, *p1, *pfile; int cached=0; - + fpath = util_abs_path(path); fpath2 = strdup(fpath); - + if(!strcmp(fpath,env_dir)) { ppath = fpath; pfile = "."; @@ -564,19 +568,19 @@ int util_stat PROTO2(char *, path, struct stat *, sbuf) /* send a new FSP_STAT command to server */ ub = client_interact(CC_STAT,0L, strlen(fpath2), (unsigned char *) fpath2+1, 0, 0); - if(ub->cmd == CC_STAT) + if(ub->cmd == CC_STAT) { sbuf->st_uid = 0; sbuf->st_gid = 0; - sbuf->st_atime = sbuf->st_mtime = + sbuf->st_atime = sbuf->st_mtime = sbuf->st_ctime = BB_READ4((ub->buf)); sbuf->st_size = BB_READ4((ub->buf+4)); - if((ub->buf[8]) == RDTYPE_DIR) + if((ub->buf[8]) == RDTYPE_DIR) { sbuf->st_mode = 0777 | S_IFDIR; sbuf->st_nlink = 2; } - else + else { sbuf->st_mode = 0666 | S_IFREG; sbuf->st_nlink = 1; @@ -584,11 +588,11 @@ int util_stat PROTO2(char *, path, struct stat *, sbuf) free(fpath); free(fpath2); - - if(ub->buf[8]==0) + + if(ub->buf[8]==0) { errno = ENOENT; - return -1; + return -1; } return 0; } @@ -597,27 +601,27 @@ int util_stat PROTO2(char *, path, struct stat *, sbuf) statworks=0; } } /* CC_STAT */ - - if( (drp = util_opendir(ppath)) ) + + if( (drp = util_opendir(ppath)) ) { - for(dep = drp->dep; *dep; dep++) + for(dep = drp->dep; *dep; dep++) { - if(!strcmp((*dep)->name,pfile)) + if(!strcmp((*dep)->name,pfile)) { - if((*dep)->type == RDTYPE_DIR) + if((*dep)->type == RDTYPE_DIR) sbuf->st_mode = 0777 | S_IFDIR; - else + else sbuf->st_mode = 0666 | S_IFREG; - - if((*dep)->type == RDTYPE_DIR) + + if((*dep)->type == RDTYPE_DIR) sbuf->st_nlink = 2; - else + else sbuf->st_nlink = 1; sbuf->st_uid = 0; sbuf->st_gid = 0; sbuf->st_size = BB_READ4((*dep)->bb_size); - sbuf->st_atime = sbuf->st_mtime = + sbuf->st_atime = sbuf->st_mtime = sbuf->st_ctime = BB_READ4((*dep)->bb_time); util_closedir(drp); free(fpath); @@ -627,7 +631,7 @@ int util_stat PROTO2(char *, path, struct stat *, sbuf) } util_closedir(drp); } - + free(fpath); free(fpath2); errno = ENOENT; @@ -639,11 +643,11 @@ int util_cd PROTO1(char *, p) char *fpath; UBUF *ub; DDLIST *ddp; - + fpath = util_abs_path(p); for(ddp = ddroot; ddp; ddp = ddp->next) if(!strcmp(ddp->path,fpath)) break; - + if(!ddp && strcmp(p,".") && strcmp(p,"..")) { ub = client_interact(CC_GET_DIR,0L, strlen(fpath), (unsigned char *) fpath+1, 2, @@ -655,7 +659,7 @@ int util_cd PROTO1(char *, p) return(-1); } } - + if(env_dir_malloced) free(env_dir); env_dir_malloced = 1; env_dir = fpath; @@ -668,9 +672,9 @@ int util_cd PROTO1(char *, p) int util_cd2 PROTO1(char *, p) { char *fpath; - + fpath = util_abs_path(p); - + if(env_dir_malloced) free(env_dir); env_dir_malloced = 1; env_dir = fpath; @@ -678,9 +682,9 @@ int util_cd2 PROTO1(char *, p) } #ifdef PROTOTYPES -void util_process_file(char *path, int mode, +void util_process_file(char *path, int mode, void (*process_file)(char *,struct stat *, int, int), - int (*process_start_dir)(char *,struct stat *,u_long *), + int (*process_start_dir)(char *,struct stat *,u_long *), void (*process_end_dir)(char *,int,u_long,int), int level) #else @@ -703,7 +707,7 @@ void util_process_file(path, mode, process_file, process_start_dir, perror(path); return; } - + if (S_ISREG(sbuf.st_mode)) { if(process_file) (*process_file)(path, &sbuf, mode, level); } else if (S_ISDIR(sbuf.st_mode)) { diff --git a/clients/fcatcmd.c b/clients/fcatcmd.c index d9c86c3..92e8ae6 100644 --- a/clients/fcatcmd.c +++ b/clients/fcatcmd.c @@ -23,15 +23,15 @@ static RETSIGTYPE dont_die PROTO1(int, signum) { #ifndef RELIABLE_SIGNALS signal(SIGPIPE,dont_die); -#endif +#endif } - + int main PROTO2(int, argc, char **, argv) { char **av; env_client(); - + signal(SIGPIPE,dont_die); if(isatty(1)) client_trace = 0; @@ -44,8 +44,8 @@ int main PROTO2(int, argc, char **, argv) *av++; } } - + client_done(); - + exit(0); } diff --git a/clients/fcdcmd.c b/clients/fcdcmd.c index 164ab75..175764b 100644 --- a/clients/fcdcmd.c +++ b/clients/fcdcmd.c @@ -23,10 +23,10 @@ static int f_cd PROTO1(const char *, p) { UBUF *ub; - + ub = client_interact(CC_GET_PRO,0L, strlen(p), (unsigned const char *)p+1, 0, (unsigned char *)NULLP); - + if(ub->cmd == CC_ERR) { fprintf(stderr, "ERR: %s\n",ub->buf); return(0); @@ -41,7 +41,7 @@ int main PROTO2(int, argc, char **, argv) { char *np; char **av, *av2[2]; - + env_client(); if(argc == 1) { f_cd("/"); diff --git a/clients/fducmd.c b/clients/fducmd.c index e5bf036..72012b1 100644 --- a/clients/fducmd.c +++ b/clients/fducmd.c @@ -37,7 +37,7 @@ static void add_file_size PROTO4(char *, name, struct stat *, sbufp, int, mode, int, level) { register u_long file_size; - + file_size = (sbufp->st_size + 1023) / 1024; total_file_size += file_size; if(((mode & EACH) && (mode & RECURSIVE)) || @@ -70,9 +70,9 @@ int main PROTO2(int, argc, char **, argv) static const char *wild[2] = { ".", 0 }; char **files, *singlefile[2]; int optletter; - + env_client(); - + while ((optletter=getopt(argc, argv,"ras")) != EOF) switch (optletter) { case 'r': @@ -88,31 +88,31 @@ int main PROTO2(int, argc, char **, argv) fprintf(stderr,"Usage: du [-r|a|s] directory name.\n"); exit(0); } - + /* special case `du' without file arguments -- becomes `du .' */ if (argc == optind) { argv=wild; optind=0; } - + for ( ; argv[optind]; optind++) { if (!(files = glob(argv[optind]))) { files = singlefile; singlefile[0] = argv[optind]; singlefile[1] = 0; } - + for ( ; *files; files++) { util_process_file(*files, mode, add_file_size, start_dir, end_dir, 0); filcnt++; } } - + if (filcnt > 1) { fprintf(stdout, "--------:------\n"); fprintf(stdout, "%-7ld TOTAL\n", total_file_size); } - + client_done(); return 0; diff --git a/clients/ffindcmd.c b/clients/ffindcmd.c index 1c1bac2..b0b672b 100644 --- a/clients/ffindcmd.c +++ b/clients/ffindcmd.c @@ -69,14 +69,14 @@ static void eval_file PROTO4(char *, name, struct stat *, sbufp, int, mode, int, level) { register PLAN *p; - + for (p = plan; p && (p->eval)(p, sbufp, name); p = p->next); } static int eval_dir PROTO3(char *, name, struct stat *, sbufp, u_long *, sum) { register PLAN *p; - + process = 0; for (p = plan; p && (p->eval)(p, sbufp, name); p = p->next); return (process); @@ -86,18 +86,18 @@ int main PROTO2(int, argc, char **, argv) { register char **p; char *singlefile[2], **files; - + env_client(); (void)time(&now); /* initialize the time-of-day */ - + p = ++argv; - + /* First option delimits the file list. */ while (*p && !option(*p)) p++; if (p == argv) usage_ffind(); - + find_formplan(p); - + /* Execute plan for all file lists */ while (*argv) { if (argv >= p) break; @@ -108,10 +108,10 @@ int main PROTO2(int, argc, char **, argv) } for ( ; *files; files++) util_process_file(*files, 0, eval_file, eval_dir, 0L, 0); - + argv++; } - + client_done(); return(0); } diff --git a/clients/fgetcmd.c b/clients/fgetcmd.c index e4bca2a..eb84fd1 100644 --- a/clients/fgetcmd.c +++ b/clients/fgetcmd.c @@ -27,11 +27,11 @@ #if !defined(COMMAND_GRAB) && !defined(COMMAND_GET) #error "#define COMMAND_XXX to GET or GRAB when compiling this file" -#endif +#endif #if defined(COMMAND_GRAB) && defined(COMMAND_GET) #error "You must define COMMAND_GRAB -OR- COMMAND_GET" -#endif +#endif static int clobbertype=C_UNIQUE; static int preserve=0; @@ -50,9 +50,9 @@ static RETSIGTYPE fsp_cleanup PROTO1(int, signum) exit(1); } -static void +static void #ifdef COMMAND_GET -get_file +get_file #else grab_file #endif @@ -64,15 +64,15 @@ PROTO4(char *, path, struct stat *, sbufp, int, mode, int, level) #ifdef HAVE_UTIME_H struct utimbuf tb; #endif - - start_from = 0; - /* printf("Get function called!\n"); + + start_from = 0; + /* printf("Get function called!\n"); if(sbufp) { printf("We have stat *!\n"); } */ - + if (clobbertype==C_NOCLOBBER) { if ( (fp=fopen(name,"r"))) { fclose(fp); @@ -80,7 +80,7 @@ PROTO4(char *, path, struct stat *, sbufp, int, mode, int, level) return; } } - + if (clobbertype==C_UNIQUE) { fname=name; name=(char *)malloc(strlen(fname)+5); @@ -90,13 +90,13 @@ PROTO4(char *, path, struct stat *, sbufp, int, mode, int, level) sprintf(name,"%s-%d",fname,suffix); } } - + if (clobbertype==C_TEMPNAME) { fname=name; name=(char*)malloc(20); sprintf(name,".fsp.%d",getpid()); } - + if(clobbertype == C_APPEND) { if(stat(name, &statbuf) == 0) { start_from = statbuf.st_size; @@ -105,14 +105,14 @@ PROTO4(char *, path, struct stat *, sbufp, int, mode, int, level) start_from = 0;} } else start_from = 0; } else start_from = 0; - + if(start_from == 0) { fp = fopen(name, "w"); if (fp == NULL ) fprintf(stderr,"Cannot create %s\n",name); } - - if(fp) + + if(fp) { if( #ifdef COMMAND_GET @@ -120,7 +120,7 @@ PROTO4(char *, path, struct stat *, sbufp, int, mode, int, level) #else util_grab_file #endif - (path,fp, start_from) == -1) + (path,fp, start_from) == -1) { fclose(fp); if(clobbertype==C_TEMPNAME) @@ -128,7 +128,7 @@ PROTO4(char *, path, struct stat *, sbufp, int, mode, int, level) } else fclose(fp); } else fprintf(stderr,"Cannot write %s\n",name); - + #ifdef HAVE_UTIME_H /* update last modified time stamp */ if(preserve && sbufp) @@ -142,7 +142,7 @@ PROTO4(char *, path, struct stat *, sbufp, int, mode, int, level) rename(name,fname); free(name); } - + if (clobbertype==C_UNIQUE) { free(name); } @@ -179,7 +179,7 @@ static int make_dir PROTO3(char *, name, struct stat *, sbufp, u_long *, mode) static void usage PROTO0((void)) { - + #ifdef COMMAND_GET printf("fgetcmd"); #else @@ -187,7 +187,7 @@ static void usage PROTO0((void)) #endif printf(" -[|u|t|n|] -r -p -h -?\n"); } - + /* Parse options * -f forces overwrite (clobber) * -u forces unique names (unique) @@ -196,14 +196,14 @@ static void usage PROTO0((void)) * -a append to files if they exist (append) * -c same as -a * -o same as -f - * -r recursively get directories + * -r recursively get directories * -p preserve date/times of original file on downloaded copy */ int main PROTO2(int, argc, char **, argv) { char **av, *av2[2], n[1024]; int prompt, mode = 0; - + signal(SIGHUP,fsp_cleanup); signal(SIGINT,fsp_cleanup); signal(SIGQUIT,fsp_cleanup); @@ -224,7 +224,7 @@ int main PROTO2(int, argc, char **, argv) perror("chdir"); exit(1); } - + while ((optletter=getopt(argc, argv,"ofutnacrph?")) != EOF) switch (optletter) { case 'o': @@ -255,7 +255,7 @@ int main PROTO2(int, argc, char **, argv) usage(); exit(0); } - + if(argc > optind) { for( ; argc>optind ; optind++) { if(!(av = glob(argv[optind]))) { @@ -267,9 +267,9 @@ int main PROTO2(int, argc, char **, argv) { for(len = strlen(*av); len >= 0 && (*av)[len] != '/'; len--); len++; - util_process_file(*av, mode, + util_process_file(*av, mode, #ifdef COMMAND_GET - get_file, + get_file, #else grab_file, #endif @@ -303,7 +303,7 @@ int main PROTO2(int, argc, char **, argv) len++; util_process_file(*av, mode, #ifdef COMMAND_GET - get_file, + get_file, #else grab_file, #endif @@ -312,8 +312,8 @@ int main PROTO2(int, argc, char **, argv) } } } - + client_done(); - + exit(0); } diff --git a/clients/fhostcmd.c b/clients/fhostcmd.c index 73dfc34..372d772 100644 --- a/clients/fhostcmd.c +++ b/clients/fhostcmd.c @@ -96,7 +96,7 @@ void add_host(struct fsp_host *h) static struct fsp_host *find_host(const char *name) { int i,j; - + if(name==NULL || hostsize==0 ) return NULL; for(i=0;ipw_dir; /* for default search for file .fsp_prof*/ } else home=getenv("HOME"); - + /* * Figure out what shell we're using. A hack, we look for a shell * ending in "csh". @@ -189,7 +189,7 @@ int main PROTO2(int, argc, char **, argv) { csh = !strcmp(log + strlen(log) - 3, "csh"); } - + setup=init_host(); while ((optletter=getopt(argc, argv,"d:p:l:t:o:f:h:w:bc?")) != EOF) switch (optletter) { @@ -347,7 +347,7 @@ int main PROTO2(int, argc, char **, argv) } /* - * search order: curdir, homedir, sysdir + * search order: curdir, homedir, sysdir * * Returns: 1 for terminating scanner or 0 for switching */ @@ -356,7 +356,7 @@ int yywrap(void) { char *f2=NULL; int rc; - + if(yyin!=NULL) { fclose(yyin); @@ -393,6 +393,6 @@ int yywrap(void) rc=yywrap(); return rc; } - - return 0; + + return 0; } diff --git a/clients/flscmd.c b/clients/flscmd.c index a18ef0d..bdbef66 100644 --- a/clients/flscmd.c +++ b/clients/flscmd.c @@ -28,10 +28,10 @@ int ls_bad PROTO1(int, n) int main PROTO2(int, argc, char **, argv) { env_client(); - + fls_main(argc,argv); - + client_done(); - + exit(0); } diff --git a/clients/fmkdir.c b/clients/fmkdir.c index 1fde601..63cbed4 100644 --- a/clients/fmkdir.c +++ b/clients/fmkdir.c @@ -22,20 +22,20 @@ static int make_dir PROTO1(char *, p) { char *op; UBUF *ub; - + op = util_abs_path(p); - + ub = client_interact(CC_MAKE_DIR,0L, strlen(op), (unsigned char *)op+1, 0, (unsigned char *)NULLP); - + if(ub->cmd == CC_ERR) { fprintf(stderr,"Can't create %s: %s\n",p,ub->buf); free(op); return(-1); } - + printf("%s\t: %s\n",p,ub->buf); - + free(op); return(0); } @@ -45,6 +45,6 @@ int main PROTO2(int, argc, char **, argv) env_client(); while(*++argv) make_dir(*argv); client_done(); - + exit(0); } diff --git a/clients/fprocmd.c b/clients/fprocmd.c index b34d3e2..aa2d80a 100644 --- a/clients/fprocmd.c +++ b/clients/fprocmd.c @@ -24,9 +24,9 @@ static int get_pro PROTO1(const char *, p) { char *op; UBUF *ub; - + op = util_abs_path(p); - + ub = client_interact(CC_GET_PRO,0L, strlen(op), (unsigned char *)op+1, 0, (unsigned char *)NULLP); if(ub->cmd == CC_ERR) { @@ -35,7 +35,7 @@ static int get_pro PROTO1(const char *, p) } printf("%s\n",p); print_pro(ub,stdout); - + return(0); } @@ -43,9 +43,9 @@ static int set_pro PROTO2(char *, p, char *, key) { char *op; UBUF *ub; - + op = util_abs_path(p); - + ub = client_interact(CC_SET_PRO,0L, strlen(op), (unsigned char *)op+1, strlen(key)+1, (unsigned char *)key); if(ub->cmd == CC_ERR) { @@ -54,16 +54,16 @@ static int set_pro PROTO2(char *, p, char *, key) } printf("%s\n",p); print_pro(ub,stdout); - + return(0); } int main PROTO2(int, argc, char **, argv) { char **av, *av2[2], *key; - + env_client(); - + if(argv[1] && (argv[1][0] == '+' || argv[1][0] == '-') && !argv[1][2]) { key = *++argv; while(*++argv) { @@ -84,8 +84,8 @@ int main PROTO2(int, argc, char **, argv) while(*av) get_pro(*av++); } else get_pro(env_dir); } - + client_done(); - + exit(0); } diff --git a/clients/fput.c b/clients/fput.c index 653b7f1..35c9128 100644 --- a/clients/fput.c +++ b/clients/fput.c @@ -33,7 +33,7 @@ static int put_file PROTO1(char *, path) struct stat sb; char *name, *t2; FILE *fp; - + if(stat(path,&sb) != 0) { perror(path); return(0); @@ -42,10 +42,10 @@ static int put_file PROTO1(char *, path) fprintf(stderr,"%s: not a file\n",path); return(0); } - + for(name = t2 = path; *t2; t2++) if(*t2 == '/') name = t2 + 1; - + if( (fp = fopen(path,"rb"))) { util_upload(name,fp,timestamps==1?sb.st_mtime:0); fclose(fp); @@ -58,13 +58,13 @@ int main PROTO2(int, argc, char **, argv) { char n[1024]; int prompt; - + env_client(); if (strcmp(env_local_dir,".") && chdir(env_local_dir)) { perror("chdir"); exit(1); } - + while ((optletter=getopt(argc, argv,"ph?")) != EOF) switch (optletter) { case 'h': @@ -88,8 +88,8 @@ int main PROTO2(int, argc, char **, argv) put_file(n); } } - + client_done(); - + exit(0); } diff --git a/clients/frmcmd.c b/clients/frmcmd.c index 0ade708..47784a2 100644 --- a/clients/frmcmd.c +++ b/clients/frmcmd.c @@ -23,12 +23,12 @@ static int remove_it PROTO1(char *, p) { char *op; UBUF *ub; - + op = util_abs_path(p); - + ub = client_interact(CC_DEL_FILE,0L, strlen(op), (unsigned char *)op+1, 0, (unsigned char *)NULLP); - + if(ub->cmd == CC_ERR) { fprintf(stderr,"Can't remove %s: %s\n",p,ub->buf); free(op); return(-1); @@ -39,9 +39,9 @@ static int remove_it PROTO1(char *, p) int main PROTO2(int, argc, char **, argv) { char **av, *av2[2]; - + env_client(); - + while(*++argv) { if(!(av = glob(*argv))) { av = av2; @@ -50,8 +50,8 @@ int main PROTO2(int, argc, char **, argv) } while(*av) remove_it(*av++); } - + client_done(); - + exit(0); } diff --git a/clients/frmdircmd.c b/clients/frmdircmd.c index 8ac0320..d607e1c 100644 --- a/clients/frmdircmd.c +++ b/clients/frmdircmd.c @@ -23,12 +23,12 @@ static int remove_it PROTO1(char *, p) { char *op; UBUF *ub; - + op = util_abs_path(p); - + ub = client_interact(CC_DEL_DIR,0L, strlen(op), (unsigned char *)op+1, 0, (unsigned char *)NULLP); - + if(ub->cmd == CC_ERR) { fprintf(stderr,"Can't remove %s: %s\n",p,ub->buf); free(op); @@ -40,9 +40,9 @@ static int remove_it PROTO1(char *, p) int main PROTO2(int, argc, char **, argv) { char **av, *av2[2]; - + env_client(); - + while(*++argv) { if(!(av = glob(*argv))) { av = av2; @@ -51,8 +51,8 @@ int main PROTO2(int, argc, char **, argv) } while(*av) remove_it(*av++); } - + client_done(); - + exit(0); } diff --git a/clients/fspprof.l b/clients/fspprof.l index 6808de8..d186799 100644 --- a/clients/fspprof.l +++ b/clients/fspprof.l @@ -59,13 +59,13 @@ HOSTNAME [[:alpha:]][\-._[:alnum:]]+ } .|\n fprintf(stderr,"invalid hostname `%s`\n",yytext);BEGIN(INITIAL); (fsp{WHITESPACE})?port BEGIN(sport); -{WHITESPACE} +{WHITESPACE} {NUMBER} host->port=atoi(yytext);BEGIN(shost); .|\n fprintf(stderr,"invalid port `%s`\n",yytext);BEGIN(shost); alias{WHITESPACE} BEGIN(salias); {HOSTNAME} add_host_alias(host,yytext);BEGIN(shost); local{WHITESPACE}port BEGIN(slport); -{WHITESPACE} +{WHITESPACE} {NUMBER} host->local_port=atoi(yytext);BEGIN(shost); (fsp{WHITESPACE})?directory{WHITESPACE} BEGIN(sdir); \/[[:graph:]]* host->dir=strdup(yytext);BEGIN(shost); @@ -74,11 +74,11 @@ HOSTNAME [[:alpha:]][\-._[:alnum:]]+ [[:graph:]]* host->local_dir=strdup(yytext);BEGIN(shost); .|\n fprintf(stderr,"invalid local directory `%s`\n",yytext);BEGIN(shost); delay BEGIN(sdelay); -{WHITESPACE} +{WHITESPACE} {NUMBER} host->delay=atoi(yytext);BEGIN(shost); .|\n fprintf(stderr,"invalid delay `%s`\n",yytext);BEGIN(shost); timeout BEGIN(stimeout); -{WHITESPACE} +{WHITESPACE} {NUMBER} host->timeout=atoi(yytext);BEGIN(shost); .|\n fprintf(stderr,"invalid timeout `%s`\n",yytext);BEGIN(shost); trace{WHITESPACE}on host->trace=1; diff --git a/clients/fstatcmd.c b/clients/fstatcmd.c index 39962c0..fb6cac4 100644 --- a/clients/fstatcmd.c +++ b/clients/fstatcmd.c @@ -26,7 +26,7 @@ static void stat_file PROTO1(const char *,fname) struct stat sb; struct tm *ftime; char buf[35]; - + if(util_stat(fname,&sb)) { printf("%s: stat error\n",fname); @@ -37,7 +37,7 @@ static void stat_file PROTO1(const char *,fname) else if(S_ISDIR(sb.st_mode)) printf("Directory"); - + ftime=localtime(&sb.st_mtime); strftime(buf,35,"%Y-%m-%d %H:%M:%S",ftime); #ifdef NATIVE_LARGEFILES @@ -47,8 +47,8 @@ static void stat_file PROTO1(const char *,fname) #endif printf(": %s Size: "SFORM" Time: %s\n",fname,sb.st_size,buf); } - - + + } int main PROTO2(int, argc, char **, argv) @@ -56,20 +56,20 @@ int main PROTO2(int, argc, char **, argv) char n[1024]; int prompt; char **av, *av2[2]; - + env_client(); - + if(argc>1) { - for( optind=1; argc>optind ; optind++) + for( optind=1; argc>optind ; optind++) { - if(!(av = glob(argv[optind]))) + if(!(av = glob(argv[optind]))) { av = av2; av2[0] = argv[optind]; av2[1] = 0; } - while(*av) + while(*av) stat_file(*av++); } } else { @@ -86,12 +86,12 @@ int main PROTO2(int, argc, char **, argv) av2[0] = n; av2[1] = 0; } - while(*av) + while(*av) stat_file(*av++); } } - + client_done(); - + exit(0); } diff --git a/clients/fver.c b/clients/fver.c index b57aa62..84fc11b 100644 --- a/clients/fver.c +++ b/clients/fver.c @@ -24,7 +24,7 @@ int main PROTO2(int, argc, char **, argv) UBUF *ub; unsigned int len, tput = 0, len2; char *v1, *v2; - + if(argc == 1) { /* no arg supplied, get version string of server */ env_client(); ub = client_interact(CC_VERSION,0L, 0, (unsigned char *)NULLP, 0, @@ -64,6 +64,13 @@ int main PROTO2(int, argc, char **, argv) printf(" (max %d bytes/sec)\n", tput); } else printf("\tRemote server throughput control is DISABLED.\n"); + /* check for optional max. packet size block */ + if(++v2 < ub->buf+len+len2) + { + tput=0; + tput = BB_READ2(v2); + printf("\tMax. packet size supported by server is %d bytes.\n",tput); + } } else printf("\tRemote server do not send extended info.\n"); diff --git a/clients/merge.c b/clients/merge.c index 976da35..2068c0f 100644 --- a/clients/merge.c +++ b/clients/merge.c @@ -39,7 +39,7 @@ int main PROTO2(int, argc, char **, argv) char *p, *q; for(p = q = argv[0]; *p; p++) if(*p == '/') q = p+1; - + if(!strcmp(q,"fcatcmd")) fcatcmd_main(argc,argv); else if(!strcmp(q,"fcdcmd")) fcdcmd_main(argc,argv); else if(!strcmp(q,"fgetcmd")) fgetcmd_main(argc,argv); diff --git a/clients/printpro.c b/clients/printpro.c index 27d8b21..c69f171 100644 --- a/clients/printpro.c +++ b/clients/printpro.c @@ -28,12 +28,12 @@ int print_pro PROTO2(UBUF *, ub, FILE *, where) char flags; unsigned len, len1; char *pro1, *pro2; - + len = BB_READ2(ub->bb_len); len1 = BB_READ4(ub->bb_pos); pro1 = ub->buf; pro2 = ub->buf+len; - + if(len1) { flags = *pro2; fprintf(where,"owner: %s, del: %s, create: %s, mkdir: %s, get: %s, list: %s, rename: %s.\n", @@ -43,6 +43,6 @@ int print_pro PROTO2(UBUF *, ub, FILE *, where) } fprintf(where,"%s", pro1); fprintf(where,"\n"); - + return(0); } diff --git a/common/random.c b/common/random.c index 5921e7b..91e6e30 100644 --- a/common/random.c +++ b/common/random.c @@ -43,7 +43,7 @@ static char sccsid[] = "@(#)random.c 5.7 (Berkeley) 6/1/90"; * zeroeth element of the array is the type of R.N.G. being used (small * integer); the remainder of the array is the state information for the * R.N.G. Thus, 32 bytes of state information will give 7 longs worth of - * state information, which will allow a degree seven polynomial. (Note: the + * state information, which will allow a degree seven polynomial. (Note: the * zeroeth word of state information also has some other information stored * in it -- see setstate() for details). * The random number generation technique is a linear feedback shift register @@ -74,7 +74,7 @@ static char sccsid[] = "@(#)random.c 5.7 (Berkeley) 6/1/90"; #define BREAK_0 8 #define DEG_0 0 #define SEP_0 0 - + #define TYPE_1 1 /* x**7 + x**3 + 1 */ #define BREAK_1 32 #define DEG_1 7 @@ -104,7 +104,7 @@ static char sccsid[] = "@(#)random.c 5.7 (Berkeley) 6/1/90"; static int degrees[MAX_TYPES] = {DEG_0, DEG_1, DEG_2, DEG_3, DEG_4}; static int seps[MAX_TYPES] = {SEP_0, SEP_1, SEP_2, SEP_3, SEP_4}; - + /* * Initially, everything is set up as if from : * initstate( 1, &randtbl, 128 ); @@ -115,20 +115,20 @@ static int seps[MAX_TYPES] = {SEP_0, SEP_1, SEP_2, SEP_3, SEP_4}; * position of the rear pointer is just * MAX_TYPES*(rptr - state) + TYPE_3 == TYPE_3. */ - + static long randtbl[DEG_3+1] = {TYPE_3, - 0x9a319039, 0x32d9c024, 0x9b663182, + 0x9a319039, 0x32d9c024, 0x9b663182, 0x5da1f342, 0xde3b81e0, 0xdf0a6fb5, 0xf103bc02, 0x48f340fb, 0x7449e56b, 0xbeb1dbb0, 0xab5c5918, 0x946554fd, 0x8c2e680f, 0xeb3d799f, 0xb11ee0b7, 0x2d436b86, 0xda672e2a, 0x1588ca88, 0xe369735d, 0x904f35f7, 0xd7158fd6, - 0x6fa6f051, 0x616e6b96, 0xac94efdc, + 0x6fa6f051, 0x616e6b96, 0xac94efdc, 0x36413f93, 0xc622c298, 0xf5a42ab8, 0x8a88d77b, 0xf5ad9d0e, 0x8999220b, 0x27fb47b9 }; - + /* * fptr and rptr are two pointers into the state info, a front and a rear * pointer. These two pointers are always rand_sep places aparts, as they @@ -140,7 +140,7 @@ static long randtbl[DEG_3+1] = {TYPE_3, * randtbl) because the state table pointer is set to point to randtbl[1] * (as explained below). */ - + static long *fptr = &randtbl[SEP_3+1]; static long *rptr = &randtbl[1]; @@ -179,7 +179,7 @@ void srandom PROTO1(unsigned int, x) { register int i, j; long random(); - + if(rand_type == TYPE_0) state[0] = x; else { j = 1; @@ -212,7 +212,7 @@ void srandom PROTO1(unsigned int, x) char * initstate PROTO3(unsigned int, seed, char *, arg_state, int, n ) { register char *ostate = (char *)(&state[-1]); - + if(rand_type == TYPE_0) state[-1] = rand_type; else state[-1] = MAX_TYPES*(rptr - state) + rand_type; if(n < BREAK_1) { @@ -272,7 +272,7 @@ char *setstate PROTO1(char *, arg_state) register int type = new_state[0]%MAX_TYPES; register int rear = new_state[0]/MAX_TYPES; char *ostate = (char *)(&state[-1]); - + if(rand_type == TYPE_0) state[-1] = rand_type; else state[-1] = MAX_TYPES*(rptr - state) + rand_type; switch(type) { @@ -315,7 +315,7 @@ char *setstate PROTO1(char *, arg_state) long random PROTO0((void)) { long i; - + if(rand_type == TYPE_0) { i = state[0] = (state[0]*1103515245 + 12345)&0x7fffffff; } else { diff --git a/common/udp_io.c b/common/udp_io.c index 12a7d62..26ea4ab 100644 --- a/common/udp_io.c +++ b/common/udp_io.c @@ -33,14 +33,14 @@ int _x_udp PROTO1(unsigned short *, port) struct sockaddr_in me ; struct sockaddr_in myadr; int zz=1; - + memset(&me,0,sizeof(me)); - + me.sin_port = htons(*port); me.sin_family = AF_INET; len=sizeof(me); - + if((f=socket(AF_INET,SOCK_DGRAM,0)) == -1) return(-1); if(setsockopt(f,SOL_SOCKET,SO_REUSEADDR,(char *)&zz,sizeof(zz)) < 0 || @@ -51,7 +51,7 @@ int _x_udp PROTO1(unsigned short *, port) } if(!*port) *port = ntohs((unsigned short) myadr.sin_port); return(f); -} +} int _x_adr PROTO3(const char *, host, int, port, struct sockaddr_in *, his) { @@ -59,7 +59,7 @@ int _x_adr PROTO3(const char *, host, int, port, struct sockaddr_in *, his) struct hostent *H; int i; char *s, *d; - + memset(his,0,sizeof(his)); if(!host) { gethostname(myhost,sizeof(myhost)); @@ -76,21 +76,21 @@ int _x_adr PROTO3(const char *, host, int, port, struct sockaddr_in *, his) his->sin_family = H->h_addrtype; } else return(-1); his->sin_port = htons((unsigned short) port); - + return(0); } int _x_select PROTO2(fd_set *, rf, long, tt) /* tt is in unit of ms */ { struct timeval timeout; - + if(tt != -1) { if(tt < MIN_DELAY) tt = MIN_DELAY; timeout.tv_sec = tt / 1000; timeout.tv_usec = (tt % 1000)*1000; return(select(DSIZE, rf, NULL, NULL, &timeout)); } - + return(select(DSIZE, rf, NULL, NULL , (struct timeval *) 0)); } #endif /* not EXOS_IPC */ @@ -102,7 +102,7 @@ extern long rhost(); int _x_udp PROTO1(int *, port) { struct sockaddr_in sin; int f; - + sin = INET_ZERO; sin.sin_family = AF_INET; sin.sin_port = htons((unsigned short) *port); @@ -122,15 +122,15 @@ int _x_adr PROTO3(char *, host, int, port, struct sockaddr_in *, his) { char myhost[128]; int f; - + *his = INET_ZERO; if(!host) (void) gethostname(host = myhost,sizeof(myhost)); - + his->sin_family = AF_INET; his->sin_port = htons((unsigned short) port); - + if((his->sin_addr.s_addr = rhost(&host)) == -1) return(-1); - + return(0); } @@ -138,13 +138,13 @@ int _x_select PROTO2(unsigned int *, readfds, long, tt) { int code; long mask = *readfds; - + if(tt & 0xc0000000) tt = 0x3fffffff;/* It does not like 0x7fffffff. */ - + code = select(DSIZE, &mask, (long *) 0, tt); - + *readfds = mask; - + return(code); } diff --git a/configure.ac b/configure.ac index 476e263..9d03314 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ dnl Process this file with autoconf to produce a working configure script. dnl tested with autoconf 2.57 -AC_INIT(fsp,2.8.1b19,hsn@netmag.cz) +AC_INIT(fsp,2.8.1b20,hsn@netmag.cz) AC_CONFIG_SRCDIR(server/main.c) AM_INIT_AUTOMAKE([dist-bzip2]) AM_MAINTAINER_MODE diff --git a/contrib/fspscan.c b/contrib/fspscan.c index b58c2d9..d56e0e5 100644 --- a/contrib/fspscan.c +++ b/contrib/fspscan.c @@ -39,7 +39,7 @@ suite. Don't blame me for the code, i have not touched it. char *host = NULL; char *outputfile = NULL; /* Default values */ -int localport = 9191; +int localport = 9191; int remoteport = 21; int endport = 65535; int retries = 3; @@ -123,7 +123,7 @@ int main(int argc,char **argv) fprintf(stderr,"This error should not happen\n"); } } - + if (host == NULL) { fprintf(stderr, "host/ip not specified, unable to continue\n"); printhelp(argc, argv); @@ -148,7 +148,7 @@ int main(int argc,char **argv) fprintf(logfile,"Found FSP ver: %s on port %0d\n", ub->buf,remoteport); else - fprintf(logfile,"%0d...nada\n",remoteport); + fprintf(logfile,"%0d...nada\n",remoteport); fflush(logfile); fdclose(); } @@ -187,7 +187,7 @@ UBUF *client_interact(cmd,pos,l1,p1,l2,p2) for(t = (unsigned char *) &sbuf, sum = n = mlen; n--; sum += *t++); sbuf.sum = sum + (sum >> 8); - if(client_trace && retry) + if(client_trace && retry) write(2,"R",1); if(sendto(myfd,&sbuf,mlen,0,(struct sockaddr*)&server_addr,sizeof(server_addr)) == -1) @@ -237,7 +237,7 @@ void init_client(char *myhost,int port,int myport) { perror("socket open"); exit(1); } if(_x_adr(myhost,port,&server_addr) == -1) - { perror("server addr"); exit(1); } + { perror("server addr"); exit(1); } } @@ -261,15 +261,15 @@ int _x_udp(int *port) me.sin_port = htons((unsigned short) *port); me.sin_family = AF_INET; - + if((f=socket(AF_INET,SOCK_DGRAM,0)) == -1) return(-1); - + if( setsockopt(f,SOL_SOCKET,SO_REUSEADDR,&zz,sizeof(zz)) < 0 || bind(f,(struct sockaddr *) &me,(len = sizeof(me))) < 0 || getsockname(f,(struct sockaddr*)&sin,&len) < 0) { SAVE(((void) close(f))); return(-1); } if(!*port) *port = ntohs((unsigned short) sin.sin_port); return(f); -} +} int _x_adr(char *host,int port,struct sockaddr_in *his) { @@ -277,34 +277,34 @@ int _x_adr(char *host,int port,struct sockaddr_in *his) struct hostent *H; int i; char *s, *d; - + *his = INET_ZERO; if(!host) (void) gethostname(host = myhost,sizeof(myhost)); - - if((his->sin_addr.s_addr = inet_addr(host)) != INADDR_NONE) { + + if((his->sin_addr.s_addr = inet_addr(host)) != INADDR_NONE) { his->sin_family = AF_INET; } else - if(H = gethostbyname(host)) { - for(s = (char *)H->h_addr, - d = (char *)&his->sin_addr, + if(H = gethostbyname(host)) { + for(s = (char *)H->h_addr, + d = (char *)&his->sin_addr, i = H->h_length; i--; *d++ = *s++); his->sin_family = H->h_addrtype; } else return(-1); his->sin_port = htons((unsigned short) port); - + return(0); } int _x_select(fd_set *rf, long tt) /* tt is in unit of ms */ { struct timeval timeout; - + if(tt != -1) { timeout.tv_sec = tt / 1000; timeout.tv_usec = (tt % 1000)*1000; return(select(DSIZE, rf, NULL, NULL, &timeout)); } - + return(select(DSIZE, rf, NULL, NULL, (struct timeval *) 0)); } diff --git a/contrib/fspscan.h b/contrib/fspscan.h index b0497ff..0122921 100644 --- a/contrib/fspscan.h +++ b/contrib/fspscan.h @@ -12,7 +12,7 @@ #include /**************************************************************************** -* UBUF is the structure of message exchanged between server and clients. +* UBUF is the structure of message exchanged between server and clients. * * The 'buf' part of the buffer is variable lenght up to max of 1024. * The 'key' field is used by the server for sequence identification. @@ -21,7 +21,7 @@ * 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. Similarly, * the server's message to client contains a seq value that is the same -* as the seq value of the previous message from the client. +* as the seq value of the previous message from the client. * * The buf field is logically partitioned into two parts by the len field. * The len field indicate the size of the first part of the buffer starting diff --git a/doc/PROTOCOL b/doc/PROTOCOL index 0661371..35a9221 100644 --- a/doc/PROTOCOL +++ b/doc/PROTOCOL @@ -1,18 +1,17 @@ - File Service Protocol version 2 - specification + FILE SERVICE PROTOCOL VERSION 2 - Document version 0.9 - Last updated 18 Nov 2003 + Document version 0.10 + Last updated 18 Oct 2004 - Also known as - File Slurping Protocol, - Flaky Stream Protocol, + Also known as + File Slurping Protocol, + Flaky Stream Protocol, FTP's Sexier Partner, File Sharing Protocol or Fucking Slow Protocol. `FSP is what anonymous FTP *should* be' - + This document was created by Radim Kolar, because there is no RFC for FSP. It was planed, but never comes out. Based on sources of FSP 2.8.1 Beta 13. This document is not copyrighted and is placed into public domain. @@ -20,7 +19,7 @@ This document is not copyrighted and is placed into public domain. Data formats used in this document byte - unsigned 1 byte integer 0-255 word - unsigned 2 byte integer 0-65535 - long - unsigned 4 byte integer 0-4294967295 + long - unsigned 4 byte integer 0-4294967295 bits - counted from right to left. bit 0 is the lowest. NULL - byte 00 ASCIIZ - ASCII string terminated with one NULL (the same as used in C @@ -34,10 +33,31 @@ Data formats used in this document Numbers starting with 0x are in hexadecimal (base 16) notation. Transport + FSP uses UDP datagrams as transport medium. Minimum UDP packet size (not including size of UDP, IP and link layer headers) is 12 bytes, maximum UDP packet size is 1024+12 bytes. +Security + + Design + + FSP protocol was not designed to transfer secret data. It was designed as + alternative protocol for providing lightweight access to collection of public + files. FSP has the same user level of security as the anonymous FTP file + server. FSP has better network level security, because it was designed + to ressist various denial-of-service attacks. FSP protocol v3 will be + designed to be fully secure. FSP3 will not be backward compatible with + FSP2. + + Passwords + + Recently, password support was added to protocol, because just + too many people wants it and there were hacked version of FSP with + password support floating around. Passwords are transmited in clear + text over network which makes them a weak protection for determined + intruder. + FSP Packet format: HEADER - size = Fixed size 12 bytes. Always present. DATA - size = defined in header (DATA_LENGTH) @@ -57,9 +77,15 @@ HEADER FORMAT (12 bytes) MESSAGE_CHECKSUM Entire packet (HEADER + DATA + XTRA DATA) is checksumed. When computing a -checksum use zero in place of MESSAGE_CHECKSUM header field. Checksums are -computed as follows: - +checksum use zero in place of MESSAGE_CHECKSUM header field. + +Due to some unknown reason, method of computing checksums is different in each +direction. For packets travelling from server to client initial checksum +value is zero, otherwise it is HEADER + DATA + XTRA DATA size. + +Checksums in server->client direction are computed as follows: + + /* assume that we have already zeroed checksum in packet */ unsigned int sum,checksum; for(t = packet_start, sum = 0; t < packet_end; sum += *t++); checksum= sum + (sum >> 8); @@ -72,7 +98,7 @@ by server. TIMEOUTS Resends: Server will accept resent message from client with old KEY after 3 seconds. -Client MUST wait at least 1 second before resending a message. +Client MUST wait at least 1 second before resending a message. It is recommended to use initial delay of 1.34 second and after each unsuccessfull resend multiply delay time by 1.5. Maximum recommended delay time is 300 seconds. @@ -110,12 +136,12 @@ FSP File servers MUST supports following commands: CC_VERSION 0x10 - Get server version string and setup - + request file position: ignored data: not used xtra data: not used - + reply file position: size of optional extra version data data: ASCIIZ Server version string @@ -126,15 +152,21 @@ FSP File servers MUST supports following commands: bit 2 set - reverse lookup required bit 3 set - server is in private mode bit 4 set - thruput control + if bit 4 is set thruput info follows long - max_thruput allowed (in bytes/sec) + word - max. packet size supported by server + + Compatibility + + Max. packet size supported is reported only by fspd 2.8.1 b20 + or newer. - CC_ERR 0x40 - error response from server If you want to get a error from server, send any unknown client command (for example CC_ERR). CC_ERRs are normally sent only by server on - errors. + errors conditions. request (not used) file position: not used @@ -163,7 +195,7 @@ RDIRENT is the structure of a directory entry contained in a directory listing. Each entry contains a HEADER, which has 4 bytes quantity 'time' in Unix standard format, a 4 bytes quantity 'size', and 1 byte of 'type'. Header is followed by ASCIIZ encoded 'name'. RDIRENT is followed by enough number of -padding to fill to an 4-byte boundary. +padding to fill to an 4-byte boundary. At this point, if the next RDIRENT entry to follow will spread across 1k boundary, then two possible things will happen: @@ -171,14 +203,14 @@ boundary, then two possible things will happen: 1) if the HEADER fits between this entry and the 1k boundary, a complete header will be filled in with a 'type' set to RDTYPE_SKIP. Repeat this step as neceseary until no HEADER fits. - 2) if the HEADER does not fit, then simply pad to the 1k boundary. - + 2) if the HEADER does not fit, then simply pad to the 1k boundary. + This will make sure that messages carrying directory information carry only complete directory entries and no fragmented entries. - + The last entry is type RDTYPE_END. - struct RDIRENT { + struct RDIRENT { struct HEADER { long time; long size; @@ -205,7 +237,7 @@ RDIRENT.HEADER types: file position: same as in request data: binary file data xtra data: not used - + CC_UP_LOAD 0x43 - open a file for writing request @@ -217,7 +249,7 @@ RDIRENT.HEADER types: file position: same as in request data: not used xtra data: not used - + CC_INSTALL 0x44 - close and install file opened for writing request @@ -230,9 +262,9 @@ RDIRENT.HEADER types: file position: not used data: not used xtra data: not used - + CC_DEL_FILE 0x45 - delete a file - + request file position: not used data: ASCIIZ filename @@ -242,7 +274,7 @@ RDIRENT.HEADER types: file position: not used data: not used xtra data: not used - + CC_DEL_DIR 0x46 - delete a directory request @@ -262,21 +294,27 @@ RDIRENT.HEADER types: data: ASCIIZ directory xtra data: (not required) word - size of reply's optional data block - + reply file position: number of extra protection bytes (now 1) data: ASCIIZ directory readme xtra data: extra protection data (format follows) -Protection bits: - 0 - caller owns the directory - 1 - files can be deleted from this dir - 2 - files can be added to this dir - 3 - new subdirectories can be created - 4 - files are NOT readable by non-owners - 5 - directory contain an readme file - 6 - directory can be listed - 7 - files can be renamed in this directory + Protection bits: + 0 - caller owns the directory + 1 - files can be deleted from this dir + 2 - files can be added to this dir + 3 - new subdirectories can be created + 4 - files are NOT readable by non-owners + 5 - directory contain an readme file + 6 - directory can be listed + 7 - files can be renamed in this directory + + Compatibility + + Versions older than 2.8.1b6 do not uses bits 6 and 7. This + causes that directory can be listable even it do not have + 6th bit set. CC_SET_PRO 0x48 - set directory protection @@ -297,9 +335,13 @@ Protection bits: reply same as CC_GET_PRO + + Compatibility + FSP versions older than 2.8.1 beta15 used p flag instead + g flag. +p = -g CC_MAKE_DIR 0x49 - create a directory - + request file position: not used data: ASCIIZ directory name @@ -319,16 +361,20 @@ Protection bits: optional data: not used xtra data: not used + You should send this packet when you are done with + talking to server. This causes that server will + accept next packet from your IP with any key. + Commands starting from FSP version 2.4 ( released March 27, 1992 ) - + CC_GRAB_FILE 0x4B - atomic get+delete a file - + same format as CC_GET_FILE, but file is deleted after sucessfull transfer is done. If there are multiple grabs for the same file, only one will succeed. - + CC_GRAB_DONE 0x4C - atomic get+delete a file done - + same format as CC_INSTALL. File is not installed, but deleted. @@ -349,21 +395,27 @@ Commands starting from FSP 2.8.1 Beta 11 data format is the same as in directory listing with exception that there is no file name appended. If file do not exists or there is other problem (no access rights) return type of file is - 0. CC_ERR message is NOT returned in this case. - - struct STAT { - long time; - long size; - byte type; - } - + 0. + + struct STAT { + long time; + long size; + byte type; + } + + Compatibility + CC_ERR message is NEVER returned as reply to CC_STAT command + by server supporting CC_STAT command. If you have got CC_ERR reply, + you are talking to old server, which do not supports this + command. + CC_RENAME 0x4E - rename file or directory request file position: not used data: ASCIIZ source file or directory ASCIIZ destination file or directory xtra data: not used - + Note: It is possible to do cross-directory rename. In this case you must have rights to DELETE in source directory and to CREATE in target directory. @@ -380,6 +432,7 @@ Reserved commands: CC_LIMIT 0x80 - commands > 0x7F will have extended header. No such extensions or commands - which uses that are known today. - + which uses that are known today. This + header will be used in protocol version 3. + CC_TEST 0x81 - reserved for testing of new header diff --git a/fspd.conf b/fspd.conf index 97fae1d..c9cf9aa 100644 --- a/fspd.conf +++ b/fspd.conf @@ -42,12 +42,13 @@ use_access_files yes permit_passwordless_owners off # The 'tmpdir' command controls where the server stores temporary files -# during upload or grab. +# during upload or grab. You must have it or server will support +# read operations only. This can be absolute or relative path to home +# dir. Server will try to create it. # tmpdir /tmp/fsp -# The 'pidlogname command controls where we write the fspd pid -# This command is required! +# The 'pidlogname command controls where we write the fspd pid. pidlogname /var/run/fspd.pid # The 'grabcommand' can turn grab command on or off. @@ -64,12 +65,12 @@ vercommand on # readme .README # The 'dircache' command controls how much directories listings gets cached. -dircache 50 +dircache 100 # 'use_prebuild_dirlists' allows to load/save prebuilded directories # listing from filesystem. It is a good idea to allow that. -# Win32: Set to NO -use_prebuild_dirlists yes +# Do not use on Win32 system. +#use_prebuild_dirlists yes # The 'statcache' command controls how many directories are placed into # stat cache. Cache contains last modified time and access rights. @@ -82,8 +83,8 @@ statcache_timeout 15 # 'use_directory_mtime'. If your filesystem changes mtime when directory # is updated, set it to YES. If set to NO, directory will be rechecked # after statcache_timeout and dircache entry invalidated. -# Win32: Set to NO -use_directory_mtime yes +# Do not use on Win32 system. +#use_directory_mtime yes # The 'filecache' command controls maximal number of open files by server. # After this limit will be reached, server will close last recently used files. @@ -229,11 +230,12 @@ xferlog ../logs/xferlog # pass after new packet with the old KEY from client will be accepted # FSP protocol definition says that must be at least 3 secs, but you # can set this to shorter time and allow faster error recovery. It is -# higly recommended to keep 3 seconds. +# higly recommended to keep it at least 3 seconds. # retry 3 # The "timeout" command specifies how much time must pass after new # packet with wrong KEY number is accepted. FSP definition sets this -# to 60 seconds. +# to 60 seconds. You can set it to lower value for faster clients +# recovery (about 20 sec is fine). # timeout 60 diff --git a/include/c_extern.h b/include/c_extern.h index b4883ee..beef653 100644 --- a/include/c_extern.h +++ b/include/c_extern.h @@ -3,9 +3,9 @@ /* lib.c */ extern int client_trace; -extern unsigned long udp_sent_time,target_delay; +extern unsigned long udp_sent_time,target_delay,target_maxdelay; UBUF *client_interact PROTO0((unsigned char, unsigned long, unsigned int, - unsigned const char *, unsigned int, + unsigned const char *, unsigned int, unsigned const char *)); void init_client PROTO0((const char *, unsigned short, unsigned short)); int client_done PROTO0((void)); @@ -14,12 +14,13 @@ int client_done PROTO0((void)); extern int key_persists; unsigned short client_get_key PROTO0((void)); void client_set_key PROTO0((unsigned short)); +void client_destroy_key PROTO0((void)); void client_init_key PROTO0((unsigned long, unsigned long, unsigned short)); /* util.c */ extern const char *env_dir,*env_passwd,*env_local_dir,*env_port,*env_myport,*env_host; -extern int env_timeout; +extern unsigned int env_timeout; extern unsigned short client_buf_len,client_net_len; char *util_abs_path PROTO0((const char *)); char *util_getwd PROTO0((char *)); @@ -33,10 +34,10 @@ rdirent *util_readdir PROTO0((RDIR *)); int util_stat PROTO0((char *, struct stat *)); int util_cd PROTO0((char *)); int util_cd2 PROTO0((char *)); -void util_process_file PROTO0((char *, int, - void (*)PROTO0((char *,struct stat *,int,int)), +void util_process_file PROTO0((char *, int, + void (*)PROTO0((char *,struct stat *,int,int)), int (*)PROTO0((char *,struct stat *,u_long *)), - void (*)PROTO0((char *,int,u_long,int)), + void (*)PROTO0((char *,int,u_long,int)), int)); #endif /* _FSP_C_EXTERN_H_ */ diff --git a/include/client_def.h b/include/client_def.h index 15c9916..83c3f86 100644 --- a/include/client_def.h +++ b/include/client_def.h @@ -24,7 +24,7 @@ remote file is not found */ #define C_UNIQUE 3 /* Create unique name to avoid overwrite */ #define C_TEMPNAME 4 /* Download to temp name */ -#define C_APPEND 5 /* Downloads will attempt to append to +#define C_APPEND 5 /* Downloads will attempt to append to end of file if it already exists */ /**************************************************************************** diff --git a/include/common_def.h b/include/common_def.h index cdc325c..5a1b544 100644 --- a/include/common_def.h +++ b/include/common_def.h @@ -62,7 +62,7 @@ #endif /**************************************************************************** -* UBUF is the structure of message exchanged between server and clients. +* UBUF is the structure of message exchanged between server and clients. * * The 'buf' part of the buffer is variable length up to max of 1024. * The 'key' field is used by the server for sequence identification. @@ -71,7 +71,7 @@ * 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. Similarly, * the server's message to client contains a seq value that is the same -* as the seq value of the previous message from the client. +* as the seq value of the previous message from the client. * * The buf field is logically partitioned into two parts by the len field. * The len field indicate the size of the first part of the buffer starting @@ -169,6 +169,8 @@ typedef struct RDIRENT { unsigned char bb_time[4]; #define MIN_DELAY 1000L #define DEFAULT_DELAY 1340L -#define MAX_DELAY 300000L +#define DEFAULT_MAXDELAY 60000L +#define MAX_DELAY 300000L +#define DEFAULT_TIMEOUT 360 #endif /* _FSP_COMMON_DEF_H_ */ diff --git a/include/proto.h b/include/proto.h index 087fd3b..a9cbf4a 100644 --- a/include/proto.h +++ b/include/proto.h @@ -3,7 +3,7 @@ /* #ifdef UNDERSTANDS_PROTOTYPES */ -#ifdef PROTOTYPES +#ifdef PROTOTYPES #define PROTO0(a) a #define PROTO1(a, b) (a b) #define PROTO2(a, b, c, d) (a b, c d) diff --git a/include/server_conf.h b/include/server_conf.h index 7b96821..3c2cacd 100644 --- a/include/server_conf.h +++ b/include/server_conf.h @@ -24,16 +24,16 @@ * Following setting is a minimum recommended size. * ****************************************************************************/ -#define DEFAULT_DIRLISTCACHE_SIZE 32 +#define DEFAULT_DIRLISTCACHE_SIZE 50 /**************************************************************************** * DEFAULT_DIRSTATCACHE_SIZE should be set to contain the number of dirs * * you want to held in dirstat memory cache. This cache avoids calling stat * - * on directory and loading access perms. This operation is far less + * on directory and loading access perms. This operation is far less * expensive than listing a directory, so if can be a lower number. */ -#define DEFAULT_DIRSTATCACHE_SIZE 20 +#define DEFAULT_DIRSTATCACHE_SIZE 30 /* THCCOUNT is the number of seconds used to compute average throughput. * 10 seconds seems to be a good value diff --git a/include/server_def.h b/include/server_def.h index 2a9d07e..b2b91a6 100644 --- a/include/server_def.h +++ b/include/server_def.h @@ -45,7 +45,7 @@ typedef struct { * path string. See server_file.c for more info. *****************************************************************************/ -typedef struct { +typedef struct { const char *fullp; /* ptr to string containing full pathname */ const char *f_ptr; /* ptr to begining of last path component */ unsigned int f_len; /* length of last component in path */ @@ -101,7 +101,7 @@ typedef struct { #define L_MAKEDIR 0x0200 #define L_GRABFILE 0x0400 #define L_GETPRO 0x0800 -#define L_RDONLY 0x1000 +#define L_RDONLY 0x1000 #define L_STAT 0x2000 #define L_RENAME 0x4000 #define L_ALL 0xffff @@ -118,5 +118,5 @@ typedef struct { #define FSP_OWNER ".FSP_OWNER" #define FSP_PASSWORD ".FSP_OK_PASSWORD" #define FSP_OWNERPASSWORD ".FSP_OWNER_PASSWORD" - + #endif /* _FSP_SERVER_DEF_H_ */ diff --git a/include/tweak.h b/include/tweak.h index e4b5497..79268aa 100644 --- a/include/tweak.h +++ b/include/tweak.h @@ -77,7 +77,7 @@ #ifdef WORD_TYPE_4 /* there is an integer type of size 4 */ -#define BB_READ4(V) ntohl(*(WORD_TYPE_4 *)(V)) +#define BB_READ4(V) ntohl(*(const WORD_TYPE_4 *)(V)) #define BB_WRITE4(V,A) *(WORD_TYPE_4 *)(V) = htonl(A) #else /* there is no integer type of size 4 */ diff --git a/man/Makefile.am b/man/Makefile.am index 602888d..4037448 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -2,6 +2,7 @@ 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 + frmdircmd.1 fsp_prof.5 fspd.1 fver.1 fstatcmd.1 fspscan.1 \ + fsp_env.7 -EXTRA_DIST=$(man_MANS) +EXTRA_DIST=$(man_MANS) diff --git a/man/fsp_env.7 b/man/fsp_env.7 index 02a5ac9..078e9ff 100644 --- a/man/fsp_env.7 +++ b/man/fsp_env.7 @@ -42,11 +42,15 @@ so that network speed has an indicator. This variable has no effect when the standard output is a terminal. .TP .B FSP_TIMEOUT -If this variable is set, it contains the timeout value. The default value is 180. +If this variable is set, it contains the timeout value in seconds. +The default value is 360. No function if program was compiled without timeout code. .TP .B FSP_DELAY Minimum wait time before resending packet in milliseconds. .TP +.B FSP_MAXDELAY +Maximum wait time before resending packet in milliseconds. +.TP .B FSP_LOCAL_DIR Where to look for local files. Default is current directory. diff --git a/man/fspd.1 b/man/fspd.1 index 5461f67..573d65d 100644 --- a/man/fspd.1 +++ b/man/fspd.1 @@ -1,8 +1,8 @@ -.TH FSPD 1 "29 Sep 2003" FSP +.TH FSPD 1 "18 Oct 2004" FSP .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 fspd [-f configfile] [-p port] [-i] [-v|-V] [-t timeout] [-X] [-d directory] [-F ] [-T temporary directory] [-l logfile] [-P pidlogname] [-b bandwidth] .SH DESCRIPTION .B fspd is the server for an anonymous-ftp style archive called FSP. The main @@ -69,8 +69,14 @@ Write log output to file. .PD 0 .TP 20 .B -P pidlogname -Write pid to the given file name. This Option is required, if it's -not given in your fspd.conf or on command line fspd will fail to start. +Write pid to the given file name. + +.PD 0 +.TP 20 +.B -b bandwidth +Enable bandwidth limiting. Limit output to +.I bandwidth +bytes per second. .LP .SH FILES @@ -163,6 +169,12 @@ Server dumps stats to file specified as dumpfile in configuration. This file must be writeable by server or server must have rights to create it. +.TP +.B SIGINT | SIGTERM +Server performs cleaup and exits. All connected clients will be +disconnected. Because FSP is stateless protocol, if you start +server later, than can continue without breakage. + .SH EXIT CODES .B 1 configuration or command line invocation error. diff --git a/man/fver.1 b/man/fver.1 index f530816..798a285 100644 --- a/man/fver.1 +++ b/man/fver.1 @@ -1,4 +1,4 @@ -.TH FVER 1 "8 December 1991" FSP +.TH FVER 1 "Oct 2004" FSP .SH NAME fver \- displays the version number string of the FSP database .SH SYNOPSIS @@ -8,7 +8,7 @@ fver \- displays the version number string of the FSP database .LP Without arguments, .B fver -displays the version string of the FSP database. +displays the version string of the FSP server. Otherwise, the version string of the client utilities is displayed. .SH ENVIRONMENT .LP diff --git a/server/Makefile.am b/server/Makefile.am index 7cca6c2..310f389 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -2,7 +2,7 @@ bin_PROGRAMS=fspd -fspd_SOURCES=file.c host.c main.c conf.c filecache.c server.c fifocache.c \ +fspd_SOURCES=file.c host.c main.c conf.c server.c fifocache.c \ log.c iprange.c acl.c path.c random.c pidfile.c fspd_CFLAGS=-DSYSCONFDIR="\"@sysconfdir@\"" $(AM_CFLAGS) fspd_LDADD=-L../common -lcommon diff --git a/server/acl.c b/server/acl.c index ea25c64..eaaa0bc 100644 --- a/server/acl.c +++ b/server/acl.c @@ -60,7 +60,7 @@ void save_access_rights PROTO1(DIRINFO *,di) unlink(FSP_OWNER); unlink(FSP_OWNERPASSWORD); unlink(FSP_DIRLISTING); - + if(!use_access_files) return; /* step2 save flagfiles */ @@ -110,8 +110,8 @@ void load_access_rights PROTO1(DIRINFO *,di) { unsigned int s; /* max readme file size is - * packetsize - pro_bytes (now 1) - 1 (for /0) - */ + * packetsize - pro_bytes (now 1) - 1 (for /0) + */ s=min(packetsize-PRO_BYTES-1,sf.st_size); di->readme=malloc(s+1); if(di->readme) @@ -124,7 +124,7 @@ void load_access_rights PROTO1(DIRINFO *,di) } if(!use_access_files) return; - + /* LOAD ACCESS RIGHTS FROM FILES IN CURRENT DIRECTORY */ if(fexist(FSP_NOGET)) di->protection^=DIR_GET; if(fexist(FSP_DEL)) di->protection|=DIR_DEL; @@ -135,13 +135,13 @@ void load_access_rights PROTO1(DIRINFO *,di) if(!FSP_STAT(FSP_PASSWORD,&sf)) if(sf.st_size>0) di->public_password=load_password(FSP_PASSWORD); - + /* load owner info */ f=fopen(FSP_OWNER,"r"); if(!f) return; - while(fscanf(f, "%255[^\n\r]", owner_line) == 1) + while(fscanf(f, "%255[^\n\r]", owner_line) == 1) { add_ipline(owner_line,&di->owner); } @@ -162,17 +162,17 @@ void load_access_rights PROTO1(DIRINFO *,di) const char * require_access_rights PROTO4(const DIRINFO *,di,unsigned char,rights,unsigned long, ip_addr, const char *, passwd) { const char *acc=NULL; - + /* check if we has record in an owner tabl. */ if(di->owner) { /* check ip access */ acc=check_ip_table(ip_addr,di->owner); } - + if(acc!=NULL) { - if(acc[0]=='I' || acc[0]=='D') + if(acc[0]=='I' || acc[0]=='D') /* bazmeg IP! */ return acc; if(acc[0]=='O') /* possible owner */ @@ -209,8 +209,8 @@ const char * require_access_rights PROTO4(const DIRINFO *,di,unsigned char,right } /* now check public access rights */ - if( (rights & di->protection) || - (rights==0) + if( (rights & di->protection) || + (rights==0) ) return "NWelcome on board captain!"; else diff --git a/server/conf.c b/server/conf.c index 5399991..8b3bad2 100644 --- a/server/conf.c +++ b/server/conf.c @@ -22,7 +22,7 @@ static int conf_read = 0; int daemonize = 1; -int use_prebuild_dirlists = +int use_prebuild_dirlists = #ifdef OS_CYGWIN 0; #else @@ -40,7 +40,7 @@ int no_unnamed = 0; int logging = 0; int use_access_files = 1; int use_directory_mtime = -#ifdef OS_CYGWIN +#ifdef OS_CYGWIN 0; #else 1; @@ -94,7 +94,7 @@ static int get_boolean PROTO1(const char, *q) else if(strcmp(q, "1") == 0) return 1; else - + fprintf(stderr,"Bogus boolean value '%s'. Exiting.\n",q); exit(1); return -1; @@ -157,7 +157,7 @@ static void read_configuration PROTO1(const char *, name) int neg; do { /* skip to next token */ - r = q; while(*r && !isspace(*r)) r++; + r = q; while(*r && !isspace(*r)) r++; if (*r) { *r++ = 0 ; while(*r && isspace(*r)) r++; } if(strcasecmp(q, "none") == 0) { logging = L_NONE; @@ -210,11 +210,11 @@ static void read_configuration PROTO1(const char *, name) retry_timeout = atoi(q); if(retry_timeout < 1 ) retry_timeout = 3; } - else if(strcasecmp(p, "timeout") == 0) { + else if(strcasecmp(p, "timeout") == 0) { session_timeout = atoi(q); if(session_timeout <= 5 ) session_timeout = 60; } - else if(strcasecmp(p, "statcache_timeout") == 0) { + else if(strcasecmp(p, "statcache_timeout") == 0) { session_timeout = atoi(q); if(stat_cache_timeout <= 0 ) stat_cache_timeout = 20; } @@ -289,5 +289,6 @@ void destroy_configuration PROTO0((void)) if(iptab) free_ip_table(iptab); readme_file = home_dir = logname = tmp_dir = dumpname = NULL; - iptab = pidlogname = NULL; + iptab = NULL; + pidlogname = NULL; } diff --git a/server/fifocache.c b/server/fifocache.c index 8ef330c..43a3696 100644 --- a/server/fifocache.c +++ b/server/fifocache.c @@ -1,5 +1,5 @@ -/* - * Simple FIFO generic cache. (c) Radim Kolar 2003. +/* + * Simple FIFO generic cache. (c) Radim Kolar 2003. * This file is copyrighted as LGPL. * * When this file is used as part of FSP, it uses 2-term BSD license @@ -30,7 +30,7 @@ struct FifoCache * f_cache_new(unsigned int cachesize,unsigned int entrysize, cache->e_head=calloc(1,1); else cache->e_head=calloc(cachesize,entrysize); - + if(keysize==0) cache->k_head=calloc(1,1); else @@ -42,18 +42,18 @@ struct FifoCache * f_cache_new(unsigned int cachesize,unsigned int entrysize, return NULL; } cache->k_next=cache->k_head; - + if(keysize==0) cache->k_stop=NULL; else cache->k_stop=cache->k_head+cache->keysize*cache->cachesize; - + cache->e_next=cache->e_head; if(entrysize==0) cache->e_stop=NULL; else cache->e_stop=cache->e_head+cache->entrysize*cache->cachesize; - + cache->k_destroy_func=kdf; cache->e_destroy_func=edf; cache->k_compare_func=kcf; @@ -120,7 +120,7 @@ unsigned int f_cache_void_profiler(void *anything) void f_cache_destroy(struct FifoCache *cache) { if(cache==NULL) return; - if(cache->e_head) + if(cache->e_head) { memset(cache->e_head,0,cache->entrysize*cache->cachesize); free(cache->e_head); @@ -151,7 +151,7 @@ void * f_cache_put(struct FifoCache *cache,const void *key,const void *data) /* update next pos. */ cache->e_next+=cache->entrysize; cache->k_next+=cache->keysize; - + /* roll over? */ if(cache->e_next==cache->e_stop || cache->k_next==cache->k_stop) { @@ -166,10 +166,10 @@ void * f_cache_put(struct FifoCache *cache,const void *key,const void *data) void *f_cache_find(struct FifoCache *cache,const void *key) { unsigned int i; - + if(!cache->k_compare_func) return NULL; if(cache->keysize==0) return NULL; - + for(i=0;icachesize;i++) if(!cache->k_compare_func(key,cache->k_head+i*cache->keysize)) { @@ -188,16 +188,16 @@ void f_cache_clear(struct FifoCache *cache) /* free entries */ for(i=0;icachesize;i++) { - if(cache->k_destroy_func) + if(cache->k_destroy_func) cache->k_destroy_func(cache->k_head+i*cache->keysize); - if(cache->e_destroy_func) + if(cache->e_destroy_func) cache->e_destroy_func(cache->e_head+i*cache->entrysize); } /* clear entries */ memset(cache->k_head,0,cache->cachesize*cache->keysize); memset(cache->e_head,0,cache->cachesize*cache->entrysize); - + cache->k_next=cache->k_head; cache->e_next=cache->e_head; @@ -227,14 +227,14 @@ int f_cache_delete_entry(struct FifoCache *cache, void *entry) if(entry<(const void *)cache->e_head || entry>=(const void *)cache->e_stop) return 0; /* find cache index */ i=((BYTE *)(entry)-cache->e_head)/cache->entrysize; - + /* deallocate */ if(cache->k_destroy_func) cache->k_destroy_func(cache->k_head+cache->keysize*i); if(cache->e_destroy_func) cache->e_destroy_func(entry); /* zero them */ memset(entry,0,cache->entrysize); memset(cache->k_head+cache->keysize*i,0,cache->keysize); - + return 1; } diff --git a/server/file.c b/server/file.c index 6ff33ce..8b25024 100644 --- a/server/file.c +++ b/server/file.c @@ -37,15 +37,15 @@ static struct FifoCache *fpcache; #define TWOGIGS 0x7fffffffUL static FPCACHE *search_fpcache PROTO3(unsigned long, inet_num, - unsigned short, port_num, + unsigned short, port_num, const char *, fname) { unsigned int i; FPCACHE *entry; const char **key; - - for (i=0;ie_head+i*sizeof(FPCACHE)); if (port_num==entry->port_num && inet_num==entry->inet_num) @@ -85,7 +85,7 @@ static unsigned int fpcache_entry_profiler PROTO1(void *,entry) static void dirlistcache_free_entry PROTO1(void *, entry) { DIRLISTING *d=entry; - + if(d->listing) free(d->listing); } @@ -100,7 +100,7 @@ static unsigned int dirlistcache_entry_profiler PROTO1(void *,entry) static void dirstatcache_free_entry PROTO1(void *, entry) { DIRINFO *d=entry; - + if(d->realname) free(d->realname); if(d->owner_password) @@ -155,7 +155,7 @@ static void string_free PROTO1(void *, entry) static unsigned int string_profiler PROTO1(void *,entry) { char **s=entry; - + if(*s!=NULL) return(strlen(*s)); else @@ -231,14 +231,14 @@ void shutdown_caches PROTO0((void)) /***************************************************************************** * Validate path - check that path does not fall outside the bounds of the - * FSP root directory, weed out references to / and ../.. type links. + * FSP root directory, weed out references to / and ../.. type links. * Input: fullp - pointer to full filename * lenfullp - length of full filename (including \0) * *di - where to return DIRINFO information about directory - * want_directory - want to operate on directory, not a file + * want_directory - want to operate on directory, not a file *****************************************************************************/ const char *validate_path PROTO5(char *, fullp, unsigned, lenfullp, PPATH *, pp,DIRINFO **,di, int, want_directory) -{ +{ char work [NBSIZE]; const char *err; char *s; @@ -350,7 +350,7 @@ static const char *copy_file PROTO2(const char *, n1, const char *, n2) if(!(ft = fopen(n1,"rb"))) { return("Can't open temporary file"); } - + if(!(fp = fopen(n2,"wb"))) { fclose(ft); return("Can't open file for output"); @@ -359,7 +359,7 @@ static const char *copy_file PROTO2(const char *, n1, const char *, n2) /* copy temporary file to actual fput file */ while( (bytes = fread(buf,1,sizeof(buf),ft))) fwrite(buf,1,bytes,fp); - + fclose(ft); fclose(fp); return NULL; @@ -369,7 +369,7 @@ static const char *copy_file PROTO2(const char *, n1, const char *, n2) static int append_dir_listing PROTO3(DIRLISTING *, dl,const char *, buf,unsigned int, size) { BYTE *newbuf; - + /* append this buffer */ newbuf=realloc(dl->listing,dl->listing_size+size); if(newbuf==NULL) @@ -381,12 +381,12 @@ static int append_dir_listing PROTO3(DIRLISTING *, dl,const char *, buf,unsigned memcpy(newbuf+dl->listing_size,buf,size); dl->listing_size+=size; dl->listing=newbuf; - + return 0; } /* builds directory listing into DIRLISTING structure, in case of any - * error. nulls dl->listing + * error. nulls dl->listing */ static void build_dir_listing PROTO2(DIRLISTING *, dl,const char *,directory) { @@ -401,7 +401,7 @@ static void build_dir_listing PROTO2(DIRLISTING *, dl,const char *,directory) char name[NBSIZE]; /* buffer for stat name */ int namelen; /* directory name length */ unsigned int bufpos; /* current write pos. in buffer */ - + /* init pointers */ dl->listing=NULL; dl->listing_size=0; @@ -411,16 +411,16 @@ static void build_dir_listing PROTO2(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 */ - strcpy(name,directory); + strcpy(name,directory); namelen=strlen(directory); name[namelen++]='/'; /* add directory separator to name */ - + for(rem = packetsize; (dp = readdir(dir_f)); ) { if (dp->d_ino == 0) continue; s = dp->d_name; - + /* hide dot files, but allow . or .. */ if((s[0]=='.') && ((s[1]!=0) && (s[1] != '.' || s[2] != 0))) continue; @@ -428,7 +428,7 @@ static void build_dir_listing PROTO2(DIRLISTING *, dl,const char *,directory) if(FSP_STAT(name,&sb)) continue; if(!S_ISDIR(sb.st_mode) && !S_ISREG(sb.st_mode)) continue; if(sb.st_size>FOURGIGS) sb.st_size=FOURGIGS; - + nlen = strlen(s)+1; /* do we have space in buffer for entire entry? */ @@ -444,7 +444,7 @@ static void build_dir_listing PROTO2(DIRLISTING *, dl,const char *,directory) rem = packetsize; bufpos = 0; } - + BB_WRITE4(buffer+bufpos,sb.st_mtime); bufpos+=4; BB_WRITE4(buffer+bufpos,sb.st_size ); @@ -462,7 +462,7 @@ static void build_dir_listing PROTO2(DIRLISTING *, dl,const char *,directory) } } closedir(dir_f); - + /* do we have space for final END entry? */ if(rem realname); *dl=f_cache_find(dirlistcache,&(di->realname)); @@ -504,7 +504,7 @@ const char *server_get_dir PROTO2(DIRLISTING **, dl, const DIRINFO *, di) DIRLISTING dlnew; char *key; unsigned int ok; - + if(dbug) fprintf(stderr," miss.\n"); ok=0; if(use_prebuild_dirlists) @@ -515,14 +515,14 @@ const char *server_get_dir PROTO2(DIRLISTING **, dl, const DIRINFO *, di) if(sf.st_mtime>=di->mtime) { /* try to load it */ FILE *f; - + dlnew.listing_size=sf.st_size; dlnew.listing=malloc(dlnew.listing_size); if(dlnew.listing) { - if( (f=fopen(list_p,"rb")) ) + if( (f=fopen(list_p,"rb")) ) { - if(dlnew.listing_size==fread(dlnew.listing,1,dlnew.listing_size,f)) + if(dlnew.listing_size==fread(dlnew.listing,1,dlnew.listing_size,f)) ok=1; fclose(f); } @@ -578,19 +578,19 @@ const char *server_get_dir PROTO2(DIRLISTING **, dl, const DIRINFO *, di) const char *server_del_file PROTO2(PPATH *, pp, DIRINFO *, di) { struct stat sb; - + if(FSP_STAT(pp->fullp,&sb)) return("unlink: file not accessible"); if(!(S_ISREG(sb.st_mode))) return("unlink: not an ordinary file"); - + if(unlink(pp->fullp) == -1) return("unlink: cannot unlink"); di->mtime=cur_time; di->lastcheck=cur_time; - + return(NULLP); } - + /**********************************************************************/ - + const char *server_del_dir PROTO2(PPATH *, pp, DIRINFO *,di) { struct stat sb; @@ -598,11 +598,11 @@ const char *server_del_dir PROTO2(PPATH *, pp, DIRINFO *,di) if(FSP_STAT(pp->fullp,&sb)) return("rmdir: directory not accessible"); if(!(S_ISDIR(sb.st_mode))) return("rmdir: not an ordinary directory"); - + memset(&null,0,sizeof(DIRINFO)); - + chdir(pp->fullp); - save_access_rights(&null); + save_access_rights(&null); chdir(home_dir); if(rmdir(pp->fullp) != 0) { chdir(pp->fullp); @@ -614,12 +614,12 @@ const char *server_del_dir PROTO2(PPATH *, pp, DIRINFO *,di) { di->lastcheck=0; } - + return(NULLP); } - + /**********************************************************************/ - + const char *server_make_dir PROTO3(PPATH *, pp, unsigned long, inet_num,DIRINFO, **di) { DIRINFO newdir; @@ -652,10 +652,10 @@ const char *server_make_dir PROTO3(PPATH *, pp, unsigned long, inet_num,DIRINFO, *di=f_cache_put(dirstatcache,&name,&newdir); return(NULLP); } - + /**********************************************************************/ - -const char *server_get_file PROTO5(PPATH *, pp, + +const char *server_get_file PROTO5(PPATH *, pp, FILE **, fp, unsigned long, inet_num, unsigned short, port_num, @@ -665,17 +665,17 @@ const char *server_get_file PROTO5(PPATH *, pp, struct stat sb; char realfn[NBSIZE]; FPCACHE *cache_f; - + sprintf(realfn,"%s/%s",di->realname,pp->f_ptr); cache_f=search_fpcache(inet_num,port_num,realfn); - + if(!cache_f) { FPCACHE newfile; char *key; /* file not found in cache? */ if (FSP_STAT(realfn,&sb)) return("No such file"); - if(!(S_ISREG(sb.st_mode))) + if(!(S_ISREG(sb.st_mode))) { if(S_ISDIR(sb.st_mode)) return ("Is a directory"); @@ -693,17 +693,17 @@ const char *server_get_file PROTO5(PPATH *, pp, f_cache_put(fpcache,&key,&newfile); } /* get filepoint from cache */ - else *fp = cache_f->fp; - + else *fp = cache_f->fp; + return(NULLP); } - + /**********************************************************************/ /* result and pp->fullp may overlap */ const char *server_get_pro PROTO3(DIRINFO *, di, char *, result, const char *, acc) { result[0]='\0'; /* truncate output buffer */ - + if(di->readme) strcat(result,di->readme); result[strlen(result)+1] = di->protection^DIR_GET; if(acc[0]=='O') @@ -711,7 +711,7 @@ const char *server_get_pro PROTO3(DIRINFO *, di, char *, result, const char *, a return(NULLP); } - + /**********************************************************************/ const char *server_set_pro PROTO2(DIRINFO *,di, const char *, key) @@ -739,7 +739,7 @@ const char *server_set_pro PROTO2(DIRINFO *,di, const char *, key) default: return("Invalid syntax. <+|-> "); } - + switch(key[0]) { case '+': di->protection|=act; @@ -750,21 +750,21 @@ const char *server_set_pro PROTO2(DIRINFO *,di, const char *, key) default: return("Invalid syntax. <+|-> "); } - + di->mtime=cur_time; di->lastcheck=cur_time; chdir(di->realname); save_access_rights (di); chdir(home_dir); - + return(NULLP); } - + /********************************************************************** * These two are used for file uploading. **********************************************************************/ - + const char *server_up_load PROTO5(char *, data, unsigned int, len, unsigned long, pos, unsigned long, inet_num, unsigned short, port_num) { @@ -775,26 +775,45 @@ const char *server_up_load PROTO5(char *, data, unsigned int, len, unsigned long struct stat sf; sprintf(tname, "%s/.T%08lX%04X", tmp_dir,inet_num, port_num); - + tmp=tname; cache_f=f_cache_find(fpcache,&tmp); if(! cache_f ) { + /* file not found in cache */ FPCACHE newfile; - /* file not found in cache? */ if (pos) { fp = fopen(tname, "r+b"); } else { unlink(tname); fp = fopen(tname,"wb"); } - + if(!fp) return("Cannot open temporary file"); - - if(lstat(tname,&sf) || !S_ISREG(sf.st_mode)) + + /* check for symlinks or other junk */ + if(lstat(tname,&sf) || !S_ISREG(sf.st_mode)) + { + fclose(fp); + remove(tname); + return("Temporary file is NOT a regular file"); + } + /* test if we do not create hole in file which is caused that + client continues upload across server crash, which causes + some data loss due to libc stdio write caching */ + /* server do not cleans temporary directory on startup - so + uploads across restart should work */ + if(pos > sf.st_size || pos < sf.st_size - UBUF_SPACE) { fclose(fp); unlink(tname); - return("Temporary file is NOT a regular file"); + return("Non continuous upload detected. Restart upload please."); + } + /* seek to starting position */ + if(fseeko(fp, pos, SEEK_SET)) + { + fclose(fp); + unlink(tname); + return("Seeking in file failed"); } /* protect temporary file */ chmod(tname,S_IRUSR|S_IWUSR); @@ -804,16 +823,36 @@ const char *server_up_load PROTO5(char *, data, unsigned int, len, unsigned long newfile.fp=fp; tmp=strdup(tname); f_cache_put(fpcache,&tmp,&newfile); - } else + } else { + /* get file pointer from cache */ fp=cache_f->fp; - + } + + /* check for uploading on non-tail of file */ + sf.st_size= ftello(fp); + if(pos > sf.st_size || pos < sf.st_size - UBUF_SPACE) + { + f_cache_delete_entry(fpcache,cache_f); + unlink(tname); + if( pos == 0) + { + /* we can retry */ + return server_up_load (data,len,pos,inet_num,port_num); + } + return("Non continuous upload detected. Restart upload please."); + } + /* if(fseeko(fp, pos, SEEK_SET)) return("Seeking in file failed"); + */ if(len!=fwrite(data, 1, len, fp)) + { + f_cache_delete_entry(fpcache,cache_f); return("Writing to file failed"); + } return(NULLP); } - + const char *server_install PROTO7(PPATH *, pp, unsigned long, inet_num, unsigned short, port_num, const char *, acc, DIRINFO *,di, unsigned int, l2, const char *,s2) { @@ -823,26 +862,26 @@ const char *server_install PROTO7(PPATH *, pp, unsigned long, inet_num, #ifdef HAVE_UTIME_H struct utimbuf ut; #endif - + sprintf(tname, "%s/.T%08lX%04X", tmp_dir,inet_num, port_num); /* if file still in cache, then close it & remove it from cache */ tmp=tname; cache_f=f_cache_find(fpcache,&tmp); f_cache_delete_entry(fpcache,cache_f); - + if (dbug) fprintf(stderr,"server_install: tname: %s, pp->fullp: %s\n",tname, pp->fullp); - if(fexist(pp->fullp) && + if(fexist(pp->fullp) && ( (di->protection & DIR_DEL) || acc[0]=='O' ) - ) + ) { unlink(tname); - if(dbug) + if(dbug) fprintf(stderr,"File %s already exists, but there is no user is not directory owner and public can't delete files.\n",pp->fullp); return("no permission for replacing that file. Not an owner."); } - + di->lastcheck=cur_time; di->mtime=cur_time; @@ -855,7 +894,7 @@ const char *server_install PROTO7(PPATH *, pp, unsigned long, inet_num, unlink(tname); umask(system_umask); #ifdef HAVE_UTIME_H - if(l2>=4) + if(l2>=4) { ut.modtime=BB_READ4(s2); ut.actime=cur_time; @@ -865,7 +904,7 @@ const char *server_install PROTO7(PPATH *, pp, unsigned long, inet_num, return(tmp); } - + /**********************************************************************/ /* assume path is validated */ /* start GRAB OPERATION! */ @@ -875,12 +914,12 @@ const char *server_secure_file PROTO4(PPATH *, pp, unsigned long, inet_num, struct stat sb; char temp_p[NBSIZE]; const char *tmp; - + if(FSP_STAT(pp->fullp,&sb)) return("grab: file not accessible"); if(!(S_ISREG(sb.st_mode))) return("grab: not an ordinary file"); - + sprintf(temp_p,"%s/.G%08lX%04X", tmp_dir, inet_num,port_num); - + unlink(temp_p); /* link emulated as a filecopy */ tmp=copy_file(pp->fullp,temp_p); @@ -890,13 +929,13 @@ const char *server_secure_file PROTO4(PPATH *, pp, unsigned long, inet_num, unlink(temp_p); return("grab: cannot unlink original file"); } - + di->lastcheck=cur_time; di->mtime=cur_time; - + return(NULLP); } - + const char *server_grab_file PROTO3(FILE **, fp, unsigned long, inet_num, unsigned short, port_num) @@ -905,7 +944,7 @@ const char *server_grab_file PROTO3(FILE **, fp, char temp_p[NBSIZE]; FPCACHE *cache_f; char *key; - + sprintf(temp_p,"%s/.G%08lX%04X",tmp_dir,inet_num,port_num); key=temp_p; cache_f=f_cache_find(fpcache,&key); @@ -926,7 +965,7 @@ const char *server_grab_file PROTO3(FILE **, fp, return(NULLP); } - + const char *server_grab_done PROTO2(unsigned long, inet_num, unsigned short, port_num) { @@ -934,7 +973,7 @@ const char *server_grab_done PROTO2(unsigned long, inet_num, char temp_p[NBSIZE]; FPCACHE *cache_f; char *key; - + sprintf(temp_p,"%s/.G%08lX%04X",tmp_dir,inet_num,port_num); if(FSP_STAT(temp_p,&sb)) return("grabdone: can't find temporary file"); key=temp_p; @@ -981,11 +1020,11 @@ const char *server_stat PROTO1(UBUF *, ubuf ) } } } - + BB_WRITE4(ubuf->buf,sb.st_mtime); BB_WRITE4(ubuf->buf+4,sb.st_size ); - - if(rc) + + if(rc) rc=0; else if S_ISDIR(sb.st_mode) rc=RDTYPE_DIR; @@ -993,7 +1032,7 @@ const char *server_stat PROTO1(UBUF *, ubuf ) if S_ISREG(sb.st_mode) rc=RDTYPE_FILE; else rc=0; /* not a file or directory */ - + (ubuf->buf)[8]=rc; return(NULLP); } @@ -1007,10 +1046,10 @@ const char *server_rename PROTO3(char *, ub, unsigned int, l1, unsigned int, l2) int srcdir; /* is source object a directory ? */ PPATH dest; const char *pe; - + if(FSP_STAT(pp->fullp,&sb)) return("can't find source file or directory"); if(S_ISDIR(sb.st_mode)) - srcdir=1; + srcdir=1; else if(S_ISREG(sb.st_mode)) srcdir=0; @@ -1024,11 +1063,11 @@ const char *server_rename PROTO3(char *, ub, unsigned int, l1, unsigned int, l2) /********************************************************************* test and resolve home directory *********************************************************************/ - + void init_home_dir PROTO0((void)) { void *newhd; - + /* test and goto home dir */ if(chdir(home_dir) == -1) { perror(home_dir); diff --git a/server/filecache.c b/server/filecache.c index d152e30..3f4bd2e 100644 --- a/server/filecache.c +++ b/server/filecache.c @@ -2,6 +2,6 @@ * * 05-MAR-93 First Version * 10-MAR-93 Merged into standard distribution by jtraub@cs.cmu.edu - * 03-JUL-2003 Last Version (c) Radim Kolar. I have thrown out all previous + * 03-JUL-2003 Last Version (c) Radim Kolar. I have thrown out all previous * code and write a new one. New code has been moved into file.c */ diff --git a/server/host.c b/server/host.c index 8b9f931..4c4d444 100644 --- a/server/host.c +++ b/server/host.c @@ -36,13 +36,13 @@ static char *find_hostname PROTO1(unsigned long, inet_num) { struct hostent *he; char *hostname; - + if ((he = gethostbyaddr((char*)&inet_num, sizeof(inet_num), AF_INET))) { hostname = malloc(strlen(he->h_name)+1); strcpy(hostname, he->h_name); } else hostname = 0; - + return hostname; } @@ -58,7 +58,7 @@ HTAB *find_host PROTO1(unsigned long, inet_num) unsigned l, h, m, i; unsigned long inum; HTAB *hs, *hd; - + for(l = 0, h = hcnt-1; (m = (l + h) >> 1) != l; ) { /* binary search */ inum = htab[m].inet_num; if(inum > inet_num) h = m; @@ -72,20 +72,20 @@ HTAB *find_host PROTO1(unsigned long, inet_num) return(htab+m); } } - + if(htab[m].inet_num < inet_num) m++; /* locate first entry that is > */ - + if((hcnt+1) > htot) { /* need more space */ htot += HALLOC_SIZE; /* add HALLOC_SIZE entries at a time */ - + if(!(htab = (HTAB *) realloc(htab,sizeof(HTAB)*htot))) { perror("grow_htab realloc"); exit(5); } } - + for(i = hcnt-m, hs = htab+hcnt, hd=htab+hcnt+1; i--; *--hd = *--hs); - + htab[m]=hzero; htab[m].inet_num = inet_num; htab[m].hostname = find_hostname(inet_num); @@ -119,17 +119,17 @@ int dump_htab PROTO1(FILE *,fp) { int i; HTAB *hp; - + if( fp == NULL) { - if(dbug) + if(dbug) fp=stdout; else return(0); } fprintf(fp,"#FSP Server "PACKAGE_VERSION", dumping at %s\nHost table content:\n",ctime(&cur_time)); - + fprintf(fp,"#IP address\tcount last access date\n"); for(i = hcnt-2, hp = htab+1; i--; hp++) { fprintf(fp,"%d.%d.%d.%d\t%5d %s", ((unsigned char *)(&hp->inet_num))[0], diff --git a/server/iprange.c b/server/iprange.c index 7005ccc..80410af 100644 --- a/server/iprange.c +++ b/server/iprange.c @@ -30,7 +30,7 @@ static char *check_ip PROTO2(unsigned long, inet_num, const IPrange *, iprange) unsigned char val[4]; inet_num = ntohl(inet_num); - + val[0] = (inet_num & 0x000000ff) ; val[1] = (inet_num & 0x0000ff00) >> 8; val[2] = (inet_num & 0x00ff0000) >> 16; @@ -38,7 +38,7 @@ static char *check_ip PROTO2(unsigned long, inet_num, const IPrange *, iprange) for (j = 0; j < 4; j++) if (iprange->lo[j] > val[j] || val[j] > iprange->hi[j]) return NULL; - + return iprange->text; } @@ -46,7 +46,7 @@ static char *check_ip PROTO2(unsigned long, inet_num, const IPrange *, iprange) const char *check_ip_table PROTO2(unsigned long, inet_num,IPrange *,table) { char *res; - + while(table) { if(!table->text) return NULL; /* EOT! */ @@ -77,7 +77,7 @@ void free_ip_table PROTO1(IPrange *,table) static unsigned char parse_ipcomponentnum PROTO1(const char * *, textp) { unsigned long val = 0; - + if (!isdigit(**textp)) { *textp = 0; } else @@ -85,12 +85,12 @@ static unsigned char parse_ipcomponentnum PROTO1(const char * *, textp) val = 10 * val + (**textp - '0'); (*textp)++; } while (isdigit(**textp)); - + if (val > 0xff) { val = 0; *textp = 0; } - + return val; } @@ -107,15 +107,15 @@ static const char *parse_ipcomponent PROTO3(const char *, text, unsigned char *, *hi = 0xff; return (text + 1); } - + *lo = parse_ipcomponentnum(&text); if (!text) return 0; - + if (*text == '-') { text++; *hi = parse_ipcomponentnum(&text); } else *hi = *lo; - + return text; } @@ -123,9 +123,9 @@ static IPrange *parse_ipnumber PROTO1(const char *, text) { IPrange *reply; int i; - + reply = (IPrange *)malloc(sizeof(IPrange)); - + for (i = 3; i >= 0 && !isspace(*text); i--) { if (i < 3) { if (*text != '.') return 0; @@ -137,14 +137,14 @@ static IPrange *parse_ipnumber PROTO1(const char *, text) return 0; } } - + /* fill in the gaps in the case that the loop terminated due to the occurrence of white-space */ for (; i >= 0; i--) { reply->lo[i] = 0x00; reply->hi[i] = 0xff; } - + return reply; } @@ -154,23 +154,23 @@ static IPrange *parse_hostname PROTO2(const char *, text, unsigned int, len) struct hostent *hostaddr; unsigned long inet_num; char *hostname; - + hostname = malloc(len + 1); strncpy(hostname, text, len); hostname[len] = 0; - + hostaddr = gethostbyname(hostname); free(hostname); - + if (!hostaddr) return 0; - + reply = (IPrange *)malloc(sizeof(IPrange)); inet_num = ((struct in_addr *)(hostaddr->h_addr))->s_addr; reply->lo[0] = reply->hi[0] = (inet_num & 0x000000ff) ; reply->lo[1] = reply->hi[1] = (inet_num & 0x0000ff00) >> 8; reply->lo[2] = reply->hi[2] = (inet_num & 0x00ff0000) >> 16; reply->lo[3] = reply->hi[3] = (inet_num & 0xff000000) >> 24; - + return reply; } @@ -192,12 +192,12 @@ static IPrange *parse_ipline PROTO1(const char *, text) char type = 0; const char *message = 0; size_t messlen = 0, addresslen; - + /* skip the leading white-space */ - skip_whitespace(text); + skip_whitespace(text); /* if the line is commented or empty, ignore it */ if (!*text || *text == '#') return 0; - + /* load hostname range (can not have spaces inside) */ message = text; while (*message && !isspace(*message)) message++; @@ -206,7 +206,7 @@ static IPrange *parse_ipline PROTO1(const char *, text) /* find the first non-space character after the address - this identifies the type of host this is */ skip_whitespace(message); - + if (!*message || *message == '#') { fprintf(stderr, "No host type specified in config file:\n\t%s\n", text); /* if a host name is mentioned by itself, then treat it as ignored @@ -216,28 +216,28 @@ static IPrange *parse_ipline PROTO1(const char *, text) /* the first character after the host name is the type of host */ type = *message; - + /* skip over the white space trailing the type - the start of the associated message */ message++; /* remember skip_whitespace() is a macro... */ skip_whitespace(message); - + /* `remove' the trailing white-space from the message */ messlen = strlen(message); while (messlen > 0 && isspace(message[messlen-1])) messlen--; - + /* if the first character of the address is numerical or '*' then parse as a numerical address, otherwise we do a host lookup on the name. */ if (*text == '*' || isdigit(*text)) reply = parse_ipnumber(text); else reply = parse_hostname(text, addresslen); - + if (!reply) { fprintf(stderr, "Badly formed address in config file:\n\t%s\n", text); return 0; } - + /* allocate a string to hold the message */ reply->text = malloc(1 + messlen + 1); /* type + text + '\0' */ if(!reply->text) @@ -248,7 +248,7 @@ static IPrange *parse_ipline PROTO1(const char *, text) reply->text[0] = type; strncpy(&reply->text[1], message, messlen); reply->text[1 + messlen] = '\0'; - + return reply; } @@ -258,7 +258,7 @@ void add_ipline PROTO2(const char *, text, IPrange **, table) IPrange *nl; IPrange *newtab; int i; - + nl = parse_ipline(text); if(!nl) return; /* add a new record to table */ @@ -287,7 +287,7 @@ void add_ipline PROTO2(const char *, text, IPrange **, table) void dump_iptab PROTO2(IPrange *,table,FILE *, fp) { - + if(fp==NULL) { if(dbug) @@ -295,7 +295,7 @@ void dump_iptab PROTO2(IPrange *,table,FILE *, fp) else return; } - + while(table) { if(!table->text) break; fprintf(fp, "%d-%d.%d-%d.%d-%d.%d-%d %c %s\n", diff --git a/server/log.c b/server/log.c index 2f103e2..2c9d475 100644 --- a/server/log.c +++ b/server/log.c @@ -72,7 +72,7 @@ void xferlog(char direction, const char *filename,unsigned long filesize,const c { size_t pos=0,timelen; char *timestr; - + if(!tlogname) return; /* xfer logging is not enabled */ /* current-time */ diff --git a/server/main.c b/server/main.c index f7c9f43..73097de 100644 --- a/server/main.c +++ b/server/main.c @@ -24,7 +24,7 @@ static void display_version PROTO0((void)) { printf( "File Service Protocol Daemon - FSP "PACKAGE_VERSION"\n" - "Copyright (c) 1991-1996 by A. J. Doherty, 2001-2003 by Radim Kolar.\n" + "Copyright (c) 1991-1996 by A. J. Doherty, 2001-2004 by Radim Kolar.\n" "All of the FSP code is free software with revised BSD license.\n" "Portions copyright by BSD, Wen-King Su, Philip G. Richards, Michael Meskes.\n" #ifdef __GNUC__ @@ -37,15 +37,15 @@ static void display_version PROTO0((void)) static void arg_err PROTO0((void)) { - fputs("Usage: fspd [-f configfile] [-d directory] [-v|-V] [-i] [-F] [-p port] [-X] [-t timeout] [-T temporary directory] [-l logfile] [-P pidlogname]\n", stderr); + 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); } static void check_required_vars PROTO0((void)) { double rnd; - + if(!inetd_mode && udp_port==0) { - fprintf(stderr, "No port set. Exiting. (Use 65535 for random port)\n"); + fprintf(stderr, "Error: No port set. (Use 65535 for random port)\n"); exit(1); } if(udp_port == 65535) @@ -55,17 +55,21 @@ static void check_required_vars PROTO0((void)) udp_port=rnd*(65535-1024)+1024; } if(!home_dir) { - fprintf(stderr, "No home directory set.\n"); + fprintf(stderr, "Error: No home directory set.\n"); exit(1); } - if(*home_dir != '/') { - fprintf(stderr,"home directory [%s] does not start with a /.\n", home_dir); - exit(1); +#if 0 + if(*home_dir != '/') { + fprintf(stderr,"Error: home directory [%s] does not start with a /.\n", home_dir); + exit(1); } +#endif +#if 0 if(!pidlogname) { fprintf(stderr, "No pidlogname set in your fspd.conf.\n"); exit(1); } +#endif if(!readme_file) { readme_file = strdup(".README"); } @@ -78,7 +82,7 @@ static void check_required_vars PROTO0((void)) dbug = 0; if(!tmp_dir && !read_only) { - if(!inetd_mode) + if(!inetd_mode) fprintf(stderr,"Warning: no tmpdir set, switching to readonly mode.\n"); read_only = 1; } @@ -104,11 +108,11 @@ int main PROTO2(int, argc, char **, argv) { int opt; long inetd_timeout=0; - + if(strlen(argv[0])>=7) inetd_mode = !strcasecmp(&argv[0][strlen(argv[0])-7],"in.fspd"); - while( (opt=getopt(argc,argv,"h?Xd:f:vVip:t:FT:l:P:"))!=EOF) + while( (opt=getopt(argc,argv,"h?Xd:f:vVip:t:FT:l:P:b:"))!=EOF) { switch(opt) { @@ -143,6 +147,9 @@ int main PROTO2(int, argc, char **, argv) case 'p': udp_port = atoi (optarg); break; + case 'b': + maxthcallowed = atoi (optarg); + break; case 't': inetd_timeout = 1000L * atoi (optarg); break; @@ -171,7 +178,7 @@ int main PROTO2(int, argc, char **, argv) { opt=_x_udp(&udp_port); if(opt == -1) { - perror("socket open"); + perror("Error: socket open"); exit(2); } if(dbug) { @@ -190,14 +197,14 @@ int main PROTO2(int, argc, char **, argv) fprintf(stderr,"Can not change my uid to %d.\n",run_uid); exit(3); } - + if(run_gid) if(setgid(run_gid) != 0) { fprintf(stderr,"Can not change my gid to %d.\n",run_uid); exit(4); } init_home_dir(); - + if(init_caches()) { perror("init_caches"); @@ -205,13 +212,13 @@ int main PROTO2(int, argc, char **, argv) } umask(system_umask); - + if (logging) { - if (dbug) + if (dbug) fprintf(stderr,"logging to %s\n",logname); /* test to see if logfile can be written */ /* open it append mode so that it doesn't wipe the file when - * you are running under inetd. + * you are running under inetd. */ if((logfd=open(logname, O_WRONLY | O_APPEND | O_CREAT, 0640)) < 0) { if(! inetd_mode ) @@ -223,11 +230,11 @@ int main PROTO2(int, argc, char **, argv) if(tlogname) { - if (dbug) + if (dbug) fprintf(stderr,"logging transfers to %s\n",tlogname); /* test to see if logfile can be written */ - if((tlogfd=open(tlogname, O_WRONLY | O_APPEND | O_CREAT, 0640)) < 0) + if((tlogfd=open(tlogname, O_WRONLY | O_APPEND | O_CREAT, 0640)) < 0) { if(! inetd_mode ) fprintf(stderr, "Error opening transferfile: %s, transfer logging disabled.\n",tlogname); @@ -236,6 +243,17 @@ int main PROTO2(int, argc, char **, argv) } } + /* With pidfile we have currently 2 problems: + 1) creating pidfile after we have droped root rights. We can not + write to root only directories like /var/run + 2) If we create pidfile early before setuid() we can't write + new pid to it after we setuid()+fork() + */ + if (pidfile(pidlogname)) { + fprintf(stderr,"Error: can not write pidfile - exiting.\n"); + exit(1);/* cannot write pid file - exit */ + } + init_htab(); /* we can enable table dumping from there */ signal(SIGINT,server_interrupt); @@ -264,7 +282,7 @@ int main PROTO2(int, argc, char **, argv) freopen(NULL_DEV,"w",stderr); } - + if(!inetd_mode) { /* Fork and die to drop daemon into background */ /* Added Alban E J Fellows 12 Jan 93 */ @@ -274,8 +292,10 @@ int main PROTO2(int, argc, char **, argv) pid_t forkpid; forkpid = fork(); if (forkpid == 0) { /* child prozess */ - if (pidfile(pidlogname)) + if (pidfile(pidlogname)) { + pidfile_cleanup(pidlogname); /* try cleanup */ exit(1);/* cannot write pid file - exit */ + } } else if (forkpid > 0) { /* father prozess */ _exit(0); } @@ -288,7 +308,7 @@ int main PROTO2(int, argc, char **, argv) while(1) { - server_loop(opt,inetd_timeout); + server_loop(opt,inetd_timeout); if(inetd_mode||dbug||shutdowning) break; } diff --git a/server/path.c b/server/path.c index c330bff..6a9a497 100644 --- a/server/path.c +++ b/server/path.c @@ -22,7 +22,7 @@ * * The PPATH structure is filled in by the function check_path when given a * path string. The elements are filled in as such: - * + * * fullp pointer to a string containing the full path name * f_ptr pointer to begining of the last component of the path * f_len length of the last component of the path @@ -43,32 +43,32 @@ const char *parse_path PROTO3(char *, fullp, unsigned int, len, PPATH *, pp) if(len < 1) return("Path must have non-zero length"); if(fullp[len-1]) return("Path must be null terminated"); - + pp->passwd = NULL; /* default, no password */ pp->d_len = 0; for( s = pp->fullp = pp->f_ptr = pp->d_ptr = fullp, state = 0; - *s; + *s; s++ - ) + ) { - if(*s == '\n') + if(*s == '\n') { p=strrchr(pp->fullp,'\n'); - pp->passwd = p+1; + pp->passwd = p+1; *p = '\0'; *s = '\0'; if(dbug) fprintf(stderr,"parse_path: found password field %s\n", p+1); break; } - else + else if(*s < ' ') return("Path contains control chars"); else if(*s >= '~') return("Path contains high chars"); - - switch(*s) + + switch(*s) { case '\\': case '.': @@ -99,14 +99,14 @@ const char *parse_path PROTO3(char *, fullp, unsigned int, len, PPATH *, pp) } /* pp->d_len = pp->f_ptr - pp->fullp; */ - + /* turn empty directory into "." */ if(pp->d_len == 0) { pp->d_ptr = "."; pp->d_len = 1; } - + pp->f_len = s - pp->f_ptr; /* turn empty file into "." */ @@ -115,13 +115,13 @@ const char *parse_path PROTO3(char *, fullp, unsigned int, len, PPATH *, pp) pp->f_ptr = "."; pp->f_len = 1; } - + /* turn empty fullp into "." */ if(pp->fullp[0] == 0) - { + { /* null path --> root */ pp->fullp = "."; } - + return(NULLP); } diff --git a/server/pidfile.c b/server/pidfile.c index 5e49511..1a9248b 100644 --- a/server/pidfile.c +++ b/server/pidfile.c @@ -5,6 +5,8 @@ * This code is derived from software contributed to The NetBSD Foundation * by Jason R. Thorpe. * + * Modified by Sven Hoaxter and Radim Kolar for FSP project. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -45,19 +47,18 @@ static pid_t pidfile_pid; -int pidfile(char *pidfile_path) +int pidfile(const char *pidfile_path) { FILE *f; int save_errno; pid_t pid; if (pidfile_path == NULL) - return (-1); + return (0); if ((f = fopen(pidfile_path, "w")) == NULL) { save_errno = errno; - free(pidfile_path); - pidfile_path = NULL; + (void) unlink(pidfile_path); errno = save_errno; return (-1); } @@ -66,8 +67,6 @@ int pidfile(char *pidfile_path) if (fprintf(f, "%ld\n", (long)pid) <= 0 || fclose(f) != 0) { save_errno = errno; (void) unlink(pidfile_path); - free(pidfile_path); - pidfile_path = NULL; errno = save_errno; return (-1); } @@ -77,7 +76,9 @@ int pidfile(char *pidfile_path) } -void pidfile_cleanup(char *pidfile_path) +void pidfile_cleanup(const char *pidfile_path) { + if (pidfile_path) { (void) unlink(pidfile_path); + } } diff --git a/server/pidfile.h b/server/pidfile.h index 4f04493..8648f06 100644 --- a/server/pidfile.h +++ b/server/pidfile.h @@ -1,2 +1,2 @@ -int pidfile(char *); -void pidfile_cleanup(char *); +int pidfile(const char *); +void pidfile_cleanup(const char *); diff --git a/server/random.c b/server/random.c index 956b197..b93f419 100644 --- a/server/random.c +++ b/server/random.c @@ -7,6 +7,13 @@ ****************************************************************************/ +/* get high bits from random result - better */ +unsigned short gen_next_key PROTO0((void)) +{ + return (random() >> 15); +} + +#if 0 /* The following algorithm is recommended by Numerical Recipies. */ /* Best, but needs floating point division. */ unsigned short gen_next_key PROTO0 ((void)) @@ -14,15 +21,16 @@ unsigned short gen_next_key PROTO0 ((void)) unsigned short ulRandom = ((float)(0xffff)*rand()/(RAND_MAX+1.0f)); return(ulRandom); } - -#if 0 +#endif +#if 0 +/* FSP original */ unsigned short gen_next_key PROTO0((void)) { unsigned long k; - + k = random(); k = k ^ (k >> 8) ^ (k >> 16) ^ (k << 8); - + return k; } #endif diff --git a/server/server.c b/server/server.c index a9238a4..a6b122e 100644 --- a/server/server.c +++ b/server/server.c @@ -142,11 +142,11 @@ static const char * print_command(unsigned char cmd) static void send_error PROTO3(struct sockaddr_in *, from, UBUF *, ub, const char *, msg) { size_t sz; - + sz=strlen(msg)+1; memcpy(ub->buf,msg,sz); ub->cmd = CC_ERR; - + server_reply(from,ub,sz,0); } @@ -168,7 +168,7 @@ int server_loop PROTO2(int, fd, time_t, timeout) socklen_t bytes; unsigned char *s, *d, *t; fd_set mask; - + FD_ZERO(&mask); myfd=fd; @@ -190,7 +190,7 @@ int server_loop PROTO2(int, fd, time_t, timeout) dump_htab(fp); dump_iptab(iptab,fp); stat_caches(fp); - if(fp) + if(fp) { fclose(fp); } @@ -199,13 +199,13 @@ int server_loop PROTO2(int, fd, time_t, timeout) if(shutdowning) return 1; retval = _x_select(&mask, timeout); - + if(retval == -1) { if(errno == EINTR) continue; perror("select"); exit(7); } - + if(retval == 1) { /* an incoming message is waiting */ bytes = sizeof(from); if((bytes = recvfrom(myfd,(char*)&rbuf,sizeof(rbuf),0, @@ -214,19 +214,19 @@ int server_loop PROTO2(int, fd, time_t, timeout) if(dbug) fprintf(stderr,"Header truncated.\n"); continue; } - + rlen = BB_READ2(rbuf.bb_len); - if((rlen+UBUF_HSIZE) > bytes) + if((rlen+UBUF_HSIZE) > bytes) { if(dbug) fprintf(stderr,"Message truncated.\n"); continue; /* truncated. */ } - + if(!(ir = check_ip_table(from.sin_addr.s_addr,iptab))) { /* host not found in table */ ir = priv_mode ? "DFSP service not available": "N"; } - + switch (*ir) { case 'D': /* disabled host - return error message */ if (rbuf.cmd == CC_BYE) @@ -241,17 +241,17 @@ int server_loop PROTO2(int, fd, time_t, timeout) fputs("check_ip() returned illegal host type\n",stderr); exit(99); } - + hp = find_host(from.sin_addr.s_addr); if(hp->hostname == 0 && no_unnamed) { send_error(&from,&rbuf, REVERSE_ERR_MSG); continue; } - + old = 0; cur_time = time((time_t *) 0); - + rkey = BB_READ2(rbuf.bb_key); if(hp->next_key != rkey) { if(!hp->active) @@ -259,16 +259,16 @@ int server_loop PROTO2(int, fd, time_t, timeout) else { if(hp->last_key == rkey) { if(cur_time < hp->last_acc + retry_timeout) { - if(dbug) fprintf(stderr,"Ignoring too early retry request (rtime=%ld,timeout=%d).\n",cur_time-hp->last_acc,(int)retry_timeout); + if(dbug) fprintf(stderr,"Ignoring too early retry request (rtime=%ld,timeout=%d).\n",(long)cur_time-hp->last_acc,(int)retry_timeout); continue; } old = 1; } else { if(cur_time < hp->last_acc + session_timeout ) { - if(dbug) fprintf(stderr,"Request with bad key (rtime=%ld,timeout=%d).\n",cur_time-hp->last_acc, (int)session_timeout); + if(dbug) fprintf(stderr,"Request with bad key (rtime=%ld,timeout=%d).\n",(long)cur_time-hp->last_acc, (int)session_timeout); continue; } - hp->active = 0; + hp->active = 0; hp->next_key = rkey; } } @@ -284,12 +284,12 @@ int server_loop PROTO2(int, fd, time_t, timeout) u = rbuf.sum; rbuf.sum = 0; for(t = s, sum = bytes; t < d; sum += *t++); sum = (sum + (sum >> 8)) & 0xff; - if(sum != u) + if(sum != u) { if(dbug) fprintf(stderr,"Wrong checksum got %x, expected %x\n",u,sum); continue; /* wrong check sum */ } - + server_process_packet(bytes,&rbuf,old,hp,&from); } else return(0); /* got a timeout */ } @@ -309,23 +309,23 @@ int server_reply PROTO4(struct sockaddr_in *, from, UBUF *, ub, unsigned sum; int i; unsigned int thcsum; - - if(dbug) + + if(dbug) fprintf(stderr,"snd (%s,key=0x%0X,seq=0x%0X,len=%d,len2=%d,pos=%u) ---> %d.%d.%d.%d\n", print_command(ub->cmd), BB_READ2(ub->bb_key), BB_READ2(ub->bb_seq),len1, len2, BB_READ4(ub->bb_pos), ((unsigned char *)(&(from->sin_addr.s_addr)))[0], ((unsigned char *)(&(from->sin_addr.s_addr)))[1], ((unsigned char *)(&(from->sin_addr.s_addr)))[2], ((unsigned char *)(&(from->sin_addr.s_addr)))[3]); - + BB_WRITE2(ub->bb_len,len1); - + ub->sum = 0; s = (unsigned char *) ub; d = s + (len1 + len2 + UBUF_HSIZE); for(t = s, sum = 0; t < d; sum += *t++); ub->sum = sum + (sum >> 8); - + /* * Check that we do not exceed maximum throughput allowed before sending */ @@ -358,7 +358,7 @@ fprintf(stderr,"\n") ; if(dbug) fprintf(stderr, "Throughput too high, waiting.\n"); sleep(1); } - + if(sendto(myfd,(char *)ub,(len1 + len2 + UBUF_HSIZE),0, (struct sockaddr *)from,sizeof(struct sockaddr_in)) == -1) { perror("sendto"); @@ -380,7 +380,7 @@ void send_file PROTO5(struct sockaddr_in *, from, UBUF *, ub, FILE *, fp, size_t bytes; unsigned len; unsigned long pos; - + if(has_len == 2) { /* recover length field if it exists */ len=lp[0] << 8; len = len + lp[1]; @@ -388,23 +388,23 @@ void send_file PROTO5(struct sockaddr_in *, from, UBUF *, ub, FILE *, fp, } else len = packetsize; /* use default if it doesn't exist */ pos = BB_READ4(ub->bb_pos); - + #ifndef NATIVE_LARGEFILES #if SIZEOF_OFF_T == 4 if(pos>TWOGIGS) len=0; #endif -#endif - +#endif + if(fseeko(fp,pos,SEEK_SET)) { /* seek failed, do not send any more data */ /* TODO: or can we return error instead? */ len=0; } - + bytes = fread(ub->buf, 1, len, fp); - + server_reply(from,ub,bytes,0); } @@ -416,6 +416,7 @@ void send_file PROTO5(struct sockaddr_in *, from, UBUF *, ub, FILE *, fp, static void server_show_version PROTO2(struct sockaddr_in *, from, UBUF *, ub) { char buf[UBUF_SPACE], verflags = 0; + unsigned int xtra = VER_BYTES; strcpy(buf, "fspd " PACKAGE_VERSION); strcat(buf, "\n"); @@ -427,24 +428,22 @@ static void server_show_version PROTO2(struct sockaddr_in *, from, UBUF *, ub) if (maxthcallowed) verflags |= VER_THRUPUT; strcpy(ub->buf, buf); - BB_WRITE4(ub->bb_pos,VER_BYTES); ub->buf[strlen(ub->buf)] = '\0'; ub->buf[strlen(ub->buf)+1] = verflags; + /* add optional thruput data */ if(maxthcallowed) { - BB_WRITE4(ub->bb_pos,VER_BYTES+4); - ub->buf[strlen(ub->buf)+2] = (char)((maxthcallowed & 0xff000000)>>24); - ub->buf[strlen(ub->buf)+3] = (char)((maxthcallowed & 0x00ff0000)>>16); - ub->buf[strlen(ub->buf)+4] = (char)((maxthcallowed & 0x0000ff00)>>8); - ub->buf[strlen(ub->buf)+5] = (char)(maxthcallowed & 0x000000ff); - - server_reply(from, ub, strlen(ub->buf)+1, VER_BYTES+4); - } else { - server_reply(from, ub, strlen(ub->buf)+1, VER_BYTES); + BB_WRITE4(ub->buf+strlen(ub->buf)+2,maxthcallowed); + xtra+=4; } + /* Add packetsize - 2.8.1 b20 extension */ + BB_WRITE2(ub->buf+strlen(ub->buf)+xtra+1,packetsize); + xtra+=2; + BB_WRITE4(ub->bb_pos,xtra); + server_reply(from, ub, strlen(ub->buf)+1, xtra); } /**************************************************************************** -* This is the dispatch loop for message that has been accepted. +* This is the dispatch loop for message that has been accepted. * Serves command in message and sends out a reply. * bytes: size of the message received. * ub: pointer to the message buffer. @@ -807,7 +806,7 @@ static void server_process_packet PROTO5(unsigned, bytes, UBUF *, ub, int, old, ACTIONLOG1(L_GRABFILE,"GRABFILE"); } pe = validate_path(s1,l1,&pp,&di,0); - if(pe) + if(pe) { ACTIONLOG1(L_ERR|L_GRABFILE,"GRABFILE"); ACTIONFAILED(L_ERR|L_GRABFILE,pe); @@ -827,7 +826,7 @@ static void server_process_packet PROTO5(unsigned, bytes, UBUF *, ub, int, old, } } pe = server_grab_file(&fp, inet_num, port_num); - if(pe) + if(pe) { ACTIONLOG1(L_ERR|L_GRABFILE,"GRABFILE"); ACTIONFAILED(L_ERR|L_GRABFILE,pe); diff --git a/tests/cachecheck.c b/tests/cachecheck.c index 8f86dc9..6ecb271 100644 --- a/tests/cachecheck.c +++ b/tests/cachecheck.c @@ -68,7 +68,7 @@ int main(int argv,char **argc) cache=f_cache_new(4,0,0,sizeof(char *),string_free,string_compare); assert(cache!=NULL); - + s="lamer1"; f_cache_put(cache,&s,NULL); s="lamer2"; diff --git a/tests/mklargefile.c b/tests/mklargefile.c index d1fa3f5..c6ea7cd 100644 --- a/tests/mklargefile.c +++ b/tests/mklargefile.c @@ -1,5 +1,5 @@ /* this file is public domain */ -/* return values: +/* return values: * 3 - invocation error * 2 - no LFS support * 1 - file creation failed @@ -20,7 +20,7 @@ int main(int argc,char *argv[]) FILE *fd; off_t pos; float size; - + if(argc<3) { printf("Makes a large file with hole using fseeko\n"); @@ -35,7 +35,7 @@ int main(int argc,char *argv[]) return 1; } size=atof(argv[2]); -#if SIZEOF_OFF_T <= 4 +#if SIZEOF_OFF_T <= 4 if(size>2) { printf("You do not have LFS your system.\nMaximum supported filesize is 2 GB.\n"); diff --git a/tests/parsecheck.c b/tests/parsecheck.c index dce361d..364a7c9 100644 --- a/tests/parsecheck.c +++ b/tests/parsecheck.c @@ -11,7 +11,7 @@ int dbug=1; -const char *testcases[]={ +const char *testcases[]={ "", ".","/", "filename","/filename","//filename", "dirname/filename","//dirname/filename","//dirname//filename", @@ -26,7 +26,7 @@ PPATH testresults[]={ {"dir1name/dir2name/",".",1,"dir1name/dir2name",17}, {"dir1name//dir2name//",".",1,"dir1name//dir2name",18}, {"filename","filename",8,".",1,"passwd"}, {"filename","filename",8,".",1,"passwd"}, {NULL},{NULL},{NULL}, - + }; @@ -45,7 +45,7 @@ static void print_path(PPATH *pp) } /* returns: 0 okay, 1 different */ - + static int compareresults(PPATH *p1,PPATH *p2) { if(p1->fullp==NULL && p2->fullp==NULL) return 0; @@ -76,7 +76,7 @@ static int runtestcase(void) pp.fullp=NULL; err=parse_path(test,strlen(test)+1,&pp); printf("parsing: '%s'",test); - if(err) + if(err) { printf(" parse err: '%s'. ",err); pp.fullp=NULL; diff --git a/tests/randomcheck.c b/tests/randomcheck.c index 2c27c61..7c8634a 100644 --- a/tests/randomcheck.c +++ b/tests/randomcheck.c @@ -7,7 +7,7 @@ static int bitcount[16]; static int rounds; static int result; -#define MAX_WORST_ALLOWED 0.2f +#define MAX_WORST_ALLOWED 0.1f /* FSP classic algo */ static unsigned short classic PROTO0((void)) @@ -44,7 +44,7 @@ static void run_randomtest( unsigned short (*keygen)(void) ) { int i,j; unsigned short rnd; - + /* zero bitcount first */ memset(bitcount,0,16*sizeof(int)); @@ -66,7 +66,7 @@ static void print_bitcount(void) int i; float worst; float ratio; - + printf("Set ratio: "); worst=0; @@ -84,20 +84,20 @@ static void print_bitcount(void) int main(int argc,const char *argv[]) { - rounds=200; + rounds=2000; if(argc>1) { rounds=atoi(argv[1]); } printf("Running %d rounds.\n\n",rounds); - + result=0; printf("Generator: classic\n"); run_randomtest(classic); print_bitcount(); - + printf("Generator: simple\n"); run_randomtest(simple); print_bitcount();