# # delete_file "botan/base_eng.h" # # delete_file "botan/def_eng.cpp" # # delete_file "botan/dl_get.cpp" # # delete_file "botan/fips_rng.cpp" # # delete_file "botan/fips_rng.h" # # delete_file "botan/secalloc.h" # # delete_file "botan/x917_rng.cpp" # # delete_file "botan/x917_rng.h" # # delete_file "unix/platform_netsync.cc" # # delete_file "win32/platform_netsync.cc" # # add_file "botan/def_alg.cpp" # # add_file "botan/def_mode.cpp" # # add_file "botan/sha256.cpp" # # add_file "botan/sha256.h" # # add_file "botan/x931_rng.cpp" # # add_file "botan/x931_rng.h" # # patch "ChangeLog" # from [697656aa85ec213e93ffc360131160e721788cc0] # to [85c91026c2337bcd14c921adfe24326327ae6199] # # patch "Makefile.am" # from [5f3e4aae1a4f7f3de4b7336190009b720b04432c] # to [c2264e8c492e621716d9426975a3c805a99873b2] # # patch "botan/algolist.cpp" # from [e73a701e948afdcb723a29f89e88dbc793764d76] # to [59b2c8ae247e6e6791f5bf1f17fa447c2f887fc6] # # patch "botan/algolist.h" # from [ef9d8f0eb6210c1b316298d4ca6f53013db1cef0] # to [09a35cd375bf11ebeb7b6231db219ef73e9ee645] # # patch "botan/base.cpp" # from [3fcd48a2b31dc404fcc861f0c1150d764f276e1f] # to [782844d8ab6ab22b787eadda7392a3e23445662e] # # patch "botan/base.h" # from [7223b306fb862c20a89c03a1460c366aca16fc6f] # to [de06367b6bc1d60bfe3dbaeee2eb958757dbd0d1] # # patch "botan/def_alg.cpp" # from [] # to [79162d3aecd53ba9f1c78742ff5146b790b91851] # # patch "botan/def_mode.cpp" # from [] # to [a06fee4078dafe7958ae460df501247ad6788178] # # patch "botan/engine.h" # from [e564fba257a1af6a72dfb4e68dfa387846189ee0] # to [bf1afaedad957edbc26e34b4a0490cc156e6789c] # # patch "botan/init.cpp" # from [2b67a947e2133a4a9fbd93774c2a67a5d7cf5344] # to [e654bf9fc3a87be25a40bf183a843d6be139de98] # # patch "botan/mem_pool.cpp" # from [e2303f64ab0a279072bdbe59313ed10842702c20] # to [cc72eb332ab2c10e96d65332b22dec4d46fc5621] # # patch "botan/mem_pool.h" # from [79cc34c1b88e2ab2419e609d8c0c208a490f913e] # to [96e6c390b555075bc0335932142680360ef49f8b] # # patch "botan/mode_pad.h" # from [d33d5fd3116799e3acc4510bbe8ec00b9ecf203a] # to [0ec59170055c96be7b3e7a70aa3a4e25baefbfcd] # # patch "botan/pipe_rw.cpp" # from [a26836077fabc8d34bc89c1b96876391494fca1e] # to [d93a14d30e1feb8c498c90ddf0c4596716994536] # # patch "botan/pkcs8.cpp" # from [6d12f636a9d038c815ba1a19ed4b5dafa2f4a052] # to [7f055238216229a265c733ab7e79edc252a54d93] # # patch "botan/pubkey.cpp" # from [a79e182ed1aabf231ff5fd910240fd9e2fc517c3] # to [ab5b94948a910abe6d83b35148ac6c460f790a11] # # patch "botan/pubkey.h" # from [eb5a007ee85161d484036b2325def6afa731be7c] # to [dfcf36d1bc7eb006d8a593eb5f5a4a7e876171b8] # # patch "botan/randpool.cpp" # from [5d45a17b8b6f6311a3dd39fa0e1e8825164d8204] # to [4cd57635f9b7a10426ff4ce53e630dbe86358083] # # patch "botan/randpool.h" # from [8c3837ac3ca62bdbf5e584ca350aee650df6dd56] # to [9e5e53dac9493dd855fa05a563fb80769d5b8988] # # patch "botan/rng.cpp" # from [a87b1336b2275f4083f991b28ec602681eb17e1b] # to [6241291f961c12f562c194b7cd2a57a7fa41e3f9] # # patch "botan/sha160.cpp" # from [f3c39163a2977d63f172f75ffe1891f2a2832239] # to [283762dff556d9a03a0921634c178e7d5e84bda5] # # patch "botan/sha160.h" # from [e2ad1d38fddf6502076da1b95be4eafbbc7a54a2] # to [ed9b5ecfb4120f6b0c8f5c930705c56959944ef9] # # patch "botan/sha256.cpp" # from [] # to [763f18fe97915f53be1b159f7dd29145384d32ad] # # patch "botan/sha256.h" # from [] # to [ad8001298ac6bfcef4891124d3f8ebd9c2011366] # # patch "botan/x931_rng.cpp" # from [] # to [7f93d680b7e6c71a3b9fcf1f8af051062cdddb16] # # patch "botan/x931_rng.h" # from [] # to [867850aff3df63007e12886ed6d00c338496b93e] # # patch "commands.cc" # from [889b85e8285c01cbd3cfecfecc5b2d687f9cdcd3] # to [6368c2bb3e6de393e4ffdaa9a65a6f3b541b1f85] # # patch "file_io.cc" # from [e39a1c13030c5378ea4cb3aa9621148ce0c8fb7d] # to [c5541a89410a0194523e41bfcadb27f58124ee70] # # patch "main.cc" # from [ca8383ced00bdb686905f58eaeac7b1446347219] # to [93c14a170425bd2be15e68d0f4eed476f9b77144] # # patch "monotone.cc" # from [cab8b2b01a23a5e82a37761b90517703c57c241a] # to [07d7a968c1ea02cff2f2cd60def4980c6e781c21] # # patch "monotone.texi" # from [5cc1a931d274bc7d3f0cc95fc932162506011cb6] # to [e053856be27fa9eb51ef40088fa8253ddefa081c] # # patch "netsync.cc" # from [b253cccce899ebf482d4b14f0ce08139079018c2] # to [248489d7ad1d4b104cd1e607ad1714205be6c5a2] # # patch "platform.hh" # from [0c8532e0798d470031bc897517234e3c8f4b9be9] # to [9ab0db8ce56f0fead355f2e8477669748bee8a7e] # # patch "std_hooks.lua" # from [a2a27daced7769d54850f059f39554cb1e0fc78d] # to [956a176b43d8425910623c605d405c2678676e55] # # patch "ui.cc" # from [0fa61fa5c584e05a187d6c7e29c8336e4d7f3455] # to [3cbe9c661750040b4663d3f1b05d85ff964707ff] # # patch "unix/fs.cc" # from [1bb3dcff181451829c42a1d34c1111d486437fda] # to [6b71610c94a70ecabfecdcf10f0aa0d880fffc7f] # # patch "win32/fs.cc" # from [bfc8bc3aaa07a3ec97a5d555ee4af563a118546d] # to [409c24f9c6ca1d1b9de8f951885c3044d16dfbd0] # ======================================================================== --- ChangeLog 697656aa85ec213e93ffc360131160e721788cc0 +++ ChangeLog 85c91026c2337bcd14c921adfe24326327ae6199 @@ -1,3 +1,46 @@ +2005-10-06 Matthew Gregan + + * std_hooks.lua (merge3_emacs_cmd): Minor cleanup. + * std_hooks.lua: Pass '--eval' rather than '-eval' to Emacs; the + CVS emacsclient does not consider '-eval' as valid. + * platform.hh, unix/fs.cc, win32/fs.cc (rename_clobberingly): New + function for best-effort atomic renames. This will probably never + be atomic on Win32. + * file_io.cc (write_data_impl): Append process ID to temporary + file name so that multiple monotone processes operating on the + same working copy are less likely to clobber each other. Use + rename_clobberingly(). + * ui.cc (user_interface): Allow std::cout to raise + ios_base::failure exceptions if stream goes bad (e.g. stream + receives EPIPE). + * monotone.cc (cpp_main): Catch ios_base::failure exceptions and + exit cleanly. + * main.cc (main_with_signal_handlers): Install handler to ignore + SIGPIPE. + * Makefile.am: Remove platform_netsync.cc references. + * {unix,win32}/platform_netsync.cc: Remove files. + * platform.hh, netsync.cc (run_netsync_protocol): + Remove {start,end}_platform_netsync() calls. + +2005-10-04 Nathaniel Smith + + * monotone.texi (Automation): Document the mysterious columns of + numbers in 'automate inventory' output format. + +2005-10-04 Matt Johnston + + * botan/, Makefile.am: update to Botan 1.4.7 + +2005-10-03 Nathaniel Smith + + * monotone.texi (Automation): Clean up formatting and description + of 'automate inventory' sample output. + +2005-10-02 Marcel van der Boom + + * commands.cc (CMD(checkout)): Check for non-existant checkout dir + earlier, so we can fail earlier. + 2005-09-30 Nathaniel Smith * Makefile.am (AM_CFLAGS, AM_CXXFLAGS): Add @@ -12212,3 +12255,4 @@ 2003-04-06 graydon hoare * initial release. + ======================================================================== --- Makefile.am 5f3e4aae1a4f7f3de4b7336190009b720b04432c +++ Makefile.am c2264e8c492e621716d9426975a3c805a99873b2 @@ -79,17 +79,17 @@ botan/buf_filt.cpp botan/cbc.cpp botan/certstore.cpp \ botan/cfb.cpp botan/charset.cpp botan/conf.cpp botan/crc32.cpp \ botan/crl_ent.cpp botan/ctr.cpp botan/cts.cpp \ - botan/data_snk.cpp botan/data_src.cpp botan/def_eng.cpp \ + botan/data_snk.cpp botan/data_src.cpp \ botan/def_ops.cpp botan/defalloc.cpp botan/der_code.cpp \ botan/der_enc.cpp botan/divide.cpp botan/dl_algo.cpp \ - botan/dl_get.cpp botan/dl_group.cpp botan/dl_param.cpp \ + botan/dl_group.cpp botan/dl_param.cpp \ botan/dl_cache.cpp \ botan/dlies.cpp botan/eax.cpp botan/ecb.cpp botan/eme1.cpp \ botan/eme_pkcs.cpp botan/emsa1.cpp botan/emsa2.cpp \ botan/emsa3.cpp botan/emsa4.cpp botan/emsa_raw.cpp \ botan/eng_base.cpp botan/engine.cpp botan/es_file.cpp \ botan/exceptn.cpp botan/filter.cpp botan/filters.cpp \ - botan/fips140.cpp botan/fips_rng.cpp botan/fused.cpp \ + botan/fips140.cpp botan/fused.cpp \ botan/get_algo.cpp botan/get_enc.cpp botan/get_pbe.cpp \ botan/gzip.cpp botan/hash_id.cpp botan/hex.cpp botan/hmac.cpp \ botan/if_algo.cpp botan/inifile.cpp botan/init.cpp \ @@ -113,7 +113,8 @@ botan/ui.cpp botan/util.cpp botan/x509_ca.cpp \ botan/x509_crl.cpp botan/x509_key.cpp botan/x509_obj.cpp \ botan/x509cert.cpp botan/x509find.cpp botan/x509opt.cpp \ - botan/x509self.cpp botan/x509stor.cpp botan/x917_rng.cpp \ + botan/x509self.cpp botan/x509stor.cpp \ + botan/def_alg.cpp botan/def_mode.cpp botan/sha256.cpp \ \ botan/aes.h botan/botan.h botan/def_eng.h botan/es_win32.h \ botan/lookup.h botan/omac.h botan/randpool.h botan/version.h \ @@ -127,14 +128,14 @@ botan/certstor.h botan/dlies.h botan/fips140.h botan/mgf1.h \ botan/pem.h botan/s2k.h botan/x509_key.h botan/asn1_obj.h \ botan/cfb.h botan/dl_param.h botan/fips_rng.h botan/modebase.h \ - botan/pipe.h botan/secalloc.h botan/x509_obj.h \ + botan/pipe.h botan/x509_obj.h \ botan/asn1_oid.h botan/conf.h botan/eax.h botan/gzip.h \ botan/mode_pad.h botan/pk_algs.h botan/secmem.h \ botan/x509self.h botan/barrett.h botan/config.h botan/ecb.h \ botan/hex.h botan/mod_exp.h botan/pk_core.h botan/secqueue.h \ botan/x509stor.h botan/base64.h botan/crc32.h botan/eme.h \ botan/hmac.h botan/mp_core.h botan/pkcs10.h botan/sha160.h \ - botan/x917_rng.h botan/base_eng.h botan/crl_ent.h botan/emsa.h \ + botan/crl_ent.h botan/emsa.h \ botan/if_algo.h botan/mp_madd.h botan/pkcs8.h botan/socket.h \ botan/x919_mac.h botan/basefilt.h botan/ctr.h botan/engine.h \ botan/init.h botan/mp_types.h botan/pk_filts.h botan/symkey.h \ @@ -145,7 +146,8 @@ botan/data_src.h botan/es_egd.h botan/look_add.h botan/ofb.h \ botan/pk_util.h botan/ui.h botan/blinding.h botan/defalloc.h \ botan/es_file.h botan/look_pk.h botan/oids.h botan/pubkey.h \ - botan/util.h botan/charset.h botan/hash_id.h + botan/util.h botan/charset.h botan/hash_id.h \ + botan/x931_rng.cpp botan/x931_rng.h botan/sha256.h BOOST_SANDBOX_SOURCES = \ @@ -199,11 +201,11 @@ UNIX_PLATFORM_SOURCES = \ unix/read_password.cc unix/get_system_flavour.cc unix/process.cc unix/terminal.cc \ - unix/platform_netsync.cc unix/inodeprint.cc unix/fs.cc + unix/inodeprint.cc unix/fs.cc WIN32_PLATFORM_SOURCES = \ win32/read_password.cc win32/get_system_flavour.cc win32/process.cc win32/terminal.cc \ - win32/platform_netsync.cc win32/inodeprint.cc win32/fs.cc + win32/inodeprint.cc win32/fs.cc # primaries ======================================================================== --- botan/algolist.cpp e73a701e948afdcb723a29f89e88dbc793764d76 +++ botan/algolist.cpp 59b2c8ae247e6e6791f5bf1f17fa447c2f887fc6 @@ -1,19 +1,10 @@ /************************************************* * Algorithms List Source File * -* (C) 1999-2004 The Botan Project * +* (C) 1999-2005 The Botan Project * *************************************************/ #include -#include - -#include - -#include -#include - -#include - #include namespace Botan { @@ -21,125 +12,27 @@ namespace Algolist { /************************************************* -* Some macros to simplify control flow * +* Attempt to get a string to key object * *************************************************/ -#define HANDLE_TYPE_NO_ARGS(NAME, TYPE) \ - if(algo_name == NAME) \ - { \ - if(name.size() == 1) \ - return new TYPE; \ - throw Invalid_Algorithm_Name(algo_spec); \ - } - -#define HANDLE_TYPE_ONE_U32BIT(NAME, TYPE, DEFAULT) \ - if(algo_name == NAME) \ - { \ - if(name.size() == 1) \ - return new TYPE(DEFAULT); \ - if(name.size() == 2) \ - return new TYPE(to_u32bit(name[1])); \ - throw Invalid_Algorithm_Name(algo_spec); \ - } - -#define HANDLE_TYPE_TWO_U32BIT(NAME, TYPE, DEFAULT) \ - if(algo_name == NAME) \ - { \ - if(name.size() == 1) \ - return new TYPE(DEFAULT); \ - if(name.size() == 2) \ - return new TYPE(to_u32bit(name[1])); \ - if(name.size() == 3) \ - return new TYPE(to_u32bit(name[1]), to_u32bit(name[2])); \ - throw Invalid_Algorithm_Name(algo_spec); \ - } - -#define HANDLE_TYPE_ONE_STRING(NAME, TYPE) \ - if(algo_name == NAME) \ - { \ - if(name.size() == 2) \ - return new TYPE(name[1]); \ - throw Invalid_Algorithm_Name(algo_spec); \ - } - -/************************************************* -* Attempt to get a block cipher object * -*************************************************/ -BlockCipher* get_block_cipher(const std::string& algo_spec) +S2K* get_s2k(const std::string& algo_spec) { std::vector name = parse_algorithm_name(algo_spec); if(name.size() == 0) return 0; - const std::string algo_name = deref_alias(name[0]); + if(name.size() != 2) + throw Invalid_Algorithm_Name(algo_spec); - HANDLE_TYPE_NO_ARGS("AES", AES); - HANDLE_TYPE_NO_ARGS("AES-128", AES_128); - HANDLE_TYPE_NO_ARGS("AES-192", AES_192); - HANDLE_TYPE_NO_ARGS("AES-256", AES_256); - - return 0; - } - -/************************************************* -* Attempt to get a stream cipher object * -*************************************************/ -StreamCipher* get_stream_cipher(const std::string& algo_spec) - { - std::vector name = parse_algorithm_name(algo_spec); - if(name.size() == 0) - return 0; const std::string algo_name = deref_alias(name[0]); - HANDLE_TYPE_ONE_U32BIT("ARC4", ARC4, 0); - HANDLE_TYPE_ONE_U32BIT("RC4_drop", ARC4, 768); + // removed in monotone + //if(algo_name == "OpenPGP-S2K") return new OpenPGP_S2K(name[1]); + //if(algo_name == "PBKDF1") return new PKCS5_PBKDF1(name[1]); + //if(algo_name == "PBKDF2") return new PKCS5_PBKDF2(name[1]); return 0; } /************************************************* -* Attempt to get a hash function object * -*************************************************/ -HashFunction* get_hash(const std::string& algo_spec) - { - std::vector name = parse_algorithm_name(algo_spec); - if(name.size() == 0) - return 0; - const std::string algo_name = deref_alias(name[0]); - - HANDLE_TYPE_NO_ARGS("CRC32", CRC32); - HANDLE_TYPE_NO_ARGS("SHA-160", SHA_160); - - return 0; - } - -/************************************************* -* Attempt to get an authentication code object * -*************************************************/ -MessageAuthenticationCode* get_mac(const std::string& algo_spec) - { - std::vector name = parse_algorithm_name(algo_spec); - if(name.size() == 0) - return 0; - const std::string algo_name = deref_alias(name[0]); - - HANDLE_TYPE_ONE_STRING("HMAC", HMAC); - - return 0; - } - -/************************************************* -* Attempt to get a string to key object * -*************************************************/ -S2K* get_s2k(const std::string& algo_spec) - { - std::vector name = parse_algorithm_name(algo_spec); - if(name.size() == 0) - return 0; - const std::string algo_name = deref_alias(name[0]); - - return 0; - } - -/************************************************* * Attempt to get a block cipher padding method * *************************************************/ BlockCipherModePaddingMethod* get_bc_pad(const std::string& algo_spec) @@ -147,12 +40,15 @@ std::vector name = parse_algorithm_name(algo_spec); if(name.size() == 0) return 0; + if(name.size() != 1) + throw Invalid_Algorithm_Name(algo_spec); + const std::string algo_name = deref_alias(name[0]); - HANDLE_TYPE_NO_ARGS("PKCS7", PKCS7_Padding); - HANDLE_TYPE_NO_ARGS("OneAndZeros", OneAndZeros_Padding); - HANDLE_TYPE_NO_ARGS("X9.23", ANSI_X923_Padding); - HANDLE_TYPE_NO_ARGS("NoPadding", Null_Padding); + if(algo_name == "PKCS7") return new PKCS7_Padding; + if(algo_name == "OneAndZeros") return new OneAndZeros_Padding; + if(algo_name == "X9.23") return new ANSI_X923_Padding; + if(algo_name == "NoPadding") return new Null_Padding; return 0; } ======================================================================== --- botan/algolist.h ef9d8f0eb6210c1b316298d4ca6f53013db1cef0 +++ botan/algolist.h 09a35cd375bf11ebeb7b6231db219ef73e9ee645 @@ -17,10 +17,6 @@ /************************************************* * Lookup an algorithm in the table * *************************************************/ -BlockCipher* get_block_cipher(const std::string&); -StreamCipher* get_stream_cipher(const std::string&); -HashFunction* get_hash(const std::string&); -MessageAuthenticationCode* get_mac(const std::string&); S2K* get_s2k(const std::string&); BlockCipherModePaddingMethod* get_bc_pad(const std::string&); ======================================================================== --- botan/base.cpp 3fcd48a2b31dc404fcc861f0c1150d764f276e1f +++ botan/base.cpp 782844d8ab6ab22b787eadda7392a3e23445662e @@ -227,18 +227,6 @@ } /************************************************* -* Update the internal entropy count * -*************************************************/ -void RandomNumberGenerator::update_entropy(const byte data[], u32bit length, - u32bit state_size) throw() - { - if(entropy == 8*state_size) - return; - entropy += entropy_estimate(data, length); - entropy = std::min(entropy, 8*state_size); - } - -/************************************************* * Return the version as a string * *************************************************/ std::string version_string() ======================================================================== --- botan/base.h 7223b306fb862c20a89c03a1460c366aca16fc6f +++ botan/base.h de06367b6bc1d60bfe3dbaeee2eb958757dbd0d1 @@ -27,7 +27,9 @@ virtual void clear() throw() {}; virtual std::string name() const = 0; virtual ~Algorithm() {} + Algorithm() {} private: + Algorithm(const Algorithm&) {} Algorithm& operator=(const Algorithm&) { return (*this); } }; @@ -159,11 +161,8 @@ void add_entropy(const byte[], u32bit); void add_entropy(EntropySource&, bool = true); virtual ~RandomNumberGenerator() {} - protected: - void update_entropy(const byte[], u32bit, u32bit) throw(); - u32bit entropy; private: - virtual void add_randomness(const byte[], u32bit) throw() = 0; + virtual void add_randomness(const byte[], u32bit) = 0; }; } ======================================================================== --- botan/def_alg.cpp +++ botan/def_alg.cpp 79162d3aecd53ba9f1c78742ff5146b790b91851 @@ -0,0 +1,129 @@ +/************************************************* +* Default Engine Algorithms Source File * +* (C) 1999-2005 The Botan Project * +*************************************************/ + +#include +#include + +#include + +#include + +#include +#include +#include + +#include + +namespace Botan { + +/************************************************* +* Some macros to simplify control flow * +*************************************************/ +#define HANDLE_TYPE_NO_ARGS(NAME, TYPE) \ + if(algo_name == NAME) \ + { \ + if(name.size() == 1) \ + return new TYPE; \ + throw Invalid_Algorithm_Name(algo_spec); \ + } + +#define HANDLE_TYPE_ONE_U32BIT(NAME, TYPE, DEFAULT) \ + if(algo_name == NAME) \ + { \ + if(name.size() == 1) \ + return new TYPE(DEFAULT); \ + if(name.size() == 2) \ + return new TYPE(to_u32bit(name[1])); \ + throw Invalid_Algorithm_Name(algo_spec); \ + } + +#define HANDLE_TYPE_TWO_U32BIT(NAME, TYPE, DEFAULT) \ + if(algo_name == NAME) \ + { \ + if(name.size() == 1) \ + return new TYPE(DEFAULT); \ + if(name.size() == 2) \ + return new TYPE(to_u32bit(name[1])); \ + if(name.size() == 3) \ + return new TYPE(to_u32bit(name[1]), to_u32bit(name[2])); \ + throw Invalid_Algorithm_Name(algo_spec); \ + } + +#define HANDLE_TYPE_ONE_STRING(NAME, TYPE) \ + if(algo_name == NAME) \ + { \ + if(name.size() == 2) \ + return new TYPE(name[1]); \ + throw Invalid_Algorithm_Name(algo_spec); \ + } + +/************************************************* +* Look for an algorithm with this name * +*************************************************/ +BlockCipher* +Default_Engine::find_block_cipher(const std::string& algo_spec) const + { + std::vector name = parse_algorithm_name(algo_spec); + if(name.size() == 0) + return 0; + const std::string algo_name = deref_alias(name[0]); + + HANDLE_TYPE_NO_ARGS("AES", AES); + HANDLE_TYPE_NO_ARGS("AES-128", AES_128); + HANDLE_TYPE_NO_ARGS("AES-192", AES_192); + HANDLE_TYPE_NO_ARGS("AES-256", AES_256); + return 0; + } + +/************************************************* +* Look for an algorithm with this name * +*************************************************/ +StreamCipher* +Default_Engine::find_stream_cipher(const std::string& algo_spec) const + { + std::vector name = parse_algorithm_name(algo_spec); + if(name.size() == 0) + return 0; + const std::string algo_name = deref_alias(name[0]); + + HANDLE_TYPE_ONE_U32BIT("ARC4", ARC4, 0); + + return 0; + } + +/************************************************* +* Look for an algorithm with this name * +*************************************************/ +HashFunction* +Default_Engine::find_hash(const std::string& algo_spec) const + { + std::vector name = parse_algorithm_name(algo_spec); + if(name.size() == 0) + return 0; + const std::string algo_name = deref_alias(name[0]); + + HANDLE_TYPE_NO_ARGS("CRC32", CRC32); + HANDLE_TYPE_NO_ARGS("SHA-160", SHA_160); + HANDLE_TYPE_NO_ARGS("SHA-256", SHA_256); + return 0; + } + +/************************************************* +* Look for an algorithm with this name * +*************************************************/ +MessageAuthenticationCode* +Default_Engine::find_mac(const std::string& algo_spec) const + { + std::vector name = parse_algorithm_name(algo_spec); + if(name.size() == 0) + return 0; + const std::string algo_name = deref_alias(name[0]); + + HANDLE_TYPE_ONE_STRING("HMAC", HMAC); + + return 0; + } + +} ======================================================================== --- botan/def_mode.cpp +++ botan/def_mode.cpp a06fee4078dafe7958ae460df501247ad6788178 @@ -0,0 +1,121 @@ +/************************************************* +* Default Engine Source File * +* (C) 1999-2005 The Botan Project * +*************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Botan { + +namespace { + +/************************************************* +* Simply return a mode object of choice * +*************************************************/ +Keyed_Filter* get_mode(Cipher_Dir direction, const std::string& cipher, + const std::string& mode, const std::string& pad = "", + u32bit bits = 0) + { + if(mode == "ECB") + { + if(direction == ENCRYPTION) return new ECB_Encryption(cipher, pad); + else return new ECB_Decryption(cipher, pad); + } + else if(mode == "CFB") + { + if(direction == ENCRYPTION) return new CFB_Encryption(cipher, bits); + else return new CFB_Decryption(cipher, bits); + } + else if(mode == "CBC") + { + if(pad == "CTS") + { + if(direction == ENCRYPTION) return new CTS_Encryption(cipher); + else return new CTS_Decryption(cipher); + } + if(direction == ENCRYPTION) return new CBC_Encryption(cipher, pad); + else return new CBC_Decryption(cipher, pad); + } + else if(mode == "EAX") + { + if(direction == ENCRYPTION) return new EAX_Encryption(cipher, bits); + else return new EAX_Decryption(cipher, bits); + } + else + throw Internal_Error("get_mode: " + cipher + "/" + mode + "/" + pad); + } + +} +/************************************************* +* Get a cipher object * +*************************************************/ +Keyed_Filter* Default_Engine::get_cipher(const std::string& algo_spec, + Cipher_Dir direction) + { + std::vector algo_parts = split_on(algo_spec, '/'); + if(algo_parts.size() == 0) + throw Invalid_Algorithm_Name(algo_spec); + + const std::string cipher = algo_parts[0]; + + if(have_stream_cipher(cipher)) + { + if(algo_parts.size() == 1) + return new StreamCipher_Filter(cipher); + return 0; + } + else if(have_block_cipher(cipher)) + { + if(algo_parts.size() != 2 && algo_parts.size() != 3) + return 0; + + std::string mode = algo_parts[1]; + u32bit bits = 0; + + if(mode.find("CFB") != std::string::npos || + mode.find("EAX") != std::string::npos) + { + std::vector algo_info = parse_algorithm_name(mode); + mode = algo_info[0]; + if(algo_info.size() == 1) + bits = 8*block_size_of(cipher); + else if(algo_info.size() == 2) + bits = to_u32bit(algo_info[1]); + else + throw Invalid_Algorithm_Name(algo_spec); + } + + std::string padding; + if(algo_parts.size() == 3) + padding = algo_parts[2]; + else + padding = (mode == "CBC") ? "PKCS7" : "NoPadding"; + + if(mode == "ECB" && padding == "CTS") + return 0; + else if((mode != "CBC" && mode != "ECB") && padding != "NoPadding") + throw Invalid_Algorithm_Name(algo_spec); + + if(mode == "OFB") return new OFB(cipher); + else if(mode == "CTR-BE") return new CTR_BE(cipher); + else if(mode == "ECB" || mode == "CBC" || mode == "CTS" || + mode == "CFB" || mode == "EAX") + return get_mode(direction, cipher, mode, padding, bits); + else + return 0; + } + + return 0; + } + +} ======================================================================== --- botan/engine.h e564fba257a1af6a72dfb4e68dfa387846189ee0 +++ botan/engine.h bf1afaedad957edbc26e34b4a0490cc156e6789c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include ======================================================================== --- botan/init.cpp 2b67a947e2133a4a9fbd93774c2a67a5d7cf5344 +++ botan/init.cpp e654bf9fc3a87be25a40bf183a843d6be139de98 @@ -9,9 +9,7 @@ #include #include #include -#include -#include -#include +#include #include #include #include @@ -261,11 +259,7 @@ set_engines(); init_rng_subsystem(); - if(arg_set(args, "fips140")) - set_global_rngs(new FIPS_186_RNG, new FIPS_186_RNG); - else - set_global_rngs(new Randpool, new ANSI_X917_RNG); - + set_global_rngs(new ANSI_X931_RNG, new ANSI_X931_RNG); add_entropy_sources(); if(!FIPS140::passes_self_tests()) ======================================================================== --- botan/mem_pool.cpp e2303f64ab0a279072bdbe59313ed10842702c20 +++ botan/mem_pool.cpp cc72eb332ab2c10e96d65332b22dec4d46fc5621 @@ -36,14 +36,6 @@ } /************************************************* -* Buffer Comparison * -*************************************************/ -bool Pooling_Allocator::is_empty_buffer(const Buffer& block) - { - return (block.length == 0); - } - -/************************************************* * Allocate some initial buffers * *************************************************/ void Pooling_Allocator::init() @@ -86,6 +78,14 @@ } /************************************************* +* Buffer Comparison * +*************************************************/ +bool Pooling_Allocator::is_empty_buffer(const Buffer& block) + { + return (block.length == 0); + } + +/************************************************* * Return true if these buffers are contiguous * *************************************************/ bool Pooling_Allocator::are_contiguous(const Buffer& a, const Buffer& b) ======================================================================== --- botan/mem_pool.h 79cc34c1b88e2ab2419e609d8c0c208a490f913e +++ botan/mem_pool.h 96e6c390b555075bc0335932142680360ef49f8b @@ -58,12 +58,12 @@ void* find_free_block(u32bit) const; void defrag_free_list() const; - static bool are_contiguous(const Buffer&, const Buffer&); u32bit find_block(void*) const; bool same_buffer(Buffer&, Buffer&) const; void remove_empty_buffers(std::vector&) const; static bool is_empty_buffer(const Buffer&); + static bool are_contiguous(const Buffer&, const Buffer&); const u32bit PREF_SIZE, ALIGN_TO; mutable std::vector real_mem, free_list; ======================================================================== --- botan/mode_pad.h d33d5fd3116799e3acc4510bbe8ec00b9ecf203a +++ botan/mode_pad.h 0ec59170055c96be7b3e7a70aa3a4e25baefbfcd @@ -17,12 +17,12 @@ class BlockCipherModePaddingMethod { public: - virtual ~BlockCipherModePaddingMethod() {} virtual void pad(byte[], u32bit, u32bit) const = 0; virtual u32bit unpad(const byte[], u32bit) const = 0; virtual u32bit pad_bytes(u32bit, u32bit) const; virtual bool valid_blocksize(u32bit) const = 0; virtual std::string name() const = 0; + virtual ~BlockCipherModePaddingMethod() {} }; /************************************************* ======================================================================== --- botan/pipe_rw.cpp a26836077fabc8d34bc89c1b96876391494fca1e +++ botan/pipe_rw.cpp d93a14d30e1feb8c498c90ddf0c4596716994536 @@ -123,13 +123,15 @@ SecureVector buffer(DEFAULT_BUFFERSIZE); std::string str; str.reserve(remaining(msg)); - while (true) + + while(true) { u32bit got = read(buffer, buffer.size(), msg); - if (got == 0) - break; + if(got == 0) + break; str.append((const char*)buffer.begin(), got); } + return str; } ======================================================================== --- botan/pkcs8.cpp 6d12f636a9d038c815ba1a19ed4b5dafa2f4a052 +++ botan/pkcs8.cpp 7f055238216229a265c733ab7e79edc252a54d93 @@ -132,11 +132,12 @@ if(!is_encrypted) key = key_data; + const u32bit max_tries = Config::get_u32bit("base/pkcs8_tries"); u32bit tries = 0; while(true) { try { - if(tries >= Config::get_u32bit("base/pkcs8_tries")) + if(max_tries && tries >= max_tries) break; if(is_encrypted) ======================================================================== --- botan/pubkey.cpp a79e182ed1aabf231ff5fd910240fd9e2fc517c3 +++ botan/pubkey.cpp ab5b94948a910abe6d83b35148ac6c460f790a11 @@ -256,14 +256,6 @@ /************************************************* * Check a signature * *************************************************/ -bool PK_Verifier::valid_signature(const byte sig[], u32bit length) - { - return check_signature(sig, length); - } - -/************************************************* -* Check a signature * -*************************************************/ bool PK_Verifier::check_signature(const MemoryRegion& sig) { return check_signature(sig, sig.size()); ======================================================================== --- botan/pubkey.h eb5a007ee85161d484036b2325def6afa731be7c +++ botan/pubkey.h dfcf36d1bc7eb006d8a593eb5f5a4a7e876171b8 @@ -77,9 +77,6 @@ bool check_signature(const byte[], u32bit); bool check_signature(const MemoryRegion&); - // DEPRECATED FUNCTION - bool valid_signature(const byte[], u32bit); - void set_input_format(Signature_Format); PK_Verifier(const PK_Key&, const std::string&); ======================================================================== --- botan/randpool.cpp 5d45a17b8b6f6311a3dd39fa0e1e8825164d8204 +++ botan/randpool.cpp 4cd57635f9b7a10426ff4ce53e630dbe86358083 @@ -16,49 +16,54 @@ if(!is_seeded()) throw PRNG_Unseeded(name()); - generate(system_clock()); - while(length >= output.size()) + update_buffer(); + while(length) { - xor_buf(out, output, output.size()); - length -= output.size(); - out += output.size(); - generate(system_clock()); + const u32bit copied = std::min(length, buffer.size()); + copy_mem(out, buffer.begin(), copied); + out += copied; + length -= copied; + update_buffer(); } - xor_buf(out, output, length); } /************************************************* * Refill the output buffer * *************************************************/ -void Randpool::generate(u64bit input) throw() +void Randpool::update_buffer() { + const u64bit timestamp = system_clock(); + counter++; + for(u32bit j = 0; j != 4; j++) hash->update(get_byte(j, counter)); for(u32bit j = 0; j != 8; j++) - hash->update(get_byte(j, input)); - hash->update(pool); + hash->update(get_byte(j, timestamp)); + hash->update(poolhash); - SecureVector poolhash = hash->final(); + SecureVector outerhash = hash->final(); - for(u32bit j = 0; j != poolhash.size(); j++) - output[j % output.size()] ^= poolhash[j]; - cipher->encrypt(output); + for(u32bit j = 0; j != outerhash.size(); j++) + buffer[j % buffer.size()] ^= outerhash[j]; + cipher->encrypt(buffer); if(counter % ITERATIONS_BEFORE_RESEED == 0) + { mix_pool(); - counter++; + update_buffer(); + } } /************************************************* -* Mix the randomness pool * +* Mix the entropy pool * *************************************************/ -void Randpool::mix_pool() throw() +void Randpool::mix_pool() { const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE; - cipher->set_key(output, output.size()); + cipher->set_key(poolhash); - xor_buf(pool, pool + BLOCK_SIZE*(POOL_BLOCKS-1), BLOCK_SIZE); + xor_buf(pool, buffer, BLOCK_SIZE); cipher->encrypt(pool); for(u32bit j = 1; j != POOL_BLOCKS; j++) { @@ -68,29 +73,29 @@ cipher->encrypt(this_block); } - for(u32bit j = 0; j != output.size(); j++) - output[j] ^= 0xFF; - cipher->encrypt(output); + poolhash = hash->process(pool); } /************************************************* * Add entropy to the internal state * *************************************************/ -void Randpool::add_randomness(const byte data[], u32bit length) throw() +void Randpool::add_randomness(const byte data[], u32bit length) { - update_entropy(data, length, pool.size()); + u32bit this_entropy = entropy_estimate(data, length); + entropy += std::min(this_entropy, 8*hash->OUTPUT_LENGTH); + entropy = std::min(entropy, 8 * pool.size()); while(length) { u32bit added = std::min(pool.size() / 2, length); + xor_buf(pool, data, added); - generate(system_clock()); + poolhash = hash->process(pool); mix_pool(); + length -= added; data += added; } - generate(system_time()); - mix_pool(); } /************************************************* @@ -109,7 +114,8 @@ cipher->clear(); hash->clear(); pool.clear(); - output.clear(); + poolhash.clear(); + buffer.clear(); entropy = counter = 0; } @@ -118,29 +124,37 @@ *************************************************/ std::string Randpool::name() const { - return "Randpool"; + return "Randpool(" + cipher->name() + "," + hash->name() + ")"; } /************************************************* * Randpool Constructor * *************************************************/ -Randpool::Randpool() : ITERATIONS_BEFORE_RESEED(8), POOL_BLOCKS(64) +Randpool::Randpool() : ITERATIONS_BEFORE_RESEED(8), POOL_BLOCKS(32) { - cipher = get_block_cipher("AES-128"); - hash = get_hash("SHA-1"); + const std::string CIPHER_NAME = "AES-256"; + const std::string HASH_NAME = "SHA-256"; + cipher = get_block_cipher(CIPHER_NAME); + hash = get_hash(HASH_NAME); + const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE; - output.create(BLOCK_SIZE); - pool.create(POOL_BLOCKS * BLOCK_SIZE); - entropy = counter = 0; + const u32bit OUTPUT_LENGTH = hash->OUTPUT_LENGTH; - if(hash->OUTPUT_LENGTH < BLOCK_SIZE || !cipher->valid_keylength(BLOCK_SIZE)) + if(OUTPUT_LENGTH < BLOCK_SIZE || !cipher->valid_keylength(OUTPUT_LENGTH)) + { + delete cipher; + delete hash; throw Internal_Error("Randpool: Invalid algorithm combination " + - cipher->name() + "/" + hash->name()); + CIPHER_NAME + "/" + HASH_NAME); + } - cipher->set_key(output, output.size()); - for(u32bit j = 0; j != ITERATIONS_BEFORE_RESEED + 1; j++) - generate(system_clock()); + poolhash = hash->process(pool); + buffer.create(BLOCK_SIZE); + pool.create(POOL_BLOCKS * BLOCK_SIZE); + entropy = counter = 0; + + mix_pool(); } /************************************************* @@ -150,6 +164,7 @@ { delete cipher; delete hash; + entropy = counter = 0; } } ======================================================================== --- botan/randpool.h 8c3837ac3ca62bdbf5e584ca350aee650df6dd56 +++ botan/randpool.h 9e5e53dac9493dd855fa05a563fb80769d5b8988 @@ -20,17 +20,19 @@ bool is_seeded() const; void clear() throw(); std::string name() const; + Randpool(); ~Randpool(); private: - void add_randomness(const byte[], u32bit) throw(); - void generate(u64bit) throw(); - void mix_pool() throw(); + void add_randomness(const byte[], u32bit); + void update_buffer(); + void mix_pool(); + const u32bit ITERATIONS_BEFORE_RESEED, POOL_BLOCKS; BlockCipher* cipher; HashFunction* hash; - SecureVector pool, output; - u32bit counter; + SecureVector pool, poolhash, buffer; + u32bit entropy, counter; }; } ======================================================================== --- botan/rng.cpp a87b1336b2275f4083f991b28ec602681eb17e1b +++ botan/rng.cpp 6241291f961c12f562c194b7cd2a57a7fa41e3f9 @@ -290,7 +290,7 @@ void set_global_rngs(RandomNumberGenerator* rng1, RandomNumberGenerator* rng2) { if(!rng_state) - throw Internal_Error("Global_RNG::seed: RNG state never created"); + throw Internal_Error("set_global_rngs: RNG state never created"); rng_state->set_rngs(rng1, rng2); } ======================================================================== --- botan/sha160.cpp f3c39163a2977d63f172f75ffe1891f2a2832239 +++ botan/sha160.cpp 283762dff556d9a03a0921634c178e7d5e84bda5 @@ -7,136 +7,115 @@ namespace Botan { - namespace { +namespace { - /************************************************* - * SHA-160 F1 Function * - *************************************************/ - inline void F1(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E, u32bit msg) - { - E += rotate_left(A, 5) + (D ^ (B & (C ^ D))) + msg + 0x5A827999; - B = rotate_left(B, 30); - } +/************************************************* +* SHA-160 F1 Function * +*************************************************/ +inline void F1(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E, u32bit msg) + { + E += (D ^ (B & (C ^ D))) + msg + 0x5A827999 + rotate_left(A, 5); + B = rotate_left(B, 30); + } - /************************************************* - * SHA-160 F2 Function * - *************************************************/ - inline void F2(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E, u32bit msg) - { - E += rotate_left(A, 5) + (B ^ C ^ D) + msg + 0x6ED9EBA1; - B = rotate_left(B, 30); - } +/************************************************* +* SHA-160 F2 Function * +*************************************************/ +inline void F2(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E, u32bit msg) + { + E += (B ^ C ^ D) + msg + 0x6ED9EBA1 + rotate_left(A, 5); + B = rotate_left(B, 30); + } - /************************************************* - * SHA-160 F3 Function * - *************************************************/ - inline void F3(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E, u32bit msg) - { - E += rotate_left(A, 5) + ((B & C) | ((B | C) & D)) + msg + 0x8F1BBCDC; - B = rotate_left(B, 30); - } +/************************************************* +* SHA-160 F3 Function * +*************************************************/ +inline void F3(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E, u32bit msg) + { + E += ((B & C) | ((B | C) & D)) + msg + 0x8F1BBCDC + rotate_left(A, 5); + B = rotate_left(B, 30); + } - /************************************************* - * SHA-160 F4 Function * - *************************************************/ - inline void F4(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E, u32bit msg) - { - E += rotate_left(A, 5) + (B ^ C ^ D) + msg + 0xCA62C1D6; - B = rotate_left(B, 30); - } +/************************************************* +* SHA-160 F4 Function * +*************************************************/ +inline void F4(u32bit A, u32bit& B, u32bit C, u32bit D, u32bit& E, u32bit msg) + { + E += (B ^ C ^ D) + msg + 0xCA62C1D6 + rotate_left(A, 5); + B = rotate_left(B, 30); + } - } +} - /************************************************* - * SHA-160 Compression Function * - *************************************************/ - void SHA_160::hash(const byte input[]) - { - class SHA_Expander - { - public: - u32bit operator[](u32bit i) - { - if(i < 16) - W[i] = make_u32bit(in[4*i], in[4*i+1], in[4*i+2], in[4*i+3]); - else - W[i%16] = rotate_left(W[(i+13)%16] ^ W[(i+8)%16] ^ - W[(i+2)%16] ^ W[i%16], 1); +/************************************************* +* SHA-160 Compression Function * +*************************************************/ +void SHA_160::hash(const byte input[]) + { + for(u32bit j = 0; j != 16; j++) + W[j] = make_u32bit(input[4*j], input[4*j+1], input[4*j+2], input[4*j+3]); + for(u32bit j = 16; j != 80; j++) + W[j] = rotate_left((W[j-3] ^ W[j-8] ^ W[j-14] ^ W[j-16]), 1); - return W[i%16]; - } + u32bit A = digest[0], B = digest[1], C = digest[2], + D = digest[3], E = digest[4]; - void set_input(const byte* x) { in = x; } + F1(A,B,C,D,E,W[ 0]); F1(E,A,B,C,D,W[ 1]); F1(D,E,A,B,C,W[ 2]); + F1(C,D,E,A,B,W[ 3]); F1(B,C,D,E,A,W[ 4]); F1(A,B,C,D,E,W[ 5]); + F1(E,A,B,C,D,W[ 6]); F1(D,E,A,B,C,W[ 7]); F1(C,D,E,A,B,W[ 8]); + F1(B,C,D,E,A,W[ 9]); F1(A,B,C,D,E,W[10]); F1(E,A,B,C,D,W[11]); + F1(D,E,A,B,C,W[12]); F1(C,D,E,A,B,W[13]); F1(B,C,D,E,A,W[14]); + F1(A,B,C,D,E,W[15]); F1(E,A,B,C,D,W[16]); F1(D,E,A,B,C,W[17]); + F1(C,D,E,A,B,W[18]); F1(B,C,D,E,A,W[19]); - ~SHA_Expander() { clear_mem(W, 16); } - private: - const byte* in; - u32bit W[16]; - }; + F2(A,B,C,D,E,W[20]); F2(E,A,B,C,D,W[21]); F2(D,E,A,B,C,W[22]); + F2(C,D,E,A,B,W[23]); F2(B,C,D,E,A,W[24]); F2(A,B,C,D,E,W[25]); + F2(E,A,B,C,D,W[26]); F2(D,E,A,B,C,W[27]); F2(C,D,E,A,B,W[28]); + F2(B,C,D,E,A,W[29]); F2(A,B,C,D,E,W[30]); F2(E,A,B,C,D,W[31]); + F2(D,E,A,B,C,W[32]); F2(C,D,E,A,B,W[33]); F2(B,C,D,E,A,W[34]); + F2(A,B,C,D,E,W[35]); F2(E,A,B,C,D,W[36]); F2(D,E,A,B,C,W[37]); + F2(C,D,E,A,B,W[38]); F2(B,C,D,E,A,W[39]); - SHA_Expander W; - W.set_input(input); + F3(A,B,C,D,E,W[40]); F3(E,A,B,C,D,W[41]); F3(D,E,A,B,C,W[42]); + F3(C,D,E,A,B,W[43]); F3(B,C,D,E,A,W[44]); F3(A,B,C,D,E,W[45]); + F3(E,A,B,C,D,W[46]); F3(D,E,A,B,C,W[47]); F3(C,D,E,A,B,W[48]); + F3(B,C,D,E,A,W[49]); F3(A,B,C,D,E,W[50]); F3(E,A,B,C,D,W[51]); + F3(D,E,A,B,C,W[52]); F3(C,D,E,A,B,W[53]); F3(B,C,D,E,A,W[54]); + F3(A,B,C,D,E,W[55]); F3(E,A,B,C,D,W[56]); F3(D,E,A,B,C,W[57]); + F3(C,D,E,A,B,W[58]); F3(B,C,D,E,A,W[59]); - u32bit A = digest[0], B = digest[1], C = digest[2], - D = digest[3], E = digest[4]; + F4(A,B,C,D,E,W[60]); F4(E,A,B,C,D,W[61]); F4(D,E,A,B,C,W[62]); + F4(C,D,E,A,B,W[63]); F4(B,C,D,E,A,W[64]); F4(A,B,C,D,E,W[65]); + F4(E,A,B,C,D,W[66]); F4(D,E,A,B,C,W[67]); F4(C,D,E,A,B,W[68]); + F4(B,C,D,E,A,W[69]); F4(A,B,C,D,E,W[70]); F4(E,A,B,C,D,W[71]); + F4(D,E,A,B,C,W[72]); F4(C,D,E,A,B,W[73]); F4(B,C,D,E,A,W[74]); + F4(A,B,C,D,E,W[75]); F4(E,A,B,C,D,W[76]); F4(D,E,A,B,C,W[77]); + F4(C,D,E,A,B,W[78]); F4(B,C,D,E,A,W[79]); - F1(A,B,C,D,E,W[ 0]); F1(E,A,B,C,D,W[ 1]); F1(D,E,A,B,C,W[ 2]); - F1(C,D,E,A,B,W[ 3]); F1(B,C,D,E,A,W[ 4]); F1(A,B,C,D,E,W[ 5]); - F1(E,A,B,C,D,W[ 6]); F1(D,E,A,B,C,W[ 7]); F1(C,D,E,A,B,W[ 8]); - F1(B,C,D,E,A,W[ 9]); F1(A,B,C,D,E,W[10]); F1(E,A,B,C,D,W[11]); - F1(D,E,A,B,C,W[12]); F1(C,D,E,A,B,W[13]); F1(B,C,D,E,A,W[14]); - F1(A,B,C,D,E,W[15]); F1(E,A,B,C,D,W[16]); F1(D,E,A,B,C,W[17]); - F1(C,D,E,A,B,W[18]); F1(B,C,D,E,A,W[19]); + digest[0] += A; digest[1] += B; digest[2] += C; + digest[3] += D; digest[4] += E; + } - F2(A,B,C,D,E,W[20]); F2(E,A,B,C,D,W[21]); F2(D,E,A,B,C,W[22]); - F2(C,D,E,A,B,W[23]); F2(B,C,D,E,A,W[24]); F2(A,B,C,D,E,W[25]); - F2(E,A,B,C,D,W[26]); F2(D,E,A,B,C,W[27]); F2(C,D,E,A,B,W[28]); - F2(B,C,D,E,A,W[29]); F2(A,B,C,D,E,W[30]); F2(E,A,B,C,D,W[31]); - F2(D,E,A,B,C,W[32]); F2(C,D,E,A,B,W[33]); F2(B,C,D,E,A,W[34]); - F2(A,B,C,D,E,W[35]); F2(E,A,B,C,D,W[36]); F2(D,E,A,B,C,W[37]); - F2(C,D,E,A,B,W[38]); F2(B,C,D,E,A,W[39]); - - F3(A,B,C,D,E,W[40]); F3(E,A,B,C,D,W[41]); F3(D,E,A,B,C,W[42]); - F3(C,D,E,A,B,W[43]); F3(B,C,D,E,A,W[44]); F3(A,B,C,D,E,W[45]); - F3(E,A,B,C,D,W[46]); F3(D,E,A,B,C,W[47]); F3(C,D,E,A,B,W[48]); - F3(B,C,D,E,A,W[49]); F3(A,B,C,D,E,W[50]); F3(E,A,B,C,D,W[51]); - F3(D,E,A,B,C,W[52]); F3(C,D,E,A,B,W[53]); F3(B,C,D,E,A,W[54]); - F3(A,B,C,D,E,W[55]); F3(E,A,B,C,D,W[56]); F3(D,E,A,B,C,W[57]); - F3(C,D,E,A,B,W[58]); F3(B,C,D,E,A,W[59]); - - F4(A,B,C,D,E,W[60]); F4(E,A,B,C,D,W[61]); F4(D,E,A,B,C,W[62]); - F4(C,D,E,A,B,W[63]); F4(B,C,D,E,A,W[64]); F4(A,B,C,D,E,W[65]); - F4(E,A,B,C,D,W[66]); F4(D,E,A,B,C,W[67]); F4(C,D,E,A,B,W[68]); - F4(B,C,D,E,A,W[69]); F4(A,B,C,D,E,W[70]); F4(E,A,B,C,D,W[71]); - F4(D,E,A,B,C,W[72]); F4(C,D,E,A,B,W[73]); F4(B,C,D,E,A,W[74]); - F4(A,B,C,D,E,W[75]); F4(E,A,B,C,D,W[76]); F4(D,E,A,B,C,W[77]); - F4(C,D,E,A,B,W[78]); F4(B,C,D,E,A,W[79]); - - digest[0] += A; digest[1] += B; digest[2] += C; - digest[3] += D; digest[4] += E; - } - - /************************************************* - * Copy out the digest * - *************************************************/ - void SHA_160::copy_out(byte output[]) - { - for(u32bit j = 0; j != OUTPUT_LENGTH; j++) +/************************************************* +* Copy out the digest * +*************************************************/ +void SHA_160::copy_out(byte output[]) + { + for(u32bit j = 0; j != OUTPUT_LENGTH; j++) output[j] = get_byte(j % 4, digest[j/4]); - } + } - /************************************************* - * Clear memory of sensitive data * - *************************************************/ - void SHA_160::clear() throw() - { - MDx_HashFunction::clear(); - digest[0] = 0x67452301; - digest[1] = 0xEFCDAB89; - digest[2] = 0x98BADCFE; - digest[3] = 0x10325476; - digest[4] = 0xC3D2E1F0; - } +/************************************************* +* Clear memory of sensitive data * +*************************************************/ +void SHA_160::clear() throw() + { + MDx_HashFunction::clear(); + digest[0] = 0x67452301; + digest[1] = 0xEFCDAB89; + digest[2] = 0x98BADCFE; + digest[3] = 0x10325476; + digest[4] = 0xC3D2E1F0; + } } - ======================================================================== --- botan/sha160.h e2ad1d38fddf6502076da1b95be4eafbbc7a54a2 +++ botan/sha160.h ed9b5ecfb4120f6b0c8f5c930705c56959944ef9 @@ -28,9 +28,9 @@ void copy_out(byte[]); SecureBuffer digest; + SecureBuffer W; }; } #endif - ======================================================================== --- botan/sha256.cpp +++ botan/sha256.cpp 763f18fe97915f53be1b159f7dd29145384d32ad @@ -0,0 +1,122 @@ +/************************************************* +* SHA-256 Source File * +* (C) 1999-2005 The Botan Project * +*************************************************/ + +#include + +namespace Botan { + +namespace { + +/************************************************* +* SHA-256 Rho Function * +*************************************************/ +inline u32bit rho(u32bit X, u32bit rot1, u32bit rot2, u32bit rot3) + { + return (rotate_right(X, rot1) ^ rotate_right(X, rot2) ^ + rotate_right(X, rot3)); + } + +/************************************************* +* SHA-256 Sigma Function * +*************************************************/ +inline u32bit sigma(u32bit X, u32bit rot1, u32bit rot2, u32bit shift) + { + return (rotate_right(X, rot1) ^ rotate_right(X, rot2) ^ (X >> shift)); + } + +/************************************************* +* SHA-256 F1 Function * +*************************************************/ +inline void F1(u32bit A, u32bit B, u32bit C, u32bit& D, + u32bit E, u32bit F, u32bit G, u32bit& H, + u32bit msg, u32bit magic) + { + magic += rho(E, 6, 11, 25) + ((E & F) ^ (~E & G)) + msg; + D += magic + H; + H += magic + rho(A, 2, 13, 22) + ((A & B) ^ (A & C) ^ (B & C)); + } + +} + +/************************************************* +* SHA-256 Compression Function * +*************************************************/ +void SHA_256::hash(const byte input[]) + { + for(u32bit j = 0; j != 16; j++) + W[j] = make_u32bit(input[4*j], input[4*j+1], input[4*j+2], input[4*j+3]); + for(u32bit j = 16; j != 64; j++) + W[j] = sigma(W[j- 2], 17, 19, 10) + W[j- 7] + + sigma(W[j-15], 7, 18, 3) + W[j-16]; + + u32bit A = digest[0], B = digest[1], C = digest[2], + D = digest[3], E = digest[4], F = digest[5], + G = digest[6], H = digest[7]; + + F1(A,B,C,D,E,F,G,H,W[ 0],0x428A2F98); F1(H,A,B,C,D,E,F,G,W[ 1],0x71374491); + F1(G,H,A,B,C,D,E,F,W[ 2],0xB5C0FBCF); F1(F,G,H,A,B,C,D,E,W[ 3],0xE9B5DBA5); + F1(E,F,G,H,A,B,C,D,W[ 4],0x3956C25B); F1(D,E,F,G,H,A,B,C,W[ 5],0x59F111F1); + F1(C,D,E,F,G,H,A,B,W[ 6],0x923F82A4); F1(B,C,D,E,F,G,H,A,W[ 7],0xAB1C5ED5); + F1(A,B,C,D,E,F,G,H,W[ 8],0xD807AA98); F1(H,A,B,C,D,E,F,G,W[ 9],0x12835B01); + F1(G,H,A,B,C,D,E,F,W[10],0x243185BE); F1(F,G,H,A,B,C,D,E,W[11],0x550C7DC3); + F1(E,F,G,H,A,B,C,D,W[12],0x72BE5D74); F1(D,E,F,G,H,A,B,C,W[13],0x80DEB1FE); + F1(C,D,E,F,G,H,A,B,W[14],0x9BDC06A7); F1(B,C,D,E,F,G,H,A,W[15],0xC19BF174); + F1(A,B,C,D,E,F,G,H,W[16],0xE49B69C1); F1(H,A,B,C,D,E,F,G,W[17],0xEFBE4786); + F1(G,H,A,B,C,D,E,F,W[18],0x0FC19DC6); F1(F,G,H,A,B,C,D,E,W[19],0x240CA1CC); + F1(E,F,G,H,A,B,C,D,W[20],0x2DE92C6F); F1(D,E,F,G,H,A,B,C,W[21],0x4A7484AA); + F1(C,D,E,F,G,H,A,B,W[22],0x5CB0A9DC); F1(B,C,D,E,F,G,H,A,W[23],0x76F988DA); + F1(A,B,C,D,E,F,G,H,W[24],0x983E5152); F1(H,A,B,C,D,E,F,G,W[25],0xA831C66D); + F1(G,H,A,B,C,D,E,F,W[26],0xB00327C8); F1(F,G,H,A,B,C,D,E,W[27],0xBF597FC7); + F1(E,F,G,H,A,B,C,D,W[28],0xC6E00BF3); F1(D,E,F,G,H,A,B,C,W[29],0xD5A79147); + F1(C,D,E,F,G,H,A,B,W[30],0x06CA6351); F1(B,C,D,E,F,G,H,A,W[31],0x14292967); + F1(A,B,C,D,E,F,G,H,W[32],0x27B70A85); F1(H,A,B,C,D,E,F,G,W[33],0x2E1B2138); + F1(G,H,A,B,C,D,E,F,W[34],0x4D2C6DFC); F1(F,G,H,A,B,C,D,E,W[35],0x53380D13); + F1(E,F,G,H,A,B,C,D,W[36],0x650A7354); F1(D,E,F,G,H,A,B,C,W[37],0x766A0ABB); + F1(C,D,E,F,G,H,A,B,W[38],0x81C2C92E); F1(B,C,D,E,F,G,H,A,W[39],0x92722C85); + F1(A,B,C,D,E,F,G,H,W[40],0xA2BFE8A1); F1(H,A,B,C,D,E,F,G,W[41],0xA81A664B); + F1(G,H,A,B,C,D,E,F,W[42],0xC24B8B70); F1(F,G,H,A,B,C,D,E,W[43],0xC76C51A3); + F1(E,F,G,H,A,B,C,D,W[44],0xD192E819); F1(D,E,F,G,H,A,B,C,W[45],0xD6990624); + F1(C,D,E,F,G,H,A,B,W[46],0xF40E3585); F1(B,C,D,E,F,G,H,A,W[47],0x106AA070); + F1(A,B,C,D,E,F,G,H,W[48],0x19A4C116); F1(H,A,B,C,D,E,F,G,W[49],0x1E376C08); + F1(G,H,A,B,C,D,E,F,W[50],0x2748774C); F1(F,G,H,A,B,C,D,E,W[51],0x34B0BCB5); + F1(E,F,G,H,A,B,C,D,W[52],0x391C0CB3); F1(D,E,F,G,H,A,B,C,W[53],0x4ED8AA4A); + F1(C,D,E,F,G,H,A,B,W[54],0x5B9CCA4F); F1(B,C,D,E,F,G,H,A,W[55],0x682E6FF3); + F1(A,B,C,D,E,F,G,H,W[56],0x748F82EE); F1(H,A,B,C,D,E,F,G,W[57],0x78A5636F); + F1(G,H,A,B,C,D,E,F,W[58],0x84C87814); F1(F,G,H,A,B,C,D,E,W[59],0x8CC70208); + F1(E,F,G,H,A,B,C,D,W[60],0x90BEFFFA); F1(D,E,F,G,H,A,B,C,W[61],0xA4506CEB); + F1(C,D,E,F,G,H,A,B,W[62],0xBEF9A3F7); F1(B,C,D,E,F,G,H,A,W[63],0xC67178F2); + + digest[0] += A; digest[1] += B; digest[2] += C; + digest[3] += D; digest[4] += E; digest[5] += F; + digest[6] += G; digest[7] += H; + } + +/************************************************* +* Copy out the digest * +*************************************************/ +void SHA_256::copy_out(byte output[]) + { + for(u32bit j = 0; j != OUTPUT_LENGTH; j++) + output[j] = get_byte(j % 4, digest[j/4]); + } + +/************************************************* +* Clear memory of sensitive data * +*************************************************/ +void SHA_256::clear() throw() + { + MDx_HashFunction::clear(); + W.clear(); + digest[0] = 0x6A09E667; + digest[1] = 0xBB67AE85; + digest[2] = 0x3C6EF372; + digest[3] = 0xA54FF53A; + digest[4] = 0x510E527F; + digest[5] = 0x9B05688C; + digest[6] = 0x1F83D9AB; + digest[7] = 0x5BE0CD19; + } + +} ======================================================================== --- botan/sha256.h +++ botan/sha256.h ad8001298ac6bfcef4891124d3f8ebd9c2011366 @@ -0,0 +1,33 @@ +/************************************************* +* SHA-256 Header File * +* (C) 1999-2005 The Botan Project * +*************************************************/ + +#ifndef BOTAN_SHA_256_H__ +#define BOTAN_SHA_256_H__ + +#include + +namespace Botan { + +/************************************************* +* SHA-256 * +*************************************************/ +class SHA_256 : public MDx_HashFunction + { + public: + void clear() throw(); + std::string name() const { return "SHA-256"; } + HashFunction* clone() const { return new SHA_256; } + SHA_256() : MDx_HashFunction(32, 64, true, true) { clear(); } + private: + void hash(const byte[]); + void copy_out(byte[]); + + SecureBuffer W; + SecureBuffer digest; + }; + +} + +#endif ======================================================================== --- botan/x931_rng.cpp +++ botan/x931_rng.cpp 7f93d680b7e6c71a3b9fcf1f8af051062cdddb16 @@ -0,0 +1,133 @@ +/************************************************* +* ANSI X9.31 RNG Source File * +* (C) 1999-2005 The Botan Project * +*************************************************/ + +#include +#include +#include + +namespace Botan { + +/************************************************* +* Generate a buffer of random bytes * +*************************************************/ +void ANSI_X931_RNG::randomize(byte out[], u32bit length) throw(PRNG_Unseeded) + { + if(!is_seeded()) + throw PRNG_Unseeded(name()); + + while(length) + { + const u32bit copied = std::min(length, R.size() - position); + + copy_mem(out, R + position, copied); + out += copied; + length -= copied; + position += copied; + + if(position == R.size()) + { + update_buffer(); + position = 0; + } + } + } + +/************************************************* +* Refill the internal state * +*************************************************/ +void ANSI_X931_RNG::update_buffer() + { + const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE; + + SecureVector DT(BLOCK_SIZE); + + prng->randomize(DT, DT.size()); + cipher->encrypt(DT); + + xor_buf(R, V, DT, BLOCK_SIZE); + cipher->encrypt(R); + + xor_buf(V, R, DT, BLOCK_SIZE); + cipher->encrypt(V); + } + +/************************************************* +* Add entropy to internal state * +*************************************************/ +void ANSI_X931_RNG::add_randomness(const byte data[], u32bit length) + { + prng->add_entropy(data, length); + + if(is_seeded()) + { + SecureVector key(cipher->MAXIMUM_KEYLENGTH); + prng->randomize(key, key.size()); + cipher->set_key(key, key.size()); + + prng->randomize(V, V.size()); + + update_buffer(); + } + } + +/************************************************* +* Check if the the PRNG is seeded * +*************************************************/ +bool ANSI_X931_RNG::is_seeded() const + { + return prng->is_seeded(); + } + +/************************************************* +* Clear memory of sensitive data * +*************************************************/ +void ANSI_X931_RNG::clear() throw() + { + cipher->clear(); + prng->clear(); + R.clear(); + V.clear(); + + position = 0; + } + +/************************************************* +* Return the name of this type * +*************************************************/ +std::string ANSI_X931_RNG::name() const + { + return "X9.31(" + cipher->name() + ")"; + } + +/************************************************* +* ANSI X931 RNG Constructor * +*************************************************/ +ANSI_X931_RNG::ANSI_X931_RNG(RandomNumberGenerator* prng_ptr) + { + cipher = get_block_cipher("AES-256"); + + const u32bit BLOCK_SIZE = cipher->BLOCK_SIZE; + + V.create(BLOCK_SIZE); + R.create(BLOCK_SIZE); + + if(prng_ptr) + prng = prng_ptr; + else + prng = new Randpool; + + position = 0; + } + +/************************************************* +* ANSI X931 RNG Destructor * +*************************************************/ +ANSI_X931_RNG::~ANSI_X931_RNG() + { + delete cipher; + delete prng; + } + +} ======================================================================== --- botan/x931_rng.h +++ botan/x931_rng.h 867850aff3df63007e12886ed6d00c338496b93e @@ -0,0 +1,37 @@ +/************************************************* +* ANSI X9.31 RNG Header File * +* (C) 1999-2005 The Botan Project * +*************************************************/ + +#ifndef BOTAN_ANSI_X931_RNG_H__ +#define BOTAN_ANSI_X931_RNG_H__ + +#include + +namespace Botan { + +/************************************************* +* ANSI X9.31 RNG * +*************************************************/ +class ANSI_X931_RNG : public RandomNumberGenerator + { + public: + void randomize(byte[], u32bit) throw(PRNG_Unseeded); + bool is_seeded() const; + void clear() throw(); + std::string name() const; + ANSI_X931_RNG(RandomNumberGenerator* = 0); + ~ANSI_X931_RNG(); + private: + void add_randomness(const byte[], u32bit); + void update_buffer(); + + BlockCipher* cipher; + RandomNumberGenerator* prng; + SecureVector V, R; + u32bit position; + }; + +} + +#endif ======================================================================== --- commands.cc 889b85e8285c01cbd3cfecfecc5b2d687f9cdcd3 +++ commands.cc 6368c2bb3e6de393e4ffdaa9a65a6f3b541b1f85 @@ -1366,6 +1366,11 @@ checkout_dot = true; } + if (!checkout_dot) + require_path_is_nonexistent(dir, + F("checkout directory '%s' already exists") + % dir); + if (app.revision_selectors.size() == 0) { // use branch head revision @@ -1403,10 +1408,6 @@ % ident % app.branch_name); } - if (!checkout_dot) - require_path_is_nonexistent(dir, - F("checkout directory '%s' already exists") - % dir); app.create_working_copy(dir); transaction_guard guard(app.db); ======================================================================== --- file_io.cc e39a1c13030c5378ea4cb3aa9621148ce0c8fb7d +++ file_io.cc c5541a89410a0194523e41bfcadb27f58124ee70 @@ -359,7 +359,8 @@ // nb: no mucking around with multiple-writer conditions. we're a // single-user single-threaded program. you get what you paid for. assert_path_is_directory(bookkeeping_root); - bookkeeping_path tmp = bookkeeping_root / "data.tmp"; + bookkeeping_path tmp = bookkeeping_root / (boost::format("data.tmp.%d") % + get_process_id()).str(); { // data.tmp opens @@ -371,9 +372,7 @@ // data.tmp closes } - if (path_exists(p)) - N(fs::remove(mkdir(p)), F("removing %s failed") % p); - fs::rename(mkdir(tmp), mkdir(p)); + rename_clobberingly(tmp, p); } void ======================================================================== --- main.cc ca8383ced00bdb686905f58eaeac7b1446347219 +++ main.cc 93c14a170425bd2be15e68d0f4eed476f9b77144 @@ -260,21 +260,28 @@ { typedef struct sigaction* sigaction_ptr; static struct sigaction all_signals_action; + static struct sigaction ignore_signals_action; struct sigaction old_SIGFPE_action; struct sigaction old_SIGTRAP_action; struct sigaction old_SIGSEGV_action; struct sigaction old_SIGBUS_action; struct sigaction old_SIGABRT_action; + struct sigaction old_SIGPIPE_action; all_signals_action.sa_flags = 0; all_signals_action.sa_handler = &unix_style_signal_handler; sigemptyset(&all_signals_action.sa_mask); + ignore_signals_action.sa_flags = 0; + ignore_signals_action.sa_handler = SIG_IGN; + sigemptyset(&ignore_signals_action.sa_mask); + sigaction(SIGFPE , &all_signals_action, &old_SIGFPE_action); sigaction(SIGTRAP, &all_signals_action, &old_SIGTRAP_action); sigaction(SIGSEGV, &all_signals_action, &old_SIGSEGV_action); sigaction(SIGBUS , &all_signals_action, &old_SIGBUS_action); sigaction(SIGABRT, &all_signals_action, &old_SIGABRT_action); + sigaction(SIGPIPE, &ignore_signals_action, &old_SIGPIPE_action); int result = 0; bool trapped_signal = false; @@ -315,6 +322,7 @@ sigaction(SIGSEGV, &old_SIGSEGV_action, sigaction_ptr()); sigaction(SIGBUS , &old_SIGBUS_action , sigaction_ptr()); sigaction(SIGABRT, &old_SIGABRT_action, sigaction_ptr()); + sigaction(SIGPIPE, &old_SIGPIPE_action, sigaction_ptr()); if(trapped_signal) throw unix_signal_exception(em); ======================================================================== --- monotone.cc cab8b2b01a23a5e82a37761b90517703c57c241a +++ monotone.cc 07d7a968c1ea02cff2f2cd60def4980c6e781c21 @@ -548,6 +548,11 @@ clean_shutdown = true; return 1; } + catch (std::ios_base::failure const & ex) + { + clean_shutdown = true; + return 1; + } clean_shutdown = true; return ret; ======================================================================== --- monotone.texi 5cc1a931d274bc7d3f0cc95fc932162506011cb6 +++ monotone.texi e053856be27fa9eb51ef40088fa8253ddefa081c @@ -1645,7 +1645,12 @@ @end smallexample This command sets up a single listener loop on the host address@hidden, serving all branches matching address@hidden@footnote{Make sure that the name +resolves to the right IP address. E.g. by checking @code{ping +jim-laptop.juicebot.co.jp}. A server listening on localhost +(127.0.0.1) will not be reachable by other computers. If you don't want +to think about interfaces and addresses start monotone on @code{0.0.0.0}. +}, serving all branches matching @code{jp.co.juicebot.jb7*}. This will naturally include the @code{jp.co.juicebot.jb7} branch, and any sub-branches. The quotes around @code{"jp.co.juicebot.jb7*"} are there to protect the @code{*} @@ -5018,9 +5023,11 @@ @item Sample output: +All basic status codes: + @verbatim M 0 0 missing - AP 0 0 added patched + AP 0 0 added D 0 0 dropped R 1 0 renamed-from-this R 0 1 renamed-to-this @@ -5028,57 +5035,81 @@ 0 0 unchanged U 0 0 unknown I 0 0 ignored address@hidden verbatim -# swapped but not moved +Two files swapped: -RRP 1 2 unchanged -RRP 2 1 original address@hidden +RR 1 2 unchanged +RR 2 1 original address@hidden verbatim -# swapped and moved +Recorded with monotone that two files were swapped, but they were not +actually swapped in the filesystem. Thus they both appear as patched: -RR 1 2 unchanged -RR 2 1 original address@hidden +RRP 1 2 unchanged +RRP 2 1 original address@hidden verbatim -# rename foo bar; add foo +Rename @file{foo} to @file{bar}; add new file @file{foo}: address@hidden RAP 1 0 foo R 0 1 bar address@hidden verbatim -# rotated but not moved dropped -> missing -> original -> dropped +Rotated files @file{foo} -> @file{bar} -> @file{baz} -> @file{foo}: -RRP 1 3 dropped -RRP 2 1 missing -RRP 3 2 original address@hidden +RR 1 3 foo +RR 2 1 bar +RR 3 2 baz address@hidden verbatim -# rotated and moved +Recorded the rotation of files @file{foo} -> @file{bar} -> @file{baz} -> address@hidden, but the actual files in the working directory were not +moved, so monotone interprets all files as having been patched: -RR 1 3 dropped -RR 2 1 missing -RR 3 2 original address@hidden +RRP 1 3 foo +RRP 2 1 bar +RRP 3 2 baz address@hidden verbatim -# dropped but not removed and thus unknown +Dropped but not removed and thus unknown: address@hidden D U 0 0 dropped address@hidden verbatim -# added but removed and thus missing +Added a non-existent file which is thus missing: address@hidden AM 0 0 added address@hidden verbatim -# renamed but not moved and thus unknown source and missing target +Recorded a rename, but not moved in the filesystem, and thus unknown +source and missing target: address@hidden R U 1 0 original RM 0 1 renamed address@hidden verbatim -# moved but not renamed and thus missing source and unknown target +Moved in the filesystem but no rename recorded, and thus missing source +and unknown target: address@hidden M 0 0 original U 0 0 renamed address@hidden verbatim -# renamed and patched +Renamed and patched: address@hidden R 1 0 original RP 0 1 renamed - @end verbatim @item Output format: @@ -5168,6 +5199,34 @@ 'RRM' rename source and target and target missing @end verbatim +The two numbers are used to match up the pre-state and post-state of a +rename. Imagine a situation where there are two renames. address@hidden inventory} will print something like: + address@hidden +R 1 0 a +R 2 0 b + R 0 2 c + R 0 1 d address@hidden verbatim + +Here the status characters tell us that @file{a} and @file{b} were +renamed, and we can tell that one was renamed to @file{c} and one was +renamed to @file{d}, but we can't tell which was renamed to which. To +do that, we have to refer to the numbers. The numbers do not themselves +mean anything; their only purpose is to let you match up the two +``ends'' of a rename. The 1 in the left column by @file{a} means that address@hidden was the source of a rename, and the 1 in the right column by address@hidden means that @file{d} was the target of that same rename. +Similarly, the two 2's tell us that @file{b} was renamed to @file{c}. + +There are two columns of numbers because the same file can +simultaneously be the target and source of a rename. The number '0' is +used as a meaningless placeholder in all cases where a file is not a +source or target of a rename. Any non-zero number that occurs at all +will occur exactly once in the first column and exactly once in the +second column. + Full support for versioned directories is not yet complete and the inventory will only list entries for renamed or dropped directories. ======================================================================== --- netsync.cc b253cccce899ebf482d4b14f0ce08139079018c2 +++ netsync.cc 248489d7ad1d4b104cd1e607ad1714205be6c5a2 @@ -3591,7 +3591,6 @@ { try { - start_platform_netsync(); if (voice == server_voice) { serve_connections(role, include_pattern, exclude_pattern, app, @@ -3611,15 +3610,12 @@ } catch (Netxx::NetworkException & e) { - end_platform_netsync(); throw informative_failure((F("network error: %s") % e.what()).str()); } catch (Netxx::Exception & e) { - end_platform_netsync(); throw oops((F("network error: %s") % e.what()).str());; } - end_platform_netsync(); } ======================================================================== --- platform.hh 0c8532e0798d470031bc897517234e3c8f4b9be9 +++ platform.hh 9ab0db8ce56f0fead355f2e8477669748bee8a7e @@ -34,10 +34,6 @@ // return value of 0 means "unlimited" unsigned int terminal_width(); -// for netsync -void start_platform_netsync(); -void end_platform_netsync(); - // for "reckless mode" working copy change detection. // returns 'true' if it has generated a valid inodeprint; returns 'false' if // there was a problem, in which case we should act as if the inodeprint has @@ -59,5 +55,7 @@ typedef enum { nonexistent, directory, file } status; }; path::status get_path_status(any_path const & path); - + +void rename_clobberingly(any_path const & from, any_path const & to); + #endif // __PLATFORM_HH__ ======================================================================== --- std_hooks.lua a2a27daced7769d54850f059f39554cb1e0fc78d +++ std_hooks.lua 956a176b43d8425910623c605d405c2678676e55 @@ -337,18 +337,17 @@ local elisp = "(ediff-merge-files \"%s\" \"%s\" nil \"%s\")" return function() - return execute(emacs, "-eval", + return execute(emacs, "--eval", string.format(elisp, lfile, rfile, outfile)) end end function merge3_emacs_cmd(emacs, lfile, afile, rfile, outfile) local elisp = "(ediff-merge-files-with-ancestor \"%s\" \"%s\" \"%s\" nil \"%s\")" - local cmd_fmt = "%s -eval " .. elisp return function() - execute(emacs, "-eval", - string.format(elisp, lfile, rfile, afile, outfile)) + return execute(emacs, "--eval", + string.format(elisp, lfile, rfile, afile, outfile)) end end ======================================================================== --- ui.cc 0fa61fa5c584e05a187d6c7e29c8336e4d7f3455 +++ ui.cc 3cbe9c661750040b4663d3f1b05d85ff964707ff @@ -262,6 +262,7 @@ last_write_was_a_tick(false), t_writer(0) { + cout.exceptions(ios_base::badbit); #ifndef WIN32 clog.sync_with_stdio(false); #endif ======================================================================== --- unix/fs.cc 1bb3dcff181451829c42a1d34c1111d486437fda +++ unix/fs.cc 6b71610c94a70ecabfecdcf10f0aa0d880fffc7f @@ -104,3 +104,10 @@ E(false, F("cannot handle special file %s") % path); } } + +void +rename_clobberingly(any_path const & from, any_path const & to) +{ + E(!rename(from.as_external().c_str(), to.as_external().c_str()), + F("renaming '%s' to '%s' failed: %s") % from % to % std::strerror(errno)); +} ======================================================================== --- win32/fs.cc bfc8bc3aaa07a3ec97a5d555ee4af563a118546d +++ win32/fs.cc 409c24f9c6ca1d1b9de8f951885c3044d16dfbd0 @@ -21,7 +21,7 @@ F("cannot get working directory: %s") % strerror(errno)); return std::string(buffer); } - + void change_current_working_dir(any_path const & to) { E(!chdir(to.as_external().c_str()), @@ -114,3 +114,54 @@ else return path::file; } + +static bool +rename_clobberingly_impl(const char* from, const char* to) +{ + // MoveFileEx is only available on NT-based systems. We will revert to a + // more compatible DeleteFile/MoveFile pair as a compatibility fall-back. + typedef BOOL (*MoveFileExFun)(LPCTSTR, LPCTSTR, DWORD); + static MoveFileExFun MoveFileEx = 0; + if (MoveFileEx == 0) { + HMODULE hModule = LoadLibrary("kernel32"); + MoveFileEx = reinterpret_cast + (GetProcAddress(hModule, "MoveFileExA")); + if (MoveFileEx) + L(F("using MoveFileEx for renames")); + } + + if (MoveFileEx) { + if (MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING)) + return true; + } else { + // This is not even remotely atomic, but what can you do? + DeleteFile(to); + if (MoveFile(from, to)) + return true; + } + return false; +} + +void +rename_clobberingly(any_path const & from, any_path const & to) +{ + const char* szFrom = from.as_external().c_str(); + const char* szTo = to.as_external().c_str(); + static const int renameAttempts = 16; + DWORD sleepTime = 1; + + // If a clobbering rename attempt fails, we wait and try again, up to an + // (arbitrary) maximum of 16 attempts. This is a gross hack to work + // around the common problem where another process (e.g. a virus checker) + // will exclusive open a file you've just touched. + for (int i = 0; i < renameAttempts; ++i) { + if (rename_clobberingly_impl(szFrom, szTo)) + return; + L(F("attempted rename of '%s' to '%s' failed: %d") + % szFrom % szTo % GetLastError()); + Sleep(sleepTime); + if (sleepTime < 250) + sleepTime *= 2; + } + E(false, F("renaming '%s' to '%s' failed: %d") % from % to); +}