#! /bin/sh # not checked (list incomplete): # --timeout if test "x$PUBLICFILE_FTPD" = x ; then PUBLICFILE_FTPD="/usr/local/publicfile/bin/ftpd" fi LC_ALL=C ; export LC_ALL LANG=C ; export LANG unset BC_LINE_LENGTH unset BC_ENV_ARGS shortcut=0 # or 0 for full test for i in `echo $PATH | sed 's/:/ /g'` ; do if test -x $i/printenv ; then PRINTENV=$i/printenv fi done if test "x$PRINTENV" = x ; then echo "printenv not found" >&2 ; exit 1 ; fi rm -rf tmp.check mkdir tmp.check || exit 1 O=`pwd` cd tmp.check N=`pwd` mkdir client || exit 1 # find out how to set the time zone to POSIX UTC (not that it's better # than right/UTC, but the tests expect POSIX). cat >auto-tztest.c < #include #include int main(void) { time_t x=0x3fffffff; fputs(ctime(&x),stdout); return 0; } EOF $O/auto-compile.sh -g -O2 -o $O/auto-tztest auto-tztest.c || exit 1 for i in posix/UTC UTC ; do t=`TZ=$i $O/auto-tztest` if test "x$t" = "xSat Jan 10 13:37:03 2004" ; then mytz=$i fi done rm $O/auto-tztest if test "x$mytz" = x ; then echo "failed to find out how to use posix/UTC" >&2 exit 1 fi TZ=$mytz export TZ echo '--- canon works as expected' $O/auto-compile.sh -I$O -DTEST -g -O2 -o $O/auto-canon $O/canon.c \ $O/libuomisc.a $O/libunix.a $O/libbyte.a $O/auto-canon <fptest.c < #include #include #include "$O/ftpparse.h" int main(int argc, char **argv) { char buf[1024]; struct ftpparse f; while (fgets(buf,sizeof(buf),stdin)) { char *p; char *c=strchr(buf,'\n'); int x; if (c) *c=0; if (*buf=='#') {puts(buf); continue; } printf("in: %s:\n",buf); /* for the sake of memory debuggers */ p=strdup(buf); if (!p) return 1; if (0==strncmp(p,"MLST:",5)) x=ftpparse_mlsx(&f, p+5,strlen(p)-5,1); else if (0==strncmp(p,"MLSD:",5)) x=ftpparse_mlsx(&f, p+5,strlen(p)-5,0); else x=ftpparse(&f, p,strlen(p), argc>1); if (!x) { puts(" unparsable\n"); continue; } fputs(" name: ",stdout); fwrite(f.name,f.namelen,1,stdout); printf("\n namelen: %d\n",f.namelen); if (f.flagtrycwd) fputs(" may be directory\n",stdout); if (f.flagtryretr) fputs(" may be file\n",stdout); if (f.sizetype==FTPPARSE_SIZE_UNKNOWN) { puts(" size: unknown"); } else { printf(" sizetype: %d\n",f.sizetype); printf(" size: "); #define MRD 1000000000 if (f.size >= MRD) { unsigned long x,y; x=f.size / MRD; y=f.size % MRD; printf("%lu%08lu\n",x,y); } else printf("%lu\n",(unsigned long)f.size); } if (f.mtimetype == FTPPARSE_MTIME_UNKNOWN) { puts(" mtime: unknown"); } else { time_t t; t=f.mtime.x-4611686018427387914ULL; printf(" mtimetype: %d\n",f.mtimetype); printf(" mtime: %ld %s",t,ctime(&t)); } if (f.idtype == FTPPARSE_ID_UNKNOWN) { puts(" id: unknown"); } else { printf(" idtype: %d\n",f.idtype); fputs(" id: ",stdout); fwrite(f.id,f.idlen,1,stdout); printf("\n idlen: %d\n",f.idlen); } if (f.flagbrokenmlsx) puts(" has unterminated MLSX fact list"); free(p); } return 0; } EOF $O/auto-compile.sh -g -O2 -o fptest fptest.c \ $O/ftpparse.o $O/utcdate2tai.o $O/libtai.a $O/libbyte.a THISYEAR=`date +%Y` LASTYEAR=`echo $THISYEAR - 1 | bc` ( ./fptest < licensed 04-27-99 07:28:39 licensed 04-27-99 17:28:39 licensed 04-27-99 07:28:39AM licensed 04-27-99 07:28:39PM licensed 04-27-99 7:28 licensed 04-27-99 07:28 licensed 04-27-99 07:28AM licensed 04-27-99 07:28PM licensed # bad things 04-27-99 :28:39 licensed 04-27-99 :28 licensed 04-27-99 7:2:39 licensed 04-27-99 07:28:3 licensed 04-27-99 17:28: licensed 04-27-99 007:28:39 licensed 04-27-99 07:028:39 licensed 04-27-99 07:28:039 licensed 04-27-99 07:28:039AM licensed 04-27-99 07:28:039PM licensed 04-27-99 07:28:9AM licensed 04-27-99 07:28:9PM licensed 04-27-99 07:28:39A licensed 04-27-99 07:28:39P licensed 04-27-99 007:28 licensed 04-27-99 07:028 licensed 04-27-99 07:2 licensed 04-27-99 07:2 licensed 04-27-99 07 licensed 04-27-99 07:28A licensed 04-27-99 07:28P licensed # EPLF +i8388621.29609,m824255902,/, dev +i8388621.44468,m839956783,r,s10376, RFCEPLF +i8388621.44468,m839956783,r,s10000000000, RFCEPLF +i8388621.44468,m839956783,r,s10376, RFC EPLF # bad EPLF +i8388621.44468,m839956783,r,s10376, +i8388621.44468,m839956783,r,s10376, +i8388621.44468,m839956783,r,s10376 +i,m839956783,r,s10376, RFCEPLF +i8388621.44468,m,r,s10376, RFCEPLF +i8388621.44468,m839956783,r,s, RFCEPLF # note: not tab, but space. +i8388621.44468,m839956783,r,s10376, RFCEPLF # VMS / MultiNet 00README.TXT;1 2 30-DEC-1996 17:44 [SYSTEM] (RWED,RWED,RE,RE) CORE.DIR;1 1 8-SEP-1996 16:09 [SYSTEM] (RWE,RWE,RE,RE) CII-MANUAL.TEX;1 213/216 29-JAN-1996 03:33:12 [ANONYMOU,ANONYMOUS] (RWED,RWED,,) DSPD.MAN;1 9 1-APR-1991 12:55 [SG,ROSENBLUM] (RWED,RWED,RE,RE) [VMSSERV.FILES]ALARM.DIR;1 1/3 5-MAR-1993 18:09 # bad VMS / MultiNet 00README.TXT; 2 30-DEC-1996 17:44 [SYSTEM] (RWED,RWED,RE,RE) 00README.TXT 2 30-DEC-1996 17:44 [SYSTEM] (RWED,RWED,RE,RE) 00README.TXT;1 30-DEC-1996 17:44 [SYSTEM] (RWED,RWED,RE,RE) .DIR;1 2 30-DEC-1996 17:44 [SYSTEM] (RWED,RWED,RE,RE) # unix -r--r--r-- 1 uwe ohse 27040 Jan 29 16:32 s.uogetopt.c -r--r--r-- 1 uwe ohse 1382 Dec 18 1991 s.sig.c lrwxr-xr-x 1 uwe ohse 18 Dec 31 1999 SCCS -> XXXXX lrwxrwxrwx 1 root root 35 Jun 19 10:46 mmmm -> dddd -rw-r--r-- 1 root other 531 Jan 29 03:26 README dr-xr-xr-x 2 root other 512 Apr 8 1994 etc dr-xr-xr-x 2 root 512 Apr 8 1994 etc lrwxrwxrwx 1 root other 7 Jan 25 00:17 bin -> usr/bin # stranger cases -r--r--r-- 1 uwe ohse 27040 Jan 29 1996 file name -r--r--r-- 1 uwe ohse 27040 Jan 29 1996 my file name -r--r--r-- 1 uwe ohse 27040 Jan 29 1996 17:01 file name -r--r--r-- 1 uwe ohse 27040 Jan 29 1996 17:01 -rwxrwxrwx 1 uwe ohse 27040 Jan 29 1996 spacy drwxrwxrwx 1 uwe ohse 1024 Jan 29 1996 spacydir - 1 u o 3 Jan 29 1996 17:01 a b c d e f g h i j k l m n o p q r s t # bad unix -r--r--r-- 1 uwe ohse 27040 Jan 29 16:32 -r--r--r-- 1 uwe ohse 27040 Jan 29 16:32s.uogetopt.c -r--r--r-- 1 uwe ohse 27040 Jan 29 16:3 s.uogetopt.c -r--r--r-- 1 uwe ohse 27040 Jan 29 16: s.uogetopt.c -r--r--r-- 1 uwe ohse 27040 Jan 29 16 s.uogetopt.c -r--r--r-- 1 uwe ohse 27040 Jan 29 s.uogetopt.c -r--r--r-- 1 uwe ohse 27040 Jan 29 199 s.uogetopt.c -r--r--r-- 1 uwe ohse 27040 jan 29 16:32 s.uogetopt.c -r--r--r-- 1 uwe ohse 27040 an 29 16:32 s.uogetopt.c -r--r--r-- 1 uwe ohse Jan 29 16:32 s.uogetopt.c -r--r--r-- 1 uwe 27040 Jan 29 16:32 s.uogetopt.c -r--r--r-- 1 ohse 27040 Jan 29 16:32 s.uogetopt.c -r--r--r-- uwe ohse 27040 Jan 29 16:32 s.uogetopt.c 1 uwe ohse 27040 Jan 29 16:32 s.uogetopt.c l 1 uwe ohse 27040 Jan 29 16:32 s.uogetopt.c l 1 uwe ohse 27040 Jan 29 16:32 s.uogetopt.c -> ooo br--r--r-- 1 uwe ohse 27040 Jan 29 16:32 s.uogetopt.c -> ooo br--r--r-- 1 uwe ohse 12345627040 Jan 29 16:32 s.uogetopt.c br--r--r-- 1 uwe ohse 10000000000 Jan 29 16:32 s.uogetopt.c -r--r--r-- 1 uwe ohse 27040 Jan 29 96 16:32 s.uogetopt.c -r--r--r-- 1 uwe ohse 27040 Jan 29 1996 16:32 s.uogetopt.c # Microsoft's FTP server for Windows: ---------- 1 owner group 1803128 Jul 10 10:18 ls-lR.Z d--------- 1 owner group 0 May 9 19:45 Softlib # WFTPD for Windows: -rwxrwxrwx 1 noone nogroup 322 Aug 19 1996 message.ftp # NetPresenz for the Mac: -------r-- 326 1391972 1392298 Nov 22 1995 MegaPhone.sit drwxrwxr-x folder 2 May 10 1996 network # MSDOS 4-27-00 09:09PM licensed 7-18-00 10:16AM pub 4-14-00 03:47PM 589 readme.htm 03-16-94 06:29AM . 03-16-94 06:29AM .. 04-11-94 11:48PM creative 03-08-94 07:17AM 5504 article.xfiles.intro 02-28-94 11:44AM 3262 article1.gillian.anderson 02-28-04 11:44AM 3262 article1.gillian.anderson 02-28-94 11:44:55AM 3262 article1.gillian.anderson 02-28-94 11:44AM 10000000000 article1.gillian.anderson 02-28-1994 11:44AM 3262 article1.gillian.anderson # MSDOS with leading spaces, aka NT. 03-16-94 06:29AM dirnamewithleadingspace 03-16-94 06:29AM 123 filenamewithleadingspace # bad MSDOS 2-28-94 11:44AM 3262 article1.gillian.anderson 02-8-94 11:44AM 3262 article1.gillian.anderson 02-28-4 11:44AM 3262 article1.gillian.anderson 02-28-94 11:44AM article1.gillian.anderson 02-28-94 11:44AM 3262 02-28-94 11:44AM 3262 # NetWare. Quite like unix. d [R----F--] supervisor 512 Jan 16 18:53 login - [R----F--] rhesus 214059 Oct 20 15:27 cx.exe - [R----F--] jrd 197928 Sep 25 15:19 kermit.exe d [R----F--] jrd 512 Oct 06 09:31 source d [RWCEAFMS] jrd 512 Sep 04 14:38 lwp d [R----F-] 1 carl 512 Mar 12 15:47 txt - [-RWCE-F-] mlm 11820 Feb 3 93 12:00 drivers.doc -[R----F-] 1 supervis 256 Nov 15 14:21 readme.txt # supertcp . 11-16-94 17:16 .. 11-16-94 17:16 INSTALL 11-16-94 17:17 CMT 11-21-94 10:17 DESIGN1.DOC 11264 05-11-95 14:20 README.TXT 1045 05-10-95 11:01 WPKIT1.EXE 960338 06-21-95 17:01 CMT.CSV 0 07-06-95 14:56 # bad supertcp WPKIT1.EXE 06-21-95 17:01 WPKIT1.EXE 10000000000 06-21-95 17:01 WPKIT1.EXE 960338 6-21-95 17:01 # OS/2 0 DIR 04-11-95 16:26 . 0 DIR 04-11-95 16:26 .. 0 DIR 04-11-95 16:26 ADDRESS 612 A 07-28-95 16:45 air_tra1.bag 195 A 08-09-95 10:23 Alfa1.bag 0 DIR 04-11-95 16:26 ATTACH 372 A 08-09-95 10:26 Aussie_1.bag 310992 06-28-94 09:56 INSTALL.EXE # ------------------------------ VM/CMS DIRACC EXEC A1 F 132 84 3 01/25/93 14:49:47 DIRUNIX SCRIPT A1 V 77 1216 17 01/04/93 20:30:47 MAIL PROFILE A2 F 80 1 1 10/14/92 16:12:27 # MLSD MLSD:size=4161;lang=en-US;modify=19970214165800;create=19961001124534;type=file;x.myfact=foo,bar; filename MLST: Type=file;Size=1024990;Perm=r; /tmp/cap60.pl198.tar.gz MLST: Type=dir;Modify=19981107085215;Perm=el; /tmp MLSD:Type=cdir;Modify=19981107085215;Perm=el; tmp MLSD:Type=cdir;Modify=19981107085215;Perm=el; /tmp MLSD:Type=pdir;Modify=19990112030508;Perm=el; .. MLSD:Type=file;Size=25730;Modify=19940728095854;Perm=; capmux.tar.z MLSD:Type=file;Size=1830;Modify=19940916055648;Perm=r; hatch.c MLSD:Type=file;Size=25624;Modify=19951003165342;Perm=r; MacIP-02.txt MLSD:Type=file;Size=2154;Modify=19950501105033;Perm=r; uar.netbsd.patch MLSD:Type=file;Size=54757;Modify=19951105101754;Perm=r; iptnnladev.1.0.sit.hqx MLSD:Type=file;Size=226546;Modify=19970515023901;Perm=r; melbcs.tif MLSD:Type=file;Size=12927;Modify=19961025135602;Perm=r; tardis.1.6.sit.hqx MLST: Type=dir;Perm=el;Unique=keVO1+ZF4 test MLSD:Type=cdir;Perm=el;Unique=keVO1+ZF4; test MLSD:Type=pdir;Perm=e;Unique=keVO1+d?3; .. MLSD:Type=OS.unix=slink:/foobar;Perm=;Unique=keVO1+4G4; foobar MLSD:Type=OS.unix=chr-13/29;Perm=;Unique=keVO1+5G4; device MLSD:Type=OS.unix=blk-11/108;Perm=;Unique=keVO1+6G4; block MLSD:Type=file;Perm=awr;Unique=keVO1+8G4; writable MLSD:Type=dir;Perm=cpmel;Unique=keVO1+7G4; promiscuous MLSD:Type=dir;Perm=;Unique=keVO1+1t2; no-exec MLSD:Type=file;Perm=r;Unique=keVO1+EG4; two words MLSD:Type=file;Perm=r;Unique=keVO1+IH4; leading space MLSD:Type=file;Perm=r;Unique=keVO1+1G4; file1 MLSD:Type=dir;Perm=cpmel;Unique=keVO1+7G4; incoming MLSD:Type=file;Perm=r;Unique=keVO1+1G4; file2 MLSD:Type=file;Perm=r;Unique=keVO1+1G4; file3 MLSD:Type=file;Perm=r;Unique=keVO1+1G4; file4 # checking the "usual" MLSX brokeness, too. MLSD:size=4161;lang=en-US;modify=19970214165800;create=19961001124534;type=file;x.myfact=foo,bar filename EOF echo '--- ftpparse handling of file names starting with spaces' ./fptest <$N/server/ftpd/run <$N/server.log & sleep 2 F="$N/server/file/0" if test "x$shortcut" = "x0" ; then # against stupid patches. echo '--- publicfile listing format check' touch $F/file out=`$O/ftpls --raw ftp://127.0.0.1:50000/` || out="-bad" case "$out" in -*) echo "badly patched publicfile detected. Further tests not run" svc -dtx $N/server/ftpd sleep 1 # give supervise time to exit. otherwise race with supervise/status file #cat $N/server.log |grep -v ^tcpserver rm onetouch cd $O || exit 1 rm -rf tmp.check exit 0 ;; esac rm $F/file echo '--- empty start directory test' $O/ftpcopy ftp://127.0.0.1:50000/ client ; echo $? echo '--- nonexistant start entity' $O/ftpcopy ftp://127.0.0.1:50000/nonexistant client ; echo $? #mkdir "$F/t1" #mkdir "$F/t1" ; touch "$F/t1/file"; chmod 000 "$F/t1/file" echo '--- start entity is a file' touch $F/file $O/ftpcopy ftp://127.0.0.1:50000/file ./file ; echo $? $O/ftpcopy ftp://127.0.0.1:50000/file ./file ; echo $? $O/ftpcopy ftp://127.0.0.1:50000/file file ; echo $? rm file $O/ftpcopy ftp://127.0.0.1:50000/file file ; echo $? $O/ftpcopy ftp://127.0.0.1:50000/file ./file ; echo $? $O/ftpcopy ftp://127.0.0.1:50000/file file ; echo $? rm file $O/ftpcopy ftp://127.0.0.1:50000/file client ; echo $? $O/ftpcopy ftp://127.0.0.1:50000/file client ; echo $? rm client/file $O/ftpcopy ftp://127.0.0.1:50000/file client/ ; echo $? $O/ftpcopy ftp://127.0.0.1:50000/file client/ ; echo $? rm client/file $O/ftpcopy ftp://127.0.0.1:50000/file client/file ; echo $? rm client/file echo '--- start entity is a file, ftpcopy creates parent directory' $O/ftpcopy ftp://127.0.0.1:50000/file createit/file ; echo $? rm createit/file ; rmdir createit $O/ftpcopy ftp://127.0.0.1:50000/file createit/ ; echo $? rm createit/file ; rmdir createit echo '--- start entity is a file, ftpcopy handles different local name' $O/ftpcopy ftp://127.0.0.1:50000/file createit ; echo $? rm createit echo '--- start entity is a directory with one file' rm -rf client/* $O/ftpcopy ftp://127.0.0.1:50000/ client ; echo $? rm -rf client/* $O/ftpcopy ftp://127.0.0.1:50000/ client/subdir ; echo $? echo '--- start entity is a directory with two files' rm $F/file touch $F/one $F/two rm -rf client/* $O/ftpcopy ftp://127.0.0.1:50000/ client ; echo $? rm -rf client/* $O/ftpcopy ftp://127.0.0.1:50000/ client/subdir ; echo $? echo '--- start entity contains one directory with two files' rm -rf client/* rm -rf $F/* mkdir $F/dir touch $F/dir/one $F/dir/two $O/ftpcopy ftp://127.0.0.1:50000/ client ; echo $? rm -rf client/* $O/ftpcopy ftp://127.0.0.1:50000/ client/subdir ; echo $? echo '--- ftpcopy deletes superfluous files' rm -rf client/* rm -rf $F/* mkdir $F/dir touch $F/dir/one $F/dir/two cp -pr $F/dir client/dir touch client/dir/three $O/ftpcopy ftp://127.0.0.1:50000/ client ; echo $? echo '--- ftpcopy deletes superfluous directories' rm -rf client/* rm -rf $F/* mkdir $F/dir touch $F/dir/one $F/dir/two cp -pr $F/dir client/dir mkdir client/dir2 mkdir client/dir/dir4 $O/ftpcopy ftp://127.0.0.1:50000/ client | sort echo - find client -print | sort echo '--- ftpcopy survives if a file is turned into a directory' rm $F/dir/one mkdir $F/dir/one touch $F/dir/one/three # so something is downloaded $O/ftpcopy ftp://127.0.0.1:50000/ client ; echo $? find client -print | sort echo '--- ftpcopy survives if a directory is turned into a file' rm -rf $F/dir/one touch $F/dir/one $O/ftpcopy ftp://127.0.0.1:50000/ client ; echo $? find client -print | sort echo '--- ftpcopy survives local symlink loops' rm client/dir/one ln -s one client/dir/one echo "first symlink loop test" >$F/dir/one $O/ftpcopy ftp://127.0.0.1:50000/ client ; echo $? cat client/dir/one find client -print | sort rm client/dir/one ln -s one client/dir/one rm $F/dir/one mkdir $F/dir/one echo "second symlink loop test" >$F/dir/one/file $O/ftpcopy ftp://127.0.0.1:50000/ client ; echo $? cat client/dir/one/file find client -print | sort echo '--- ftpcopy recognizes changed symbolic links to directories' rm -rf client/* $F/* mkdir $F/dir1 touch $F/dir1/one (cd $F ; ln -s dir1 dir2 ) $O/ftpcopy ftp://127.0.0.1:50000/ client ; echo $? find client -print | sort rm $F/dir2 mkdir $F/dir2 touch $F/dir2/two $O/ftpcopy ftp://127.0.0.1:50000/ client ; echo $? find client -print | sort echo '--- ftpcopy handles dir -> symbolic link change' rm -rf $F/dir2 (cd $F ; ln -s dir1 dir2 ) $O/ftpcopy ftp://127.0.0.1:50000/ client ; echo $? find client -print | sort echo '--- ftpcopy deals with rename situation 1' rm -rf client/* $F/* mkdir $F/dir1 touch $F/dir1/one $O/ftpcopy ftp://127.0.0.1:50000/ client ; echo $? find client -print | sort (cd $F ; ln -s dir1 dir2 ) $O/ftpcopy ftp://127.0.0.1:50000/ client ; echo $? find client -print | sort (cd $F ; rm dir2 ; mv dir1 dir2 ; ln -s dir2 dir1 ) $O/ftpcopy ftp://127.0.0.1:50000/ client ; echo $? find client -print | sort (cd $F ; rm dir1 ) $O/ftpcopy ftp://127.0.0.1:50000/ client |sort ; echo - find client -print | sort echo '--- ftpcopy deals with symlink to upper level directories' rm -rf client/* $F/* mkdir $F/dir1 mkdir $F/dir1/dir2 touch $F/dir1/dir2/one (cd $F/dir1/dir2 ; ln -s ../../dir1 dir1 ) (cd $F/dir1/dir2 ; ln -s ../../dir1 dir2 ) $O/ftpcopy ftp://127.0.0.1:50000/ client ; echo $? touch client/dir1/dir2/dir1/1 touch client/dir1/dir2/dir2/2 find client -print | sort echo '--- ftpcopy deals with symlink to current directories' rm -rf client/* $F/* mkdir $F/dir1 mkdir $F/dir1/dir2 touch $F/dir1/dir2/one (cd $F/dir1 ; ln -s . dir1 ) (cd $F/dir1/dir2 ; ln -s . dir2 ) $O/ftpcopy ftp://127.0.0.1:50000/ client ; echo $? touch client/dir1/dir1/1 touch client/dir1/dir2/dir2/2 find client -print | sort echo '--- ftpcopy deals with symlink to top level directory' rm -rf client/* $F/* touch $F/one mkdir $F/dir1 mkdir $F/dir1/dir2 touch $F/dir1/dir2/two # can't do this since the server isn't chrooted: # (cd $F/dir1/dir2 ; ln -s / dir3 ) (cd $F/dir1 ; ln -s $F dir1 ) (cd $F/dir1 ; ln -s $F/one . ) (cd $F/dir1/dir2 ; ln -s $F dir2 ) (cd $F/dir1/dir2 ; ln -s $F/one . ) $O/ftpcopy ftp://127.0.0.1:50000/ client ; echo $? touch client/dir1/dir1/1 touch client/dir1/dir2/dir2/2 find client -print | sort echo "really a (sym)link" >client/one cat client/dir1/one echo '--- ftpcopy deals with symlink to lower level directory' rm -rf client/* $F/* (cd $F ; ln -s dir2/dir1 dir1) (cd $F ; ln -s dir2/file1 file1) mkdir $F/dir2 (cd $F ; ln -s dir2/dir3 dir3) (cd $F ; ln -s dir2/file3 file3) mkdir $F/dir2/dir1 touch $F/dir2/dir1/one touch $F/dir2/file1 touch $F/dir2/file3 mkdir $F/dir2/dir3 touch $F/dir2/dir3/three $O/ftpcopy ftp://127.0.0.1:50000/ client ; echo $? touch client/dir2/dir1/1 touch client/dir3/3 find client -print | sort echo "really a (sym)link 1" >client/dir2/dir1/new echo "really a (sym)link 2" >client/dir2/file1 echo "really a (sym)link 3" >client/dir2/file3 cat client/dir1/new cat client/file1 cat client/file3 echo '--- ftpcopy deals with /../ in local file names' # this checks a few lines of canonization code. # canonization is mainly used for the hashed file names, # the (untestable) hacking symbolic link mode, and # remote path names. rm -rf client/* $F/* echo 1 >$F/one mkdir $F/dir1 ( cd $F/dir1 ; ln -s ../one two) $O/ftpcopy -l2 ftp://127.0.0.1:50000/ client/../client/ ; echo $? find client -print | sort echo "changed" >client/one cat client/dir1/two echo '--- ftpcopy --max-days works' # to make things more interesting publicfiles ftpd doesn't output # modification time for files modified in the last 60 seconds. # ftpparse() returns them as modified 1970, and ftpcopy thinks # they are "too old". Ugly, but this is how things work. # "1" and "3" are dated 2000-01-01 -> not downloaded # "2" and "5" are one day old. -> downloaded # "3" and "6" are very young (<60 seconds) -> not downloaded cat >oneday.c < int main(void) { time_t x=time(0) - 86400; printf("%lu\n",x); exit(0); } EOF $O/auto-compile.sh -o oneday oneday.c oneday="`./oneday`" rm oneday.c oneday cat >onetouch.c < #include int main(int argc, char **argv) { unsigned long x=strtol(argv[1],0,10); int fd; struct timeval tv[2]; fd=open(argv[2],O_WRONLY|O_CREAT,0644); tv[0].tv_sec=x; tv[1].tv_sec=x; tv[0].tv_usec=0; tv[1].tv_usec=0; return utimes(argv[2],tv); } EOF $O/auto-compile.sh -o onetouch onetouch.c rm onetouch.c rm -rf client/* $F/* #touch -r $O/Makefile.pre $F/1 mkdir $F/dir ./onetouch 946753200 $F/1 ./onetouch 946753200 $F/dir/4 ./onetouch $oneday $F/2 ./onetouch $oneday $F/dir/5 touch $F/3 touch $F/dir/6 $O/ftpcopy --max-days 10 -l2 ftp://127.0.0.1:50000/ client ; echo $? #gdb $O/ftpcopy #--max-days 10 -l2 ftp://127.0.0.1:50000/ client ; echo $? find client -print | sort echo '--- ftpcopy handles excludes and includes' rm -rf client/* $F/* touch $F/0 mkdir $F/d1 touch $F/d1/1 mkdir $F/d1/d2 touch $F/d1/d2/2 mkdir $F/d1/d2/d3 touch $F/d1/d2/d3/3 echo '- e&i: download /0' rm -rf client $O/ftpcopy --exclude '*' --include /0 \ ftp://127.0.0.1:50000/ client ; echo $? echo '- e&i: no download due to not included upper level directory' rm -rf client $O/ftpcopy --exclude '*' --include /d1/1 \ ftp://127.0.0.1:50000/ client ; echo $? echo '- e&i: download /d1/1 (include /d1 and /d1/1)' rm -rf client $O/ftpcopy --exclude '*' --include '/d1' --include /d1/1 \ ftp://127.0.0.1:50000/ client ; echo $? echo '- e&i: download /d1/1 (include /d1 and /d1/?)' rm -rf client $O/ftpcopy --exclude '*' --include '/d1' --include '/d1/?' \ ftp://127.0.0.1:50000/ client ; echo $? echo '- e&i: download all (include /d1*)' rm -rf client $O/ftpcopy --exclude '*' --include '/d1*' \ ftp://127.0.0.1:50000/ client ; echo $? echo '- e&i: just get the directories (include *d?)' rm -rf client $O/ftpcopy --exclude '*' --include '*d?' \ ftp://127.0.0.1:50000/ client ; echo $? find client -print | sort echo '- e&i: just get the directories (include /d1, /d1/d2, /d1/d2/d3)' rm -rf client $O/ftpcopy --exclude '*' --include '/d1' --include '/d1/d2' \ --include '/d1/d2/d3' \ ftp://127.0.0.1:50000/ client ; echo $? find client -print | sort echo '- e&i: get all but */2*' rm -rf client $O/ftpcopy --exclude '*/2*' \ ftp://127.0.0.1:50000/ client ; echo $? find client -print | sort echo '- e&i: --in-exclude-file check (bad syntax)' rm -rf client ( echo '-*' ; echo '?/0' ; echo '+/0' ; ) >inex-file $O/ftpcopy --in-exclude-file ./inex-file ftp://127.0.0.1:50000/ client ; echo $? echo '- e&i: --in-exclude-file check' rm -rf client ( echo '-*' ; echo '+/0' ; ) >inex-file $O/ftpcopy --in-exclude-file ./inex-file ftp://127.0.0.1:50000/ client ; echo $? echo '--- ftpcopy handles subdirectory mirroring' rm -rf client/* $F/* mkdir $F/dir1 (cd $F/dir1 ; ln -s ../dir2 .) (cd $F/dir1 ; ln -s ../dir2/file21 .) mkdir $F/dir11 mkdir $F/dir2 mkdir $F/dir2/dir21 echo file211 >$F/dir2/dir21/file211 (cd $F/dir2 ; ln -s dir21/file211 file21 ) mkdir $F/dir3 (cd $F/dir3 ; ln -s . dir3) mkdir $F/dir3/dir31 echo file31 >$F/dir3/file31 echo file311 >$F/dir3/dir31/file31 echo '- subdir1:' $O/ftpcopy ftp://127.0.0.1:50000/dir1 client ; echo $? find client -print | sort echo "changed" >client/file21 cat client/dir2/file21 echo '- subdir2:' # including deletes $O/ftpcopy ftp://127.0.0.1:50000/dir2 client |sort ; echo - find client -print | sort echo '- subdir3:' # including deletes $O/ftpcopy ftp://127.0.0.1:50000/dir3 client |sort ; echo - touch client/dir3/newfile find client -print | sort echo '--- ftpcopy --directories-only works' # depends on previous file structure $O/ftpcopy --directories-only ftp://127.0.0.1:50000/ client | sort echo - find client -print | sort rm -rf client $O/ftpcopy -d 127.0.0.1:50000 / client ; echo $? find client -print | sort echo '--- ftpcopy handles absolute local directories' # this is more superfluous than not. But then again it doesn't cost that much. rm -rf client/* $F/* touch $F/0 mkdir $F/d1 touch $F/d1/1 mkdir $F/d1/d2 (cd $F/d1/d2 ; ln -s ../../0 .) (cd $F/d1/d2 ; ln -s ../1 .) (cd $F/d1/d2 ; ln -s ../.. d0) (cd $F/d1/d2 ; ln -s .. d1) (cd $F/d1/d2 ; ln -s . d2) touch $F/d1/d2/2 $O/ftpcopy 127.0.0.1:50000 / `env - pwd`/client ; echo $? touch client/d1/d2/d0/t0 touch client/d1/d2/d1/t1 touch client/d1/d2/d2/t2 echo "changed0" >client/0 echo "changed1" >client/d1/1 find client -print | sort cat client/d1/d2/0 cat client/d1/d2/1 echo '--- ftpcopy recognizes --user and --pass' # we can't really test whether these options work. common.c is too # smart for that. rm -rf client/* $F/* $O/ftpcopy -l3 --user uwe --pass 42 127.0.0.1:50000 / `pwd`/client ; echo $? $O/ftpcopy -l3 -u uwe -p 42 127.0.0.1:50000 / `pwd`/client ; echo $? echo '--- ftpcopy recognizes username in urls' $O/ftpcopy -l3 ftp://uwe@127.0.0.1:50000/ client ; echo $? echo '--- ftpcopy --dry-run works' rm -rf client/* $F/* touch $F/file0 mkdir $F/dir1 touch $F/dir1/file1 mkdir $F/dir1/dir2 touch $F/dir1/dir2/file2 (cd $F/dir1/dir2 ; ln -s '../../file0' 'linkf0') (cd $F/dir1/dir2 ; ln -s '../file1' 'linkf1') (cd $F/dir1/dir2 ; ln -s 'file2' 'linkf2') (cd $F ; ln -s 'dir1/dir2/file2' 'linkf2') (cd $F ; ln -s 'dir1/file1' 'linkf1') mkdir $F/directory_to_keep echo 123 >$F/directory_to_keep/file_to_keep echo 124 >$F/directory_to_keep/file_to_get touch client/do_delete mkdir client/directory_to_keep touch client/directory_to_keep/file_to_keep # note: will be downloaded touch client/directory_to_keep/file2delete mkdir client/directory_to_delete touch client/directory_to_delete/file2delete $O/ftpcopy --dry-run 127.0.0.1:50000 / client |sort ; echo - find client -print | sort fi echo '--- ftpcopy --interactive works' rm -rf client/* $F/* mkdir $F/dir1 (cd $F/dir1 ; ln -s ../dir2 .) (cd $F/dir1 ; ln -s ../dir2/file21 .) mkdir $F/dir11 mkdir $F/dir2 mkdir $F/dir2/dir21 echo file211 >$F/dir2/dir21/file211 (cd $F/dir2 ; ln -s dir21/file211 file21 ) mkdir $F/dir3 (cd $F/dir3 ; ln -s . dir3) mkdir $F/dir3/dir31 echo file31 >$F/dir3/file31 echo file311 >$F/dir3/dir31/file31 # This also checks how ftpcopy deals with absolute remote paths. ( cat <$F/dir1/FiLE1 (cd $F ; ln -s 'dir1/FiLE1' 'link') # "wc" tends to add different amounts of white space, depending on the # vendor. Oh. $O/ftpcopy --tolower 127.0.0.1:50000 / client | wc -l | tr -d ' ' # 1 download $O/ftpcopy --tolower 127.0.0.1:50000 / client | wc -l | tr -d ' ' # 2 downloads $O/ftpcopy --tolower 127.0.0.1:50000 / client | wc -l | tr -d ' ' # 2 downloads echo '--- ftpcopy --tolower works with exclude, too' rm -rf client/* $F/* touch $F/file0 mkdir $F/dir1 touch $F/dir1/FILE1 mkdir $F/dir1/DIR2 touch $F/dir1/DIR2/FILE2 (cd $F ; ln -s 'dir1/DIR2/FILE2' 'LINK') # the important thing is to write dir2 in lower case. $O/ftpcopy -l2 --tolower --exclude "*dir2*" 127.0.0.1:50000 / client ; echo $? find client -print | sort echo '--- ftpcopy --ignore-size works' rm -rf client/* $F/* echo 123 >$F/FILE1 $O/ftpcopy 127.0.0.1:50000 / client echo 1234 >$F/FILE1 $O/ftpcopy --ignore-size 127.0.0.1:50000 / client echo '--- ftpcopy without --ignore-size works' $O/ftpcopy 127.0.0.1:50000 / client echo '--- ftpcopy --ignore-time works' rm -rf client/* $F/* echo 123 >$F/FILE1 ./onetouch 946000000 $F/FILE1 $O/ftpcopy 127.0.0.1:50000 / client ./onetouch 947000000 $F/FILE1 $O/ftpcopy --ignore-time 127.0.0.1:50000 / client echo '--- ftpcopy --ignore-size --ignore-time works' echo >$F/FILE1 ./onetouch 945000000 $F/FILE1 $O/ftpcopy --ignore-time --ignore-size 127.0.0.1:50000 / client echo '--- ftpcopy without --ignore-time works' echo 123 >$F/FILE1 ./onetouch 944000000 $F/FILE1 $O/ftpcopy 127.0.0.1:50000 / client echo '--- ftpcopy has no file descriptor leak in remove_dir' rm -rf client/* $F/* for i in 0 1 2 3 ; do for j in 1 2 3 4 5 6 7 8 9 0 ; do mkdir client/d$i$j touch $F/d$i$j done done ( ulimit -n 12 $O/ftpcopy 127.0.0.1:50000 / client ) echo '--- ftpcopy has no file descriptor leak in loop' rm -rf client/* $F/* for i in 0 1 2 3 ; do for j in 1 2 3 4 5 6 7 8 9 0 ; do mkdir $F/d$i$j touch $F/d$i$j/f$i$j done done ( ulimit -n 12 $O/ftpcopy 127.0.0.1:50000 / client ) echo '--- ftpcopy has no file descriptor leak in delete' rm -rf client/* $F/* for i in 0 1 2 3 ; do for j in 1 2 3 4 5 6 7 8 9 0 ; do mkdir client/d$i$j touch client/d$i$j/f$i$j done done ( ulimit -n 12 $O/ftpcopy 127.0.0.1:50000 / client ) | sort echo '--- ftpcopy has no file descriptor leak in download' rm -rf client/* $F/* for i in 0 1 2 3 ; do for j in 1 2 3 4 5 6 7 8 9 0 ; do mkdir $F/d$i$j touch $F/d$i$j/f$i$j done done ( ulimit -n 12 $O/ftpcopy 127.0.0.1:50000 / client ) echo '--- ftpcopy --max-deletes works' rm -rf client/* $F/* touch $F/1 (cd client; touch 1 2 3 4 5 6 7 8 9 a b c d e f ) $O/ftpcopy -l 0 --max-deletes 10 127.0.0.1:50000 / client # note: finds directory "client", too, so the numbers are one off ... find client -print | wc -l | tr -d ' ' $O/ftpcopy -l 0 -M 1 127.0.0.1:50000 / client find client -print | wc -l | tr -d ' ' echo '--- ftpcopy --max-size works' rm -rf client/* $F/* cp $O/ftpcopy.c $F/1 head -n 100 $O/ftpcopy.c >$F/2 head -n 10 $O/ftpcopy.c >$F/3 $O/ftpcopy -l 0 --max-size 1000 127.0.0.1:50000 / client # note: finds directory "client", too, so the numbers are one off ... find client -print | sort $O/ftpcopy -l 0 127.0.0.1:50000 / client find client -print | sort echo '--- ftpcopy --ascii-listings works' # this doesn't catch everything, but might catch if something is horribly # broken. rm -rf client/* $F/* cp $O/ftpcopy.c $F/1 cp $O/ftpcopy $F/2 printf "hello\r\nworld\nHello\r\nWorld\n" >$F/3 mkdir $F/D cp $O/ftpcopy.c $F/D/1 cp $O/ftpcopy $F/D/2 printf "hello\r\nworld\nHello\r\nWorld\n" >$F/D/3 mkdir $F/D/D cp $O/ftpcopy.c $F/D/D/1 cp $O/ftpcopy $F/D/D/2 printf "hello\r\nworld\nHello\r\nWorld\n" >$F/D/D/3 echo '- part one: binary mode listing' $O/ftpcopy -l 0 127.0.0.1:50000 / client find client -print | sort cmp $F/1 client/1 && echo "client/1 ok" cmp $F/2 client/2 && echo "client/2 ok" cmp $F/3 client/3 && echo "client/3 ok" cmp $F/D/1 client/D/1 && echo "client/D/1 ok" cmp $F/D/2 client/D/2 && echo "client/D/2 ok" cmp $F/D/3 client/D/3 && echo "client/D/3 ok" cmp $F/D/D/1 client/D/D/1 && echo "client/D/D/1 ok" cmp $F/D/D/2 client/D/D/2 && echo "client/D/D/2 ok" cmp $F/D/D/3 client/D/D/3 && echo "client/D/D/3 ok" rm -rf client/* echo '- part two: ascii mode listing' $O/ftpcopy --ascii-listings -l 0 127.0.0.1:50000 / client find client -print | sort cmp $F/1 client/1 && echo "client/1 ok" cmp $F/2 client/2 && echo "client/2 ok" cmp $F/3 client/3 && echo "client/3 ok" cmp $F/D/1 client/D/1 && echo "client/D/1 ok" cmp $F/D/2 client/D/2 && echo "client/D/2 ok" cmp $F/D/3 client/D/3 && echo "client/D/3 ok" cmp $F/D/D/1 client/D/D/1 && echo "client/D/D/1 ok" cmp $F/D/D/2 client/D/D/2 && echo "client/D/D/2 ok" cmp $F/D/D/3 client/D/D/3 && echo "client/D/D/3 ok" echo '--- ftpcopy --max-depth works' rm -rf client/* $F/* mkdir $F/D1 cp $O/ftpcopy.c $F/1 mkdir $F/D1/D2 cp $O/ftpcopy.c $F/D1/2 mkdir $F/D1/D2/D3 cp $O/ftpcopy.c $F/D1/D2/3 cp $O/ftpcopy.c $F/D1/D2/D3/4 echo '- part zero: --max-depth 0' rm -rf client/ $O/ftpcopy --max-depth 0 -l 0 127.0.0.1:50000 / client find client -print | sort echo '- part one: --max-depth 1' rm -rf client/ $O/ftpcopy --max-depth 1 -l 0 127.0.0.1:50000 / client find client -print | sort echo '- part two: --max-depth 2' rm -rf client/ $O/ftpcopy --max-depth 2 -l 0 127.0.0.1:50000 / client find client -print | sort echo '- part three: --max-depth 3' rm -rf client/ $O/ftpcopy --max-depth 3 -l 0 127.0.0.1:50000 / client find client -print | sort echo '--- ftpcopy --rate-limit works' rm -rf client/* $F/* cat >a5.c <>$F/file ( exec 2>/dev/null exec 1>/dev/null ./a5 $O/ftpcopy --rate-limit 5000 -l 0 ftp://127.0.0.1:50000/file client/ ) >/dev/null 2>/dev/null # need to get rid of "alarm clock" messages of sh. cmp client/file $F/file >/dev/null 2>/dev/null \ && echo "files identical - rate limiting does not work" echo '--- ftpcopy resumes downloads' rm -rf client/* $F/* touch $F/file cat $O/ftpcopy $O/ftpls $O/*.c >>$F/ofile dd if=$F/ofile of=$F/file bs=1024 count=100 >/dev/null 2>/dev/null ./onetouch 946753000 $F/file TFILE=.tmp.file.946753000.102400 dd if=$F/file of=$F/$TFILE bs=1024 count=24 >/dev/null 2>/dev/null cp $F/$TFILE client/ $O/ftpcopy ftp://127.0.0.1:50000/file client/ echo '--- ftpcopy resume does not detect local corruption' # this actuelly tests wether there is a resume at all ... rm -f client/* ./onetouch 946753000 $F/file cp $F/$TFILE client/ echo 1 >>client/$TFILE $O/ftpcopy ftp://127.0.0.1:50000/file client/ cmp client/file $F/file >/dev/null 2>/dev/null \ || echo "file corrupted - resume done" echo '--- ftpcopy does not resume in case time changed' rm -f client/* ./onetouch 946753200 $F/file cp $F/$TFILE client/ $O/ftpcopy ftp://127.0.0.1:50000/file client/ cmp client/file $F/file echo '--- ftpcopy does not resume in case size changed' cp $F/$TFILE client/ echo 1 >>$F/file ./onetouch 946753200 $F/file $O/ftpcopy ftp://127.0.0.1:50000/file client/ cmp client/file $F/file echo '--- ftpcopy --no-resume works as expected' rm -f client/file echo 123 >client/file dd conv=notrunc if=$F/file of=client/file bs=1024 count=30 \ >/dev/null 2>/dev/null $O/ftpcopy --no-resume ftp://127.0.0.1:50000/file client/ cmp client/file $F/file svc -dtx $N/server/ftpd sleep 1 # give supervise time to exit. otherwise race with supervise/status file #cat $N/server.log |grep -v ^tcpserver rm onetouch cd $O || exit 1 rm -rf tmp.check exit 0