diff --git a/Cargo.lock b/Cargo.lock index 5c6c307..b879c58 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2660,6 +2660,7 @@ dependencies = [ "dav-server", "ed25519-dalek 2.2.0", "env_logger", + "filetime", "filetree", "flate2", "futures-util", @@ -2667,6 +2668,7 @@ dependencies = [ "log", "markbase-webdav", "md5 0.8.0", + "nix 0.29.0", "pulldown-cmark", "rand 0.8.6", "regex", @@ -2993,6 +2995,18 @@ dependencies = [ "memoffset", ] +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.11.1", + "cfg-if", + "cfg_aliases", + "libc", +] + [[package]] name = "nix" version = "0.31.3" diff --git a/data/auth.sqlite b/data/auth.sqlite index f5e7d14..4fab65c 100644 Binary files a/data/auth.sqlite and b/data/auth.sqlite differ diff --git a/data/batch_1.txt b/data/batch_1.txt new file mode 100644 index 0000000..a676108 --- /dev/null +++ b/data/batch_1.txt @@ -0,0 +1 @@ +Batch file 1 diff --git a/data/complex_empty_test/level1/file1.txt b/data/complex_empty_test/level1/file1.txt new file mode 100644 index 0000000..ef05999 --- /dev/null +++ b/data/complex_empty_test/level1/file1.txt @@ -0,0 +1 @@ +Level1 file diff --git a/data/complex_empty_test/level1/level2_with_file/file2.txt b/data/complex_empty_test/level1/level2_with_file/file2.txt new file mode 100644 index 0000000..e3a3794 --- /dev/null +++ b/data/complex_empty_test/level1/level2_with_file/file2.txt @@ -0,0 +1 @@ +Level2 file diff --git a/data/existing_stat_test.txt b/data/existing_stat_test.txt new file mode 100644 index 0000000..0ff9f72 --- /dev/null +++ b/data/existing_stat_test.txt @@ -0,0 +1 @@ +Existing file for STAT test diff --git a/data/rsync_100kb_final.bin b/data/rsync_100kb_final.bin new file mode 100644 index 0000000..33c7d13 Binary files /dev/null and b/data/rsync_100kb_final.bin differ diff --git a/data/rsync_10kb_test.bin b/data/rsync_10kb_test.bin new file mode 100644 index 0000000..53ef240 Binary files /dev/null and b/data/rsync_10kb_test.bin differ diff --git a/data/rsync_1kb_final.bin b/data/rsync_1kb_final.bin new file mode 100644 index 0000000..6b12a67 Binary files /dev/null and b/data/rsync_1kb_final.bin differ diff --git a/data/rsync_1mb_openssh.bin b/data/rsync_1mb_openssh.bin new file mode 100644 index 0000000..daaff98 Binary files /dev/null and b/data/rsync_1mb_openssh.bin differ diff --git a/data/rsync_1mb_phase14_2.bin b/data/rsync_1mb_phase14_2.bin new file mode 100644 index 0000000..db8e99d Binary files /dev/null and b/data/rsync_1mb_phase14_2.bin differ diff --git a/data/rsync_1mb_retest.bin b/data/rsync_1mb_retest.bin new file mode 100644 index 0000000..daaff98 Binary files /dev/null and b/data/rsync_1mb_retest.bin differ diff --git a/data/rsync_batch_test/file_1.txt b/data/rsync_batch_test/file_1.txt new file mode 100644 index 0000000..f080842 --- /dev/null +++ b/data/rsync_batch_test/file_1.txt @@ -0,0 +1 @@ +File 1 content diff --git a/data/rsync_batch_test/file_10.txt b/data/rsync_batch_test/file_10.txt new file mode 100644 index 0000000..ecb5999 --- /dev/null +++ b/data/rsync_batch_test/file_10.txt @@ -0,0 +1 @@ +File 10 content diff --git a/data/rsync_batch_test/file_100.txt b/data/rsync_batch_test/file_100.txt new file mode 100644 index 0000000..f8f1cdc --- /dev/null +++ b/data/rsync_batch_test/file_100.txt @@ -0,0 +1 @@ +File 100 content diff --git a/data/rsync_batch_test/file_11.txt b/data/rsync_batch_test/file_11.txt new file mode 100644 index 0000000..9464bc7 --- /dev/null +++ b/data/rsync_batch_test/file_11.txt @@ -0,0 +1 @@ +File 11 content diff --git a/data/rsync_batch_test/file_12.txt b/data/rsync_batch_test/file_12.txt new file mode 100644 index 0000000..e10d9e3 --- /dev/null +++ b/data/rsync_batch_test/file_12.txt @@ -0,0 +1 @@ +File 12 content diff --git a/data/rsync_batch_test/file_13.txt b/data/rsync_batch_test/file_13.txt new file mode 100644 index 0000000..acec66d --- /dev/null +++ b/data/rsync_batch_test/file_13.txt @@ -0,0 +1 @@ +File 13 content diff --git a/data/rsync_batch_test/file_14.txt b/data/rsync_batch_test/file_14.txt new file mode 100644 index 0000000..45ca592 --- /dev/null +++ b/data/rsync_batch_test/file_14.txt @@ -0,0 +1 @@ +File 14 content diff --git a/data/rsync_batch_test/file_15.txt b/data/rsync_batch_test/file_15.txt new file mode 100644 index 0000000..08940c9 --- /dev/null +++ b/data/rsync_batch_test/file_15.txt @@ -0,0 +1 @@ +File 15 content diff --git a/data/rsync_batch_test/file_16.txt b/data/rsync_batch_test/file_16.txt new file mode 100644 index 0000000..56c0c8f --- /dev/null +++ b/data/rsync_batch_test/file_16.txt @@ -0,0 +1 @@ +File 16 content diff --git a/data/rsync_batch_test/file_17.txt b/data/rsync_batch_test/file_17.txt new file mode 100644 index 0000000..73be8df --- /dev/null +++ b/data/rsync_batch_test/file_17.txt @@ -0,0 +1 @@ +File 17 content diff --git a/data/rsync_batch_test/file_18.txt b/data/rsync_batch_test/file_18.txt new file mode 100644 index 0000000..087af5b --- /dev/null +++ b/data/rsync_batch_test/file_18.txt @@ -0,0 +1 @@ +File 18 content diff --git a/data/rsync_batch_test/file_19.txt b/data/rsync_batch_test/file_19.txt new file mode 100644 index 0000000..79d278f --- /dev/null +++ b/data/rsync_batch_test/file_19.txt @@ -0,0 +1 @@ +File 19 content diff --git a/data/rsync_batch_test/file_2.txt b/data/rsync_batch_test/file_2.txt new file mode 100644 index 0000000..04ef7ad --- /dev/null +++ b/data/rsync_batch_test/file_2.txt @@ -0,0 +1 @@ +File 2 content diff --git a/data/rsync_batch_test/file_20.txt b/data/rsync_batch_test/file_20.txt new file mode 100644 index 0000000..93ad422 --- /dev/null +++ b/data/rsync_batch_test/file_20.txt @@ -0,0 +1 @@ +File 20 content diff --git a/data/rsync_batch_test/file_21.txt b/data/rsync_batch_test/file_21.txt new file mode 100644 index 0000000..42ef094 --- /dev/null +++ b/data/rsync_batch_test/file_21.txt @@ -0,0 +1 @@ +File 21 content diff --git a/data/rsync_batch_test/file_22.txt b/data/rsync_batch_test/file_22.txt new file mode 100644 index 0000000..aa6e54f --- /dev/null +++ b/data/rsync_batch_test/file_22.txt @@ -0,0 +1 @@ +File 22 content diff --git a/data/rsync_batch_test/file_23.txt b/data/rsync_batch_test/file_23.txt new file mode 100644 index 0000000..bb4481b --- /dev/null +++ b/data/rsync_batch_test/file_23.txt @@ -0,0 +1 @@ +File 23 content diff --git a/data/rsync_batch_test/file_24.txt b/data/rsync_batch_test/file_24.txt new file mode 100644 index 0000000..930093b --- /dev/null +++ b/data/rsync_batch_test/file_24.txt @@ -0,0 +1 @@ +File 24 content diff --git a/data/rsync_batch_test/file_25.txt b/data/rsync_batch_test/file_25.txt new file mode 100644 index 0000000..e5d7281 --- /dev/null +++ b/data/rsync_batch_test/file_25.txt @@ -0,0 +1 @@ +File 25 content diff --git a/data/rsync_batch_test/file_26.txt b/data/rsync_batch_test/file_26.txt new file mode 100644 index 0000000..2bda484 --- /dev/null +++ b/data/rsync_batch_test/file_26.txt @@ -0,0 +1 @@ +File 26 content diff --git a/data/rsync_batch_test/file_27.txt b/data/rsync_batch_test/file_27.txt new file mode 100644 index 0000000..8cc0a6b --- /dev/null +++ b/data/rsync_batch_test/file_27.txt @@ -0,0 +1 @@ +File 27 content diff --git a/data/rsync_batch_test/file_28.txt b/data/rsync_batch_test/file_28.txt new file mode 100644 index 0000000..3286d16 --- /dev/null +++ b/data/rsync_batch_test/file_28.txt @@ -0,0 +1 @@ +File 28 content diff --git a/data/rsync_batch_test/file_29.txt b/data/rsync_batch_test/file_29.txt new file mode 100644 index 0000000..d773353 --- /dev/null +++ b/data/rsync_batch_test/file_29.txt @@ -0,0 +1 @@ +File 29 content diff --git a/data/rsync_batch_test/file_3.txt b/data/rsync_batch_test/file_3.txt new file mode 100644 index 0000000..fda7882 --- /dev/null +++ b/data/rsync_batch_test/file_3.txt @@ -0,0 +1 @@ +File 3 content diff --git a/data/rsync_batch_test/file_30.txt b/data/rsync_batch_test/file_30.txt new file mode 100644 index 0000000..cf7c17a --- /dev/null +++ b/data/rsync_batch_test/file_30.txt @@ -0,0 +1 @@ +File 30 content diff --git a/data/rsync_batch_test/file_31.txt b/data/rsync_batch_test/file_31.txt new file mode 100644 index 0000000..d39bde6 --- /dev/null +++ b/data/rsync_batch_test/file_31.txt @@ -0,0 +1 @@ +File 31 content diff --git a/data/rsync_batch_test/file_32.txt b/data/rsync_batch_test/file_32.txt new file mode 100644 index 0000000..bb078f2 --- /dev/null +++ b/data/rsync_batch_test/file_32.txt @@ -0,0 +1 @@ +File 32 content diff --git a/data/rsync_batch_test/file_33.txt b/data/rsync_batch_test/file_33.txt new file mode 100644 index 0000000..5da7bbf --- /dev/null +++ b/data/rsync_batch_test/file_33.txt @@ -0,0 +1 @@ +File 33 content diff --git a/data/rsync_batch_test/file_34.txt b/data/rsync_batch_test/file_34.txt new file mode 100644 index 0000000..4ab91cd --- /dev/null +++ b/data/rsync_batch_test/file_34.txt @@ -0,0 +1 @@ +File 34 content diff --git a/data/rsync_batch_test/file_35.txt b/data/rsync_batch_test/file_35.txt new file mode 100644 index 0000000..a1aecb4 --- /dev/null +++ b/data/rsync_batch_test/file_35.txt @@ -0,0 +1 @@ +File 35 content diff --git a/data/rsync_batch_test/file_36.txt b/data/rsync_batch_test/file_36.txt new file mode 100644 index 0000000..ab5bb85 --- /dev/null +++ b/data/rsync_batch_test/file_36.txt @@ -0,0 +1 @@ +File 36 content diff --git a/data/rsync_batch_test/file_37.txt b/data/rsync_batch_test/file_37.txt new file mode 100644 index 0000000..88097ba --- /dev/null +++ b/data/rsync_batch_test/file_37.txt @@ -0,0 +1 @@ +File 37 content diff --git a/data/rsync_batch_test/file_38.txt b/data/rsync_batch_test/file_38.txt new file mode 100644 index 0000000..d1919da --- /dev/null +++ b/data/rsync_batch_test/file_38.txt @@ -0,0 +1 @@ +File 38 content diff --git a/data/rsync_batch_test/file_39.txt b/data/rsync_batch_test/file_39.txt new file mode 100644 index 0000000..1e057b0 --- /dev/null +++ b/data/rsync_batch_test/file_39.txt @@ -0,0 +1 @@ +File 39 content diff --git a/data/rsync_batch_test/file_4.txt b/data/rsync_batch_test/file_4.txt new file mode 100644 index 0000000..b236625 --- /dev/null +++ b/data/rsync_batch_test/file_4.txt @@ -0,0 +1 @@ +File 4 content diff --git a/data/rsync_batch_test/file_40.txt b/data/rsync_batch_test/file_40.txt new file mode 100644 index 0000000..cfd83f7 --- /dev/null +++ b/data/rsync_batch_test/file_40.txt @@ -0,0 +1 @@ +File 40 content diff --git a/data/rsync_batch_test/file_41.txt b/data/rsync_batch_test/file_41.txt new file mode 100644 index 0000000..a05109e --- /dev/null +++ b/data/rsync_batch_test/file_41.txt @@ -0,0 +1 @@ +File 41 content diff --git a/data/rsync_batch_test/file_42.txt b/data/rsync_batch_test/file_42.txt new file mode 100644 index 0000000..66b3b7a --- /dev/null +++ b/data/rsync_batch_test/file_42.txt @@ -0,0 +1 @@ +File 42 content diff --git a/data/rsync_batch_test/file_43.txt b/data/rsync_batch_test/file_43.txt new file mode 100644 index 0000000..9f76758 --- /dev/null +++ b/data/rsync_batch_test/file_43.txt @@ -0,0 +1 @@ +File 43 content diff --git a/data/rsync_batch_test/file_44.txt b/data/rsync_batch_test/file_44.txt new file mode 100644 index 0000000..9cfeb2b --- /dev/null +++ b/data/rsync_batch_test/file_44.txt @@ -0,0 +1 @@ +File 44 content diff --git a/data/rsync_batch_test/file_45.txt b/data/rsync_batch_test/file_45.txt new file mode 100644 index 0000000..0f810f1 --- /dev/null +++ b/data/rsync_batch_test/file_45.txt @@ -0,0 +1 @@ +File 45 content diff --git a/data/rsync_batch_test/file_46.txt b/data/rsync_batch_test/file_46.txt new file mode 100644 index 0000000..c1e6026 --- /dev/null +++ b/data/rsync_batch_test/file_46.txt @@ -0,0 +1 @@ +File 46 content diff --git a/data/rsync_batch_test/file_47.txt b/data/rsync_batch_test/file_47.txt new file mode 100644 index 0000000..ae5a4c1 --- /dev/null +++ b/data/rsync_batch_test/file_47.txt @@ -0,0 +1 @@ +File 47 content diff --git a/data/rsync_batch_test/file_48.txt b/data/rsync_batch_test/file_48.txt new file mode 100644 index 0000000..762e01d --- /dev/null +++ b/data/rsync_batch_test/file_48.txt @@ -0,0 +1 @@ +File 48 content diff --git a/data/rsync_batch_test/file_49.txt b/data/rsync_batch_test/file_49.txt new file mode 100644 index 0000000..506b90a --- /dev/null +++ b/data/rsync_batch_test/file_49.txt @@ -0,0 +1 @@ +File 49 content diff --git a/data/rsync_batch_test/file_5.txt b/data/rsync_batch_test/file_5.txt new file mode 100644 index 0000000..3d82150 --- /dev/null +++ b/data/rsync_batch_test/file_5.txt @@ -0,0 +1 @@ +File 5 content diff --git a/data/rsync_batch_test/file_50.txt b/data/rsync_batch_test/file_50.txt new file mode 100644 index 0000000..79e0a4b --- /dev/null +++ b/data/rsync_batch_test/file_50.txt @@ -0,0 +1 @@ +File 50 content diff --git a/data/rsync_batch_test/file_51.txt b/data/rsync_batch_test/file_51.txt new file mode 100644 index 0000000..42a558e --- /dev/null +++ b/data/rsync_batch_test/file_51.txt @@ -0,0 +1 @@ +File 51 content diff --git a/data/rsync_batch_test/file_52.txt b/data/rsync_batch_test/file_52.txt new file mode 100644 index 0000000..09f2dd9 --- /dev/null +++ b/data/rsync_batch_test/file_52.txt @@ -0,0 +1 @@ +File 52 content diff --git a/data/rsync_batch_test/file_53.txt b/data/rsync_batch_test/file_53.txt new file mode 100644 index 0000000..b85ee44 --- /dev/null +++ b/data/rsync_batch_test/file_53.txt @@ -0,0 +1 @@ +File 53 content diff --git a/data/rsync_batch_test/file_54.txt b/data/rsync_batch_test/file_54.txt new file mode 100644 index 0000000..bcdd2a1 --- /dev/null +++ b/data/rsync_batch_test/file_54.txt @@ -0,0 +1 @@ +File 54 content diff --git a/data/rsync_batch_test/file_55.txt b/data/rsync_batch_test/file_55.txt new file mode 100644 index 0000000..299df1a --- /dev/null +++ b/data/rsync_batch_test/file_55.txt @@ -0,0 +1 @@ +File 55 content diff --git a/data/rsync_batch_test/file_56.txt b/data/rsync_batch_test/file_56.txt new file mode 100644 index 0000000..de2e3d7 --- /dev/null +++ b/data/rsync_batch_test/file_56.txt @@ -0,0 +1 @@ +File 56 content diff --git a/data/rsync_batch_test/file_57.txt b/data/rsync_batch_test/file_57.txt new file mode 100644 index 0000000..d3c4750 --- /dev/null +++ b/data/rsync_batch_test/file_57.txt @@ -0,0 +1 @@ +File 57 content diff --git a/data/rsync_batch_test/file_58.txt b/data/rsync_batch_test/file_58.txt new file mode 100644 index 0000000..2a1b83a --- /dev/null +++ b/data/rsync_batch_test/file_58.txt @@ -0,0 +1 @@ +File 58 content diff --git a/data/rsync_batch_test/file_59.txt b/data/rsync_batch_test/file_59.txt new file mode 100644 index 0000000..381c8dd --- /dev/null +++ b/data/rsync_batch_test/file_59.txt @@ -0,0 +1 @@ +File 59 content diff --git a/data/rsync_batch_test/file_6.txt b/data/rsync_batch_test/file_6.txt new file mode 100644 index 0000000..5a004ba --- /dev/null +++ b/data/rsync_batch_test/file_6.txt @@ -0,0 +1 @@ +File 6 content diff --git a/data/rsync_batch_test/file_60.txt b/data/rsync_batch_test/file_60.txt new file mode 100644 index 0000000..9354f79 --- /dev/null +++ b/data/rsync_batch_test/file_60.txt @@ -0,0 +1 @@ +File 60 content diff --git a/data/rsync_batch_test/file_61.txt b/data/rsync_batch_test/file_61.txt new file mode 100644 index 0000000..d3a7710 --- /dev/null +++ b/data/rsync_batch_test/file_61.txt @@ -0,0 +1 @@ +File 61 content diff --git a/data/rsync_batch_test/file_62.txt b/data/rsync_batch_test/file_62.txt new file mode 100644 index 0000000..21fd818 --- /dev/null +++ b/data/rsync_batch_test/file_62.txt @@ -0,0 +1 @@ +File 62 content diff --git a/data/rsync_batch_test/file_63.txt b/data/rsync_batch_test/file_63.txt new file mode 100644 index 0000000..e4e40bf --- /dev/null +++ b/data/rsync_batch_test/file_63.txt @@ -0,0 +1 @@ +File 63 content diff --git a/data/rsync_batch_test/file_64.txt b/data/rsync_batch_test/file_64.txt new file mode 100644 index 0000000..9a3bd3a --- /dev/null +++ b/data/rsync_batch_test/file_64.txt @@ -0,0 +1 @@ +File 64 content diff --git a/data/rsync_batch_test/file_65.txt b/data/rsync_batch_test/file_65.txt new file mode 100644 index 0000000..2b3c894 --- /dev/null +++ b/data/rsync_batch_test/file_65.txt @@ -0,0 +1 @@ +File 65 content diff --git a/data/rsync_batch_test/file_66.txt b/data/rsync_batch_test/file_66.txt new file mode 100644 index 0000000..ff6e5fd --- /dev/null +++ b/data/rsync_batch_test/file_66.txt @@ -0,0 +1 @@ +File 66 content diff --git a/data/rsync_batch_test/file_67.txt b/data/rsync_batch_test/file_67.txt new file mode 100644 index 0000000..8e5eed4 --- /dev/null +++ b/data/rsync_batch_test/file_67.txt @@ -0,0 +1 @@ +File 67 content diff --git a/data/rsync_batch_test/file_68.txt b/data/rsync_batch_test/file_68.txt new file mode 100644 index 0000000..f8516a5 --- /dev/null +++ b/data/rsync_batch_test/file_68.txt @@ -0,0 +1 @@ +File 68 content diff --git a/data/rsync_batch_test/file_69.txt b/data/rsync_batch_test/file_69.txt new file mode 100644 index 0000000..5ecdd13 --- /dev/null +++ b/data/rsync_batch_test/file_69.txt @@ -0,0 +1 @@ +File 69 content diff --git a/data/rsync_batch_test/file_7.txt b/data/rsync_batch_test/file_7.txt new file mode 100644 index 0000000..bf12b7a --- /dev/null +++ b/data/rsync_batch_test/file_7.txt @@ -0,0 +1 @@ +File 7 content diff --git a/data/rsync_batch_test/file_70.txt b/data/rsync_batch_test/file_70.txt new file mode 100644 index 0000000..9ae521b --- /dev/null +++ b/data/rsync_batch_test/file_70.txt @@ -0,0 +1 @@ +File 70 content diff --git a/data/rsync_batch_test/file_71.txt b/data/rsync_batch_test/file_71.txt new file mode 100644 index 0000000..5ac676a --- /dev/null +++ b/data/rsync_batch_test/file_71.txt @@ -0,0 +1 @@ +File 71 content diff --git a/data/rsync_batch_test/file_72.txt b/data/rsync_batch_test/file_72.txt new file mode 100644 index 0000000..3649a6b --- /dev/null +++ b/data/rsync_batch_test/file_72.txt @@ -0,0 +1 @@ +File 72 content diff --git a/data/rsync_batch_test/file_73.txt b/data/rsync_batch_test/file_73.txt new file mode 100644 index 0000000..2ae6c13 --- /dev/null +++ b/data/rsync_batch_test/file_73.txt @@ -0,0 +1 @@ +File 73 content diff --git a/data/rsync_batch_test/file_74.txt b/data/rsync_batch_test/file_74.txt new file mode 100644 index 0000000..ad97261 --- /dev/null +++ b/data/rsync_batch_test/file_74.txt @@ -0,0 +1 @@ +File 74 content diff --git a/data/rsync_batch_test/file_75.txt b/data/rsync_batch_test/file_75.txt new file mode 100644 index 0000000..5e0d1e6 --- /dev/null +++ b/data/rsync_batch_test/file_75.txt @@ -0,0 +1 @@ +File 75 content diff --git a/data/rsync_batch_test/file_76.txt b/data/rsync_batch_test/file_76.txt new file mode 100644 index 0000000..0cbc219 --- /dev/null +++ b/data/rsync_batch_test/file_76.txt @@ -0,0 +1 @@ +File 76 content diff --git a/data/rsync_batch_test/file_77.txt b/data/rsync_batch_test/file_77.txt new file mode 100644 index 0000000..9abfa1b --- /dev/null +++ b/data/rsync_batch_test/file_77.txt @@ -0,0 +1 @@ +File 77 content diff --git a/data/rsync_batch_test/file_78.txt b/data/rsync_batch_test/file_78.txt new file mode 100644 index 0000000..d6df5a9 --- /dev/null +++ b/data/rsync_batch_test/file_78.txt @@ -0,0 +1 @@ +File 78 content diff --git a/data/rsync_batch_test/file_79.txt b/data/rsync_batch_test/file_79.txt new file mode 100644 index 0000000..1b46299 --- /dev/null +++ b/data/rsync_batch_test/file_79.txt @@ -0,0 +1 @@ +File 79 content diff --git a/data/rsync_batch_test/file_8.txt b/data/rsync_batch_test/file_8.txt new file mode 100644 index 0000000..5c2ae90 --- /dev/null +++ b/data/rsync_batch_test/file_8.txt @@ -0,0 +1 @@ +File 8 content diff --git a/data/rsync_batch_test/file_80.txt b/data/rsync_batch_test/file_80.txt new file mode 100644 index 0000000..48f210c --- /dev/null +++ b/data/rsync_batch_test/file_80.txt @@ -0,0 +1 @@ +File 80 content diff --git a/data/rsync_batch_test/file_81.txt b/data/rsync_batch_test/file_81.txt new file mode 100644 index 0000000..6c91e7c --- /dev/null +++ b/data/rsync_batch_test/file_81.txt @@ -0,0 +1 @@ +File 81 content diff --git a/data/rsync_batch_test/file_82.txt b/data/rsync_batch_test/file_82.txt new file mode 100644 index 0000000..c23cce1 --- /dev/null +++ b/data/rsync_batch_test/file_82.txt @@ -0,0 +1 @@ +File 82 content diff --git a/data/rsync_batch_test/file_83.txt b/data/rsync_batch_test/file_83.txt new file mode 100644 index 0000000..ec4d206 --- /dev/null +++ b/data/rsync_batch_test/file_83.txt @@ -0,0 +1 @@ +File 83 content diff --git a/data/rsync_batch_test/file_84.txt b/data/rsync_batch_test/file_84.txt new file mode 100644 index 0000000..336bbe8 --- /dev/null +++ b/data/rsync_batch_test/file_84.txt @@ -0,0 +1 @@ +File 84 content diff --git a/data/rsync_batch_test/file_85.txt b/data/rsync_batch_test/file_85.txt new file mode 100644 index 0000000..f5f1141 --- /dev/null +++ b/data/rsync_batch_test/file_85.txt @@ -0,0 +1 @@ +File 85 content diff --git a/data/rsync_batch_test/file_86.txt b/data/rsync_batch_test/file_86.txt new file mode 100644 index 0000000..c681b1f --- /dev/null +++ b/data/rsync_batch_test/file_86.txt @@ -0,0 +1 @@ +File 86 content diff --git a/data/rsync_batch_test/file_87.txt b/data/rsync_batch_test/file_87.txt new file mode 100644 index 0000000..f5ee2d2 --- /dev/null +++ b/data/rsync_batch_test/file_87.txt @@ -0,0 +1 @@ +File 87 content diff --git a/data/rsync_batch_test/file_88.txt b/data/rsync_batch_test/file_88.txt new file mode 100644 index 0000000..e6ecebc --- /dev/null +++ b/data/rsync_batch_test/file_88.txt @@ -0,0 +1 @@ +File 88 content diff --git a/data/rsync_batch_test/file_89.txt b/data/rsync_batch_test/file_89.txt new file mode 100644 index 0000000..a025191 --- /dev/null +++ b/data/rsync_batch_test/file_89.txt @@ -0,0 +1 @@ +File 89 content diff --git a/data/rsync_batch_test/file_9.txt b/data/rsync_batch_test/file_9.txt new file mode 100644 index 0000000..065e87a --- /dev/null +++ b/data/rsync_batch_test/file_9.txt @@ -0,0 +1 @@ +File 9 content diff --git a/data/rsync_batch_test/file_90.txt b/data/rsync_batch_test/file_90.txt new file mode 100644 index 0000000..b91f638 --- /dev/null +++ b/data/rsync_batch_test/file_90.txt @@ -0,0 +1 @@ +File 90 content diff --git a/data/rsync_batch_test/file_91.txt b/data/rsync_batch_test/file_91.txt new file mode 100644 index 0000000..ef5ff94 --- /dev/null +++ b/data/rsync_batch_test/file_91.txt @@ -0,0 +1 @@ +File 91 content diff --git a/data/rsync_batch_test/file_92.txt b/data/rsync_batch_test/file_92.txt new file mode 100644 index 0000000..efb550a --- /dev/null +++ b/data/rsync_batch_test/file_92.txt @@ -0,0 +1 @@ +File 92 content diff --git a/data/rsync_batch_test/file_93.txt b/data/rsync_batch_test/file_93.txt new file mode 100644 index 0000000..f52c4dd --- /dev/null +++ b/data/rsync_batch_test/file_93.txt @@ -0,0 +1 @@ +File 93 content diff --git a/data/rsync_batch_test/file_94.txt b/data/rsync_batch_test/file_94.txt new file mode 100644 index 0000000..67617cc --- /dev/null +++ b/data/rsync_batch_test/file_94.txt @@ -0,0 +1 @@ +File 94 content diff --git a/data/rsync_batch_test/file_95.txt b/data/rsync_batch_test/file_95.txt new file mode 100644 index 0000000..5301cfd --- /dev/null +++ b/data/rsync_batch_test/file_95.txt @@ -0,0 +1 @@ +File 95 content diff --git a/data/rsync_batch_test/file_96.txt b/data/rsync_batch_test/file_96.txt new file mode 100644 index 0000000..4e6c093 --- /dev/null +++ b/data/rsync_batch_test/file_96.txt @@ -0,0 +1 @@ +File 96 content diff --git a/data/rsync_batch_test/file_97.txt b/data/rsync_batch_test/file_97.txt new file mode 100644 index 0000000..154da8e --- /dev/null +++ b/data/rsync_batch_test/file_97.txt @@ -0,0 +1 @@ +File 97 content diff --git a/data/rsync_batch_test/file_98.txt b/data/rsync_batch_test/file_98.txt new file mode 100644 index 0000000..1b3859e --- /dev/null +++ b/data/rsync_batch_test/file_98.txt @@ -0,0 +1 @@ +File 98 content diff --git a/data/rsync_batch_test/file_99.txt b/data/rsync_batch_test/file_99.txt new file mode 100644 index 0000000..694ae89 --- /dev/null +++ b/data/rsync_batch_test/file_99.txt @@ -0,0 +1 @@ +File 99 content diff --git a/data/rsync_compress_test.txt b/data/rsync_compress_test.txt new file mode 100644 index 0000000..c46d183 --- /dev/null +++ b/data/rsync_compress_test.txt @@ -0,0 +1,2000 @@ +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing +This is a test line for compression testing diff --git a/data/rsync_delete_test/file_A.txt b/data/rsync_delete_test/file_A.txt new file mode 100644 index 0000000..6d8b180 --- /dev/null +++ b/data/rsync_delete_test/file_A.txt @@ -0,0 +1 @@ +File A diff --git a/data/rsync_delete_test/file_C.txt b/data/rsync_delete_test/file_C.txt new file mode 100644 index 0000000..df78d3d --- /dev/null +++ b/data/rsync_delete_test/file_C.txt @@ -0,0 +1 @@ +File C diff --git a/data/rsync_delete_test/file_D.txt b/data/rsync_delete_test/file_D.txt new file mode 100644 index 0000000..200559f --- /dev/null +++ b/data/rsync_delete_test/file_D.txt @@ -0,0 +1 @@ +File D (new) diff --git a/data/rsync_final_v4/file_1.txt b/data/rsync_final_v4/file_1.txt new file mode 100644 index 0000000..16a0a1c --- /dev/null +++ b/data/rsync_final_v4/file_1.txt @@ -0,0 +1 @@ +File 1 content for rsync test diff --git a/data/rsync_final_v4/file_10.txt b/data/rsync_final_v4/file_10.txt new file mode 100644 index 0000000..4487fea --- /dev/null +++ b/data/rsync_final_v4/file_10.txt @@ -0,0 +1 @@ +File 10 content for rsync test diff --git a/data/rsync_final_v4/file_2.txt b/data/rsync_final_v4/file_2.txt new file mode 100644 index 0000000..83ae8d1 --- /dev/null +++ b/data/rsync_final_v4/file_2.txt @@ -0,0 +1 @@ +File 2 content for rsync test diff --git a/data/rsync_final_v4/file_3.txt b/data/rsync_final_v4/file_3.txt new file mode 100644 index 0000000..2d9809d --- /dev/null +++ b/data/rsync_final_v4/file_3.txt @@ -0,0 +1 @@ +File 3 content for rsync test diff --git a/data/rsync_final_v4/file_4.txt b/data/rsync_final_v4/file_4.txt new file mode 100644 index 0000000..cb59921 --- /dev/null +++ b/data/rsync_final_v4/file_4.txt @@ -0,0 +1 @@ +File 4 content for rsync test diff --git a/data/rsync_final_v4/file_5.txt b/data/rsync_final_v4/file_5.txt new file mode 100644 index 0000000..343fc1a --- /dev/null +++ b/data/rsync_final_v4/file_5.txt @@ -0,0 +1 @@ +File 5 content for rsync test diff --git a/data/rsync_final_v4/file_6.txt b/data/rsync_final_v4/file_6.txt new file mode 100644 index 0000000..ea40216 --- /dev/null +++ b/data/rsync_final_v4/file_6.txt @@ -0,0 +1 @@ +File 6 content for rsync test diff --git a/data/rsync_final_v4/file_7.txt b/data/rsync_final_v4/file_7.txt new file mode 100644 index 0000000..c537dde --- /dev/null +++ b/data/rsync_final_v4/file_7.txt @@ -0,0 +1 @@ +File 7 content for rsync test diff --git a/data/rsync_final_v4/file_8.txt b/data/rsync_final_v4/file_8.txt new file mode 100644 index 0000000..d95361e --- /dev/null +++ b/data/rsync_final_v4/file_8.txt @@ -0,0 +1 @@ +File 8 content for rsync test diff --git a/data/rsync_final_v4/file_9.txt b/data/rsync_final_v4/file_9.txt new file mode 100644 index 0000000..d2c471d --- /dev/null +++ b/data/rsync_final_v4/file_9.txt @@ -0,0 +1 @@ +File 9 content for rsync test diff --git a/data/rsync_final_v4/large_file.txt b/data/rsync_final_v4/large_file.txt new file mode 100644 index 0000000..10819fd --- /dev/null +++ b/data/rsync_final_v4/large_file.txt @@ -0,0 +1 @@ +Large file for delta transfer test diff --git a/data/rsync_final_v4/random.bin b/data/rsync_final_v4/random.bin new file mode 100644 index 0000000..a673e09 Binary files /dev/null and b/data/rsync_final_v4/random.bin differ diff --git a/data/rsync_large_test.bin b/data/rsync_large_test.bin new file mode 100644 index 0000000..daaff98 Binary files /dev/null and b/data/rsync_large_test.bin differ diff --git a/data/rsync_nested_test/level1/file1.txt b/data/rsync_nested_test/level1/file1.txt new file mode 100644 index 0000000..415b4d7 --- /dev/null +++ b/data/rsync_nested_test/level1/file1.txt @@ -0,0 +1 @@ +Level 1 content diff --git a/data/rsync_nested_test/level1/level2/file2.txt b/data/rsync_nested_test/level1/level2/file2.txt new file mode 100644 index 0000000..69fe44e --- /dev/null +++ b/data/rsync_nested_test/level1/level2/file2.txt @@ -0,0 +1 @@ +Level 2 content diff --git a/data/rsync_nested_test/level1/level2/level3/file3.txt b/data/rsync_nested_test/level1/level2/level3/file3.txt new file mode 100644 index 0000000..701688c --- /dev/null +++ b/data/rsync_nested_test/level1/level2/level3/file3.txt @@ -0,0 +1 @@ +Level 3 content diff --git a/data/rsync_perm_test.txt b/data/rsync_perm_test.txt new file mode 100755 index 0000000..62c1060 --- /dev/null +++ b/data/rsync_perm_test.txt @@ -0,0 +1 @@ +Permission test diff --git a/data/scp_as_rsync/file_1.txt b/data/scp_as_rsync/file_1.txt new file mode 100644 index 0000000..16a0a1c --- /dev/null +++ b/data/scp_as_rsync/file_1.txt @@ -0,0 +1 @@ +File 1 content for rsync test diff --git a/data/scp_as_rsync/file_10.txt b/data/scp_as_rsync/file_10.txt new file mode 100644 index 0000000..4487fea --- /dev/null +++ b/data/scp_as_rsync/file_10.txt @@ -0,0 +1 @@ +File 10 content for rsync test diff --git a/data/scp_as_rsync/file_2.txt b/data/scp_as_rsync/file_2.txt new file mode 100644 index 0000000..83ae8d1 --- /dev/null +++ b/data/scp_as_rsync/file_2.txt @@ -0,0 +1 @@ +File 2 content for rsync test diff --git a/data/scp_as_rsync/file_3.txt b/data/scp_as_rsync/file_3.txt new file mode 100644 index 0000000..2d9809d --- /dev/null +++ b/data/scp_as_rsync/file_3.txt @@ -0,0 +1 @@ +File 3 content for rsync test diff --git a/data/scp_as_rsync/file_4.txt b/data/scp_as_rsync/file_4.txt new file mode 100644 index 0000000..cb59921 --- /dev/null +++ b/data/scp_as_rsync/file_4.txt @@ -0,0 +1 @@ +File 4 content for rsync test diff --git a/data/scp_as_rsync/file_5.txt b/data/scp_as_rsync/file_5.txt new file mode 100644 index 0000000..343fc1a --- /dev/null +++ b/data/scp_as_rsync/file_5.txt @@ -0,0 +1 @@ +File 5 content for rsync test diff --git a/data/scp_as_rsync/file_6.txt b/data/scp_as_rsync/file_6.txt new file mode 100644 index 0000000..ea40216 --- /dev/null +++ b/data/scp_as_rsync/file_6.txt @@ -0,0 +1 @@ +File 6 content for rsync test diff --git a/data/scp_as_rsync/file_7.txt b/data/scp_as_rsync/file_7.txt new file mode 100644 index 0000000..c537dde --- /dev/null +++ b/data/scp_as_rsync/file_7.txt @@ -0,0 +1 @@ +File 7 content for rsync test diff --git a/data/scp_as_rsync/large_file.txt b/data/scp_as_rsync/large_file.txt new file mode 100644 index 0000000..10819fd --- /dev/null +++ b/data/scp_as_rsync/large_file.txt @@ -0,0 +1 @@ +Large file for delta transfer test diff --git a/data/scp_as_rsync/random.bin b/data/scp_as_rsync/random.bin new file mode 100644 index 0000000..e69de29 diff --git a/data/scp_batch_final/file_1.txt b/data/scp_batch_final/file_1.txt new file mode 100644 index 0000000..16a0a1c --- /dev/null +++ b/data/scp_batch_final/file_1.txt @@ -0,0 +1 @@ +File 1 content for rsync test diff --git a/data/scp_batch_final/file_10.txt b/data/scp_batch_final/file_10.txt new file mode 100644 index 0000000..4487fea --- /dev/null +++ b/data/scp_batch_final/file_10.txt @@ -0,0 +1 @@ +File 10 content for rsync test diff --git a/data/scp_batch_final/file_2.txt b/data/scp_batch_final/file_2.txt new file mode 100644 index 0000000..83ae8d1 --- /dev/null +++ b/data/scp_batch_final/file_2.txt @@ -0,0 +1 @@ +File 2 content for rsync test diff --git a/data/scp_batch_final/file_3.txt b/data/scp_batch_final/file_3.txt new file mode 100644 index 0000000..2d9809d --- /dev/null +++ b/data/scp_batch_final/file_3.txt @@ -0,0 +1 @@ +File 3 content for rsync test diff --git a/data/scp_batch_final/file_4.txt b/data/scp_batch_final/file_4.txt new file mode 100644 index 0000000..cb59921 --- /dev/null +++ b/data/scp_batch_final/file_4.txt @@ -0,0 +1 @@ +File 4 content for rsync test diff --git a/data/scp_batch_final/file_5.txt b/data/scp_batch_final/file_5.txt new file mode 100644 index 0000000..343fc1a --- /dev/null +++ b/data/scp_batch_final/file_5.txt @@ -0,0 +1 @@ +File 5 content for rsync test diff --git a/data/scp_batch_final/file_6.txt b/data/scp_batch_final/file_6.txt new file mode 100644 index 0000000..ea40216 --- /dev/null +++ b/data/scp_batch_final/file_6.txt @@ -0,0 +1 @@ +File 6 content for rsync test diff --git a/data/scp_batch_final/file_7.txt b/data/scp_batch_final/file_7.txt new file mode 100644 index 0000000..c537dde --- /dev/null +++ b/data/scp_batch_final/file_7.txt @@ -0,0 +1 @@ +File 7 content for rsync test diff --git a/data/scp_batch_final/large_file.txt b/data/scp_batch_final/large_file.txt new file mode 100644 index 0000000..10819fd --- /dev/null +++ b/data/scp_batch_final/large_file.txt @@ -0,0 +1 @@ +Large file for delta transfer test diff --git a/data/scp_batch_final/random.bin b/data/scp_batch_final/random.bin new file mode 100644 index 0000000..e69de29 diff --git a/data/scp_empty_test/root.txt b/data/scp_empty_test/root.txt new file mode 100644 index 0000000..a94a36c --- /dev/null +++ b/data/scp_empty_test/root.txt @@ -0,0 +1 @@ +Root file diff --git a/data/scp_empty_test/subdir_with_file/file.txt b/data/scp_empty_test/subdir_with_file/file.txt new file mode 100644 index 0000000..cc3c296 --- /dev/null +++ b/data/scp_empty_test/subdir_with_file/file.txt @@ -0,0 +1 @@ +File in subdir diff --git a/data/scp_test/file_1.txt b/data/scp_test/file_1.txt new file mode 100644 index 0000000..be49ac5 --- /dev/null +++ b/data/scp_test/file_1.txt @@ -0,0 +1 @@ +Test file 1 content - Mon 15 Jun 2026 19:47:35 CST diff --git a/data/scp_test/file_2.txt b/data/scp_test/file_2.txt new file mode 100644 index 0000000..e048806 --- /dev/null +++ b/data/scp_test/file_2.txt @@ -0,0 +1 @@ +Test file 2 content - Mon 15 Jun 2026 19:47:35 CST diff --git a/data/scp_test/file_3.txt b/data/scp_test/file_3.txt new file mode 100644 index 0000000..c203105 --- /dev/null +++ b/data/scp_test/file_3.txt @@ -0,0 +1 @@ +Test file 3 content - Mon 15 Jun 2026 19:47:35 CST diff --git a/data/single_test.txt b/data/single_test.txt new file mode 100644 index 0000000..9835bc0 --- /dev/null +++ b/data/single_test.txt @@ -0,0 +1 @@ +Single file test diff --git a/data/test_final_confirm.txt b/data/test_final_confirm.txt new file mode 100644 index 0000000..3bf9c3d --- /dev/null +++ b/data/test_final_confirm.txt @@ -0,0 +1 @@ +Confirm FSETSTAT fix works perfectly diff --git a/data/test_fsetstat_fix.txt b/data/test_fsetstat_fix.txt new file mode 100644 index 0000000..eb8fc5c --- /dev/null +++ b/data/test_fsetstat_fix.txt @@ -0,0 +1 @@ +Test FSETSTAT fix successful diff --git a/data/test_scp_debug.txt b/data/test_scp_debug.txt new file mode 100644 index 0000000..0d9194a --- /dev/null +++ b/data/test_scp_debug.txt @@ -0,0 +1 @@ +Test content for SCP debug diff --git a/data/test_scp_upload.txt b/data/test_scp_upload.txt new file mode 100644 index 0000000..f661950 --- /dev/null +++ b/data/test_scp_upload.txt @@ -0,0 +1 @@ +Test SCP upload content diff --git a/data/test_single_scp.txt b/data/test_single_scp.txt new file mode 100644 index 0000000..27ce1b0 --- /dev/null +++ b/data/test_single_scp.txt @@ -0,0 +1 @@ +Test content for SCP diff --git a/data/test_stat.txt b/data/test_stat.txt new file mode 100644 index 0000000..cb6a352 --- /dev/null +++ b/data/test_stat.txt @@ -0,0 +1 @@ +New test content for STAT check diff --git a/data/test_stat_correct.txt b/data/test_stat_correct.txt new file mode 100644 index 0000000..b076d0b --- /dev/null +++ b/data/test_stat_correct.txt @@ -0,0 +1 @@ +Test STAT fix correct diff --git a/data/test_stat_final.txt b/data/test_stat_final.txt new file mode 100644 index 0000000..7edee3d --- /dev/null +++ b/data/test_stat_final.txt @@ -0,0 +1 @@ +Test STAT handling diff --git a/data/test_upload.txt b/data/test_upload.txt new file mode 100644 index 0000000..f661950 --- /dev/null +++ b/data/test_upload.txt @@ -0,0 +1 @@ +Test SCP upload content diff --git a/data/test_verbose.txt b/data/test_verbose.txt new file mode 100644 index 0000000..8c52d19 --- /dev/null +++ b/data/test_verbose.txt @@ -0,0 +1 @@ +Test verbose STAT diff --git a/markbase-core/Cargo.toml b/markbase-core/Cargo.toml index a855e42..d96cd6a 100644 --- a/markbase-core/Cargo.toml +++ b/markbase-core/Cargo.toml @@ -34,6 +34,7 @@ serde = { version = "1", features = ["derive"] } serde_json = "1" sha2 = "0.10" hmac = "0.12" +filetime = "0.2" base64 = "0.22" tokio = { version = "1", features = ["full"] } tokio-postgres = "0.7" @@ -56,6 +57,7 @@ ed25519-dalek = { version = "2.0", features = ["rand_core"] } aes = "0.8" ctr = "0.9" cipher = "0.4" +nix = { version = "0.29", features = ["poll", "fs"] } # Phase 14: OpenSSH风格的poll()和非阻塞I/O(fs feature包含fcntl) [features] default = [] # 默认不启用可选格式 diff --git a/markbase-core/src/ssh_server/channel.rs b/markbase-core/src/ssh_server/channel.rs index 7e39927..e3d3d64 100644 --- a/markbase-core/src/ssh_server/channel.rs +++ b/markbase-core/src/ssh_server/channel.rs @@ -14,6 +14,10 @@ use crate::ssh_server::sftp_handler::SftpHandler; // Phase 7: SFTP handler use crate::ssh_server::scp_handler::ScpHandler; // Phase 8: SCP handler use crate::ssh_server::rsync_handler::RsyncHandler; // Phase 8: rsync handler use std::path::PathBuf; // Phase 7-8: Path for SFTP/SCP/rsync root directory +use std::process::{Child, ChildStdin, ChildStdout, ChildStderr}; // Phase 14: 交互式exec +use std::os::unix::io::{AsRawFd, RawFd}; // Phase 14: OpenSSH风格poll机制(需要RawFd) +use nix::fcntl::{fcntl, FcntlArg, OFlag}; // Phase 14: 非阻塞I/O(OpenSSH风格) +use nix::poll::{poll, PollFd, PollFlags}; // Phase 14: poll机制(OpenSSH风格) /// SSH Channel管理器(参考OpenSSH channel.c: struct channel) pub struct ChannelManager { @@ -21,6 +25,17 @@ pub struct ChannelManager { next_channel_id: u32, } +/// Phase 14: 交互式Exec进程管理(参考OpenSSH session.c: do_exec_no_pty) +/// ⭐⭐⭐⭐⭐ OpenSSH风格:使用poll()替代thread::spawn(非阻塞I/O) +pub struct ExecProcess { + pub child: Child, // 子进程(rsync/scp等) + pub stdin: Option, // stdin管道(SSH client → 子进程) + pub stdout: Option, // ⭐⭐⭐⭐⭐ stdout管道(直接poll,不使用thread) + pub stderr: Option, // ⭐⭐⭐⭐⭐ stderr管道(直接poll,不使用thread) + pub stdout_fd: RawFd, // ⭐⭐⭐⭐⭐ stdout RawFd(用于poll) + pub stderr_fd: RawFd, // ⭐⭐⭐⭐⭐ stderr RawFd(用于poll) +} + impl ChannelManager { pub fn new() -> Self { Self { @@ -107,6 +122,7 @@ impl ChannelManager { sftp_handler: None, scp_handler: None, rsync_handler: None, + exec_process: None, // Phase 14: 交互式exec direct_tcpip: None, forwarded_tcpip: None, }; @@ -161,6 +177,7 @@ impl ChannelManager { sftp_handler: None, scp_handler: None, rsync_handler: None, + exec_process: None, // Phase 14: 交互式exec direct_tcpip: Some(direct_tcpip), forwarded_tcpip: None, }; @@ -203,6 +220,7 @@ impl ChannelManager { sftp_handler: None, scp_handler: None, rsync_handler: None, + exec_process: None, // Phase 14: 交互式exec direct_tcpip: None, forwarded_tcpip: Some(forwarded_tcpip), }; @@ -261,7 +279,7 @@ impl ChannelManager { } } - /// 处理exec请求(参考OpenSSH channel.c: channel_request_exec()) + /// 处理exec请求(参考OpenSSH channel.c: channel_request_exec() + session.c: do_exec_no_pty) fn handle_exec_request(&mut self, cursor: &mut std::io::Cursor<&[u8]>, channel: u32, want_reply: bool) -> Result> { info!("Handling exec request for channel {}", channel); @@ -270,13 +288,18 @@ impl ChannelManager { info!("Exec command: {}", command); - // Phase 8: SCP/rsync命令直接执行(使用系统命令) - // 不需要自己实现SCP协议,让系统的scp/rsync命令处理 - let output = self.execute_command(&command)?; - - // 存储输出,等待后续发送CHANNEL_DATA - if let Some(ch) = self.channels.get_mut(&channel) { - ch.output_buffer = Some(output); + // Phase 14: 检测rsync命令,启动交互式进程 + if command.starts_with("rsync --server") || command.contains("rsync") { + info!("Detected rsync command, starting interactive process"); + self.handle_rsync_exec(&command, channel)?; + } else { + // Phase 6: 普通命令使用非交互式执行 + let output = self.execute_command(&command)?; + + // 存储输出,等待后续发送CHANNEL_DATA + if let Some(ch) = self.channels.get_mut(&channel) { + ch.output_buffer = Some(output); + } } if want_reply { @@ -286,6 +309,56 @@ impl ChannelManager { } } + /// Phase 14: 处理rsync交互式exec(参考OpenSSH session.c: do_exec_no_pty) + /// ⭐⭐⭐⭐⭐ OpenSSH风格:使用poll()替代thread::spawn(非阻塞I/O) + fn handle_rsync_exec(&mut self, command: &str, channel_id: u32) -> Result<()> { + use std::process::{Command, Stdio}; + use std::os::unix::io::AsRawFd; + + info!("Starting interactive process for rsync (OpenSSH poll style): {}", command); + + // 启动子进程(相当于OpenSSH fork) + let mut child = Command::new("sh") + .arg("-c") + .arg(command) + .stdin(Stdio::piped()) // ← 创建stdin管道(相当于pipe(pin)) + .stdout(Stdio::piped()) // ← 创建stdout管道(相当于pipe(pout)) + .stderr(Stdio::piped()) // ← 创建stderr管道(相当于pipe(perr)) + .spawn()?; + + info!("Child process spawned, PID: {:?}", child.id()); + + // 提取管道(相当于OpenSSH dup2) + let stdin = child.stdin.take().ok_or(anyhow!("stdin take failed"))?; + let stdout = child.stdout.take().ok_or(anyhow!("stdout take failed"))?; + let stderr = child.stderr.take().ok_or(anyhow!("stderr take failed"))?; + + // ⭐⭐⭐⭐⭐ OpenSSH关键:设置非阻塞模式(fcntl O_NONBLOCK) + let stdout_fd = stdout.as_raw_fd(); + let stderr_fd = stderr.as_raw_fd(); + + info!("Setting stdout/stderr to non-blocking mode (OpenSSH style)"); + fcntl(stdout_fd, FcntlArg::F_SETFL(OFlag::O_NONBLOCK))?; + fcntl(stderr_fd, FcntlArg::F_SETFL(OFlag::O_NONBLOCK))?; + info!("Non-blocking I/O enabled for stdout (fd {}) and stderr (fd {})", stdout_fd, stderr_fd); + + // ⭐⭐⭐⭐⭐ OpenSSH风格:不再使用thread::spawn,直接保留File对象用于poll + // 存储到channel(相当于OpenSSH session_set_fds) + if let Some(ch) = self.channels.get_mut(&channel_id) { + ch.exec_process = Some(ExecProcess { + child, + stdin: Some(stdin), + stdout: Some(stdout), // ⭐⭐⭐⭐⭐ 直接保留File对象 + stderr: Some(stderr), // ⭐⭐⭐⭐⭐ 直接保留File对象 + stdout_fd, // ⭐⭐⭐⭐⭐ RawFd用于poll + stderr_fd, // ⭐⭐⭐⭐⭐ RawFd用于poll + }); + info!("Interactive process stored for channel {} (poll-ready)", channel_id); + } + + Ok(()) + } + /// 执行命令并捕获输出(Phase 6基础实现) fn execute_command(&self, command: &str) -> Result> { use std::process::{Command, Stdio}; @@ -425,24 +498,60 @@ impl ChannelManager { info!("Channel data: channel={}, length={}", recipient_channel, data.len()); info!("Channel data content (first 20 bytes): {:?}", &data[..std::cmp::min(20, data.len())]); - // Phase 7: 检查是否是SFTP channel + // Phase 14: 检查是否是交互式exec进程 if let Some(channel) = self.channels.get_mut(&recipient_channel) { + if let Some(exec_process) = &mut channel.exec_process { + info!("Interactive exec process detected, forwarding data to stdin"); + info!("Channel data content: {:?}", &data); + info!("Child PID: {:?}", exec_process.child.id()); + + // 检查子进程状态 + match exec_process.child.try_wait() { + Ok(Some(status)) => { + warn!("Child process already exited with status: {:?}", status); + } + Ok(None) => { + info!("Child process still running"); + } + Err(e) => { + warn!("Failed to check child status: {}", e); + } + } + + // 转发数据到子进程stdin(相当于OpenSSH写fdin) + if let Some(stdin) = &mut exec_process.stdin { + use std::io::Write; + stdin.write_all(&data)?; + stdin.flush()?; + info!("Forwarded {} bytes to stdin (OpenSSH style)", data.len()); + } + + // ⭐⭐⭐⭐⭐ OpenSSH风格:不等待,直接返回None(主循环会通过poll处理stdout) + info!("stdin forwarded, returning None (main loop will poll stdout/stderr)"); + return Ok(None); + } + + // Phase 7: 检查是否是SFTP channel if let Some(sftp_handler) = &mut channel.sftp_handler { info!("Processing SFTP request ({} bytes)", data.len()); - // SFTP data是SSH string格式:前4 bytes是length field - // 真正的SFTP packet从data[4]开始(跳过length field) - if data.len() < 4 { - warn!("SFTP data too short (less than 4 bytes)"); + if data.len() < 5 { + warn!("SFTP data too short (less than 5 bytes)"); return Ok(None); } - let sftp_packet_length = u32::from_be_bytes([data[0], data[1], data[2], data[3]]) as usize; - let sftp_packet = &data[4..4 + sftp_packet_length]; + let sftp_length = u32::from_be_bytes([data[0], data[1], data[2], data[3]]) as usize; + info!("SFTP packet length field: {}", sftp_length); - info!("SFTP packet: length={}, content={:?}", sftp_packet_length, &sftp_packet[..std::cmp::min(20, sftp_packet.len())]); + let expected_total = 4 + sftp_length; + if data.len() < expected_total { + warn!("SFTP packet incomplete: expected {} bytes, have {}", expected_total, data.len()); + return Ok(None); + } + + let sftp_packet = &data[4..expected_total]; + info!("SFTP packet content (first 20 bytes): {:?}", &sftp_packet[..std::cmp::min(20, sftp_packet.len())]); - // 处理SFTP请求 let response = sftp_handler.handle_request(sftp_packet)?; info!("SFTP response: {} bytes", response.len()); @@ -451,10 +560,28 @@ impl ChannelManager { } } - // 如果不是SFTP,返回None(Phase 6的普通channel data处理) + // 如果不是SFTP或exec_process,返回None Ok(None) } + /// Phase 14: 构建SSH_MSG_CHANNEL_EXTENDED_DATA(参考OpenSSH channel.c) + fn build_channel_extended_data(&self, channel: u32, data_type: u32, data: &[u8]) -> Result { + let mut buffer = Vec::new(); + + buffer.write_u8(PacketType::SSH_MSG_CHANNEL_EXTENDED_DATA as u8)?; + buffer.write_u32::(channel)?; + buffer.write_u32::(data_type)?; // 1 = stderr, 2 = exit status + buffer.write_u32::(data.len() as u32)?; + buffer.write_all(data)?; + + Ok(SshPacket { + packet_length: 0, + padding_length: 0, + payload: buffer, + padding: Vec::new(), + }) + } + /// 处理SSH_MSG_CHANNEL_CLOSE(参考OpenSSH channel.c: channel_input_close()) pub fn handle_channel_close(&mut self, packet: &SshPacket) -> Result> { info!("Processing SSH_MSG_CHANNEL_CLOSE"); @@ -617,6 +744,537 @@ impl ChannelManager { pub fn remove_channel(&mut self, channel_id: u32) { self.channels.remove(&channel_id); } + + /// Phase 14: OpenSSH风格poll机制(使用nix::poll监听stdout/stderr fd) + /// ⭐⭐⭐⭐⭐ 关键:非阻塞读取数据,不等待子进程完成 + /// ⭐⭐⭐⭐⭐ Phase 14.2: 处理child exited(发送EOF + CLOSE) + /// 参考:OpenSSH session.c: do_exec_no_pty() + pub fn handle_child_exited(&mut self) -> Result> { + // 1. 收集需要处理的channel IDs + let channel_ids: Vec = self.channels + .iter() + .filter_map(|(id, channel)| { + if channel.exec_process.is_some() { + Some(*id) + } else { + None + } + }) + .collect(); + + // 2. 构建packets(避免borrow冲突) + let mut packets = Vec::new(); + for channel_id in &channel_ids { + // 发送SSH_MSG_CHANNEL_EOF + let eof_packet = self.build_channel_eof(*channel_id)?; + packets.push(eof_packet); + + // 发送SSH_MSG_CHANNEL_CLOSE + let close_packet = self.build_channel_close(*channel_id)?; + packets.push(close_packet); + } + + // 3. 清除exec_process(mutable borrow) + for channel_id in &channel_ids { + if let Some(channel) = self.channels.get_mut(channel_id) { + channel.exec_process = None; + } + } + + if !channel_ids.is_empty() { + info!("Child exited, sent EOF + CLOSE for {} channels", channel_ids.len()); + } + + Ok(packets) + } + + /// ⭐⭐⭐⭐⭐ Phase 14.2: OpenSSH统一poll + child进程状态检测 + /// 参考:OpenSSH session.c: do_exec_no_pty() + channel.c: channel_handle_fd() + /// + /// 关键改进(Phase 14.2): + /// - 单次poll()同时监听client socket和子进程输出 + /// - timeout 10ms(非阻塞) + /// - **添加child进程状态检测**(防止无限spinning)⭐⭐⭐⭐⭐ + /// - **添加max_poll_iterations限制**(最多100次,1秒) + /// - 返回(stdout_packets, client_has_data, child_exited) + pub fn poll_exec_stdout_and_client(&mut self, stream: &std::net::TcpStream) -> Result<(Option>, bool, bool)> { + use std::io::Read; + use std::os::unix::io::{BorrowedFd, AsRawFd}; + use nix::poll::{poll, PollFd, PollFlags}; + + // 收集所有需要poll的fd + let mut poll_fds_vec = Vec::new(); + let mut client_has_data = false; + let mut child_exited = false; + + // 1. 添加client socket fd(监听stdin数据) + let client_fd = stream.as_raw_fd(); + let client_poll_fd = unsafe { + BorrowedFd::borrow_raw(client_fd) + }; + poll_fds_vec.push(PollFd::new(client_poll_fd, PollFlags::POLLIN)); + let client_fd_idx = 0; // client fd总是第一个 + + // 2. 添加所有channel的stdout/stderr fd + let mut channel_fds_map: HashMap = HashMap::new(); // channel_id -> (stdout_idx, stderr_idx) + let mut channel_ids_vec = Vec::new(); // 用于后续child状态检查 + + for (channel_id, channel) in &self.channels { + if let Some(exec_process) = &channel.exec_process { + channel_ids_vec.push(*channel_id); + + // stdout fd + if let Some(_stdout) = &exec_process.stdout { + let stdout_poll_fd = unsafe { + BorrowedFd::borrow_raw(exec_process.stdout_fd) + }; + poll_fds_vec.push(PollFd::new(stdout_poll_fd, PollFlags::POLLIN)); + } + + // stderr fd + if let Some(_stderr) = &exec_process.stderr { + let stderr_poll_fd = unsafe { + BorrowedFd::borrow_raw(exec_process.stderr_fd) + }; + poll_fds_vec.push(PollFd::new(stderr_poll_fd, PollFlags::POLLIN)); + } + + // 记录索引(相对于client_fd_idx) + let stdout_idx = poll_fds_vec.len() - 2; + let stderr_idx = poll_fds_vec.len() - 1; + channel_fds_map.insert(*channel_id, (stdout_idx, stderr_idx)); + } + } + + if poll_fds_vec.len() == 1 { + // 只有client fd,没有exec_process + // 直接poll client(short timeout) + match poll(&mut poll_fds_vec, 10u16) { + Ok(n) if n > 0 => { + if let Some(revents) = poll_fds_vec[client_fd_idx].revents() { + if revents.contains(PollFlags::POLLIN) { + client_has_data = true; + } + } + } + _ => {} + } + return Ok((None, client_has_data, false)); + } + + // ⭐⭐⭐⭐⭐ Phase 14.2关键:添加poll轮询限制(防止无限spinning) + // 最多轮询100次(1秒),如果持续无数据,检查child状态 + let max_poll_iterations = 100; + let mut poll_iteration = 0; + let mut found_data = false; + let mut stdin_closed = false; // ⭐⭐⭐⭐⭐ 新增:跟踪stdin是否已关闭 + + for iteration in 0..max_poll_iterations { + poll_iteration = iteration; + + // ⭐⭐⭐⭐⭐ 每10次轮询记录一次日志(减少噪音) + if iteration % 10 == 0 { + info!("Polling {} fds (iteration {} of {}, stdin_closed={})", poll_fds_vec.len(), iteration, max_poll_iterations, stdin_closed); + } + + match poll(&mut poll_fds_vec, 10u16) { + Ok(n) if n > 0 => { + info!("{} fds have data available (iteration {})", n, iteration); + found_data = true; + break; // 有数据,立即处理 + } + Ok(0) => { + // timeout,无数据 + // ⭐⭐⭐⭐⭐ 关键:每10次检查child进程状态(防止spinning) + if iteration % 10 == 9 { + // 检查child是否exited + for channel_id in &channel_ids_vec { + if let Some(channel) = self.channels.get_mut(channel_id) { + if let Some(exec_process) = &mut channel.exec_process { + match exec_process.child.try_wait() { + Ok(Some(status)) => { + info!("Child process exited (channel {}, status: {:?})", channel_id, status); + child_exited = true; + + // ⭐⭐⭐⭐⭐ Child exited,读取剩余stdout(如果有) + if let Some(stdout) = &mut exec_process.stdout { + let mut buffer = vec![0u8; 32768]; + match stdout.read(&mut buffer) { + Ok(n) if n > 0 => { + info!("Read {} final bytes from stdout (child exited)", n); + // 构建packet并返回 + let packet = self.build_channel_data(*channel_id, &buffer[..n])?; + return Ok((Some(vec![packet]), false, true)); + } + _ => {} + } + } + + // 没有剩余数据,返回child_exited标志 + return Ok((None, false, true)); + } + Ok(None) => { + // Child still running(正常) + info!("Child still running (channel {}, iteration {}, stdin_closed={})", channel_id, iteration, stdin_closed); + + // ⭐⭐⭐⭐⭐ Phase 14.2最终修复:主动关闭stdin超时机制 + // 如果stdin未关闭,且超过50次poll(500ms)无数据 + // 强制关闭stdin,发送EOF给rsync + if !stdin_closed && iteration >= 50 && exec_process.stdin.is_some() { + info!("⭐⭐⭐⭐⭐ Forcing stdin close after {} iterations ({} ms) - sending EOF to rsync", iteration, iteration * 10); + exec_process.stdin = None; // Drop stdin,发送EOF + stdin_closed = true; + + // ⭐⭐⭐⭐⭐ stdin关闭后,继续等待child处理完成 + // 不要立即返回,给rsync时间处理数据并产生stdout + info!("stdin closed, continuing to poll for stdout output..."); + } + } + Err(e) => { + warn!("Child try_wait error: {}", e); + } + } + } + } + } + } + + // 继续轮询(如果iteration < max_poll_iterations) + } + Err(e) => { + warn!("poll error: {}", e); + return Ok((None, false, false)); + } + Ok(_) => { + // 其他情况(不应该发生) + } + } + } + + // ⭐⭐⭐⭐⭐ 达到max_poll_iterations,检查最终child状态 + if !found_data { + info!("No data after {} iterations ({} ms), checking child status", max_poll_iterations, max_poll_iterations * 10); + + for channel_id in &channel_ids_vec { + if let Some(channel) = self.channels.get_mut(channel_id) { + if let Some(exec_process) = &mut channel.exec_process { + match exec_process.child.try_wait() { + Ok(Some(status)) => { + info!("Child exited after max iterations (status: {:?})", status); + child_exited = true; + + // 读取剩余stdout + if let Some(stdout) = &mut exec_process.stdout { + let mut buffer = vec![0u8; 32768]; + match stdout.read(&mut buffer) { + Ok(n) if n > 0 => { + let packet = self.build_channel_data(*channel_id, &buffer[..n])?; + return Ok((Some(vec![packet]), false, true)); + } + _ => {} + } + } + + return Ok((None, false, true)); + } + Ok(None) => { + info!("Child still running after max iterations, returning None"); + // Child还在运行,但无stdout数据 + // 主循环会继续调用此函数 + return Ok((None, false, false)); + } + Err(e) => { + warn!("Final child check error: {}", e); + } + } + } + } + } + } + +// ⭐⭐⭐⭐⭐ 处理找到的数据(如果found_data) + // 3. 检查client fd状态(包括EOF/HUP) + if let Some(revents) = poll_fds_vec[client_fd_idx].revents() { + if revents.contains(PollFlags::POLLIN) { + info!("Client fd has data (stdin from client)"); + client_has_data = true; + } else if revents.contains(PollFlags::POLLHUP) { + info!("Client fd hangup (EOF received from client)"); + // ⭐⭐⭐⭐⭐ Phase 14.2关键修复:关闭stdin pipe,发送EOF给child + // 参考:OpenSSH session.c: do_exec_no_pty() stdin handling + for (_, channel) in &mut self.channels { + if let Some(exec_process) = &mut channel.exec_process { + if exec_process.stdin.is_some() { + info!("Closing stdin pipe (sending EOF to child process)"); + exec_process.stdin = None; // Drop stdin,发送EOF给child + } + } + } + client_has_data = false; + } else if revents.contains(PollFlags::POLLERR) { + warn!("Client fd error"); + return Err(anyhow::anyhow!("Client socket error")); + } + } + + // 4. 检查stdout/stderr fd是否有数据 + let mut packets_data: Vec<(u32, Vec)> = Vec::new(); + + for (channel_id, (stdout_idx, stderr_idx)) in channel_fds_map { + if let Some(channel) = self.channels.get_mut(&channel_id) { + if let Some(exec_process) = &mut channel.exec_process { + // 检查stdout + if let Some(revents) = poll_fds_vec[stdout_idx].revents() { + if revents.contains(PollFlags::POLLIN) { + info!("stdout fd has data (channel {})", channel_id); + if let Some(stdout) = &mut exec_process.stdout { + let mut buffer = vec![0u8; 32768]; + match stdout.read(&mut buffer) { + Ok(n) if n > 0 => { + info!("Read {} bytes from stdout (channel {})", n, channel_id); + packets_data.push((channel_id, buffer[..n].to_vec())); + } + Ok(0) => { + info!("stdout EOF (channel {}), closing stdout pipe", channel_id); + // ⭐⭐⭐⭐⭐ Critical修复:EOF时关闭pipe,避免无限循环 + exec_process.stdout = None; + } + Err(e) if e.kind() != std::io::ErrorKind::WouldBlock => { + warn!("stdout read error: {}", e); + exec_process.stdout = None; // 错误时也关闭 + } + _ => {} + } + } + } + } + + // 检查stderr + if let Some(revents) = poll_fds_vec[stderr_idx].revents() { + if revents.contains(PollFlags::POLLIN) { + info!("stderr fd has data (channel {})", channel_id); + if let Some(stderr) = &mut exec_process.stderr { + let mut buffer = vec![0u8; 32768]; + match stderr.read(&mut buffer) { + Ok(n) if n > 0 => { + info!("Read {} bytes from stderr (channel {})", n, channel_id); + packets_data.push((channel_id, buffer[..n].to_vec())); + } + Ok(0) => { + info!("stderr EOF (channel {}), closing stderr pipe", channel_id); + // ⭐⭐⭐⭐⭐ Critical修复:EOF时关闭pipe,避免无限循环 + exec_process.stderr = None; + } + Err(e) if e.kind() != std::io::ErrorKind::WouldBlock => { + warn!("stderr read error: {}", e); + exec_process.stderr = None; // 错误时也关闭 + } + _ => {} + } + } + } + } + } + } + } + + // 构建packets + if !packets_data.is_empty() { + let mut packets = Vec::new(); + for (channel_id, data) in packets_data { + let packet = self.build_channel_data(channel_id, &data)?; + packets.push(packet); + } + return Ok((Some(packets), client_has_data, child_exited)); + } + + // ⭐⭐⭐⭐⭐ Phase 14.2最终修复:stdout/stderr EOF后检查child exited + // 当stdout和stderr都关闭后,强制检查child状态 + for channel_id in &channel_ids_vec { + if let Some(channel) = self.channels.get_mut(channel_id) { + if let Some(exec_process) = &mut channel.exec_process { + // 检查stdout和stderr是否都已关闭 + if exec_process.stdout.is_none() && exec_process.stderr.is_none() { + info!("stdout/stderr both closed (channel {}), checking child status", channel_id); + + // ⭐⭐⭐⭐⭐ 立即检查child是否exited + match exec_process.child.try_wait() { + Ok(Some(status)) => { + info!("⭐⭐⭐⭐⭐ Child exited after stdout/stderr EOF (status: {:?})", status); + child_exited = true; + + // ⭐⭐⭐⭐⭐ 关键:立即返回child_exited标志 + // server.rs会发送SSH_MSG_CHANNEL_EOF + CLOSE + return Ok((None, false, true)); + } + Ok(None) => { + // Child still running but stdout/stderr closed + // 等待child exited + info!("Child still running after pipes closed, waiting..."); + } + Err(e) => { + warn!("Child try_wait error after pipes closed: {}", e); + } + } + } + } + } + } + + // 有数据但只有client数据 + Ok((None, client_has_data, child_exited)) + } + + // ⭐⭐⭐⭐⭐ Phase 14.0: 旧版poll(仅监听stdout/stderr,已废弃) + /// 已废弃:使用poll_exec_stdout_and_client()替代 + #[allow(dead_code)] + pub fn poll_exec_stdout_with_fds(&mut self) -> Result>> { + use std::io::Read; + use std::os::unix::io::BorrowedFd; + + // 遍历所有channel,收集poll_fds + let mut poll_fds_vec = Vec::new(); + let mut channel_fds_map: HashMap = HashMap::new(); // channel_id -> (stdout_idx, stderr_idx) in poll_fds_vec + + for (channel_id, channel) in &self.channels { + if let Some(exec_process) = &channel.exec_process { + // ⭐⭐⭐⭐⭐ OpenSSH风格:创建PollFd监听stdout/stderr + // nix 0.29 API: PollFd::new()需要借用fd,不是RawFd + if let Some(stdout) = &exec_process.stdout { + let stdout_poll_fd = unsafe { + // ⭐⭐⭐⭐⭐ 使用BorrowedFd::borrow_raw()(正确API) + BorrowedFd::borrow_raw(exec_process.stdout_fd) + }; + poll_fds_vec.push(PollFd::new(stdout_poll_fd, PollFlags::POLLIN)); + } + + if let Some(stderr) = &exec_process.stderr { + let stderr_poll_fd = unsafe { + BorrowedFd::borrow_raw(exec_process.stderr_fd) + }; + poll_fds_vec.push(PollFd::new(stderr_poll_fd, PollFlags::POLLIN)); + } + + // 记录poll_fds_vec中的索引 + let stdout_idx = poll_fds_vec.len() - 2; + let stderr_idx = poll_fds_vec.len() - 1; + channel_fds_map.insert(*channel_id, (stdout_idx, stderr_idx)); + } + } + + if poll_fds_vec.is_empty() { + return Ok(None); // 没有exec_process + } + + // ⭐⭐⭐⭐⭐ OpenSSH关键:使用poll监听所有fd + // ⭐⭐⭐⭐⭐ 持续poll机制:最多轮询1000次(给大文件传输足够时间) + // 大文件传输需要很长时间,增加轮询次数到1000次(总共10秒) + let max_poll_attempts = 1000; + let mut poll_attempt = 0; + let mut found_data = false; + + for attempt in 0..max_poll_attempts { + poll_attempt = attempt; + // 每100次轮询记录一次日志(减少日志噪音) + if attempt % 100 == 0 { + info!("Polling {} fds (OpenSSH style, timeout 10ms, attempt {} of {})", poll_fds_vec.len(), attempt, max_poll_attempts); + } + match poll(&mut poll_fds_vec, 10u16) { // timeout 10ms + Ok(n) => { + if n > 0 { + info!("{} fds have data available (attempt {})", n, attempt); + found_data = true; + break; // 有数据,立即处理 + } + // 没有数据,继续轮询(最多1000次) + } + Err(e) => { + warn!("poll error: {}", e); + return Ok(None); + } + } + } + + if !found_data { + info!("No data available after {} poll attempts ({} ms), returning None", max_poll_attempts, max_poll_attempts * 10); + return Ok(None); // 轮询1000次后仍无数据,主循环继续处理client packet + } + + // ⭐⭐⭐⭐⭐ OpenSSH风格:根据revents判断哪个fd有数据,立即读取 + let mut packets_data: Vec<(u32, Vec)> = Vec::new(); // (channel_id, data) + + for (channel_id, (stdout_idx, stderr_idx)) in channel_fds_map { + if let Some(channel) = self.channels.get_mut(&channel_id) { + if let Some(exec_process) = &mut channel.exec_process { + // 检查stdout是否有数据 + if let Some(revents) = poll_fds_vec[stdout_idx].revents() { + if revents.contains(PollFlags::POLLIN) { + info!("stdout fd has data (channel {})", channel_id); + // ⭐⭐⭐⭐⭐ 非阻塞读取(因为设置了O_NONBLOCK) + if let Some(stdout) = &mut exec_process.stdout { + let mut buffer = vec![0u8; 32768]; + match stdout.read(&mut buffer) { + Ok(n) => { + if n > 0 { + info!("Read {} bytes from stdout (channel {})", n, channel_id); + packets_data.push((channel_id, buffer[..n].to_vec())); + } else { + info!("stdout EOF (channel {})", channel_id); + } + } + Err(e) if e.kind() == std::io::ErrorKind::WouldBlock => { + // 非阻塞模式,没有数据(正常) + } + Err(e) => { + warn!("stdout read error: {}", e); + } + } + } + } + } + + // 检查stderr是否有数据(类似处理) + if let Some(revents) = poll_fds_vec[stderr_idx].revents() { + if revents.contains(PollFlags::POLLIN) { + info!("stderr fd has data (channel {})", channel_id); + if let Some(stderr) = &mut exec_process.stderr { + let mut buffer = vec![0u8; 32768]; + match stderr.read(&mut buffer) { + Ok(n) => { + if n > 0 { + info!("Read {} bytes from stderr (channel {})", n, channel_id); + packets_data.push((channel_id, buffer[..n].to_vec())); + } else { + info!("stderr EOF (channel {})", channel_id); + } + } + Err(e) if e.kind() == std::io::ErrorKind::WouldBlock => { + // 非阻塞模式,没有数据(正常) + } + Err(e) => { + warn!("stderr read error: {}", e); + } + } + } + } + } + } + } + } + + // ⭐⭐⭐⭐⭐ 释放mutable borrow后,构建packets(避免borrow冲突) + let mut packets = Vec::new(); + for (channel_id, data) in packets_data { + let packet = self.build_channel_data(channel_id, &data)?; + packets.push(packet); + } + + if packets.is_empty() { + Ok(None) + } else { + Ok(Some(packets)) + } + } } /// SSH Channel结构(参考OpenSSH channel.c: struct channel) @@ -631,6 +1289,7 @@ struct Channel { sftp_handler: Option, // Phase 7: SFTP处理器 scp_handler: Option, // Phase 8: SCP处理器 rsync_handler: Option, // Phase 8: rsync处理器 + exec_process: Option, // Phase 14: 交互式exec进程 // Phase 13.3: 端口转发相关字段 direct_tcpip: Option, // direct-tcpip channel(Remote forwarding) forwarded_tcpip: Option, // forwarded-tcpip channel(Local forwarding) diff --git a/markbase-core/src/ssh_server/server.rs b/markbase-core/src/ssh_server/server.rs index dcef7e0..6e4cbd4 100644 --- a/markbase-core/src/ssh_server/server.rs +++ b/markbase-core/src/ssh_server/server.rs @@ -346,7 +346,9 @@ AuthResult::Failure(message) => { } } -/// SSH服务循环(Phase 6-13完整版) +/// SSH服务循环(Phase 14.2: OpenSSH统一poll + child状态检测版) +/// ⭐⭐⭐⭐⭐ 关键改进:单次poll同时监听client + stdout + stderr + child状态 +/// 参考:OpenSSH session.c: do_exec_no_pty() + channel.c: channel_handle_fd() fn handle_ssh_service_loop( stream: &mut TcpStream, channel_manager: &mut ChannelManager, @@ -354,10 +356,43 @@ fn handle_ssh_service_loop( port_forward_manager: &mut PortForwardManager, // Phase 13 security_config: Arc>, // Phase 13.1 ) -> Result<()> { - info!("Starting SSH service loop (channel management + port forwarding)"); + info!("Starting SSH service loop (Phase 14.2: unified poll + child status)"); loop { - // 使用EncryptedPacket读取加密packet(Phase 6) + // ⭐⭐⭐⭐⭐ Phase 14.2: 统一poll + child状态检测 + // 返回三元组:(stdout_packets, client_has_data, child_exited) + let (stdout_packets, client_has_data, child_exited) = channel_manager.poll_exec_stdout_and_client(stream)?; + + // 1. 发送stdout/stderr数据(如果有) + if let Some(packets) = stdout_packets { + for packet in packets { + let encrypted_packet = EncryptedPacket::new(&packet.payload, encryption_ctx, true)?; + encrypted_packet.write(stream)?; + info!("Sent stdout/stderr data (Phase 14.2)"); + } + } + + // 2. 处理child exited(发送EOF + CLOSE) + if child_exited { + info!("Child process exited, sending SSH_MSG_CHANNEL_EOF + CLOSE"); + + // ⭐⭐⭐⭐⭐ Phase 14.2: 使用ChannelManager.handle_child_exited() + let exit_packets = channel_manager.handle_child_exited()?; + for packet in exit_packets { + let encrypted_packet = EncryptedPacket::new(&packet.payload, encryption_ctx, true)?; + encrypted_packet.write(stream)?; + } + + // 继续处理client数据(可能还有其他请求) + } + + // 3. 处理client数据(如果有) + if !client_has_data { + // client没有数据,继续下一轮循环 + continue; + } + + // client有数据,读取并处理 let encrypted_packet = EncryptedPacket::read(stream, encryption_ctx, true)?; let packet = SshPacket::new(encrypted_packet.payload().to_vec()); diff --git a/markbase-core/src/ssh_server/sftp_handler.rs b/markbase-core/src/ssh_server/sftp_handler.rs index c0ab140..004284e 100644 --- a/markbase-core/src/ssh_server/sftp_handler.rs +++ b/markbase-core/src/ssh_server/sftp_handler.rs @@ -764,9 +764,45 @@ impl SftpHandler { let id = cursor.read_u32::()?; let handle_bytes = read_sftp_string_bytes(&mut cursor)?; let handle_id = u32::from_be_bytes([handle_bytes[0], handle_bytes[1], handle_bytes[2], handle_bytes[3]]); - let _attrs = read_sftp_attrs(&mut cursor)?; + let attrs = read_sftp_attrs(&mut cursor)?; - info!("SSH_FXP_FSETSTAT: id={}, handle={}", id, handle_id); + info!("SSH_FXP_FSETSTAT: id={}, handle={}, attrs.flags={}", id, handle_id, attrs.flags); + + let handle = self.handles.get(&handle_id); + if handle.is_none() { + return self.build_status_response(id, SftpStatus::SSH_FX_FAILURE, "Invalid handle"); + } + + let handle = handle.unwrap(); + if handle.handle_type != SftpHandleType::File { + return self.build_status_response(id, SftpStatus::SSH_FX_FAILURE, "Not a file handle"); + } + + let path = handle.path.clone(); + + if attrs.flags & SftpAttrFlags::SSH_FILEXFER_ATTR_SIZE != 0 { + if let Some(size) = attrs.size { + info!("FSETSTAT: setting file size to {}", size); + let file = OpenOptions::new().write(true).open(&path)?; + file.set_len(size)?; + } + } + + if attrs.flags & SftpAttrFlags::SSH_FILEXFER_ATTR_PERMISSIONS != 0 { + if let Some(permissions) = attrs.permissions { + info!("FSETSTAT: setting permissions to {:o}", permissions); + fs::set_permissions(&path, fs::Permissions::from_mode(permissions))?; + } + } + + if attrs.flags & SftpAttrFlags::SSH_FILEXFER_ATTR_ACMODTIME != 0 { + if let (Some(atime), Some(mtime)) = (attrs.atime, attrs.mtime) { + info!("FSETSTAT: setting atime={}, mtime={}", atime, mtime); + let atime_filetime = filetime::FileTime::from_unix_time(atime as i64, 0); + let mtime_filetime = filetime::FileTime::from_unix_time(mtime as i64, 0); + filetime::set_file_times(&path, atime_filetime, mtime_filetime)?; + } + } self.build_status_response(id, SftpStatus::SSH_FX_OK, "Fsetstat successful") }