]> gcc.gnu.org Git - gcc.git/commitdiff
libgo: Update to current Go library.
authorIan Lance Taylor <ian@gcc.gnu.org>
Thu, 7 Apr 2011 17:09:10 +0000 (17:09 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Thu, 7 Apr 2011 17:09:10 +0000 (17:09 +0000)
From-SVN: r172106

110 files changed:
libgo/MERGE
libgo/Makefile.am
libgo/Makefile.in
libgo/go/archive/tar/reader.go
libgo/go/archive/tar/reader_test.go
libgo/go/archive/zip/reader.go
libgo/go/bufio/bufio.go
libgo/go/compress/lzw/writer_test.go
libgo/go/compress/zlib/writer_test.go
libgo/go/crypto/block/cbc.go [deleted file]
libgo/go/crypto/block/cfb.go [deleted file]
libgo/go/crypto/block/cfb_aes_test.go [deleted file]
libgo/go/crypto/block/cipher.go [deleted file]
libgo/go/crypto/block/cmac.go [deleted file]
libgo/go/crypto/block/cmac_aes_test.go [deleted file]
libgo/go/crypto/block/ctr.go [deleted file]
libgo/go/crypto/block/eax.go [deleted file]
libgo/go/crypto/block/eax_aes_test.go [deleted file]
libgo/go/crypto/block/ecb.go [deleted file]
libgo/go/crypto/block/ecb_aes_test.go [deleted file]
libgo/go/crypto/block/ecb_test.go [deleted file]
libgo/go/crypto/block/ofb.go [deleted file]
libgo/go/crypto/block/ofb_aes_test.go [deleted file]
libgo/go/crypto/block/xor.go [deleted file]
libgo/go/crypto/block/xor_test.go [deleted file]
libgo/go/crypto/des/block.go [new file with mode: 0644]
libgo/go/crypto/des/cipher.go [new file with mode: 0644]
libgo/go/crypto/des/const.go [new file with mode: 0644]
libgo/go/crypto/des/des_test.go [new file with mode: 0644]
libgo/go/crypto/ecdsa/ecdsa.go
libgo/go/crypto/rand/rand_unix.go
libgo/go/crypto/rsa/pkcs1v15.go
libgo/go/crypto/rsa/rsa.go
libgo/go/crypto/rsa/rsa_test.go
libgo/go/crypto/tls/generate_cert.go
libgo/go/crypto/tls/tls.go
libgo/go/crypto/x509/x509.go
libgo/go/crypto/x509/x509_test.go
libgo/go/debug/elf/file.go
libgo/go/debug/macho/file.go
libgo/go/debug/pe/file.go
libgo/go/debug/proc/proc_linux.go
libgo/go/exec/exec.go
libgo/go/exp/draw/x11/auth.go
libgo/go/exp/ogle/cmd.go
libgo/go/fmt/fmt_test.go
libgo/go/fmt/format.go
libgo/go/fmt/print.go
libgo/go/go/parser/interface.go
libgo/go/go/parser/parser.go
libgo/go/html/parse_test.go
libgo/go/http/fs.go
libgo/go/http/fs_test.go
libgo/go/http/httptest/server.go
libgo/go/http/response_test.go
libgo/go/http/serve_test.go
libgo/go/http/transfer.go
libgo/go/http/transport.go
libgo/go/http/transport_test.go
libgo/go/http/url.go
libgo/go/http/url_test.go
libgo/go/image/decode_test.go
libgo/go/image/png/reader_test.go
libgo/go/io/ioutil/ioutil.go
libgo/go/io/ioutil/tempfile.go
libgo/go/log/log.go
libgo/go/log/log_test.go
libgo/go/mime/type.go
libgo/go/net/hosts.go
libgo/go/net/parse.go
libgo/go/net/parse_test.go
libgo/go/net/resolv_windows.go
libgo/go/os/dir_plan9.go [new file with mode: 0644]
libgo/go/os/dir_unix.go [new file with mode: 0644]
libgo/go/os/env_plan9.go [new file with mode: 0644]
libgo/go/os/error.go
libgo/go/os/error_plan9.go [new file with mode: 0644]
libgo/go/os/error_posix.go [new file with mode: 0644]
libgo/go/os/exec.go
libgo/go/os/exec_plan9.go [new file with mode: 0644]
libgo/go/os/exec_posix.go [new file with mode: 0644]
libgo/go/os/file.go
libgo/go/os/file_plan9.go [new file with mode: 0644]
libgo/go/os/file_posix.go [new file with mode: 0644]
libgo/go/os/file_unix.go
libgo/go/os/getwd.go
libgo/go/os/inotify/inotify_linux_test.go
libgo/go/os/os_test.go
libgo/go/os/path.go
libgo/go/os/path_test.go
libgo/go/os/proc.go
libgo/go/os/stat_plan9.go [new file with mode: 0644]
libgo/go/os/sys_linux.go
libgo/go/os/sys_plan9.go [new file with mode: 0644]
libgo/go/os/time.go
libgo/go/path/filepath/match.go
libgo/go/path/filepath/match_test.go
libgo/go/path/filepath/path.go
libgo/go/path/filepath/path_plan9.go [new file with mode: 0644]
libgo/go/path/filepath/path_test.go
libgo/go/path/filepath/path_unix.go
libgo/go/scanner/scanner.go
libgo/go/scanner/scanner_test.go
libgo/go/strconv/fp_test.go
libgo/go/testing/testing.go
libgo/mksysinfo.sh
libgo/syscalls/syscall.go
libgo/syscalls/syscall_unix.go
libgo/syscalls/sysfile_largefile.go
libgo/syscalls/sysfile_regfile.go

index b78ba690a547d433e8022494053362139b9c5059..237a0c2565e7516932cd575d4427af7677d6e13f 100644 (file)
@@ -1,4 +1,4 @@
-342e3b11f21a
+f618e5e0991d
 
 The first line of this file holds the Mercurial revision number of the
 last merge done from the master library sources.
index c40456f62f652ef2bbe0dca921e183f7b688cfca..3c9433101821a267e5baf81a060b9620934e2bfb 100644 (file)
@@ -177,10 +177,10 @@ toolexeclibgocryptodir = $(toolexeclibgodir)/crypto
 
 toolexeclibgocrypto_DATA = \
        crypto/aes.gox \
-       crypto/block.gox \
        crypto/blowfish.gox \
        crypto/cast5.gox \
        crypto/cipher.gox \
+       crypto/des.gox \
        crypto/dsa.gox \
        crypto/ecdsa.gox \
        crypto/elliptic.gox \
@@ -727,9 +727,12 @@ go_os_files = \
        go/os/env.go \
        go/os/env_unix.go \
        go/os/error.go \
+       go/os/error_posix.go \
        go/os/exec.go \
+       go/os/exec_posix.go \
        go/os/exec_unix.go \
        go/os/file.go \
+       go/os/file_posix.go \
        go/os/file_unix.go \
        go/os/getwd.go \
        go/os/path.go \
@@ -932,16 +935,6 @@ go_crypto_aes_files = \
        go/crypto/aes/block.go \
        go/crypto/aes/cipher.go \
        go/crypto/aes/const.go
-go_crypto_block_files = \
-       go/crypto/block/cbc.go \
-       go/crypto/block/cfb.go \
-       go/crypto/block/cmac.go \
-       go/crypto/block/cipher.go \
-       go/crypto/block/ctr.go \
-       go/crypto/block/eax.go \
-       go/crypto/block/ecb.go \
-       go/crypto/block/ofb.go \
-       go/crypto/block/xor.go
 go_crypto_blowfish_files = \
        go/crypto/blowfish/block.go \
        go/crypto/blowfish/const.go \
@@ -956,6 +949,10 @@ go_crypto_cipher_files = \
        go/crypto/cipher/io.go \
        go/crypto/cipher/ocfb.go \
        go/crypto/cipher/ofb.go
+go_crypto_des_files = \
+       go/crypto/des/block.go \
+       go/crypto/des/cipher.go \
+       go/crypto/des/const.go
 go_crypto_dsa_files = \
        go/crypto/dsa/dsa.go
 go_crypto_ecdsa_files = \
@@ -1428,10 +1425,10 @@ libgo_go_objs = \
        container/ring.lo \
        container/vector.lo \
        crypto/aes.lo \
-       crypto/block.lo \
        crypto/blowfish.lo \
        crypto/cast5.lo \
        crypto/cipher.lo \
+       crypto/des.lo \
        crypto/dsa.lo \
        crypto/ecdsa.lo \
        crypto/elliptic.lo \
@@ -2026,13 +2023,6 @@ crypto/aes/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: crypto/aes/check
 
-crypto/block.lo: $(go_crypto_block_files) fmt.gox io.gox os.gox strconv.gox
-       $(BUILDPACKAGE)
-crypto/block/check: $(CHECK_DEPS)
-       @$(MKDIR_P) crypto/block
-       @$(CHECK)
-.PHONY: crypto/block/check
-
 crypto/blowfish.lo: $(go_crypto_blowfish_files) os.gox strconv.gox
        $(BUILDPACKAGE)
 crypto/blowfish/check: $(CHECK_DEPS)
@@ -2054,6 +2044,13 @@ crypto/cipher/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: crypto/cipher/check
 
+crypto/des.lo: $(go_crypto_des_files) encoding/binary.gox os.gox strconv.gox
+       $(BUILDPACKAGE)
+crypto/des/check: $(CHECK_DEPS)
+       @$(MKDIR_P) crypto/des
+       @$(CHECK)
+.PHONY: crypto/des/check
+
 crypto/dsa.lo: $(go_crypto_dsa_files) big.gox io.gox os.gox
        $(BUILDPACKAGE)
 crypto/dsa/check: $(CHECK_DEPS)
@@ -2139,7 +2136,8 @@ crypto/ripemd160/check: $(CHECK_DEPS)
 .PHONY: crypto/ripemd160/check
 
 crypto/rsa.lo: $(go_crypto_rsa_files) big.gox crypto.gox crypto/sha1.gox \
-               crypto/subtle.gox encoding/hex.gox hash.gox io.gox os.gox
+               crypto/subtle.gox encoding/hex.gox hash.gox io.gox os.gox \
+               sync.gox
        $(BUILDPACKAGE)
 crypto/rsa/check: $(CHECK_DEPS)
        @$(MKDIR_P) crypto/rsa
@@ -2475,8 +2473,8 @@ http/cgi/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: http/cgi/check
 
-http/httptest.lo: $(go_http_httptest_files) bytes.gox fmt.gox http.gox \
-               net.gox os.gox
+http/httptest.lo: $(go_http_httptest_files) bytes.gox crypto/rand.gox \
+               crypto/tls.gox fmt.gox http.gox net.gox os.gox time.gox
        $(BUILDPACKAGE)
 http/httptest/check: $(CHECK_DEPS)
        @$(MKDIR_P) http/httptest
@@ -2767,14 +2765,14 @@ container/vector.gox: container/vector.lo
 
 crypto/aes.gox: crypto/aes.lo
        $(BUILDGOX)
-crypto/block.gox: crypto/block.lo
-       $(BUILDGOX)
 crypto/blowfish.gox: crypto/blowfish.lo
        $(BUILDGOX)
 crypto/cast5.gox: crypto/cast5.lo
        $(BUILDGOX)
 crypto/cipher.gox: crypto/cipher.lo
        $(BUILDGOX)
+crypto/des.gox: crypto/des.lo
+       $(BUILDGOX)
 crypto/dsa.gox: crypto/dsa.lo
        $(BUILDGOX)
 crypto/ecdsa.gox: crypto/ecdsa.lo      
@@ -3002,10 +3000,10 @@ TEST_PACKAGES = \
        container/ring/check \
        container/vector/check \
        crypto/aes/check \
-       crypto/block/check \
        crypto/blowfish/check \
        crypto/cast5/check \
        crypto/cipher/check \
+       crypto/des/check \
        crypto/dsa/check \
        crypto/ecdsa/check \
        crypto/elliptic/check \
index 10f86f168d1e63bec63e8c9ca8f38373a4876bc2..da881d574360951b9e4e5b6875a95cfb5ab2e8f1 100644 (file)
@@ -140,31 +140,30 @@ am__DEPENDENCIES_2 = asn1/asn1.lo big/big.lo bufio/bufio.lo \
        archive/zip.lo compress/bzip2.lo compress/flate.lo \
        compress/gzip.lo compress/lzw.lo compress/zlib.lo \
        container/heap.lo container/list.lo container/ring.lo \
-       container/vector.lo crypto/aes.lo crypto/block.lo \
-       crypto/blowfish.lo crypto/cast5.lo crypto/cipher.lo \
-       crypto/dsa.lo crypto/ecdsa.lo crypto/elliptic.lo \
-       crypto/hmac.lo crypto/md4.lo crypto/md5.lo crypto/ocsp.lo \
-       crypto/openpgp.lo crypto/rand.lo crypto/rc4.lo \
-       crypto/ripemd160.lo crypto/rsa.lo crypto/sha1.lo \
-       crypto/sha256.lo crypto/sha512.lo crypto/subtle.lo \
-       crypto/tls.lo crypto/twofish.lo crypto/x509.lo crypto/xtea.lo \
-       crypto/openpgp/armor.lo crypto/openpgp/error.lo \
-       crypto/openpgp/packet.lo crypto/openpgp/s2k.lo debug/dwarf.lo \
-       debug/elf.lo debug/gosym.lo debug/macho.lo debug/pe.lo \
-       debug/proc.lo encoding/ascii85.lo encoding/base32.lo \
-       encoding/base64.lo encoding/binary.lo encoding/git85.lo \
-       encoding/hex.lo encoding/line.lo encoding/pem.lo \
-       exp/datafmt.lo exp/draw.lo exp/eval.lo go/ast.lo go/doc.lo \
-       go/parser.lo go/printer.lo go/scanner.lo go/token.lo \
-       go/typechecker.lo hash/adler32.lo hash/crc32.lo hash/crc64.lo \
-       hash/fnv.lo http/cgi.lo http/httptest.lo http/pprof.lo \
-       image/jpeg.lo image/png.lo index/suffixarray.lo io/ioutil.lo \
-       mime/multipart.lo net/dict.lo net/textproto.lo \
-       $(am__DEPENDENCIES_1) os/signal.lo path/filepath.lo \
-       rpc/jsonrpc.lo runtime/debug.lo runtime/pprof.lo \
-       sync/atomic.lo sync/atomic_c.lo syscalls/syscall.lo \
-       syscalls/errno.lo testing/testing.lo testing/iotest.lo \
-       testing/quick.lo testing/script.lo
+       container/vector.lo crypto/aes.lo crypto/blowfish.lo \
+       crypto/cast5.lo crypto/cipher.lo crypto/des.lo crypto/dsa.lo \
+       crypto/ecdsa.lo crypto/elliptic.lo crypto/hmac.lo \
+       crypto/md4.lo crypto/md5.lo crypto/ocsp.lo crypto/openpgp.lo \
+       crypto/rand.lo crypto/rc4.lo crypto/ripemd160.lo crypto/rsa.lo \
+       crypto/sha1.lo crypto/sha256.lo crypto/sha512.lo \
+       crypto/subtle.lo crypto/tls.lo crypto/twofish.lo \
+       crypto/x509.lo crypto/xtea.lo crypto/openpgp/armor.lo \
+       crypto/openpgp/error.lo crypto/openpgp/packet.lo \
+       crypto/openpgp/s2k.lo debug/dwarf.lo debug/elf.lo \
+       debug/gosym.lo debug/macho.lo debug/pe.lo debug/proc.lo \
+       encoding/ascii85.lo encoding/base32.lo encoding/base64.lo \
+       encoding/binary.lo encoding/git85.lo encoding/hex.lo \
+       encoding/line.lo encoding/pem.lo exp/datafmt.lo exp/draw.lo \
+       exp/eval.lo go/ast.lo go/doc.lo go/parser.lo go/printer.lo \
+       go/scanner.lo go/token.lo go/typechecker.lo hash/adler32.lo \
+       hash/crc32.lo hash/crc64.lo hash/fnv.lo http/cgi.lo \
+       http/httptest.lo http/pprof.lo image/jpeg.lo image/png.lo \
+       index/suffixarray.lo io/ioutil.lo mime/multipart.lo \
+       net/dict.lo net/textproto.lo $(am__DEPENDENCIES_1) \
+       os/signal.lo path/filepath.lo rpc/jsonrpc.lo runtime/debug.lo \
+       runtime/pprof.lo sync/atomic.lo sync/atomic_c.lo \
+       syscalls/syscall.lo syscalls/errno.lo testing/testing.lo \
+       testing/iotest.lo testing/quick.lo testing/script.lo
 libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
        $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
        $(am__DEPENDENCIES_1)
@@ -624,10 +623,10 @@ toolexeclibgocontainer_DATA = \
 toolexeclibgocryptodir = $(toolexeclibgodir)/crypto
 toolexeclibgocrypto_DATA = \
        crypto/aes.gox \
-       crypto/block.gox \
        crypto/blowfish.gox \
        crypto/cast5.gox \
        crypto/cipher.gox \
+       crypto/des.gox \
        crypto/dsa.gox \
        crypto/ecdsa.gox \
        crypto/elliptic.gox \
@@ -1087,9 +1086,12 @@ go_os_files = \
        go/os/env.go \
        go/os/env_unix.go \
        go/os/error.go \
+       go/os/error_posix.go \
        go/os/exec.go \
+       go/os/exec_posix.go \
        go/os/exec_unix.go \
        go/os/file.go \
+       go/os/file_posix.go \
        go/os/file_unix.go \
        go/os/getwd.go \
        go/os/path.go \
@@ -1279,17 +1281,6 @@ go_crypto_aes_files = \
        go/crypto/aes/cipher.go \
        go/crypto/aes/const.go
 
-go_crypto_block_files = \
-       go/crypto/block/cbc.go \
-       go/crypto/block/cfb.go \
-       go/crypto/block/cmac.go \
-       go/crypto/block/cipher.go \
-       go/crypto/block/ctr.go \
-       go/crypto/block/eax.go \
-       go/crypto/block/ecb.go \
-       go/crypto/block/ofb.go \
-       go/crypto/block/xor.go
-
 go_crypto_blowfish_files = \
        go/crypto/blowfish/block.go \
        go/crypto/blowfish/const.go \
@@ -1307,6 +1298,11 @@ go_crypto_cipher_files = \
        go/crypto/cipher/ocfb.go \
        go/crypto/cipher/ofb.go
 
+go_crypto_des_files = \
+       go/crypto/des/block.go \
+       go/crypto/des/cipher.go \
+       go/crypto/des/const.go
+
 go_crypto_dsa_files = \
        go/crypto/dsa/dsa.go
 
@@ -1766,10 +1762,10 @@ libgo_go_objs = \
        container/ring.lo \
        container/vector.lo \
        crypto/aes.lo \
-       crypto/block.lo \
        crypto/blowfish.lo \
        crypto/cast5.lo \
        crypto/cipher.lo \
+       crypto/des.lo \
        crypto/dsa.lo \
        crypto/ecdsa.lo \
        crypto/elliptic.lo \
@@ -2008,10 +2004,10 @@ TEST_PACKAGES = \
        container/ring/check \
        container/vector/check \
        crypto/aes/check \
-       crypto/block/check \
        crypto/blowfish/check \
        crypto/cast5/check \
        crypto/cipher/check \
+       crypto/des/check \
        crypto/dsa/check \
        crypto/ecdsa/check \
        crypto/elliptic/check \
@@ -4436,13 +4432,6 @@ crypto/aes/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: crypto/aes/check
 
-crypto/block.lo: $(go_crypto_block_files) fmt.gox io.gox os.gox strconv.gox
-       $(BUILDPACKAGE)
-crypto/block/check: $(CHECK_DEPS)
-       @$(MKDIR_P) crypto/block
-       @$(CHECK)
-.PHONY: crypto/block/check
-
 crypto/blowfish.lo: $(go_crypto_blowfish_files) os.gox strconv.gox
        $(BUILDPACKAGE)
 crypto/blowfish/check: $(CHECK_DEPS)
@@ -4464,6 +4453,13 @@ crypto/cipher/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: crypto/cipher/check
 
+crypto/des.lo: $(go_crypto_des_files) encoding/binary.gox os.gox strconv.gox
+       $(BUILDPACKAGE)
+crypto/des/check: $(CHECK_DEPS)
+       @$(MKDIR_P) crypto/des
+       @$(CHECK)
+.PHONY: crypto/des/check
+
 crypto/dsa.lo: $(go_crypto_dsa_files) big.gox io.gox os.gox
        $(BUILDPACKAGE)
 crypto/dsa/check: $(CHECK_DEPS)
@@ -4549,7 +4545,8 @@ crypto/ripemd160/check: $(CHECK_DEPS)
 .PHONY: crypto/ripemd160/check
 
 crypto/rsa.lo: $(go_crypto_rsa_files) big.gox crypto.gox crypto/sha1.gox \
-               crypto/subtle.gox encoding/hex.gox hash.gox io.gox os.gox
+               crypto/subtle.gox encoding/hex.gox hash.gox io.gox os.gox \
+               sync.gox
        $(BUILDPACKAGE)
 crypto/rsa/check: $(CHECK_DEPS)
        @$(MKDIR_P) crypto/rsa
@@ -4885,8 +4882,8 @@ http/cgi/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: http/cgi/check
 
-http/httptest.lo: $(go_http_httptest_files) bytes.gox fmt.gox http.gox \
-               net.gox os.gox
+http/httptest.lo: $(go_http_httptest_files) bytes.gox crypto/rand.gox \
+               crypto/tls.gox fmt.gox http.gox net.gox os.gox time.gox
        $(BUILDPACKAGE)
 http/httptest/check: $(CHECK_DEPS)
        @$(MKDIR_P) http/httptest
@@ -5172,14 +5169,14 @@ container/vector.gox: container/vector.lo
 
 crypto/aes.gox: crypto/aes.lo
        $(BUILDGOX)
-crypto/block.gox: crypto/block.lo
-       $(BUILDGOX)
 crypto/blowfish.gox: crypto/blowfish.lo
        $(BUILDGOX)
 crypto/cast5.gox: crypto/cast5.lo
        $(BUILDGOX)
 crypto/cipher.gox: crypto/cipher.lo
        $(BUILDGOX)
+crypto/des.gox: crypto/des.lo
+       $(BUILDGOX)
 crypto/dsa.gox: crypto/dsa.lo
        $(BUILDGOX)
 crypto/ecdsa.gox: crypto/ecdsa.lo      
index 35a15f74bb1fd045e244637cc351482ec27bf5f5..1b41196a999a03344957477e906bbffaae958aae 100644 (file)
@@ -95,7 +95,7 @@ func (tr *Reader) skipUnread() {
        nr := tr.nb + tr.pad // number of bytes to skip
        tr.nb, tr.pad = 0, 0
        if sr, ok := tr.r.(io.Seeker); ok {
-               if _, err := sr.Seek(nr, 1); err == nil {
+               if _, err := sr.Seek(nr, os.SEEK_CUR); err == nil {
                        return
                }
        }
index aa4c797fb6a6535f36dff7de7b912417feea7148..32fc8f9151a61addfece5f36c7b01c9a5523ed46 100644 (file)
@@ -113,7 +113,7 @@ var untarTests = []*untarTest{
 func TestReader(t *testing.T) {
 testLoop:
        for i, test := range untarTests {
-               f, err := os.Open(test.file, os.O_RDONLY, 0444)
+               f, err := os.Open(test.file)
                if err != nil {
                        t.Errorf("test %d: Unexpected error: %v", i, err)
                        continue
@@ -143,7 +143,7 @@ testLoop:
 }
 
 func TestPartialRead(t *testing.T) {
-       f, err := os.Open("testdata/gnu.tar", os.O_RDONLY, 0444)
+       f, err := os.Open("testdata/gnu.tar")
        if err != nil {
                t.Fatalf("Unexpected error: %v", err)
        }
@@ -181,7 +181,7 @@ func TestPartialRead(t *testing.T) {
 
 func TestIncrementalRead(t *testing.T) {
        test := gnuTarTest
-       f, err := os.Open(test.file, os.O_RDONLY, 0444)
+       f, err := os.Open(test.file)
        if err != nil {
                t.Fatalf("Unexpected error: %v", err)
        }
@@ -235,7 +235,7 @@ func TestIncrementalRead(t *testing.T) {
 
 func TestNonSeekable(t *testing.T) {
        test := gnuTarTest
-       f, err := os.Open(test.file, os.O_RDONLY, 0444)
+       f, err := os.Open(test.file)
        if err != nil {
                t.Fatalf("Unexpected error: %v", err)
        }
index 3b265c9b72e6fe99cf50fb88ee13fabd44400a77..543007abfe058405b931cf41d2ab7fddc338ce83 100644 (file)
@@ -49,7 +49,7 @@ func (f *File) hasDataDescriptor() bool {
 
 // OpenReader will open the Zip file specified by name and return a Reader.
 func OpenReader(name string) (*Reader, os.Error) {
-       f, err := os.Open(name, os.O_RDONLY, 0644)
+       f, err := os.Open(name)
        if err != nil {
                return nil, err
        }
@@ -73,7 +73,7 @@ func NewReader(r io.ReaderAt, size int64) (*Reader, os.Error) {
                Comment: end.comment,
        }
        rs := io.NewSectionReader(r, 0, size)
-       if _, err = rs.Seek(int64(end.directoryOffset), 0); err != nil {
+       if _, err = rs.Seek(int64(end.directoryOffset), os.SEEK_SET); err != nil {
                return nil, err
        }
        buf := bufio.NewReader(rs)
@@ -94,7 +94,7 @@ func (f *File) Open() (rc io.ReadCloser, err os.Error) {
                if err = readFileHeader(f, r); err != nil {
                        return
                }
-               if f.bodyOffset, err = r.Seek(0, 1); err != nil {
+               if f.bodyOffset, err = r.Seek(0, os.SEEK_CUR); err != nil {
                        return
                }
        }
index eae5c5ce9754e094ee85e1a92d074ba26d976e88..cd08be31b6ac93f65eda92cd9cd539f14190c4f1 100644 (file)
@@ -415,38 +415,27 @@ func (b *Writer) Buffered() int { return b.n }
 // If nn < len(p), it also returns an error explaining
 // why the write is short.
 func (b *Writer) Write(p []byte) (nn int, err os.Error) {
-       if b.err != nil {
-               return 0, b.err
-       }
-       nn = 0
-       for len(p) > 0 {
-               n := b.Available()
-               if n <= 0 {
-                       if b.Flush(); b.err != nil {
-                               break
-                       }
-                       n = b.Available()
-               }
-               if b.Buffered() == 0 && len(p) >= len(b.buf) {
+       for len(p) > b.Available() && b.err == nil {
+               var n int
+               if b.Buffered() == 0 {
                        // Large write, empty buffer.
                        // Write directly from p to avoid copy.
                        n, b.err = b.wr.Write(p)
-                       nn += n
-                       p = p[n:]
-                       if b.err != nil {
-                               break
-                       }
-                       continue
-               }
-               if n > len(p) {
-                       n = len(p)
+               } else {
+                       n = copy(b.buf[b.n:], p)
+                       b.n += n
+                       b.Flush()
                }
-               copy(b.buf[b.n:b.n+n], p[0:n])
-               b.n += n
                nn += n
                p = p[n:]
        }
-       return nn, b.err
+       if b.err != nil {
+               return nn, b.err
+       }
+       n := copy(b.buf[b.n:], p)
+       b.n += n
+       nn += n
+       return nn, nil
 }
 
 // WriteByte writes a single byte.
@@ -496,24 +485,21 @@ func (b *Writer) WriteRune(rune int) (size int, err os.Error) {
 // If the count is less than len(s), it also returns an error explaining
 // why the write is short.
 func (b *Writer) WriteString(s string) (int, os.Error) {
-       if b.err != nil {
-               return 0, b.err
-       }
-       // Common case, worth making fast.
-       if b.Available() >= len(s) || len(b.buf) >= len(s) && b.Flush() == nil {
-               for i := 0; i < len(s); i++ { // loop over bytes, not runes.
-                       b.buf[b.n] = s[i]
-                       b.n++
-               }
-               return len(s), nil
+       nn := 0
+       for len(s) > b.Available() && b.err == nil {
+               n := copy(b.buf[b.n:], s)
+               b.n += n
+               nn += n
+               s = s[n:]
+               b.Flush()
        }
-       for i := 0; i < len(s); i++ { // loop over bytes, not runes.
-               b.WriteByte(s[i])
-               if b.err != nil {
-                       return i, b.err
-               }
+       if b.err != nil {
+               return nn, b.err
        }
-       return len(s), nil
+       n := copy(b.buf[b.n:], s)
+       b.n += n
+       nn += n
+       return nn, nil
 }
 
 // buffered input and output
index 2e0a8de0a87f84124d3c754b8b7831177b7de479..e5815a03d5d628353ac33dca133217f3c24d0308 100644 (file)
@@ -21,7 +21,7 @@ var filenames = []string{
 // the given options yields equivalent bytes to the original file.
 func testFile(t *testing.T, fn string, order Order, litWidth int) {
        // Read the file, as golden output.
-       golden, err := os.Open(fn, os.O_RDONLY, 0400)
+       golden, err := os.Open(fn)
        if err != nil {
                t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err)
                return
@@ -29,7 +29,7 @@ func testFile(t *testing.T, fn string, order Order, litWidth int) {
        defer golden.Close()
 
        // Read the file again, and push it through a pipe that compresses at the write end, and decompresses at the read end.
-       raw, err := os.Open(fn, os.O_RDONLY, 0400)
+       raw, err := os.Open(fn)
        if err != nil {
                t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err)
                return
index 5a13ba82573c19097e63a33000cc3a75a36448a4..7eb1cd494978d5e41cc997993980c114e2163aa2 100644 (file)
@@ -20,7 +20,7 @@ var filenames = []string{
 // yields equivalent bytes to the original file.
 func testFileLevel(t *testing.T, fn string, level int) {
        // Read the file, as golden output.
-       golden, err := os.Open(fn, os.O_RDONLY, 0444)
+       golden, err := os.Open(fn)
        if err != nil {
                t.Errorf("%s (level=%d): %v", fn, level, err)
                return
@@ -28,7 +28,7 @@ func testFileLevel(t *testing.T, fn string, level int) {
        defer golden.Close()
 
        // Read the file again, and push it through a pipe that compresses at the write end, and decompresses at the read end.
-       raw, err := os.Open(fn, os.O_RDONLY, 0444)
+       raw, err := os.Open(fn)
        if err != nil {
                t.Errorf("%s (level=%d): %v", fn, level, err)
                return
diff --git a/libgo/go/crypto/block/cbc.go b/libgo/go/crypto/block/cbc.go
deleted file mode 100644 (file)
index 23229c0..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Cipher block chaining (CBC) mode.
-
-// CBC provides confidentiality by xoring (chaining) each plaintext block
-// with the previous ciphertext block before applying the block cipher.
-
-// See NIST SP 800-38A, pp 10-11
-
-package block
-
-import (
-       "io"
-)
-
-type cbcCipher struct {
-       c         Cipher
-       blockSize int
-       iv        []byte
-       tmp       []byte
-}
-
-func newCBC(c Cipher, iv []byte) *cbcCipher {
-       n := c.BlockSize()
-       x := new(cbcCipher)
-       x.c = c
-       x.blockSize = n
-       x.iv = dup(iv)
-       x.tmp = make([]byte, n)
-       return x
-}
-
-func (x *cbcCipher) BlockSize() int { return x.blockSize }
-
-func (x *cbcCipher) Encrypt(dst, src []byte) {
-       for i := 0; i < x.blockSize; i++ {
-               x.iv[i] ^= src[i]
-       }
-       x.c.Encrypt(x.iv, x.iv)
-       for i := 0; i < x.blockSize; i++ {
-               dst[i] = x.iv[i]
-       }
-}
-
-func (x *cbcCipher) Decrypt(dst, src []byte) {
-       x.c.Decrypt(x.tmp, src)
-       for i := 0; i < x.blockSize; i++ {
-               x.tmp[i] ^= x.iv[i]
-               x.iv[i] = src[i]
-               dst[i] = x.tmp[i]
-       }
-}
-
-// NewCBCDecrypter returns a reader that reads data from r and decrypts it using c
-// in cipher block chaining (CBC) mode with the initialization vector iv.
-// The returned Reader does not buffer or read ahead except
-// as required by the cipher's block size.
-func NewCBCDecrypter(c Cipher, iv []byte, r io.Reader) io.Reader {
-       return NewECBDecrypter(newCBC(c, iv), r)
-}
-
-// NewCBCEncrypter returns a writer that encrypts data using c
-// in cipher block chaining (CBC) mode with the initialization vector iv
-// and writes the encrypted data to w.
-// The returned Writer does no buffering except as required
-// by the cipher's block size, so there is no need for a Flush method.
-func NewCBCEncrypter(c Cipher, iv []byte, w io.Writer) io.Writer {
-       return NewECBEncrypter(newCBC(c, iv), w)
-}
diff --git a/libgo/go/crypto/block/cfb.go b/libgo/go/crypto/block/cfb.go
deleted file mode 100644 (file)
index f20c0a0..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Cipher feedback (CFB) mode.
-
-// CFB provides confidentiality by feeding a fraction of
-// the previous ciphertext in as the plaintext for the next
-// block operation.
-
-// See NIST SP 800-38A, pp 11-13
-
-package block
-
-import (
-       "io"
-)
-
-type cfbCipher struct {
-       c          Cipher
-       blockSize  int // our block size (s/8)
-       cipherSize int // underlying cipher block size
-       iv         []byte
-       tmp        []byte
-}
-
-func newCFB(c Cipher, s int, iv []byte) *cfbCipher {
-       if s == 0 || s%8 != 0 {
-               panic("crypto/block: invalid CFB mode")
-       }
-       b := c.BlockSize()
-       x := new(cfbCipher)
-       x.c = c
-       x.blockSize = s / 8
-       x.cipherSize = b
-       x.iv = dup(iv)
-       x.tmp = make([]byte, b)
-       return x
-}
-
-func (x *cfbCipher) BlockSize() int { return x.blockSize }
-
-func (x *cfbCipher) Encrypt(dst, src []byte) {
-       // Encrypt old IV and xor prefix with src to make dst.
-       x.c.Encrypt(x.tmp, x.iv)
-       for i := 0; i < x.blockSize; i++ {
-               dst[i] = src[i] ^ x.tmp[i]
-       }
-
-       // Slide unused IV pieces down and insert dst at end.
-       for i := 0; i < x.cipherSize-x.blockSize; i++ {
-               x.iv[i] = x.iv[i+x.blockSize]
-       }
-       off := x.cipherSize - x.blockSize
-       for i := off; i < x.cipherSize; i++ {
-               x.iv[i] = dst[i-off]
-       }
-}
-
-func (x *cfbCipher) Decrypt(dst, src []byte) {
-       // Encrypt [sic] old IV and xor prefix with src to make dst.
-       x.c.Encrypt(x.tmp, x.iv)
-       for i := 0; i < x.blockSize; i++ {
-               dst[i] = src[i] ^ x.tmp[i]
-       }
-
-       // Slide unused IV pieces down and insert src at top.
-       for i := 0; i < x.cipherSize-x.blockSize; i++ {
-               x.iv[i] = x.iv[i+x.blockSize]
-       }
-       off := x.cipherSize - x.blockSize
-       for i := off; i < x.cipherSize; i++ {
-               // Reconstruct src = dst ^ x.tmp
-               // in case we overwrote src (src == dst).
-               x.iv[i] = dst[i-off] ^ x.tmp[i-off]
-       }
-}
-
-// NewCFBDecrypter returns a reader that reads data from r and decrypts it using c
-// in s-bit cipher feedback (CFB) mode with the initialization vector iv.
-// The returned Reader does not buffer or read ahead except
-// as required by the cipher's block size.
-// Modes for s not a multiple of 8 are unimplemented.
-func NewCFBDecrypter(c Cipher, s int, iv []byte, r io.Reader) io.Reader {
-       return NewECBDecrypter(newCFB(c, s, iv), r)
-}
-
-// NewCFBEncrypter returns a writer that encrypts data using c
-// in s-bit cipher feedback (CFB) mode with the initialization vector iv
-// and writes the encrypted data to w.
-// The returned Writer does no buffering except as required
-// by the cipher's block size, so there is no need for a Flush method.
-// Modes for s not a multiple of 8 are unimplemented.
-func NewCFBEncrypter(c Cipher, s int, iv []byte, w io.Writer) io.Writer {
-       return NewECBEncrypter(newCFB(c, s, iv), w)
-}
diff --git a/libgo/go/crypto/block/cfb_aes_test.go b/libgo/go/crypto/block/cfb_aes_test.go
deleted file mode 100644 (file)
index e400c18..0000000
+++ /dev/null
@@ -1,311 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// CFB AES test vectors.
-
-// See U.S. National Institute of Standards and Technology (NIST)
-// Special Publication 800-38A, ``Recommendation for Block Cipher
-// Modes of Operation,'' 2001 Edition, pp. 29-52.
-
-package block
-
-import (
-       "bytes"
-       "crypto/aes"
-       "io"
-       "testing"
-)
-
-type cfbTest struct {
-       name string
-       s    int
-       key  []byte
-       iv   []byte
-       in   []byte
-       out  []byte
-}
-
-var cfbAESTests = []cfbTest{
-       {
-               "CFB1-AES128",
-               1,
-               commonKey128,
-               commonIV,
-               []byte{
-                       0<<7 | 1<<6 | 1<<5 | 0<<4 | 1<<3 | 0<<2 | 1<<1,
-                       1<<7 | 1<<6 | 0<<5 | 0<<4 | 0<<3 | 0<<2 | 0<<1,
-               },
-               []byte{
-                       0<<7 | 1<<6 | 1<<5 | 0<<4 | 1<<3 | 0<<2 | 0<<1,
-                       1<<7 | 0<<6 | 1<<5 | 1<<4 | 0<<3 | 0<<2 | 1<<1,
-               },
-       },
-       {
-               "CFB1-AES192",
-               1,
-               commonKey192,
-               commonIV,
-               []byte{
-                       0<<7 | 1<<6 | 1<<5 | 0<<4 | 1<<3 | 0<<2 | 1<<1,
-                       1<<7 | 1<<6 | 0<<5 | 0<<4 | 0<<3 | 0<<2 | 0<<1,
-               },
-               []byte{
-                       1<<7 | 0<<6 | 0<<5 | 1<<4 | 0<<3 | 0<<2 | 1<<1,
-                       0<<7 | 1<<6 | 0<<5 | 1<<4 | 1<<3 | 0<<2 | 0<<1,
-               },
-       },
-       {
-               "CFB1-AES256",
-               1,
-               commonKey256,
-               commonIV,
-               []byte{
-                       0<<7 | 1<<6 | 1<<5 | 0<<4 | 1<<3 | 0<<2 | 1<<1,
-                       1<<7 | 1<<6 | 0<<5 | 0<<4 | 0<<3 | 0<<2 | 0<<1,
-               },
-               []byte{
-                       1<<7 | 0<<6 | 0<<5 | 1<<4 | 0<<3 | 0<<2 | 0<<1,
-                       0<<7 | 0<<6 | 1<<5 | 0<<4 | 1<<3 | 0<<2 | 0<<1,
-               },
-       },
-
-       {
-               "CFB8-AES128",
-               8,
-               commonKey128,
-               commonIV,
-               []byte{
-                       0x6b,
-                       0xc1,
-                       0xbe,
-                       0xe2,
-                       0x2e,
-                       0x40,
-                       0x9f,
-                       0x96,
-                       0xe9,
-                       0x3d,
-                       0x7e,
-                       0x11,
-                       0x73,
-                       0x93,
-                       0x17,
-                       0x2a,
-                       0xae,
-                       0x2d,
-               },
-               []byte{
-                       0x3b,
-                       0x79,
-                       0x42,
-                       0x4c,
-                       0x9c,
-                       0x0d,
-                       0xd4,
-                       0x36,
-                       0xba,
-                       0xce,
-                       0x9e,
-                       0x0e,
-                       0xd4,
-                       0x58,
-                       0x6a,
-                       0x4f,
-                       0x32,
-                       0xb9,
-               },
-       },
-
-       {
-               "CFB8-AES192",
-               8,
-               commonKey192,
-               commonIV,
-               []byte{
-                       0x6b,
-                       0xc1,
-                       0xbe,
-                       0xe2,
-                       0x2e,
-                       0x40,
-                       0x9f,
-                       0x96,
-                       0xe9,
-                       0x3d,
-                       0x7e,
-                       0x11,
-                       0x73,
-                       0x93,
-                       0x17,
-                       0x2a,
-                       0xae,
-                       0x2d,
-               },
-               []byte{
-                       0xcd,
-                       0xa2,
-                       0x52,
-                       0x1e,
-                       0xf0,
-                       0xa9,
-                       0x05,
-                       0xca,
-                       0x44,
-                       0xcd,
-                       0x05,
-                       0x7c,
-                       0xbf,
-                       0x0d,
-                       0x47,
-                       0xa0,
-                       0x67,
-                       0x8a,
-               },
-       },
-
-       {
-               "CFB8-AES256",
-               8,
-               commonKey256,
-               commonIV,
-               []byte{
-                       0x6b,
-                       0xc1,
-                       0xbe,
-                       0xe2,
-                       0x2e,
-                       0x40,
-                       0x9f,
-                       0x96,
-                       0xe9,
-                       0x3d,
-                       0x7e,
-                       0x11,
-                       0x73,
-                       0x93,
-                       0x17,
-                       0x2a,
-                       0xae,
-                       0x2d,
-               },
-               []byte{
-                       0xdc,
-                       0x1f,
-                       0x1a,
-                       0x85,
-                       0x20,
-                       0xa6,
-                       0x4d,
-                       0xb5,
-                       0x5f,
-                       0xcc,
-                       0x8a,
-                       0xc5,
-                       0x54,
-                       0x84,
-                       0x4e,
-                       0x88,
-                       0x97,
-                       0x00,
-               },
-       },
-
-       {
-               "CFB128-AES128",
-               128,
-               commonKey128,
-               commonIV,
-               []byte{
-                       0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
-                       0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
-                       0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
-                       0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10,
-               },
-               []byte{
-                       0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20, 0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a,
-                       0xc8, 0xa6, 0x45, 0x37, 0xa0, 0xb3, 0xa9, 0x3f, 0xcd, 0xe3, 0xcd, 0xad, 0x9f, 0x1c, 0xe5, 0x8b,
-                       0x26, 0x75, 0x1f, 0x67, 0xa3, 0xcb, 0xb1, 0x40, 0xb1, 0x80, 0x8c, 0xf1, 0x87, 0xa4, 0xf4, 0xdf,
-                       0xc0, 0x4b, 0x05, 0x35, 0x7c, 0x5d, 0x1c, 0x0e, 0xea, 0xc4, 0xc6, 0x6f, 0x9f, 0xf7, 0xf2, 0xe6,
-               },
-       },
-
-       {
-               "CFB128-AES192",
-               128,
-               commonKey192,
-               commonIV,
-               []byte{
-                       0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
-                       0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
-                       0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
-                       0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10,
-               },
-               []byte{
-                       0xcd, 0xc8, 0x0d, 0x6f, 0xdd, 0xf1, 0x8c, 0xab, 0x34, 0xc2, 0x59, 0x09, 0xc9, 0x9a, 0x41, 0x74,
-                       0x67, 0xce, 0x7f, 0x7f, 0x81, 0x17, 0x36, 0x21, 0x96, 0x1a, 0x2b, 0x70, 0x17, 0x1d, 0x3d, 0x7a,
-                       0x2e, 0x1e, 0x8a, 0x1d, 0xd5, 0x9b, 0x88, 0xb1, 0xc8, 0xe6, 0x0f, 0xed, 0x1e, 0xfa, 0xc4, 0xc9,
-                       0xc0, 0x5f, 0x9f, 0x9c, 0xa9, 0x83, 0x4f, 0xa0, 0x42, 0xae, 0x8f, 0xba, 0x58, 0x4b, 0x09, 0xff,
-               },
-       },
-
-       {
-               "CFB128-AES256",
-               128,
-               commonKey256,
-               commonIV,
-               []byte{
-                       0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
-                       0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
-                       0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
-                       0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10,
-               },
-               []byte{
-                       0xdc, 0x7e, 0x84, 0xbf, 0xda, 0x79, 0x16, 0x4b, 0x7e, 0xcd, 0x84, 0x86, 0x98, 0x5d, 0x38, 0x60,
-                       0x39, 0xff, 0xed, 0x14, 0x3b, 0x28, 0xb1, 0xc8, 0x32, 0x11, 0x3c, 0x63, 0x31, 0xe5, 0x40, 0x7b,
-                       0xdf, 0x10, 0x13, 0x24, 0x15, 0xe5, 0x4b, 0x92, 0xa1, 0x3e, 0xd0, 0xa8, 0x26, 0x7a, 0xe2, 0xf9,
-                       0x75, 0xa3, 0x85, 0x74, 0x1a, 0xb9, 0xce, 0xf8, 0x20, 0x31, 0x62, 0x3d, 0x55, 0xb1, 0xe4, 0x71,
-               },
-       },
-}
-
-func TestCFB_AES(t *testing.T) {
-       for _, tt := range cfbAESTests {
-               test := tt.name
-
-               if tt.s == 1 {
-                       // 1-bit CFB not implemented
-                       continue
-               }
-
-               c, err := aes.NewCipher(tt.key)
-               if err != nil {
-                       t.Errorf("%s: NewCipher(%d bytes) = %s", test, len(tt.key), err)
-                       continue
-               }
-
-               var crypt bytes.Buffer
-               w := NewCFBEncrypter(c, tt.s, tt.iv, &crypt)
-               var r io.Reader = bytes.NewBuffer(tt.in)
-               n, err := io.Copy(w, r)
-               if n != int64(len(tt.in)) || err != nil {
-                       t.Errorf("%s: CFBEncrypter io.Copy = %d, %v want %d, nil", test, n, err, len(tt.in))
-               } else if d := crypt.Bytes(); !same(tt.out, d) {
-                       t.Errorf("%s: CFBEncrypter\nhave %x\nwant %x", test, d, tt.out)
-               }
-
-               var plain bytes.Buffer
-               r = NewCFBDecrypter(c, tt.s, tt.iv, bytes.NewBuffer(tt.out))
-               w = &plain
-               n, err = io.Copy(w, r)
-               if n != int64(len(tt.out)) || err != nil {
-                       t.Errorf("%s: CFBDecrypter io.Copy = %d, %v want %d, nil", test, n, err, len(tt.out))
-               } else if d := plain.Bytes(); !same(tt.in, d) {
-                       t.Errorf("%s: CFBDecrypter\nhave %x\nwant %x", test, d, tt.in)
-               }
-
-               if t.Failed() {
-                       break
-               }
-       }
-}
diff --git a/libgo/go/crypto/block/cipher.go b/libgo/go/crypto/block/cipher.go
deleted file mode 100644 (file)
index e1099e9..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// The block package is deprecated, use cipher instead.
-// The block package implements standard block cipher modes
-// that can be wrapped around low-level block cipher implementations.
-// See http://csrc.nist.gov/groups/ST/toolkit/BCM/current_modes.html
-// and NIST Special Publication 800-38A.
-package block
-
-// A Cipher represents an implementation of block cipher
-// using a given key.  It provides the capability to encrypt
-// or decrypt individual blocks.  The mode implementations
-// extend that capability to streams of blocks.
-type Cipher interface {
-       // BlockSize returns the cipher's block size.
-       BlockSize() int
-
-       // Encrypt encrypts the first block in src into dst.
-       // Src and dst may point at the same memory.
-       Encrypt(dst, src []byte)
-
-       // Decrypt decrypts the first block in src into dst.
-       // Src and dst may point at the same memory.
-       Decrypt(dst, src []byte)
-}
-
-// Utility routines
-
-func shift1(dst, src []byte) byte {
-       var b byte
-       for i := len(src) - 1; i >= 0; i-- {
-               bb := src[i] >> 7
-               dst[i] = src[i]<<1 | b
-               b = bb
-       }
-       return b
-}
-
-func same(p, q []byte) bool {
-       if len(p) != len(q) {
-               return false
-       }
-       for i := 0; i < len(p); i++ {
-               if p[i] != q[i] {
-                       return false
-               }
-       }
-       return true
-}
-
-func dup(p []byte) []byte {
-       q := make([]byte, len(p))
-       copy(q, p)
-       return q
-}
diff --git a/libgo/go/crypto/block/cmac.go b/libgo/go/crypto/block/cmac.go
deleted file mode 100644 (file)
index b85cde7..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// CMAC message authentication code, defined in
-// NIST Special Publication SP 800-38B.
-
-package block
-
-import (
-       "hash"
-       "os"
-)
-
-const (
-       // minimal irreducible polynomial of degree b
-       r64  = 0x1b
-       r128 = 0x87
-)
-
-type cmac struct {
-       k1, k2, ci, digest []byte
-       p                  int // position in ci
-       c                  Cipher
-}
-
-// TODO(rsc): Should this return an error instead of panic?
-
-// NewCMAC returns a new instance of a CMAC message authentication code
-// digest using the given Cipher.
-func NewCMAC(c Cipher) hash.Hash {
-       var r byte
-       n := c.BlockSize()
-       switch n {
-       case 64 / 8:
-               r = r64
-       case 128 / 8:
-               r = r128
-       default:
-               panic("crypto/block: NewCMAC: invalid cipher block size")
-       }
-
-       d := new(cmac)
-       d.c = c
-       d.k1 = make([]byte, n)
-       d.k2 = make([]byte, n)
-       d.ci = make([]byte, n)
-       d.digest = make([]byte, n)
-
-       // Subkey generation, p. 7
-       c.Encrypt(d.k1, d.k1)
-       if shift1(d.k1, d.k1) != 0 {
-               d.k1[n-1] ^= r
-       }
-       if shift1(d.k2, d.k1) != 0 {
-               d.k2[n-1] ^= r
-       }
-
-       return d
-}
-
-// Reset clears the digest state, starting a new digest.
-func (d *cmac) Reset() {
-       for i := range d.ci {
-               d.ci[i] = 0
-       }
-       d.p = 0
-}
-
-// Write adds the given data to the digest state.
-func (d *cmac) Write(p []byte) (n int, err os.Error) {
-       // Xor input into ci.
-       for _, c := range p {
-               // If ci is full, encrypt and start over.
-               if d.p >= len(d.ci) {
-                       d.c.Encrypt(d.ci, d.ci)
-                       d.p = 0
-               }
-               d.ci[d.p] ^= c
-               d.p++
-       }
-       return len(p), nil
-}
-
-// Sum returns the CMAC digest, one cipher block in length,
-// of the data written with Write.
-func (d *cmac) Sum() []byte {
-       // Finish last block, mix in key, encrypt.
-       // Don't edit ci, in case caller wants
-       // to keep digesting after call to Sum.
-       k := d.k1
-       if d.p < len(d.digest) {
-               k = d.k2
-       }
-       for i := 0; i < len(d.ci); i++ {
-               d.digest[i] = d.ci[i] ^ k[i]
-       }
-       if d.p < len(d.digest) {
-               d.digest[d.p] ^= 0x80
-       }
-       d.c.Encrypt(d.digest, d.digest)
-       return d.digest
-}
-
-func (d *cmac) Size() int { return len(d.digest) }
diff --git a/libgo/go/crypto/block/cmac_aes_test.go b/libgo/go/crypto/block/cmac_aes_test.go
deleted file mode 100644 (file)
index 0a4a1a4..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// CMAC test vectors.  See NIST SP 800-38B, Appendix D.
-
-package block
-
-import (
-       "crypto/aes"
-       "testing"
-)
-
-type cmacAESTest struct {
-       key    []byte
-       in     []byte
-       digest []byte
-}
-
-var cmacAESTests = []cmacAESTest{
-       {
-               commonKey128,
-               nil,
-               []byte{0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46},
-       },
-       {
-               commonKey128,
-               []byte{0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a},
-               []byte{0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c},
-       },
-       {
-               commonKey128,
-               []byte{
-                       0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
-                       0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
-                       0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
-               },
-               []byte{0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30, 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27},
-       },
-       {
-               commonKey128,
-               []byte{
-                       0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
-                       0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
-                       0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
-                       0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10,
-               },
-               []byte{0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe},
-       },
-       {
-               commonKey192,
-               nil,
-               []byte{0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5, 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67},
-       },
-       {
-               commonKey192,
-               []byte{0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a},
-               []byte{0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90, 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84},
-       },
-       {
-               commonKey192,
-               []byte{
-                       0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
-                       0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
-                       0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
-               },
-               []byte{0x8a, 0x1d, 0xe5, 0xbe, 0x2e, 0xb3, 0x1a, 0xad, 0x08, 0x9a, 0x82, 0xe6, 0xee, 0x90, 0x8b, 0x0e},
-       },
-       {
-               commonKey192,
-               []byte{
-                       0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
-                       0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
-                       0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
-                       0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10,
-               },
-               []byte{0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79, 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11},
-       },
-       {
-               commonKey256,
-               nil,
-               []byte{0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e, 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83},
-       },
-       {
-               commonKey256,
-               []byte{0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a},
-               []byte{0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82, 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c},
-       },
-       {
-               commonKey256,
-               []byte{
-                       0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
-                       0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
-                       0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
-               },
-               []byte{0xaa, 0xf3, 0xd8, 0xf1, 0xde, 0x56, 0x40, 0xc2, 0x32, 0xf5, 0xb1, 0x69, 0xb9, 0xc9, 0x11, 0xe6},
-       },
-       {
-               commonKey256,
-               []byte{
-                       0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
-                       0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
-                       0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
-                       0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10,
-               },
-               []byte{0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5, 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10},
-       },
-}
-
-func TestCMAC_AES(t *testing.T) {
-       for i, tt := range cmacAESTests {
-               c, err := aes.NewCipher(tt.key)
-               if err != nil {
-                       t.Errorf("test %d: NewCipher: %s", i, err)
-                       continue
-               }
-               d := NewCMAC(c)
-               n, err := d.Write(tt.in)
-               if err != nil || n != len(tt.in) {
-                       t.Errorf("test %d: Write %d: %d, %s", i, len(tt.in), n, err)
-                       continue
-               }
-               sum := d.Sum()
-               if !same(sum, tt.digest) {
-                       x := d.(*cmac)
-                       t.Errorf("test %d: digest mismatch\n\twant %x\n\thave %x\n\tk1 %x\n\tk2 %x", i, tt.digest, sum, x.k1, x.k2)
-                       continue
-               }
-       }
-}
diff --git a/libgo/go/crypto/block/ctr.go b/libgo/go/crypto/block/ctr.go
deleted file mode 100644 (file)
index 5d65c0c..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Counter (CTR) mode.
-
-// CTR converts a block cipher into a stream cipher by
-// repeatedly encrypting an incrementing counter and
-// xoring the resulting stream of data with the input.
-
-// See NIST SP 800-38A, pp 13-15
-
-package block
-
-import (
-       "io"
-)
-
-type ctrStream struct {
-       c   Cipher
-       ctr []byte
-       out []byte
-}
-
-func newCTRStream(c Cipher, ctr []byte) *ctrStream {
-       x := new(ctrStream)
-       x.c = c
-       x.ctr = dup(ctr)
-       x.out = make([]byte, len(ctr))
-       return x
-}
-
-func (x *ctrStream) Next() []byte {
-       // Next block is encryption of counter.
-       x.c.Encrypt(x.out, x.ctr)
-
-       // Increment counter
-       for i := len(x.ctr) - 1; i >= 0; i-- {
-               x.ctr[i]++
-               if x.ctr[i] != 0 {
-                       break
-               }
-       }
-
-       return x.out
-}
-
-// NewCTRReader returns a reader that reads data from r, decrypts (or encrypts)
-// it using c in counter (CTR) mode with the initialization vector iv.
-// The returned Reader does not buffer and has no block size.
-// In CTR mode, encryption and decryption are the same operation:
-// a CTR reader applied to an encrypted stream produces a decrypted
-// stream and vice versa.
-func NewCTRReader(c Cipher, iv []byte, r io.Reader) io.Reader {
-       return newXorReader(newCTRStream(c, iv), r)
-}
-
-// NewCTRWriter returns a writer that encrypts (or decrypts) data using c
-// in counter (CTR) mode with the initialization vector iv
-// and writes the encrypted data to w.
-// The returned Writer does not buffer and has no block size.
-// In CTR mode, encryption and decryption are the same operation:
-// a CTR writer applied to an decrypted stream produces an encrypted
-// stream and vice versa.
-func NewCTRWriter(c Cipher, iv []byte, w io.Writer) io.Writer {
-       return newXorWriter(newCTRStream(c, iv), w)
-}
diff --git a/libgo/go/crypto/block/eax.go b/libgo/go/crypto/block/eax.go
deleted file mode 100644 (file)
index 3f3b964..0000000
+++ /dev/null
@@ -1,253 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// EAX mode, not a NIST standard (yet).
-// EAX provides encryption and authentication.
-// EAX targets the same uses as NIST's CCM mode,
-// but EAX adds the ability to run in streaming mode.
-
-// See
-// http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/eax/eax-spec.pdf
-// http://www.cs.ucdavis.edu/~rogaway/papers/eax.pdf
-// What those papers call OMAC is now called CMAC.
-
-package block
-
-import (
-       "fmt"
-       "hash"
-       "io"
-       "os"
-)
-
-// An EAXTagError is returned when the message has failed to authenticate,
-// because the tag at the end of the message stream (Read) does not match
-// the tag computed from the message itself (Computed).
-type EAXTagError struct {
-       Read     []byte
-       Computed []byte
-}
-
-func (e *EAXTagError) String() string {
-       return fmt.Sprintf("crypto/block: EAX tag mismatch: read %x but computed %x", e.Read, e.Computed)
-}
-
-func setupEAX(c Cipher, iv, hdr []byte, tagBytes int) (ctrIV, tag []byte, cmac hash.Hash) {
-       n := len(iv)
-       if n != c.BlockSize() {
-               panic(fmt.Sprintln("crypto/block: EAX: iv length", n, "!=", c.BlockSize()))
-       }
-       buf := make([]byte, n) // zeroed
-
-       // tag = CMAC(0 + iv) ^ CMAC(1 + hdr) ^ CMAC(2 + data)
-       cmac = NewCMAC(c)
-       cmac.Write(buf) // 0
-       cmac.Write(iv)
-       sum := cmac.Sum()
-       ctrIV = dup(sum)
-       tag = dup(sum[0:tagBytes])
-
-       cmac.Reset()
-       buf[n-1] = 1
-       cmac.Write(buf) // 1
-       cmac.Write(hdr)
-       sum = cmac.Sum()
-       for i := 0; i < tagBytes; i++ {
-               tag[i] ^= sum[i]
-       }
-
-       cmac.Reset()
-       buf[n-1] = 2 // 2
-       cmac.Write(buf)
-
-       return
-}
-
-func finishEAX(tag []byte, cmac hash.Hash) {
-       // Finish CMAC #2 and xor into tag.
-       sum := cmac.Sum()
-       for i := range tag {
-               tag[i] ^= sum[i]
-       }
-}
-
-// Writer adapter.  Tees writes into both w and cmac.
-// Knows that cmac never returns write errors.
-type cmacWriter struct {
-       w    io.Writer
-       cmac hash.Hash
-}
-
-func (cw *cmacWriter) Write(p []byte) (n int, err os.Error) {
-       n, err = cw.w.Write(p)
-       cw.cmac.Write(p[0:n])
-       return
-}
-
-// An eaxEncrypter implements the EAX encryption mode.
-type eaxEncrypter struct {
-       ctr io.Writer  // CTR encrypter
-       cw  cmacWriter // CTR's output stream
-       tag []byte
-}
-
-// NewEAXEncrypter creates and returns a new EAX encrypter
-// using the given cipher c, initialization vector iv, associated data hdr,
-// and tag length tagBytes.  The encrypter's Write method encrypts
-// the data it receives and writes that data to w.
-// The encrypter's Close method writes a final authenticating tag to w.
-func NewEAXEncrypter(c Cipher, iv []byte, hdr []byte, tagBytes int, w io.Writer) io.WriteCloser {
-       x := new(eaxEncrypter)
-
-       // Create new CTR instance writing to both
-       // w for encrypted output and cmac for digesting.
-       x.cw.w = w
-       var ctrIV []byte
-       ctrIV, x.tag, x.cw.cmac = setupEAX(c, iv, hdr, tagBytes)
-       x.ctr = NewCTRWriter(c, ctrIV, &x.cw)
-       return x
-}
-
-func (x *eaxEncrypter) Write(p []byte) (n int, err os.Error) {
-       return x.ctr.Write(p)
-}
-
-func (x *eaxEncrypter) Close() os.Error {
-       x.ctr = nil // crash if Write is called again
-
-       // Write tag.
-       finishEAX(x.tag, x.cw.cmac)
-       n, err := x.cw.w.Write(x.tag)
-       if n != len(x.tag) && err == nil {
-               err = io.ErrShortWrite
-       }
-
-       return err
-}
-
-// Reader adapter.  Returns data read from r but hangs
-// on to the last len(tag) bytes for itself (returns EOF len(tag)
-// bytes early).  Also tees all data returned from Read into
-// the cmac digest.  The "don't return the last t bytes"
-// and the "tee into digest" functionality could be separated,
-// but the latter half is trivial.
-type cmacReader struct {
-       r    io.Reader
-       cmac hash.Hash
-       tag  []byte
-       tmp  []byte
-}
-
-func (cr *cmacReader) Read(p []byte) (n int, err os.Error) {
-       // TODO(rsc): Maybe fall back to simpler code if
-       // we recognize the underlying r as a ByteBuffer
-       // or ByteReader.  Then we can just take the last piece
-       // off at the start.
-
-       // First, read a tag-sized chunk.
-       // It's probably not the tag (unless there's no data).
-       tag := cr.tag
-       if len(tag) < cap(tag) {
-               nt := len(tag)
-               nn, err1 := io.ReadFull(cr.r, tag[nt:cap(tag)])
-               tag = tag[0 : nt+nn]
-               cr.tag = tag
-               if err1 != nil {
-                       return 0, err1
-               }
-       }
-
-       tagBytes := len(tag)
-       if len(p) > 4*tagBytes {
-               // If p is big, try to read directly into p to avoid a copy.
-               n, err = cr.r.Read(p[tagBytes:])
-               if n == 0 {
-                       goto out
-               }
-               // copy old tag into p
-               for i := 0; i < tagBytes; i++ {
-                       p[i] = tag[i]
-               }
-               // copy new tag out of p
-               for i := 0; i < tagBytes; i++ {
-                       tag[i] = p[n+i]
-               }
-               goto out
-       }
-
-       // Otherwise, read into p and then slide data
-       n, err = cr.r.Read(p)
-       if n == 0 {
-               goto out
-       }
-
-       // copy tag+p into p+tmp and then swap tmp, tag
-       tmp := cr.tmp
-       for i := n + tagBytes - 1; i >= 0; i-- {
-               var c byte
-               if i < tagBytes {
-                       c = tag[i]
-               } else {
-                       c = p[i-tagBytes]
-               }
-               if i < n {
-                       p[i] = c
-               } else {
-                       tmp[i] = c
-               }
-       }
-       cr.tmp, cr.tag = tag, tmp
-
-out:
-       cr.cmac.Write(p[0:n])
-       return
-}
-
-type eaxDecrypter struct {
-       ctr io.Reader
-       cr  cmacReader
-       tag []byte
-}
-
-// NewEAXDecrypter creates and returns a new EAX decrypter
-// using the given cipher c, initialization vector iv, associated data hdr,
-// and tag length tagBytes.  The encrypter's Read method decrypts and
-// returns data read from r.  At r's EOF, the encrypter checks the final
-// authenticating tag and returns an EAXTagError if the tag is invalid.
-// In that case, the message should be discarded.
-// Note that the data stream returned from Read cannot be
-// assumed to be valid, authenticated data until Read returns
-// 0, nil to signal the end of the data.
-func NewEAXDecrypter(c Cipher, iv []byte, hdr []byte, tagBytes int, r io.Reader) io.Reader {
-       x := new(eaxDecrypter)
-
-       x.cr.r = r
-       x.cr.tag = make([]byte, 0, tagBytes)
-       x.cr.tmp = make([]byte, 0, tagBytes)
-       var ctrIV []byte
-       ctrIV, x.tag, x.cr.cmac = setupEAX(c, iv, hdr, tagBytes)
-       x.ctr = NewCTRReader(c, ctrIV, &x.cr)
-       return x
-}
-
-func (x *eaxDecrypter) checkTag() os.Error {
-       x.ctr = nil // crash if Read is called again
-
-       finishEAX(x.tag, x.cr.cmac)
-       if !same(x.tag, x.cr.tag) {
-               e := new(EAXTagError)
-               e.Computed = dup(x.tag)
-               e.Read = dup(x.cr.tag)
-               return e
-       }
-       return nil
-}
-
-func (x *eaxDecrypter) Read(p []byte) (n int, err os.Error) {
-       n, err = x.ctr.Read(p)
-       if n == 0 && err == nil {
-               err = x.checkTag()
-       }
-       return n, err
-}
diff --git a/libgo/go/crypto/block/eax_aes_test.go b/libgo/go/crypto/block/eax_aes_test.go
deleted file mode 100644 (file)
index 93aa771..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package block
-
-import (
-       "bytes"
-       "crypto/aes"
-       "fmt"
-       "io"
-       "testing"
-)
-
-// Test vectors from http://www.cs.ucdavis.edu/~rogaway/papers/eax.pdf
-
-type eaxAESTest struct {
-       msg    []byte
-       key    []byte
-       nonce  []byte
-       header []byte
-       cipher []byte
-}
-
-var eaxAESTests = []eaxAESTest{
-       {
-               []byte{},
-               []byte{0x23, 0x39, 0x52, 0xDE, 0xE4, 0xD5, 0xED, 0x5F, 0x9B, 0x9C, 0x6D, 0x6F, 0xF8, 0x0F, 0xF4, 0x78},
-               []byte{0x62, 0xEC, 0x67, 0xF9, 0xC3, 0xA4, 0xA4, 0x07, 0xFC, 0xB2, 0xA8, 0xC4, 0x90, 0x31, 0xA8, 0xB3},
-               []byte{0x6B, 0xFB, 0x91, 0x4F, 0xD0, 0x7E, 0xAE, 0x6B},
-               []byte{0xE0, 0x37, 0x83, 0x0E, 0x83, 0x89, 0xF2, 0x7B, 0x02, 0x5A, 0x2D, 0x65, 0x27, 0xE7, 0x9D, 0x01},
-       },
-       {
-               []byte{0xF7, 0xFB},
-               []byte{0x91, 0x94, 0x5D, 0x3F, 0x4D, 0xCB, 0xEE, 0x0B, 0xF4, 0x5E, 0xF5, 0x22, 0x55, 0xF0, 0x95, 0xA4},
-               []byte{0xBE, 0xCA, 0xF0, 0x43, 0xB0, 0xA2, 0x3D, 0x84, 0x31, 0x94, 0xBA, 0x97, 0x2C, 0x66, 0xDE, 0xBD},
-               []byte{0xFA, 0x3B, 0xFD, 0x48, 0x06, 0xEB, 0x53, 0xFA},
-               []byte{0x19, 0xDD, 0x5C, 0x4C, 0x93, 0x31, 0x04, 0x9D, 0x0B, 0xDA, 0xB0, 0x27, 0x74, 0x08, 0xF6, 0x79, 0x67, 0xE5},
-       },
-       {
-               []byte{0x1A, 0x47, 0xCB, 0x49, 0x33},
-               []byte{0x01, 0xF7, 0x4A, 0xD6, 0x40, 0x77, 0xF2, 0xE7, 0x04, 0xC0, 0xF6, 0x0A, 0xDA, 0x3D, 0xD5, 0x23},
-               []byte{0x70, 0xC3, 0xDB, 0x4F, 0x0D, 0x26, 0x36, 0x84, 0x00, 0xA1, 0x0E, 0xD0, 0x5D, 0x2B, 0xFF, 0x5E},
-               []byte{0x23, 0x4A, 0x34, 0x63, 0xC1, 0x26, 0x4A, 0xC6},
-               []byte{0xD8, 0x51, 0xD5, 0xBA, 0xE0, 0x3A, 0x59, 0xF2, 0x38, 0xA2, 0x3E, 0x39, 0x19, 0x9D, 0xC9, 0x26, 0x66, 0x26, 0xC4, 0x0F, 0x80},
-       },
-       {
-               []byte{0x48, 0x1C, 0x9E, 0x39, 0xB1},
-               []byte{0xD0, 0x7C, 0xF6, 0xCB, 0xB7, 0xF3, 0x13, 0xBD, 0xDE, 0x66, 0xB7, 0x27, 0xAF, 0xD3, 0xC5, 0xE8},
-               []byte{0x84, 0x08, 0xDF, 0xFF, 0x3C, 0x1A, 0x2B, 0x12, 0x92, 0xDC, 0x19, 0x9E, 0x46, 0xB7, 0xD6, 0x17},
-               []byte{0x33, 0xCC, 0xE2, 0xEA, 0xBF, 0xF5, 0xA7, 0x9D},
-               []byte{0x63, 0x2A, 0x9D, 0x13, 0x1A, 0xD4, 0xC1, 0x68, 0xA4, 0x22, 0x5D, 0x8E, 0x1F, 0xF7, 0x55, 0x93, 0x99, 0x74, 0xA7, 0xBE, 0xDE},
-       },
-       {
-               []byte{0x40, 0xD0, 0xC0, 0x7D, 0xA5, 0xE4},
-               []byte{0x35, 0xB6, 0xD0, 0x58, 0x00, 0x05, 0xBB, 0xC1, 0x2B, 0x05, 0x87, 0x12, 0x45, 0x57, 0xD2, 0xC2},
-               []byte{0xFD, 0xB6, 0xB0, 0x66, 0x76, 0xEE, 0xDC, 0x5C, 0x61, 0xD7, 0x42, 0x76, 0xE1, 0xF8, 0xE8, 0x16},
-               []byte{0xAE, 0xB9, 0x6E, 0xAE, 0xBE, 0x29, 0x70, 0xE9},
-               []byte{0x07, 0x1D, 0xFE, 0x16, 0xC6, 0x75, 0xCB, 0x06, 0x77, 0xE5, 0x36, 0xF7, 0x3A, 0xFE, 0x6A, 0x14, 0xB7, 0x4E, 0xE4, 0x98, 0x44, 0xDD},
-       },
-       {
-               []byte{0x4D, 0xE3, 0xB3, 0x5C, 0x3F, 0xC0, 0x39, 0x24, 0x5B, 0xD1, 0xFB, 0x7D},
-               []byte{0xBD, 0x8E, 0x6E, 0x11, 0x47, 0x5E, 0x60, 0xB2, 0x68, 0x78, 0x4C, 0x38, 0xC6, 0x2F, 0xEB, 0x22},
-               []byte{0x6E, 0xAC, 0x5C, 0x93, 0x07, 0x2D, 0x8E, 0x85, 0x13, 0xF7, 0x50, 0x93, 0x5E, 0x46, 0xDA, 0x1B},
-               []byte{0xD4, 0x48, 0x2D, 0x1C, 0xA7, 0x8D, 0xCE, 0x0F},
-               []byte{0x83, 0x5B, 0xB4, 0xF1, 0x5D, 0x74, 0x3E, 0x35, 0x0E, 0x72, 0x84, 0x14, 0xAB, 0xB8, 0x64, 0x4F, 0xD6, 0xCC, 0xB8, 0x69, 0x47, 0xC5, 0xE1, 0x05, 0x90, 0x21, 0x0A, 0x4F},
-       },
-       {
-               []byte{0x8B, 0x0A, 0x79, 0x30, 0x6C, 0x9C, 0xE7, 0xED, 0x99, 0xDA, 0xE4, 0xF8, 0x7F, 0x8D, 0xD6, 0x16, 0x36},
-               []byte{0x7C, 0x77, 0xD6, 0xE8, 0x13, 0xBE, 0xD5, 0xAC, 0x98, 0xBA, 0xA4, 0x17, 0x47, 0x7A, 0x2E, 0x7D},
-               []byte{0x1A, 0x8C, 0x98, 0xDC, 0xD7, 0x3D, 0x38, 0x39, 0x3B, 0x2B, 0xF1, 0x56, 0x9D, 0xEE, 0xFC, 0x19},
-               []byte{0x65, 0xD2, 0x01, 0x79, 0x90, 0xD6, 0x25, 0x28},
-               []byte{0x02, 0x08, 0x3E, 0x39, 0x79, 0xDA, 0x01, 0x48, 0x12, 0xF5, 0x9F, 0x11, 0xD5, 0x26, 0x30, 0xDA, 0x30, 0x13, 0x73, 0x27, 0xD1, 0x06, 0x49, 0xB0, 0xAA, 0x6E, 0x1C, 0x18, 0x1D, 0xB6, 0x17, 0xD7, 0xF2},
-       },
-       {
-               []byte{0x1B, 0xDA, 0x12, 0x2B, 0xCE, 0x8A, 0x8D, 0xBA, 0xF1, 0x87, 0x7D, 0x96, 0x2B, 0x85, 0x92, 0xDD, 0x2D, 0x56},
-               []byte{0x5F, 0xFF, 0x20, 0xCA, 0xFA, 0xB1, 0x19, 0xCA, 0x2F, 0xC7, 0x35, 0x49, 0xE2, 0x0F, 0x5B, 0x0D},
-               []byte{0xDD, 0xE5, 0x9B, 0x97, 0xD7, 0x22, 0x15, 0x6D, 0x4D, 0x9A, 0xFF, 0x2B, 0xC7, 0x55, 0x98, 0x26},
-               []byte{0x54, 0xB9, 0xF0, 0x4E, 0x6A, 0x09, 0x18, 0x9A},
-               []byte{0x2E, 0xC4, 0x7B, 0x2C, 0x49, 0x54, 0xA4, 0x89, 0xAF, 0xC7, 0xBA, 0x48, 0x97, 0xED, 0xCD, 0xAE, 0x8C, 0xC3, 0x3B, 0x60, 0x45, 0x05, 0x99, 0xBD, 0x02, 0xC9, 0x63, 0x82, 0x90, 0x2A, 0xEF, 0x7F, 0x83, 0x2A},
-       },
-       {
-               []byte{0x6C, 0xF3, 0x67, 0x20, 0x87, 0x2B, 0x85, 0x13, 0xF6, 0xEA, 0xB1, 0xA8, 0xA4, 0x44, 0x38, 0xD5, 0xEF, 0x11},
-               []byte{0xA4, 0xA4, 0x78, 0x2B, 0xCF, 0xFD, 0x3E, 0xC5, 0xE7, 0xEF, 0x6D, 0x8C, 0x34, 0xA5, 0x61, 0x23},
-               []byte{0xB7, 0x81, 0xFC, 0xF2, 0xF7, 0x5F, 0xA5, 0xA8, 0xDE, 0x97, 0xA9, 0xCA, 0x48, 0xE5, 0x22, 0xEC},
-               []byte{0x89, 0x9A, 0x17, 0x58, 0x97, 0x56, 0x1D, 0x7E},
-               []byte{0x0D, 0xE1, 0x8F, 0xD0, 0xFD, 0xD9, 0x1E, 0x7A, 0xF1, 0x9F, 0x1D, 0x8E, 0xE8, 0x73, 0x39, 0x38, 0xB1, 0xE8, 0xE7, 0xF6, 0xD2, 0x23, 0x16, 0x18, 0x10, 0x2F, 0xDB, 0x7F, 0xE5, 0x5F, 0xF1, 0x99, 0x17, 0x00},
-       },
-       {
-               []byte{0xCA, 0x40, 0xD7, 0x44, 0x6E, 0x54, 0x5F, 0xFA, 0xED, 0x3B, 0xD1, 0x2A, 0x74, 0x0A, 0x65, 0x9F, 0xFB, 0xBB, 0x3C, 0xEA, 0xB7},
-               []byte{0x83, 0x95, 0xFC, 0xF1, 0xE9, 0x5B, 0xEB, 0xD6, 0x97, 0xBD, 0x01, 0x0B, 0xC7, 0x66, 0xAA, 0xC3},
-               []byte{0x22, 0xE7, 0xAD, 0xD9, 0x3C, 0xFC, 0x63, 0x93, 0xC5, 0x7E, 0xC0, 0xB3, 0xC1, 0x7D, 0x6B, 0x44},
-               []byte{0x12, 0x67, 0x35, 0xFC, 0xC3, 0x20, 0xD2, 0x5A},
-               []byte{0xCB, 0x89, 0x20, 0xF8, 0x7A, 0x6C, 0x75, 0xCF, 0xF3, 0x96, 0x27, 0xB5, 0x6E, 0x3E, 0xD1, 0x97, 0xC5, 0x52, 0xD2, 0x95, 0xA7, 0xCF, 0xC4, 0x6A, 0xFC, 0x25, 0x3B, 0x46, 0x52, 0xB1, 0xAF, 0x37, 0x95, 0xB1, 0x24, 0xAB, 0x6E},
-       },
-}
-
-func TestEAXEncrypt_AES(t *testing.T) {
-       b := new(bytes.Buffer)
-       for i, tt := range eaxAESTests {
-               test := fmt.Sprintf("test %d", i)
-               c, err := aes.NewCipher(tt.key)
-               if err != nil {
-                       t.Fatalf("%s: NewCipher(%d bytes) = %s", test, len(tt.key), err)
-               }
-               b.Reset()
-               enc := NewEAXEncrypter(c, tt.nonce, tt.header, 16, b)
-               n, err := io.Copy(enc, bytes.NewBuffer(tt.msg))
-               if n != int64(len(tt.msg)) || err != nil {
-                       t.Fatalf("%s: io.Copy into encrypter: %d, %s", test, n, err)
-               }
-               err = enc.Close()
-               if err != nil {
-                       t.Fatalf("%s: enc.Close: %s", test, err)
-               }
-               if d := b.Bytes(); !same(d, tt.cipher) {
-                       t.Fatalf("%s: got %x want %x", test, d, tt.cipher)
-               }
-       }
-}
-
-func TestEAXDecrypt_AES(t *testing.T) {
-       b := new(bytes.Buffer)
-       for i, tt := range eaxAESTests {
-               test := fmt.Sprintf("test %d", i)
-               c, err := aes.NewCipher(tt.key)
-               if err != nil {
-                       t.Fatalf("%s: NewCipher(%d bytes) = %s", test, len(tt.key), err)
-               }
-               b.Reset()
-               dec := NewEAXDecrypter(c, tt.nonce, tt.header, 16, bytes.NewBuffer(tt.cipher))
-               n, err := io.Copy(b, dec)
-               if n != int64(len(tt.msg)) || err != nil {
-                       t.Fatalf("%s: io.Copy into decrypter: %d, %s", test, n, err)
-               }
-               if d := b.Bytes(); !same(d, tt.msg) {
-                       t.Fatalf("%s: got %x want %x", test, d, tt.msg)
-               }
-       }
-}
diff --git a/libgo/go/crypto/block/ecb.go b/libgo/go/crypto/block/ecb.go
deleted file mode 100644 (file)
index cf09f7c..0000000
+++ /dev/null
@@ -1,270 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Electronic codebook (ECB) mode.
-// ECB is a fancy name for ``encrypt and decrypt each block separately.''
-// It's a pretty bad thing to do for any large amount of data (more than one block),
-// because the individual blocks can still be identified, duplicated, and reordered.
-// The ECB implementation exists mainly to provide buffering for
-// the other modes, which wrap it by providing modified Ciphers.
-
-// See NIST SP 800-38A, pp 9-10
-
-package block
-
-import (
-       "io"
-       "os"
-       "strconv"
-)
-
-type ecbDecrypter struct {
-       c         Cipher
-       r         io.Reader
-       blockSize int // block size
-
-       // Buffered data.
-       // The buffer buf is used as storage for both
-       // plain or crypt; at least one of those is nil at any given time.
-       buf   []byte
-       plain []byte // plain text waiting to be read
-       crypt []byte // ciphertext waiting to be decrypted
-}
-
-// Read into x.crypt until it has a full block or EOF or an error happens.
-func (x *ecbDecrypter) fillCrypt() os.Error {
-       var err os.Error
-       for len(x.crypt) < x.blockSize {
-               off := len(x.crypt)
-               var m int
-               m, err = x.r.Read(x.crypt[off:x.blockSize])
-               x.crypt = x.crypt[0 : off+m]
-               if m == 0 {
-                       break
-               }
-
-               // If an error happened but we got enough
-               // data to do some decryption, we can decrypt
-               // first and report the error (with some data) later.
-               // But if we don't have enough to decrypt,
-               // have to stop now.
-               if err != nil && len(x.crypt) < x.blockSize {
-                       break
-               }
-       }
-       return err
-}
-
-// Read from plain text buffer into p.
-func (x *ecbDecrypter) readPlain(p []byte) int {
-       n := len(x.plain)
-       if n > len(p) {
-               n = len(p)
-       }
-       for i := 0; i < n; i++ {
-               p[i] = x.plain[i]
-       }
-       if n < len(x.plain) {
-               x.plain = x.plain[n:]
-       } else {
-               x.plain = nil
-       }
-       return n
-}
-
-type ecbFragmentError int
-
-func (n ecbFragmentError) String() string {
-       return "crypto/block: " + strconv.Itoa(int(n)) + "-byte fragment at EOF"
-}
-
-func (x *ecbDecrypter) Read(p []byte) (n int, err os.Error) {
-       if len(p) == 0 {
-               return
-       }
-
-       // If there's no plaintext waiting and p is not big enough
-       // to hold a whole cipher block, we'll have to work in the
-       // cipher text buffer.  Set it to non-nil so that the
-       // code below will fill it.
-       if x.plain == nil && len(p) < x.blockSize && x.crypt == nil {
-               x.crypt = x.buf[0:0]
-       }
-
-       // If there is a leftover cipher text buffer,
-       // try to accumulate a full block.
-       if x.crypt != nil {
-               err = x.fillCrypt()
-               if err != nil || len(x.crypt) == 0 {
-                       return
-               }
-               x.c.Decrypt(x.crypt, x.crypt)
-               x.plain = x.crypt
-               x.crypt = nil
-       }
-
-       // If there is a leftover plain text buffer, read from it.
-       if x.plain != nil {
-               n = x.readPlain(p)
-               return
-       }
-
-       // Read and decrypt directly in caller's buffer.
-       n, err = io.ReadAtLeast(x.r, p, x.blockSize)
-       if err == os.EOF && n > 0 {
-               // EOF is only okay on block boundary
-               err = os.ErrorString("block fragment at EOF during decryption")
-               return
-       }
-       var i int
-       for i = 0; i+x.blockSize <= n; i += x.blockSize {
-               a := p[i : i+x.blockSize]
-               x.c.Decrypt(a, a)
-       }
-
-       // There might be an encrypted fringe remaining.
-       // Save it for next time.
-       if i < n {
-               p = p[i:n]
-               copy(x.buf, p)
-               x.crypt = x.buf[0:len(p)]
-               n = i
-       }
-
-       return
-}
-
-// NewECBDecrypter returns a reader that reads data from r and decrypts it using c.
-// It decrypts by calling c.Decrypt on each block in sequence;
-// this mode is known as electronic codebook mode, or ECB.
-// The returned Reader does not buffer or read ahead except
-// as required by the cipher's block size.
-func NewECBDecrypter(c Cipher, r io.Reader) io.Reader {
-       x := new(ecbDecrypter)
-       x.c = c
-       x.r = r
-       x.blockSize = c.BlockSize()
-       x.buf = make([]byte, x.blockSize)
-       return x
-}
-
-type ecbEncrypter struct {
-       c         Cipher
-       w         io.Writer
-       blockSize int
-
-       // Buffered data.
-       // The buffer buf is used as storage for both
-       // plain or crypt.  If both are non-nil, plain
-       // follows crypt in buf.
-       buf   []byte
-       plain []byte // plain text waiting to be encrypted
-       crypt []byte // encrypted text waiting to be written
-}
-
-// Flush the x.crypt buffer to x.w.
-func (x *ecbEncrypter) flushCrypt() os.Error {
-       if len(x.crypt) == 0 {
-               return nil
-       }
-       n, err := x.w.Write(x.crypt)
-       if n < len(x.crypt) {
-               x.crypt = x.crypt[n:]
-               if err == nil {
-                       err = io.ErrShortWrite
-               }
-       }
-       if err != nil {
-               return err
-       }
-       x.crypt = nil
-       return nil
-}
-
-// Slide x.plain down to the beginning of x.buf.
-// Plain is known to have less than one block of data,
-// so this is cheap enough.
-func (x *ecbEncrypter) slidePlain() {
-       if len(x.plain) == 0 {
-               x.plain = x.buf[0:0]
-       } else if cap(x.plain) < cap(x.buf) {
-               copy(x.buf, x.plain)
-               x.plain = x.buf[0:len(x.plain)]
-       }
-}
-
-// Fill x.plain from the data in p.
-// Return the number of bytes copied.
-func (x *ecbEncrypter) fillPlain(p []byte) int {
-       off := len(x.plain)
-       n := len(p)
-       if max := cap(x.plain) - off; n > max {
-               n = max
-       }
-       x.plain = x.plain[0 : off+n]
-       for i := 0; i < n; i++ {
-               x.plain[off+i] = p[i]
-       }
-       return n
-}
-
-// Encrypt x.plain; record encrypted range as x.crypt.
-func (x *ecbEncrypter) encrypt() {
-       var i int
-       n := len(x.plain)
-       for i = 0; i+x.blockSize <= n; i += x.blockSize {
-               a := x.plain[i : i+x.blockSize]
-               x.c.Encrypt(a, a)
-       }
-       x.crypt = x.plain[0:i]
-       x.plain = x.plain[i:n]
-}
-
-func (x *ecbEncrypter) Write(p []byte) (n int, err os.Error) {
-       for {
-               // If there is data waiting to be written, write it.
-               // This can happen on the first iteration
-               // if a write failed in an earlier call.
-               if err = x.flushCrypt(); err != nil {
-                       return
-               }
-
-               // Now that encrypted data is gone (flush ran),
-               // perhaps we need to slide the plaintext down.
-               x.slidePlain()
-
-               // Fill plaintext buffer from p.
-               m := x.fillPlain(p)
-               if m == 0 {
-                       break
-               }
-               n += m
-               p = p[m:]
-
-               // Encrypt, adjusting crypt and plain.
-               x.encrypt()
-
-               // Write x.crypt.
-               if err = x.flushCrypt(); err != nil {
-                       break
-               }
-       }
-       return
-}
-
-// NewECBEncrypter returns a writer that encrypts data using c and writes it to w.
-// It encrypts by calling c.Encrypt on each block in sequence;
-// this mode is known as electronic codebook mode, or ECB.
-// The returned Writer does no buffering except as required
-// by the cipher's block size, so there is no need for a Flush method.
-func NewECBEncrypter(c Cipher, w io.Writer) io.Writer {
-       x := new(ecbEncrypter)
-       x.c = c
-       x.w = w
-       x.blockSize = c.BlockSize()
-
-       // Create a buffer that is an integral number of blocks.
-       x.buf = make([]byte, 8192/x.blockSize*x.blockSize)
-       return x
-}
diff --git a/libgo/go/crypto/block/ecb_aes_test.go b/libgo/go/crypto/block/ecb_aes_test.go
deleted file mode 100644 (file)
index 14481d0..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// ECB AES test vectors.
-
-// See U.S. National Institute of Standards and Technology (NIST)
-// Special Publication 800-38A, ``Recommendation for Block Cipher
-// Modes of Operation,'' 2001 Edition, pp. 24-27.
-
-package block
-
-import (
-       "bytes"
-       "crypto/aes"
-       "io"
-       "testing"
-)
-
-type ecbTest struct {
-       name string
-       key  []byte
-       in   []byte
-       out  []byte
-}
-
-var commonInput = []byte{
-       0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
-       0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
-       0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
-       0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10,
-}
-
-var commonKey128 = []byte{0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}
-
-var commonKey192 = []byte{
-       0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
-       0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b,
-}
-
-var commonKey256 = []byte{
-       0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
-       0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4,
-}
-
-var commonIV = []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}
-
-var ecbAESTests = []ecbTest{
-       // FIPS 197, Appendix B, C
-       {
-               "FIPS-197 Appendix B",
-               commonKey128,
-               []byte{0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d, 0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34},
-               []byte{0x39, 0x25, 0x84, 0x1d, 0x02, 0xdc, 0x09, 0xfb, 0xdc, 0x11, 0x85, 0x97, 0x19, 0x6a, 0x0b, 0x32},
-       },
-
-       // NIST SP 800-38A pp 24-27
-       {
-               "ECB-AES128",
-               commonKey128,
-               commonInput,
-               []byte{
-                       0x3a, 0xd7, 0x7b, 0xb4, 0x0d, 0x7a, 0x36, 0x60, 0xa8, 0x9e, 0xca, 0xf3, 0x24, 0x66, 0xef, 0x97,
-                       0xf5, 0xd3, 0xd5, 0x85, 0x03, 0xb9, 0x69, 0x9d, 0xe7, 0x85, 0x89, 0x5a, 0x96, 0xfd, 0xba, 0xaf,
-                       0x43, 0xb1, 0xcd, 0x7f, 0x59, 0x8e, 0xce, 0x23, 0x88, 0x1b, 0x00, 0xe3, 0xed, 0x03, 0x06, 0x88,
-                       0x7b, 0x0c, 0x78, 0x5e, 0x27, 0xe8, 0xad, 0x3f, 0x82, 0x23, 0x20, 0x71, 0x04, 0x72, 0x5d, 0xd4,
-               },
-       },
-       {
-               "ECB-AES192",
-               commonKey192,
-               commonInput,
-               []byte{
-                       0xbd, 0x33, 0x4f, 0x1d, 0x6e, 0x45, 0xf2, 0x5f, 0xf7, 0x12, 0xa2, 0x14, 0x57, 0x1f, 0xa5, 0xcc,
-                       0x97, 0x41, 0x04, 0x84, 0x6d, 0x0a, 0xd3, 0xad, 0x77, 0x34, 0xec, 0xb3, 0xec, 0xee, 0x4e, 0xef,
-                       0xef, 0x7a, 0xfd, 0x22, 0x70, 0xe2, 0xe6, 0x0a, 0xdc, 0xe0, 0xba, 0x2f, 0xac, 0xe6, 0x44, 0x4e,
-                       0x9a, 0x4b, 0x41, 0xba, 0x73, 0x8d, 0x6c, 0x72, 0xfb, 0x16, 0x69, 0x16, 0x03, 0xc1, 0x8e, 0x0e,
-               },
-       },
-       {
-               "ECB-AES256",
-               commonKey256,
-               commonInput,
-               []byte{
-                       0xf3, 0xee, 0xd1, 0xbd, 0xb5, 0xd2, 0xa0, 0x3c, 0x06, 0x4b, 0x5a, 0x7e, 0x3d, 0xb1, 0x81, 0xf8,
-                       0x59, 0x1c, 0xcb, 0x10, 0xd4, 0x10, 0xed, 0x26, 0xdc, 0x5b, 0xa7, 0x4a, 0x31, 0x36, 0x28, 0x70,
-                       0xb6, 0xed, 0x21, 0xb9, 0x9c, 0xa6, 0xf4, 0xf9, 0xf1, 0x53, 0xe7, 0xb1, 0xbe, 0xaf, 0xed, 0x1d,
-                       0x23, 0x30, 0x4b, 0x7a, 0x39, 0xf9, 0xf3, 0xff, 0x06, 0x7d, 0x8d, 0x8f, 0x9e, 0x24, 0xec, 0xc7,
-               },
-       },
-}
-
-func TestECB_AES(t *testing.T) {
-       for _, tt := range ecbAESTests {
-               test := tt.name
-
-               c, err := aes.NewCipher(tt.key)
-               if err != nil {
-                       t.Errorf("%s: NewCipher(%d bytes) = %s", test, len(tt.key), err)
-                       continue
-               }
-
-               var crypt bytes.Buffer
-               w := NewECBEncrypter(c, &crypt)
-               var r io.Reader = bytes.NewBuffer(tt.in)
-               n, err := io.Copy(w, r)
-               if n != int64(len(tt.in)) || err != nil {
-                       t.Errorf("%s: ECBReader io.Copy = %d, %v want %d, nil", test, n, err, len(tt.in))
-               } else if d := crypt.Bytes(); !same(tt.out, d) {
-                       t.Errorf("%s: ECBReader\nhave %x\nwant %x", test, d, tt.out)
-               }
-
-               var plain bytes.Buffer
-               r = NewECBDecrypter(c, bytes.NewBuffer(tt.out))
-               w = &plain
-               n, err = io.Copy(w, r)
-               if n != int64(len(tt.out)) || err != nil {
-                       t.Errorf("%s: ECBWriter io.Copy = %d, %v want %d, nil", test, n, err, len(tt.out))
-               } else if d := plain.Bytes(); !same(tt.in, d) {
-                       t.Errorf("%s: ECBWriter\nhave %x\nwant %x", test, d, tt.in)
-               }
-
-               if t.Failed() {
-                       break
-               }
-       }
-}
diff --git a/libgo/go/crypto/block/ecb_test.go b/libgo/go/crypto/block/ecb_test.go
deleted file mode 100644 (file)
index 6f79d92..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package block
-
-import (
-       "bytes"
-       "fmt"
-       "io"
-       "testing"
-       "testing/iotest"
-)
-
-// Simple Cipher for testing: adds an incrementing amount
-// to each byte in each
-type IncCipher struct {
-       blockSize  int
-       delta      byte
-       encrypting bool
-}
-
-func (c *IncCipher) BlockSize() int { return c.blockSize }
-
-func (c *IncCipher) Encrypt(dst, src []byte) {
-       if !c.encrypting {
-               panic("encrypt: not encrypting")
-       }
-       if len(src) != c.blockSize || len(dst) != c.blockSize {
-               panic(fmt.Sprintln("encrypt: wrong block size", c.blockSize, len(src), len(dst)))
-       }
-       c.delta++
-       for i, b := range src {
-               dst[i] = b + c.delta
-       }
-}
-
-func (c *IncCipher) Decrypt(dst, src []byte) {
-       if c.encrypting {
-               panic("decrypt: not decrypting")
-       }
-       if len(src) != c.blockSize || len(dst) != c.blockSize {
-               panic(fmt.Sprintln("decrypt: wrong block size ", c.blockSize, " ", len(src), " ", len(dst)))
-       }
-       c.delta--
-       for i, b := range src {
-               dst[i] = b + c.delta
-       }
-}
-
-func TestECBEncrypter(t *testing.T) {
-       var plain, crypt [256]byte
-       for i := 0; i < len(plain); i++ {
-               plain[i] = byte(i)
-       }
-       b := new(bytes.Buffer)
-       for block := 1; block <= 64; block *= 2 {
-               // compute encrypted version
-               delta := byte(0)
-               for i := 0; i < len(crypt); i++ {
-                       if i%block == 0 {
-                               delta++
-                       }
-                       crypt[i] = plain[i] + delta
-               }
-
-               for frag := 0; frag < 2; frag++ {
-                       c := &IncCipher{block, 0, true}
-                       b.Reset()
-                       r := bytes.NewBuffer(plain[0:])
-                       w := NewECBEncrypter(c, b)
-
-                       // copy plain into w in increasingly large chunks: 1, 1, 2, 4, 8, ...
-                       // if frag != 0, move the 1 to the end to cause fragmentation.
-                       if frag == 0 {
-                               _, err := io.Copyn(w, r, 1)
-                               if err != nil {
-                                       t.Errorf("block=%d frag=0: first Copyn: %s", block, err)
-                                       continue
-                               }
-                       }
-                       for n := 1; n <= len(plain)/2; n *= 2 {
-                               _, err := io.Copyn(w, r, int64(n))
-                               if err != nil {
-                                       t.Errorf("block=%d frag=%d: Copyn %d: %s", block, frag, n, err)
-                               }
-                       }
-                       if frag != 0 {
-                               _, err := io.Copyn(w, r, 1)
-                               if err != nil {
-                                       t.Errorf("block=%d frag=1: last Copyn: %s", block, err)
-                                       continue
-                               }
-                       }
-
-                       // check output
-                       data := b.Bytes()
-                       if len(data) != len(crypt) {
-                               t.Errorf("block=%d frag=%d: want %d bytes, got %d", block, frag, len(crypt), len(data))
-                               continue
-                       }
-
-                       if string(data) != string(crypt[0:]) {
-                               t.Errorf("block=%d frag=%d: want %x got %x", block, frag, data, crypt)
-                       }
-               }
-       }
-}
-
-func testECBDecrypter(t *testing.T, maxio int) {
-       var readers = []func(io.Reader) io.Reader{
-               func(r io.Reader) io.Reader { return r },
-               iotest.OneByteReader,
-               iotest.HalfReader,
-       }
-       var plain, crypt [256]byte
-       for i := 0; i < len(plain); i++ {
-               plain[i] = byte(255 - i)
-       }
-       b := new(bytes.Buffer)
-       for block := 1; block <= 64 && block <= maxio; block *= 2 {
-               // compute encrypted version
-               delta := byte(0)
-               for i := 0; i < len(crypt); i++ {
-                       if i%block == 0 {
-                               delta++
-                       }
-                       crypt[i] = plain[i] + delta
-               }
-
-               for mode := 0; mode < len(readers); mode++ {
-                       for frag := 0; frag < 2; frag++ {
-                               test := fmt.Sprintf("block=%d mode=%d frag=%d maxio=%d", block, mode, frag, maxio)
-                               c := &IncCipher{block, 0, false}
-                               b.Reset()
-                               r := NewECBDecrypter(c, readers[mode](bytes.NewBuffer(crypt[0:maxio])))
-
-                               // read from crypt in increasingly large chunks: 1, 1, 2, 4, 8, ...
-                               // if frag == 1, move the 1 to the end to cause fragmentation.
-                               if frag == 0 {
-                                       _, err := io.Copyn(b, r, 1)
-                                       if err != nil {
-                                               t.Errorf("%s: first Copyn: %s", test, err)
-                                               continue
-                                       }
-                               }
-                               for n := 1; n <= maxio/2; n *= 2 {
-                                       _, err := io.Copyn(b, r, int64(n))
-                                       if err != nil {
-                                               t.Errorf("%s: Copyn %d: %s", test, n, err)
-                                       }
-                               }
-                               if frag != 0 {
-                                       _, err := io.Copyn(b, r, 1)
-                                       if err != nil {
-                                               t.Errorf("%s: last Copyn: %s", test, err)
-                                               continue
-                                       }
-                               }
-
-                               // check output
-                               data := b.Bytes()
-                               if len(data) != maxio {
-                                       t.Errorf("%s: want %d bytes, got %d", test, maxio, len(data))
-                                       continue
-                               }
-
-                               if string(data) != string(plain[0:maxio]) {
-                                       t.Errorf("%s: input=%x want %x got %x", test, crypt[0:maxio], plain[0:maxio], data)
-                               }
-                       }
-               }
-       }
-}
-
-func TestECBDecrypter(t *testing.T) {
-       // Do shorter I/O sizes first; they're easier to debug.
-       for n := 1; n <= 256 && !t.Failed(); n *= 2 {
-               testECBDecrypter(t, n)
-       }
-}
diff --git a/libgo/go/crypto/block/ofb.go b/libgo/go/crypto/block/ofb.go
deleted file mode 100644 (file)
index 11aaaa4..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Output feedback (OFB) mode.
-
-// OFB converts a block cipher into a stream cipher by
-// repeatedly encrypting an initialization vector and
-// xoring the resulting stream of data with the input.
-
-// See NIST SP 800-38A, pp 13-15
-
-package block
-
-import (
-       "fmt"
-       "io"
-)
-
-type ofbStream struct {
-       c  Cipher
-       iv []byte
-}
-
-func newOFBStream(c Cipher, iv []byte) *ofbStream {
-       x := new(ofbStream)
-       x.c = c
-       n := len(iv)
-       if n != c.BlockSize() {
-               panic(fmt.Sprintln("crypto/block: newOFBStream: invalid iv size", n, "!=", c.BlockSize()))
-       }
-       x.iv = dup(iv)
-       return x
-}
-
-func (x *ofbStream) Next() []byte {
-       x.c.Encrypt(x.iv, x.iv)
-       return x.iv
-}
-
-// NewOFBReader returns a reader that reads data from r, decrypts (or encrypts)
-// it using c in output feedback (OFB) mode with the initialization vector iv.
-// The returned Reader does not buffer and has no block size.
-// In OFB mode, encryption and decryption are the same operation:
-// an OFB reader applied to an encrypted stream produces a decrypted
-// stream and vice versa.
-func NewOFBReader(c Cipher, iv []byte, r io.Reader) io.Reader {
-       return newXorReader(newOFBStream(c, iv), r)
-}
-
-// NewOFBWriter returns a writer that encrypts (or decrypts) data using c
-// in cipher feedback (OFB) mode with the initialization vector iv
-// and writes the encrypted data to w.
-// The returned Writer does not buffer and has no block size.
-// In OFB mode, encryption and decryption are the same operation:
-// an OFB writer applied to an decrypted stream produces an encrypted
-// stream and vice versa.
-func NewOFBWriter(c Cipher, iv []byte, w io.Writer) io.Writer {
-       return newXorWriter(newOFBStream(c, iv), w)
-}
diff --git a/libgo/go/crypto/block/ofb_aes_test.go b/libgo/go/crypto/block/ofb_aes_test.go
deleted file mode 100644 (file)
index 9c527a6..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// OFB AES test vectors.
-
-// See U.S. National Institute of Standards and Technology (NIST)
-// Special Publication 800-38A, ``Recommendation for Block Cipher
-// Modes of Operation,'' 2001 Edition, pp. 52-55.
-
-package block
-
-import (
-       "bytes"
-       "crypto/aes"
-       "io"
-       "testing"
-)
-
-type ofbTest struct {
-       name string
-       key  []byte
-       iv   []byte
-       in   []byte
-       out  []byte
-}
-
-var ofbAESTests = []ofbTest{
-       // NIST SP 800-38A pp 52-55
-       {
-               "OFB-AES128",
-               commonKey128,
-               commonIV,
-               commonInput,
-               []byte{
-                       0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20, 0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a,
-                       0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03, 0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25,
-                       0x97, 0x40, 0x05, 0x1e, 0x9c, 0x5f, 0xec, 0xf6, 0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc,
-                       0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78, 0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e,
-               },
-       },
-       {
-               "OFB-AES192",
-               commonKey192,
-               commonIV,
-               commonInput,
-               []byte{
-                       0xcd, 0xc8, 0x0d, 0x6f, 0xdd, 0xf1, 0x8c, 0xab, 0x34, 0xc2, 0x59, 0x09, 0xc9, 0x9a, 0x41, 0x74,
-                       0xfc, 0xc2, 0x8b, 0x8d, 0x4c, 0x63, 0x83, 0x7c, 0x09, 0xe8, 0x17, 0x00, 0xc1, 0x10, 0x04, 0x01,
-                       0x8d, 0x9a, 0x9a, 0xea, 0xc0, 0xf6, 0x59, 0x6f, 0x55, 0x9c, 0x6d, 0x4d, 0xaf, 0x59, 0xa5, 0xf2,
-                       0x6d, 0x9f, 0x20, 0x08, 0x57, 0xca, 0x6c, 0x3e, 0x9c, 0xac, 0x52, 0x4b, 0xd9, 0xac, 0xc9, 0x2a,
-               },
-       },
-       {
-               "OFB-AES256",
-               commonKey256,
-               commonIV,
-               commonInput,
-               []byte{
-                       0xdc, 0x7e, 0x84, 0xbf, 0xda, 0x79, 0x16, 0x4b, 0x7e, 0xcd, 0x84, 0x86, 0x98, 0x5d, 0x38, 0x60,
-                       0x4f, 0xeb, 0xdc, 0x67, 0x40, 0xd2, 0x0b, 0x3a, 0xc8, 0x8f, 0x6a, 0xd8, 0x2a, 0x4f, 0xb0, 0x8d,
-                       0x71, 0xab, 0x47, 0xa0, 0x86, 0xe8, 0x6e, 0xed, 0xf3, 0x9d, 0x1c, 0x5b, 0xba, 0x97, 0xc4, 0x08,
-                       0x01, 0x26, 0x14, 0x1d, 0x67, 0xf3, 0x7b, 0xe8, 0x53, 0x8f, 0x5a, 0x8b, 0xe7, 0x40, 0xe4, 0x84,
-               },
-       },
-}
-
-func TestOFB_AES(t *testing.T) {
-       for _, tt := range ofbAESTests {
-               test := tt.name
-
-               c, err := aes.NewCipher(tt.key)
-               if err != nil {
-                       t.Errorf("%s: NewCipher(%d bytes) = %s", test, len(tt.key), err)
-                       continue
-               }
-
-               for j := 0; j <= 5; j += 5 {
-                       var crypt bytes.Buffer
-                       in := tt.in[0 : len(tt.in)-j]
-                       w := NewOFBWriter(c, tt.iv, &crypt)
-                       var r io.Reader = bytes.NewBuffer(in)
-                       n, err := io.Copy(w, r)
-                       if n != int64(len(in)) || err != nil {
-                               t.Errorf("%s/%d: OFBWriter io.Copy = %d, %v want %d, nil", test, len(in), n, err, len(in))
-                       } else if d, out := crypt.Bytes(), tt.out[0:len(in)]; !same(out, d) {
-                               t.Errorf("%s/%d: OFBWriter\ninpt %x\nhave %x\nwant %x", test, len(in), in, d, out)
-                       }
-               }
-
-               for j := 0; j <= 7; j += 7 {
-                       var plain bytes.Buffer
-                       out := tt.out[0 : len(tt.out)-j]
-                       r := NewOFBReader(c, tt.iv, bytes.NewBuffer(out))
-                       w := &plain
-                       n, err := io.Copy(w, r)
-                       if n != int64(len(out)) || err != nil {
-                               t.Errorf("%s/%d: OFBReader io.Copy = %d, %v want %d, nil", test, len(out), n, err, len(out))
-                       } else if d, in := plain.Bytes(), tt.in[0:len(out)]; !same(in, d) {
-                               t.Errorf("%s/%d: OFBReader\nhave %x\nwant %x", test, len(out), d, in)
-                       }
-               }
-
-               if t.Failed() {
-                       break
-               }
-       }
-}
diff --git a/libgo/go/crypto/block/xor.go b/libgo/go/crypto/block/xor.go
deleted file mode 100644 (file)
index 9d8b172..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Encrypt/decrypt data by xor with a pseudo-random data stream.
-
-package block
-
-import (
-       "io"
-       "os"
-)
-
-// A dataStream is an interface to an unending stream of data,
-// used by XorReader and XorWriter to model a pseudo-random generator.
-// Calls to Next() return sequential blocks of data from the stream.
-// Each call must return at least one byte: there is no EOF.
-type dataStream interface {
-       Next() []byte
-}
-
-type xorReader struct {
-       r    io.Reader
-       rand dataStream // pseudo-random
-       buf  []byte     // data available from last call to rand
-}
-
-func newXorReader(rand dataStream, r io.Reader) io.Reader {
-       x := new(xorReader)
-       x.r = r
-       x.rand = rand
-       return x
-}
-
-func (x *xorReader) Read(p []byte) (n int, err os.Error) {
-       n, err = x.r.Read(p)
-
-       // xor input with stream.
-       bp := 0
-       buf := x.buf
-       for i := 0; i < n; i++ {
-               if bp >= len(buf) {
-                       buf = x.rand.Next()
-                       bp = 0
-               }
-               p[i] ^= buf[bp]
-               bp++
-       }
-       x.buf = buf[bp:]
-       return n, err
-}
-
-type xorWriter struct {
-       w     io.Writer
-       rand  dataStream // pseudo-random
-       buf   []byte     // last buffer returned by rand
-       extra []byte     // extra random data (use before buf)
-       work  []byte     // work space
-}
-
-func newXorWriter(rand dataStream, w io.Writer) io.Writer {
-       x := new(xorWriter)
-       x.w = w
-       x.rand = rand
-       x.work = make([]byte, 4096)
-       return x
-}
-
-func (x *xorWriter) Write(p []byte) (n int, err os.Error) {
-       for len(p) > 0 {
-               // Determine next chunk of random data
-               // and xor with p into x.work.
-               var chunk []byte
-               m := len(p)
-               if nn := len(x.extra); nn > 0 {
-                       // extra points into work, so edit directly
-                       if m > nn {
-                               m = nn
-                       }
-                       for i := 0; i < m; i++ {
-                               x.extra[i] ^= p[i]
-                       }
-                       chunk = x.extra[0:m]
-               } else {
-                       // xor p ^ buf into work, refreshing buf as needed
-                       if nn := len(x.work); m > nn {
-                               m = nn
-                       }
-                       bp := 0
-                       buf := x.buf
-                       for i := 0; i < m; i++ {
-                               if bp >= len(buf) {
-                                       buf = x.rand.Next()
-                                       bp = 0
-                               }
-                               x.work[i] = buf[bp] ^ p[i]
-                               bp++
-                       }
-                       x.buf = buf[bp:]
-                       chunk = x.work[0:m]
-               }
-
-               // Write chunk.
-               var nn int
-               nn, err = x.w.Write(chunk)
-               if nn != len(chunk) && err == nil {
-                       err = io.ErrShortWrite
-               }
-               if nn < len(chunk) {
-                       // Reconstruct the random bits from the unwritten
-                       // data and save them for next time.
-                       for i := nn; i < m; i++ {
-                               chunk[i] ^= p[i]
-                       }
-                       x.extra = chunk[nn:]
-               }
-               n += nn
-               if err != nil {
-                       return
-               }
-               p = p[m:]
-       }
-       return
-}
diff --git a/libgo/go/crypto/block/xor_test.go b/libgo/go/crypto/block/xor_test.go
deleted file mode 100644 (file)
index 50f6bb0..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package block
-
-import (
-       "bytes"
-       "fmt"
-       "io"
-       "testing"
-       "testing/iotest"
-)
-
-// Simple "pseudo-random" stream for testing.
-type incStream struct {
-       buf []byte
-       n   byte
-}
-
-func newIncStream(blockSize int) *incStream {
-       x := new(incStream)
-       x.buf = make([]byte, blockSize)
-       return x
-}
-
-func (x *incStream) Next() []byte {
-       x.n++
-       for i := range x.buf {
-               x.buf[i] = x.n
-               x.n++
-       }
-       return x.buf
-}
-
-func testXorWriter(t *testing.T, maxio int) {
-       var plain, crypt [256]byte
-       for i := 0; i < len(plain); i++ {
-               plain[i] = byte(i)
-       }
-       b := new(bytes.Buffer)
-       for block := 1; block <= 64 && block <= maxio; block *= 2 {
-               // compute encrypted version
-               n := byte(0)
-               for i := 0; i < len(crypt); i++ {
-                       if i%block == 0 {
-                               n++
-                       }
-                       crypt[i] = plain[i] ^ n
-                       n++
-               }
-
-               for frag := 0; frag < 2; frag++ {
-                       test := fmt.Sprintf("block=%d frag=%d maxio=%d", block, frag, maxio)
-                       b.Reset()
-                       r := bytes.NewBuffer(plain[0:])
-                       s := newIncStream(block)
-                       w := newXorWriter(s, b)
-
-                       // copy plain into w in increasingly large chunks: 1, 1, 2, 4, 8, ...
-                       // if frag != 0, move the 1 to the end to cause fragmentation.
-                       if frag == 0 {
-                               _, err := io.Copyn(w, r, 1)
-                               if err != nil {
-                                       t.Errorf("%s: first Copyn: %s", test, err)
-                                       continue
-                               }
-                       }
-                       for n := 1; n <= len(plain)/2; n *= 2 {
-                               _, err := io.Copyn(w, r, int64(n))
-                               if err != nil {
-                                       t.Errorf("%s: Copyn %d: %s", test, n, err)
-                               }
-                       }
-
-                       // check output
-                       crypt := crypt[0 : len(crypt)-frag]
-                       data := b.Bytes()
-                       if len(data) != len(crypt) {
-                               t.Errorf("%s: want %d bytes, got %d", test, len(crypt), len(data))
-                               continue
-                       }
-
-                       if string(data) != string(crypt) {
-                               t.Errorf("%s: want %x got %x", test, data, crypt)
-                       }
-               }
-       }
-}
-
-
-func TestXorWriter(t *testing.T) {
-       // Do shorter I/O sizes first; they're easier to debug.
-       for n := 1; n <= 256 && !t.Failed(); n *= 2 {
-               testXorWriter(t, n)
-       }
-}
-
-func testXorReader(t *testing.T, maxio int) {
-       var readers = []func(io.Reader) io.Reader{
-               func(r io.Reader) io.Reader { return r },
-               iotest.OneByteReader,
-               iotest.HalfReader,
-       }
-       var plain, crypt [256]byte
-       for i := 0; i < len(plain); i++ {
-               plain[i] = byte(255 - i)
-       }
-       b := new(bytes.Buffer)
-       for block := 1; block <= 64 && block <= maxio; block *= 2 {
-               // compute encrypted version
-               n := byte(0)
-               for i := 0; i < len(crypt); i++ {
-                       if i%block == 0 {
-                               n++
-                       }
-                       crypt[i] = plain[i] ^ n
-                       n++
-               }
-
-               for mode := 0; mode < len(readers); mode++ {
-                       for frag := 0; frag < 2; frag++ {
-                               test := fmt.Sprintf("block=%d mode=%d frag=%d maxio=%d", block, mode, frag, maxio)
-                               s := newIncStream(block)
-                               b.Reset()
-                               r := newXorReader(s, readers[mode](bytes.NewBuffer(crypt[0:maxio])))
-
-                               // read from crypt in increasingly large chunks: 1, 1, 2, 4, 8, ...
-                               // if frag == 1, move the 1 to the end to cause fragmentation.
-                               if frag == 0 {
-                                       _, err := io.Copyn(b, r, 1)
-                                       if err != nil {
-                                               t.Errorf("%s: first Copyn: %s", test, err)
-                                               continue
-                                       }
-                               }
-                               for n := 1; n <= maxio/2; n *= 2 {
-                                       _, err := io.Copyn(b, r, int64(n))
-                                       if err != nil {
-                                               t.Errorf("%s: Copyn %d: %s", test, n, err)
-                                       }
-                               }
-
-                               // check output
-                               data := b.Bytes()
-                               crypt := crypt[0 : maxio-frag]
-                               plain := plain[0 : maxio-frag]
-                               if len(data) != len(plain) {
-                                       t.Errorf("%s: want %d bytes, got %d", test, len(plain), len(data))
-                                       continue
-                               }
-
-                               if string(data) != string(plain) {
-                                       t.Errorf("%s: input=%x want %x got %x", test, crypt, plain, data)
-                               }
-                       }
-               }
-       }
-}
-
-func TestXorReader(t *testing.T) {
-       // Do shorter I/O sizes first; they're easier to debug.
-       for n := 1; n <= 256 && !t.Failed(); n *= 2 {
-               testXorReader(t, n)
-       }
-}
-
-// TODO(rsc): Test handling of writes after write errors.
diff --git a/libgo/go/crypto/des/block.go b/libgo/go/crypto/des/block.go
new file mode 100644 (file)
index 0000000..e18eaed
--- /dev/null
@@ -0,0 +1,98 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package des
+
+import (
+       "encoding/binary"
+)
+
+func cryptBlock(subkeys []uint64, dst, src []byte, decrypt bool) {
+       b := binary.BigEndian.Uint64(src)
+       b = permuteBlock(b, initialPermutation[:])
+       left, right := uint32(b>>32), uint32(b)
+
+       var subkey uint64
+       for i := 0; i < 16; i++ {
+               if decrypt {
+                       subkey = subkeys[15-i]
+               } else {
+                       subkey = subkeys[i]
+               }
+
+               left, right = right, left^feistel(right, subkey)
+       }
+       // switch left & right and perform final permutation
+       preOutput := (uint64(right) << 32) | uint64(left)
+       binary.BigEndian.PutUint64(dst, permuteBlock(preOutput, finalPermutation[:]))
+}
+
+// Encrypt one block from src into dst, using the subkeys.
+func encryptBlock(subkeys []uint64, dst, src []byte) {
+       cryptBlock(subkeys, dst, src, false)
+}
+
+// Decrypt one block from src into dst, using the subkeys.
+func decryptBlock(subkeys []uint64, dst, src []byte) {
+       cryptBlock(subkeys, dst, src, true)
+}
+
+// DES Feistel function
+func feistel(right uint32, key uint64) (result uint32) {
+       sBoxLocations := key ^ permuteBlock(uint64(right), expansionFunction[:])
+       var sBoxResult uint32
+       for i := uint8(0); i < 8; i++ {
+               sBoxLocation := uint8(sBoxLocations>>42) & 0x3f
+               sBoxLocations <<= 6
+               // row determined by 1st and 6th bit
+               row := (sBoxLocation & 0x1) | ((sBoxLocation & 0x20) >> 4)
+               // column is middle four bits
+               column := (sBoxLocation >> 1) & 0xf
+               sBoxResult |= uint32(sBoxes[i][row][column]) << (4 * (7 - i))
+       }
+       return uint32(permuteBlock(uint64(sBoxResult), permutationFunction[:]))
+}
+
+// general purpose function to perform DES block permutations
+func permuteBlock(src uint64, permutation []uint8) (block uint64) {
+       for position, n := range permutation {
+               bit := (src >> n) & 1
+               block |= bit << uint((len(permutation)-1)-position)
+       }
+       return
+}
+
+// creates 16 28-bit blocks rotated according
+// to the rotation schedule
+func ksRotate(in uint32) (out []uint32) {
+       out = make([]uint32, 16)
+       last := in
+       for i := 0; i < 16; i++ {
+               // 28-bit circular left shift
+               left := (last << (4 + ksRotations[i])) >> 4
+               right := (last << 4) >> (32 - ksRotations[i])
+               out[i] = left | right
+               last = out[i]
+       }
+       return
+}
+
+// creates 16 56-bit subkeys from the original key
+func (c *Cipher) generateSubkeys(keyBytes []byte) {
+       // apply PC1 permutation to key
+       key := binary.BigEndian.Uint64(keyBytes)
+       permutedKey := permuteBlock(key, permutedChoice1[:])
+
+       // rotate halves of permuted key according to the rotation schedule
+       leftRotations := ksRotate(uint32(permutedKey >> 28))
+       rightRotations := ksRotate(uint32(permutedKey<<4) >> 4)
+
+       // generate subkeys
+       for i := 0; i < 16; i++ {
+               // combine halves to form 56-bit input to PC2
+               pc2Input := uint64(leftRotations[i])<<28 | uint64(rightRotations[i])
+               // apply PC2 permutation to 7 byte input
+               c.subkeys[i] = permuteBlock(pc2Input, permutedChoice2[:])
+       }
+}
diff --git a/libgo/go/crypto/des/cipher.go b/libgo/go/crypto/des/cipher.go
new file mode 100644 (file)
index 0000000..d17a1a7
--- /dev/null
@@ -0,0 +1,103 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package des
+
+import (
+       "os"
+       "strconv"
+)
+
+// The DES block size in bytes.
+const BlockSize = 8
+
+type KeySizeError int
+
+func (k KeySizeError) String() string {
+       return "crypto/des: invalid key size " + strconv.Itoa(int(k))
+}
+
+// Cipher is an instance of DES encryption.
+type Cipher struct {
+       subkeys [16]uint64
+}
+
+// NewCipher creates and returns a new Cipher.
+func NewCipher(key []byte) (*Cipher, os.Error) {
+       if len(key) != 8 {
+               return nil, KeySizeError(len(key))
+       }
+
+       c := new(Cipher)
+       c.generateSubkeys(key)
+       return c, nil
+}
+
+// BlockSize returns the DES block size, 8 bytes.
+func (c *Cipher) BlockSize() int { return BlockSize }
+
+// Encrypts the 8-byte buffer src and stores the result in dst.
+// Note that for amounts of data larger than a block,
+// it is not safe to just call Encrypt on successive blocks;
+// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
+func (c *Cipher) Encrypt(dst, src []byte) { encryptBlock(c.subkeys[:], dst, src) }
+
+// Decrypts the 8-byte buffer src and stores the result in dst.
+func (c *Cipher) Decrypt(dst, src []byte) { decryptBlock(c.subkeys[:], dst, src) }
+
+// Reset zeros the key data, so that it will no longer
+// appear in the process's memory.
+func (c *Cipher) Reset() {
+       for i := 0; i < len(c.subkeys); i++ {
+               c.subkeys[i] = 0
+       }
+}
+
+// A TripleDESCipher is an instance of TripleDES encryption.
+type TripleDESCipher struct {
+       cipher1, cipher2, cipher3 Cipher
+}
+
+// NewCipher creates and returns a new Cipher.
+func NewTripleDESCipher(key []byte) (*TripleDESCipher, os.Error) {
+       if len(key) != 24 {
+               return nil, KeySizeError(len(key))
+       }
+
+       c := new(TripleDESCipher)
+       c.cipher1.generateSubkeys(key[:8])
+       c.cipher2.generateSubkeys(key[8:16])
+       c.cipher3.generateSubkeys(key[16:])
+       return c, nil
+}
+
+// BlockSize returns the TripleDES block size, 8 bytes.
+// It is necessary to satisfy the Block interface in the
+// package "crypto/cipher".
+func (c *TripleDESCipher) BlockSize() int { return BlockSize }
+
+// Encrypts the 8-byte buffer src and stores the result in dst.
+// Note that for amounts of data larger than a block,
+// it is not safe to just call Encrypt on successive blocks;
+// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
+func (c *TripleDESCipher) Encrypt(dst, src []byte) {
+       c.cipher1.Encrypt(dst, src)
+       c.cipher2.Decrypt(dst, dst)
+       c.cipher3.Encrypt(dst, dst)
+}
+
+// Decrypts the 8-byte buffer src and stores the result in dst.
+func (c *TripleDESCipher) Decrypt(dst, src []byte) {
+       c.cipher3.Decrypt(dst, src)
+       c.cipher2.Encrypt(dst, dst)
+       c.cipher1.Decrypt(dst, dst)
+}
+
+// Reset zeros the key data, so that it will no longer
+// appear in the process's memory.
+func (c *TripleDESCipher) Reset() {
+       c.cipher1.Reset()
+       c.cipher2.Reset()
+       c.cipher3.Reset()
+}
diff --git a/libgo/go/crypto/des/const.go b/libgo/go/crypto/des/const.go
new file mode 100644 (file)
index 0000000..2bd485e
--- /dev/null
@@ -0,0 +1,139 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package des implements the Data Encryption Standard (DES) and the
+// Triple Data Encryption Algorithm (TDEA) as defined
+// in U.S. Federal Information Processing Standards Publication 46-3.
+package des
+
+// Used to perform an initial permutation of a 64-bit input block.
+var initialPermutation = [64]byte{
+       6, 14, 22, 30, 38, 46, 54, 62,
+       4, 12, 20, 28, 36, 44, 52, 60,
+       2, 10, 18, 26, 34, 42, 50, 58,
+       0, 8, 16, 24, 32, 40, 48, 56,
+       7, 15, 23, 31, 39, 47, 55, 63,
+       5, 13, 21, 29, 37, 45, 53, 61,
+       3, 11, 19, 27, 35, 43, 51, 59,
+       1, 9, 17, 25, 33, 41, 49, 57,
+}
+
+// Used to perform a final permutation of a 4-bit preoutput block. This is the
+// inverse of initialPermutation
+var finalPermutation = [64]byte{
+       24, 56, 16, 48, 8, 40, 0, 32,
+       25, 57, 17, 49, 9, 41, 1, 33,
+       26, 58, 18, 50, 10, 42, 2, 34,
+       27, 59, 19, 51, 11, 43, 3, 35,
+       28, 60, 20, 52, 12, 44, 4, 36,
+       29, 61, 21, 53, 13, 45, 5, 37,
+       30, 62, 22, 54, 14, 46, 6, 38,
+       31, 63, 23, 55, 15, 47, 7, 39,
+}
+
+// Used to expand an input block of 32 bits, producing an output block of 48
+// bits.
+var expansionFunction = [48]byte{
+       0, 31, 30, 29, 28, 27, 28, 27,
+       26, 25, 24, 23, 24, 23, 22, 21,
+       20, 19, 20, 19, 18, 17, 16, 15,
+       16, 15, 14, 13, 12, 11, 12, 11,
+       10, 9, 8, 7, 8, 7, 6, 5,
+       4, 3, 4, 3, 2, 1, 0, 31,
+}
+
+// Yields a 32-bit output from a 32-bit input
+var permutationFunction = [32]byte{
+       16, 25, 12, 11, 3, 20, 4, 15,
+       31, 17, 9, 6, 27, 14, 1, 22,
+       30, 24, 8, 18, 0, 5, 29, 23,
+       13, 19, 2, 26, 10, 21, 28, 7,
+}
+
+// Used in the key schedule to select 56 bits
+// from a 64-bit input.
+var permutedChoice1 = [56]byte{
+       7, 15, 23, 31, 39, 47, 55, 63,
+       6, 14, 22, 30, 38, 46, 54, 62,
+       5, 13, 21, 29, 37, 45, 53, 61,
+       4, 12, 20, 28, 1, 9, 17, 25,
+       33, 41, 49, 57, 2, 10, 18, 26,
+       34, 42, 50, 58, 3, 11, 19, 27,
+       35, 43, 51, 59, 36, 44, 52, 60,
+}
+
+// Used in the key schedule to produce each subkey by selecting 48 bits from
+// the 56-bit input
+var permutedChoice2 = [48]byte{
+       42, 39, 45, 32, 55, 51, 53, 28,
+       41, 50, 35, 46, 33, 37, 44, 52,
+       30, 48, 40, 49, 29, 36, 43, 54,
+       15, 4, 25, 19, 9, 1, 26, 16,
+       5, 11, 23, 8, 12, 7, 17, 0,
+       22, 3, 10, 14, 6, 20, 27, 24,
+}
+
+// 8 S-boxes composed of 4 rows and 16 columns
+// Used in the DES cipher function
+var sBoxes = [8][4][16]uint8{
+       // S-box 1
+       {
+               {14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
+               {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
+               {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
+               {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13},
+       },
+       // S-box 2
+       {
+               {15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
+               {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
+               {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
+               {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9},
+       },
+       // S-box 3
+       {
+               {10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
+               {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
+               {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
+               {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12},
+       },
+       // S-box 4
+       {
+               {7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
+               {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
+               {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
+               {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14},
+       },
+       // S-box 5
+       {
+               {2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
+               {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
+               {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
+               {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3},
+       },
+       // S-box 6
+       {
+               {12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
+               {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
+               {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
+               {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13},
+       },
+       // S-box 7
+       {
+               {4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
+               {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
+               {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
+               {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12},
+       },
+       // S-box 8
+       {
+               {13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
+               {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
+               {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
+               {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11},
+       },
+}
+
+// Size of left rotation per round in each half of the key schedule
+var ksRotations = [16]uint8{1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1}
diff --git a/libgo/go/crypto/des/des_test.go b/libgo/go/crypto/des/des_test.go
new file mode 100644 (file)
index 0000000..d1f3aa7
--- /dev/null
@@ -0,0 +1,1497 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package des
+
+import (
+       "bytes"
+       "testing"
+)
+
+type CryptTest struct {
+       key []byte
+       in  []byte
+       out []byte
+}
+
+// some custom tests for DES
+var encryptDESTests = []CryptTest{
+       {
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0x8c, 0xa6, 0x4d, 0xe9, 0xc1, 0xb1, 0x23, 0xa7}},
+       {
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+               []byte{0x35, 0x55, 0x50, 0xb2, 0x15, 0x0e, 0x24, 0x51}},
+       {
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+               []byte{0x61, 0x7b, 0x3a, 0x0c, 0xe8, 0xf0, 0x71, 0x00}},
+       {
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+               []byte{0x92, 0x31, 0xf2, 0x36, 0xff, 0x9a, 0xa9, 0x5c}},
+       {
+               []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0xca, 0xaa, 0xaf, 0x4d, 0xea, 0xf1, 0xdb, 0xae}},
+       {
+               []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+               []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+               []byte{0x73, 0x59, 0xb2, 0x16, 0x3e, 0x4e, 0xdc, 0x58}},
+       {
+               []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+               []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+               []byte{0x6d, 0xce, 0x0d, 0xc9, 0x00, 0x65, 0x56, 0xa3}},
+       {
+               []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+               []byte{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+               []byte{0x9e, 0x84, 0xc5, 0xf3, 0x17, 0x0f, 0x8e, 0xff}},
+       {
+               []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0xd5, 0xd4, 0x4f, 0xf7, 0x20, 0x68, 0x3d, 0x0d}},
+       {
+               []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+               []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+               []byte{0x59, 0x73, 0x23, 0x56, 0xf3, 0x6f, 0xde, 0x06}},
+       {
+               []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+               []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+               []byte{0x56, 0xcc, 0x09, 0xe7, 0xcf, 0xdc, 0x4c, 0xef}},
+       {
+               []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+               []byte{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+               []byte{0x12, 0xc6, 0x26, 0xaf, 0x05, 0x8b, 0x43, 0x3b}},
+       {
+               []byte{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0xa6, 0x8c, 0xdc, 0xa9, 0x0c, 0x90, 0x21, 0xf9}},
+       {
+               []byte{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+               []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+               []byte{0x2a, 0x2b, 0xb0, 0x08, 0xdf, 0x97, 0xc2, 0xf2}},
+       {
+               []byte{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+               []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+               []byte{0xed, 0x39, 0xd9, 0x50, 0xfa, 0x74, 0xbc, 0xc4}},
+       {
+               []byte{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+               []byte{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+               []byte{0xa9, 0x33, 0xf6, 0x18, 0x30, 0x23, 0xb3, 0x10}},
+       {
+               []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+               []byte{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
+               []byte{0x17, 0x66, 0x8d, 0xfc, 0x72, 0x92, 0x53, 0x2d}},
+       {
+               []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
+               []byte{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+               []byte{0xb4, 0xfd, 0x23, 0x16, 0x47, 0xa5, 0xbe, 0xc0}},
+       {
+               []byte{0x0e, 0x32, 0x92, 0x32, 0xea, 0x6d, 0x0d, 0x73},
+               []byte{0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87},
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
+       {
+               []byte{0x73, 0x65, 0x63, 0x52, 0x33, 0x74, 0x24, 0x3b}, // "secR3t$;"
+               []byte{0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x31, 0x32}, // "a test12"
+               []byte{0x37, 0x0d, 0xee, 0x2c, 0x1f, 0xb4, 0xf7, 0xa5}},
+       {
+               []byte{0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68}, // "abcdefgh"
+               []byte{0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68}, // "abcdefgh"
+               []byte{0x2a, 0x8d, 0x69, 0xde, 0x9d, 0x5f, 0xdf, 0xf9}},
+       {
+               []byte{0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68}, // "abcdefgh"
+               []byte{0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38}, // "12345678"
+               []byte{0x21, 0xc6, 0x0d, 0xa5, 0x34, 0x24, 0x8b, 0xce}},
+       {
+               []byte{0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38}, // "12345678"
+               []byte{0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68}, // "abcdefgh"
+               []byte{0x94, 0xd4, 0x43, 0x6b, 0xc3, 0xb5, 0xb6, 0x93}},
+       {
+               []byte{0x1f, 0x79, 0x90, 0x5f, 0x88, 0x01, 0xc8, 0x88}, // random
+               []byte{0xc7, 0x46, 0x18, 0x73, 0xaf, 0x48, 0x5f, 0xb3}, // random
+               []byte{0xb0, 0x93, 0x50, 0x88, 0xf9, 0x92, 0x44, 0x6a}},
+       {
+               []byte{0xe6, 0xf4, 0xf2, 0xdb, 0x31, 0x42, 0x53, 0x01}, // random
+               []byte{0xff, 0x3d, 0x25, 0x50, 0x12, 0xe3, 0x4a, 0xc5}, // random
+               []byte{0x86, 0x08, 0xd3, 0xd1, 0x6c, 0x2f, 0xd2, 0x55}},
+       {
+               []byte{0x69, 0xc1, 0x9d, 0xc1, 0x15, 0xc5, 0xfb, 0x2b}, // random
+               []byte{0x1a, 0x22, 0x5c, 0xaf, 0x1f, 0x1d, 0xa3, 0xf9}, // random
+               []byte{0x64, 0xba, 0x31, 0x67, 0x56, 0x91, 0x1e, 0xa7}},
+       {
+               []byte{0x6e, 0x5e, 0xe2, 0x47, 0xc4, 0xbf, 0xf6, 0x51}, // random
+               []byte{0x11, 0xc9, 0x57, 0xff, 0x66, 0x89, 0x0e, 0xf0}, // random
+               []byte{0x94, 0xc5, 0x35, 0xb2, 0xc5, 0x8b, 0x39, 0x72}},
+}
+
+var weakKeyTests = []CryptTest{
+       {
+               []byte{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+               []byte{0x55, 0x74, 0xc0, 0xbd, 0x7c, 0xdf, 0xf7, 0x39}, // random
+               nil},
+       {
+               []byte{0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe},
+               []byte{0xe8, 0xe1, 0xa7, 0xc1, 0xde, 0x11, 0x89, 0xaa}, // random
+               nil},
+       {
+               []byte{0xe0, 0xe0, 0xe0, 0xe0, 0xf1, 0xf1, 0xf1, 0xf1},
+               []byte{0x50, 0x6a, 0x4b, 0x94, 0x3b, 0xed, 0x7d, 0xdc}, // random
+               nil},
+       {
+               []byte{0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e},
+               []byte{0x88, 0x81, 0x56, 0x38, 0xec, 0x3b, 0x1c, 0x97}, // random
+               nil},
+       {
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0x17, 0xa0, 0x83, 0x62, 0x32, 0xfe, 0x9a, 0x0b}, // random
+               nil},
+       {
+               []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+               []byte{0xca, 0x8f, 0xca, 0x1f, 0x50, 0xc5, 0x7b, 0x49}, // random
+               nil},
+       {
+               []byte{0xe1, 0xe1, 0xe1, 0xe1, 0xf0, 0xf0, 0xf0, 0xf0},
+               []byte{0xb1, 0xea, 0xad, 0x7d, 0xe7, 0xc3, 0x7a, 0x43}, // random
+               nil},
+       {
+               []byte{0x1e, 0x1e, 0x1e, 0x1e, 0x0f, 0x0f, 0x0f, 0x0f},
+               []byte{0xae, 0x74, 0x7d, 0x6f, 0xef, 0x16, 0xbb, 0x81}, // random
+               nil},
+}
+
+var semiWeakKeyTests = []CryptTest{
+       // key and out contain the semi-weak key pair
+       {
+               []byte{0x01, 0x1f, 0x01, 0x1f, 0x01, 0x0e, 0x01, 0x0e},
+               []byte{0x12, 0xfa, 0x31, 0x16, 0xf9, 0xc5, 0x0a, 0xe4}, // random
+               []byte{0x1f, 0x01, 0x1f, 0x01, 0x0e, 0x01, 0x0e, 0x01}},
+       {
+               []byte{0x01, 0xe0, 0x01, 0xe0, 0x01, 0xf1, 0x01, 0xf1},
+               []byte{0xb0, 0x4c, 0x7a, 0xee, 0xd2, 0xe5, 0x4d, 0xb7}, // random
+               []byte{0xe0, 0x01, 0xe0, 0x01, 0xf1, 0x01, 0xf1, 0x01}},
+       {
+               []byte{0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe},
+               []byte{0xa4, 0x81, 0xcd, 0xb1, 0x64, 0x6f, 0xd3, 0xbc}, // random
+               []byte{0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01}},
+       {
+               []byte{0x1f, 0xe0, 0x1f, 0xe0, 0x0e, 0xf1, 0x0e, 0xf1},
+               []byte{0xee, 0x27, 0xdd, 0x88, 0x4c, 0x22, 0xcd, 0xce}, // random
+               []byte{0xe0, 0x1f, 0xe0, 0x1f, 0xf1, 0x0e, 0xf1, 0x0e}},
+       {
+               []byte{0x1f, 0xfe, 0x1f, 0xfe, 0x0e, 0xfe, 0x0e, 0xfe},
+               []byte{0x19, 0x3d, 0xcf, 0x97, 0x70, 0xfb, 0xab, 0xe1}, // random
+               []byte{0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x0e, 0xfe, 0x0e}},
+       {
+               []byte{0xe0, 0xfe, 0xe0, 0xfe, 0xf1, 0xfe, 0xf1, 0xfe},
+               []byte{0x7c, 0x82, 0x69, 0xe4, 0x1e, 0x86, 0x99, 0xd7}, // random
+               []byte{0xfe, 0xe0, 0xfe, 0xe0, 0xfe, 0xf1, 0xfe, 0xf1}},
+}
+
+// some custom tests for TripleDES
+var encryptTripleDESTests = []CryptTest{
+       {
+               []byte{
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0x92, 0x95, 0xb5, 0x9b, 0xb3, 0x84, 0x73, 0x6e}},
+       {
+               []byte{
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+               []byte{0xc1, 0x97, 0xf5, 0x58, 0x74, 0x8a, 0x20, 0xe7}},
+       {
+               []byte{
+                       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0x3e, 0x68, 0x0a, 0xa7, 0x8b, 0x75, 0xdf, 0x18}},
+       {
+               []byte{
+                       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+               []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+               []byte{0x6d, 0x6a, 0x4a, 0x64, 0x4c, 0x7b, 0x8c, 0x91}},
+       {
+               []byte{ // "abcdefgh12345678ABCDEFGH"
+                       0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+                       0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
+                       0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48},
+               []byte{0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30}, // "00000000"
+               []byte{0xe4, 0x61, 0xb7, 0x59, 0x68, 0x8b, 0xff, 0x66}},
+       {
+               []byte{ // "abcdefgh12345678ABCDEFGH"
+                       0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+                       0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
+                       0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48},
+               []byte{0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38}, // "12345678"
+               []byte{0xdb, 0xd0, 0x92, 0xde, 0xf8, 0x34, 0xff, 0x58}},
+       {
+               []byte{ // "abcdefgh12345678ABCDEFGH"
+                       0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+                       0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
+                       0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48},
+               []byte{0xf0, 0xc5, 0x82, 0x22, 0xd3, 0xe6, 0x12, 0xd2}, // random
+               []byte{0xba, 0xe4, 0x41, 0xb1, 0x3c, 0x37, 0x4d, 0xf4}},
+       {
+               []byte{ // random
+                       0xd3, 0x7d, 0x45, 0xee, 0x22, 0xe9, 0xcf, 0x52,
+                       0xf4, 0x65, 0xa2, 0x4f, 0x70, 0xd1, 0x81, 0x8a,
+                       0x3d, 0xbe, 0x2f, 0x39, 0xc7, 0x71, 0xd2, 0xe9},
+               []byte{0x49, 0x53, 0xc3, 0xe9, 0x78, 0xdf, 0x9f, 0xaf}, // random
+               []byte{0x53, 0x40, 0x51, 0x24, 0xd8, 0x3c, 0xf9, 0x88}},
+       {
+               []byte{ // random
+                       0xcb, 0x10, 0x7d, 0xda, 0x7e, 0x96, 0x57, 0x0a,
+                       0xe8, 0xeb, 0xe8, 0x07, 0x8e, 0x87, 0xd3, 0x57,
+                       0xb2, 0x61, 0x12, 0xb8, 0x2a, 0x90, 0xb7, 0x2f},
+               []byte{0xa3, 0xc2, 0x60, 0xb1, 0x0b, 0xb7, 0x28, 0x6e}, // random
+               []byte{0x56, 0x73, 0x7d, 0xfb, 0xb5, 0xa1, 0xc3, 0xde}},
+}
+
+// NIST Special Publication 800-20, Appendix A
+// Key for use with Table A.1 tests
+var tableA1Key = []byte{
+       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+}
+
+// Table A.1 Resulting Ciphertext from the Variable Plaintext Known Answer Test
+var tableA1Tests = []CryptTest{
+       {nil, // 0
+               []byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0x95, 0xf8, 0xa5, 0xe5, 0xdd, 0x31, 0xd9, 0x00}},
+       {nil, // 1
+               []byte{0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0xdd, 0x7f, 0x12, 0x1c, 0xa5, 0x01, 0x56, 0x19}},
+       {nil, // 2
+               []byte{0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0x2e, 0x86, 0x53, 0x10, 0x4f, 0x38, 0x34, 0xea}},
+       {nil, // 3
+               []byte{0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0x4b, 0xd3, 0x88, 0xff, 0x6c, 0xd8, 0x1d, 0x4f}},
+       {nil, // 4
+               []byte{0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0x20, 0xb9, 0xe7, 0x67, 0xb2, 0xfb, 0x14, 0x56}},
+       {nil, // 5
+               []byte{0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0x55, 0x57, 0x93, 0x80, 0xd7, 0x71, 0x38, 0xef}},
+       {nil, // 6
+               []byte{0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0x6c, 0xc5, 0xde, 0xfa, 0xaf, 0x04, 0x51, 0x2f}},
+       {nil, // 7
+               []byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0x0d, 0x9f, 0x27, 0x9b, 0xa5, 0xd8, 0x72, 0x60}},
+       {nil, // 8
+               []byte{0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0xd9, 0x03, 0x1b, 0x02, 0x71, 0xbd, 0x5a, 0x0a}},
+       {nil, // 9
+               []byte{0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0x42, 0x42, 0x50, 0xb3, 0x7c, 0x3d, 0xd9, 0x51}},
+       {nil, // 10
+               []byte{0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0xb8, 0x06, 0x1b, 0x7e, 0xcd, 0x9a, 0x21, 0xe5}},
+       {nil, // 11
+               []byte{0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0xf1, 0x5d, 0x0f, 0x28, 0x6b, 0x65, 0xbd, 0x28}},
+       {nil, // 12
+               []byte{0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0xad, 0xd0, 0xcc, 0x8d, 0x6e, 0x5d, 0xeb, 0xa1}},
+       {nil, // 13
+               []byte{0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0xe6, 0xd5, 0xf8, 0x27, 0x52, 0xad, 0x63, 0xd1}},
+       {nil, // 14
+               []byte{0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0xec, 0xbf, 0xe3, 0xbd, 0x3f, 0x59, 0x1a, 0x5e}},
+       {nil, // 15
+               []byte{0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0xf3, 0x56, 0x83, 0x43, 0x79, 0xd1, 0x65, 0xcd}},
+       {nil, // 16
+               []byte{0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0x2b, 0x9f, 0x98, 0x2f, 0x20, 0x03, 0x7f, 0xa9}},
+       {nil, // 17
+               []byte{0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0x88, 0x9d, 0xe0, 0x68, 0xa1, 0x6f, 0x0b, 0xe6}},
+       {nil, // 18
+               []byte{0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0xe1, 0x9e, 0x27, 0x5d, 0x84, 0x6a, 0x12, 0x98}},
+       {nil, // 19
+               []byte{0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0x32, 0x9a, 0x8e, 0xd5, 0x23, 0xd7, 0x1a, 0xec}},
+       {nil, // 20
+               []byte{0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0xe7, 0xfc, 0xe2, 0x25, 0x57, 0xd2, 0x3c, 0x97}},
+       {nil, // 21
+               []byte{0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0x12, 0xa9, 0xf5, 0x81, 0x7f, 0xf2, 0xd6, 0x5d}},
+       {nil, // 22
+               []byte{0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0xa4, 0x84, 0xc3, 0xad, 0x38, 0xdc, 0x9c, 0x19}},
+       {nil, // 23
+               []byte{0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00},
+               []byte{0xfb, 0xe0, 0x0a, 0x8a, 0x1e, 0xf8, 0xad, 0x72}},
+       {nil, // 24
+               []byte{0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00},
+               []byte{0x75, 0x0d, 0x07, 0x94, 0x07, 0x52, 0x13, 0x63}},
+       {nil, // 25
+               []byte{0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00},
+               []byte{0x64, 0xfe, 0xed, 0x9c, 0x72, 0x4c, 0x2f, 0xaf}},
+       {nil, // 26
+               []byte{0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00},
+               []byte{0xf0, 0x2b, 0x26, 0x3b, 0x32, 0x8e, 0x2b, 0x60}},
+       {nil, // 27
+               []byte{0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00},
+               []byte{0x9d, 0x64, 0x55, 0x5a, 0x9a, 0x10, 0xb8, 0x52}},
+       {nil, // 28
+               []byte{0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00},
+               []byte{0xd1, 0x06, 0xff, 0x0b, 0xed, 0x52, 0x55, 0xd7}},
+       {nil, // 29
+               []byte{0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00},
+               []byte{0xe1, 0x65, 0x2c, 0x6b, 0x13, 0x8c, 0x64, 0xa5}},
+       {nil, // 30
+               []byte{0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00},
+               []byte{0xe4, 0x28, 0x58, 0x11, 0x86, 0xec, 0x8f, 0x46}},
+       {nil, // 31
+               []byte{0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00},
+               []byte{0xae, 0xb5, 0xf5, 0xed, 0xe2, 0x2d, 0x1a, 0x36}},
+       {nil, // 32
+               []byte{0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00},
+               []byte{0xe9, 0x43, 0xd7, 0x56, 0x8a, 0xec, 0x0c, 0x5c}},
+       {nil, // 33
+               []byte{0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00},
+               []byte{0xdf, 0x98, 0xc8, 0x27, 0x6f, 0x54, 0xb0, 0x4b}},
+       {nil, // 34
+               []byte{0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00},
+               []byte{0xb1, 0x60, 0xe4, 0x68, 0x0f, 0x6c, 0x69, 0x6f}},
+       {nil, // 35
+               []byte{0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00},
+               []byte{0xfa, 0x07, 0x52, 0xb0, 0x7d, 0x9c, 0x4a, 0xb8}},
+       {nil, // 36
+               []byte{0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00},
+               []byte{0xca, 0x3a, 0x2b, 0x03, 0x6d, 0xbc, 0x85, 0x02}},
+       {nil, // 37
+               []byte{0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00},
+               []byte{0x5e, 0x09, 0x05, 0x51, 0x7b, 0xb5, 0x9b, 0xcf}},
+       {nil, // 38
+               []byte{0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00},
+               []byte{0x81, 0x4e, 0xeb, 0x3b, 0x91, 0xd9, 0x07, 0x26}},
+       {nil, // 39
+               []byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00},
+               []byte{0x4d, 0x49, 0xdb, 0x15, 0x32, 0x91, 0x9c, 0x9f}},
+       {nil, // 40
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00},
+               []byte{0x25, 0xeb, 0x5f, 0xc3, 0xf8, 0xcf, 0x06, 0x21}},
+       {nil, // 41
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00},
+               []byte{0xab, 0x6a, 0x20, 0xc0, 0x62, 0x0d, 0x1c, 0x6f}},
+       {nil, // 42
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00},
+               []byte{0x79, 0xe9, 0x0d, 0xbc, 0x98, 0xf9, 0x2c, 0xca}},
+       {nil, // 43
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00},
+               []byte{0x86, 0x6e, 0xce, 0xdd, 0x80, 0x72, 0xbb, 0x0e}},
+       {nil, // 44
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00},
+               []byte{0x8b, 0x54, 0x53, 0x6f, 0x2f, 0x3e, 0x64, 0xa8}},
+       {nil, // 45
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00},
+               []byte{0xea, 0x51, 0xd3, 0x97, 0x55, 0x95, 0xb8, 0x6b}},
+       {nil, // 46
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00},
+               []byte{0xca, 0xff, 0xc6, 0xac, 0x45, 0x42, 0xde, 0x31}},
+       {nil, // 47
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00},
+               []byte{0x8d, 0xd4, 0x5a, 0x2d, 0xdf, 0x90, 0x79, 0x6c}},
+       {nil, // 48
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00},
+               []byte{0x10, 0x29, 0xd5, 0x5e, 0x88, 0x0e, 0xc2, 0xd0}},
+       {nil, // 49
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00},
+               []byte{0x5d, 0x86, 0xcb, 0x23, 0x63, 0x9d, 0xbe, 0xa9}},
+       {nil, // 50
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00},
+               []byte{0x1d, 0x1c, 0xa8, 0x53, 0xae, 0x7c, 0x0c, 0x5f}},
+       {nil, // 51
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00},
+               []byte{0xce, 0x33, 0x23, 0x29, 0x24, 0x8f, 0x32, 0x28}},
+       {nil, // 52
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00},
+               []byte{0x84, 0x05, 0xd1, 0xab, 0xe2, 0x4f, 0xb9, 0x42}},
+       {nil, // 53
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00},
+               []byte{0xe6, 0x43, 0xd7, 0x80, 0x90, 0xca, 0x42, 0x07}},
+       {nil, // 54
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00},
+               []byte{0x48, 0x22, 0x1b, 0x99, 0x37, 0x74, 0x8a, 0x23}},
+       {nil, // 55
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00},
+               []byte{0xdd, 0x7c, 0x0b, 0xbd, 0x61, 0xfa, 0xfd, 0x54}},
+       {nil, // 56
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80},
+               []byte{0x2f, 0xbc, 0x29, 0x1a, 0x57, 0x0d, 0xb5, 0xc4}},
+       {nil, // 57
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40},
+               []byte{0xe0, 0x7c, 0x30, 0xd7, 0xe4, 0xe2, 0x6e, 0x12}},
+       {nil, // 58
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20},
+               []byte{0x09, 0x53, 0xe2, 0x25, 0x8e, 0x8e, 0x90, 0xa1}},
+       {nil, // 59
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
+               []byte{0x5b, 0x71, 0x1b, 0xc4, 0xce, 0xeb, 0xf2, 0xee}},
+       {nil, // 60
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08},
+               []byte{0xcc, 0x08, 0x3f, 0x1e, 0x6d, 0x9e, 0x85, 0xf6}},
+       {nil, // 61
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04},
+               []byte{0xd2, 0xfd, 0x88, 0x67, 0xd5, 0x0d, 0x2d, 0xfe}},
+       {nil, // 62
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
+               []byte{0x06, 0xe7, 0xea, 0x22, 0xce, 0x92, 0x70, 0x8f}},
+       {nil, // 63
+               []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
+               []byte{0x16, 0x6b, 0x40, 0xb4, 0x4a, 0xba, 0x4b, 0xd6}},
+}
+
+// Plaintext for use with Table A.2 tests
+var tableA2Plaintext = []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+
+// Table A.2 Resulting Ciphertext from the Variable Key Known Answer Test
+var tableA2Tests = []CryptTest{
+       { // 0
+               []byte{
+                       0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0x95, 0xa8, 0xd7, 0x28, 0x13, 0xda, 0xa9, 0x4d}},
+       { // 1
+               []byte{
+                       0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0x0e, 0xec, 0x14, 0x87, 0xdd, 0x8c, 0x26, 0xd5}},
+       { // 2
+               []byte{
+                       0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0x7a, 0xd1, 0x6f, 0xfb, 0x79, 0xc4, 0x59, 0x26}},
+       { // 3
+               []byte{
+                       0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0xd3, 0x74, 0x62, 0x94, 0xca, 0x6a, 0x6c, 0xf3}},
+       { // 4
+               []byte{
+                       0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0x80, 0x9f, 0x5f, 0x87, 0x3c, 0x1f, 0xd7, 0x61}},
+       { // 5
+               []byte{
+                       0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0xc0, 0x2f, 0xaf, 0xfe, 0xc9, 0x89, 0xd1, 0xfc}},
+       { // 6
+               []byte{
+                       0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0x46, 0x15, 0xaa, 0x1d, 0x33, 0xe7, 0x2f, 0x10}},
+       { // 7
+               []byte{
+                       0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0x20, 0x55, 0x12, 0x33, 0x50, 0xc0, 0x08, 0x58}},
+       { // 8
+               []byte{
+                       0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0xdf, 0x3b, 0x99, 0xd6, 0x57, 0x73, 0x97, 0xc8}},
+       { // 9
+               []byte{
+                       0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0x31, 0xfe, 0x17, 0x36, 0x9b, 0x52, 0x88, 0xc9}},
+       { // 10
+               []byte{
+                       0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0xdf, 0xdd, 0x3c, 0xc6, 0x4d, 0xae, 0x16, 0x42}},
+       { // 11
+               []byte{
+                       0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0x17, 0x8c, 0x83, 0xce, 0x2b, 0x39, 0x9d, 0x94}},
+       { // 12
+               []byte{
+                       0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0x50, 0xf6, 0x36, 0x32, 0x4a, 0x9b, 0x7f, 0x80}},
+       { // 13
+               []byte{
+                       0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0xa8, 0x46, 0x8e, 0xe3, 0xbc, 0x18, 0xf0, 0x6d}},
+       { // 14
+               []byte{
+                       0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0xa2, 0xdc, 0x9e, 0x92, 0xfd, 0x3c, 0xde, 0x92}},
+       { // 15
+               []byte{
+                       0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0xca, 0xc0, 0x9f, 0x79, 0x7d, 0x03, 0x12, 0x87}},
+       { // 16
+               []byte{
+                       0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0x90, 0xba, 0x68, 0x0b, 0x22, 0xae, 0xb5, 0x25}},
+       { // 17
+               []byte{
+                       0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0xce, 0x7a, 0x24, 0xf3, 0x50, 0xe2, 0x80, 0xb6}},
+       { // 18
+               []byte{
+                       0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0x88, 0x2b, 0xff, 0x0a, 0xa0, 0x1a, 0x0b, 0x87}},
+       { // 19
+               []byte{
+                       0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0x25, 0x61, 0x02, 0x88, 0x92, 0x45, 0x11, 0xc2}},
+       { // 20
+               []byte{
+                       0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0xc7, 0x15, 0x16, 0xc2, 0x9c, 0x75, 0xd1, 0x70}},
+       { // 21
+               []byte{
+                       0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0x51, 0x99, 0xc2, 0x9a, 0x52, 0xc9, 0xf0, 0x59}},
+       { // 22
+               []byte{
+                       0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0xc2, 0x2f, 0x0a, 0x29, 0x4a, 0x71, 0xf2, 0x9f}},
+       { // 23
+               []byte{
+                       0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0xee, 0x37, 0x14, 0x83, 0x71, 0x4c, 0x02, 0xea}},
+       { // 24
+               []byte{
+                       0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0xa8, 0x1f, 0xbd, 0x44, 0x8f, 0x9e, 0x52, 0x2f}},
+       { // 25
+               []byte{
+                       0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0x4f, 0x64, 0x4c, 0x92, 0xe1, 0x92, 0xdf, 0xed}},
+       { // 26
+               []byte{
+                       0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0x1a, 0xfa, 0x9a, 0x66, 0xa6, 0xdf, 0x92, 0xae}},
+       { // 27
+               []byte{
+                       0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0xb3, 0xc1, 0xcc, 0x71, 0x5c, 0xb8, 0x79, 0xd8}},
+       { // 28
+               []byte{
+                       0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0x19, 0xd0, 0x32, 0xe6, 0x4a, 0xb0, 0xbd, 0x8b}},
+       { // 29
+               []byte{
+                       0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0x3c, 0xfa, 0xa7, 0xa7, 0xdc, 0x87, 0x20, 0xdc}},
+       { // 30
+               []byte{
+                       0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0xb7, 0x26, 0x5f, 0x7f, 0x44, 0x7a, 0xc6, 0xf3}},
+       { // 31
+               []byte{
+                       0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0x9d, 0xb7, 0x3b, 0x3c, 0x0d, 0x16, 0x3f, 0x54}},
+       { // 32
+               []byte{
+                       0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0x81, 0x81, 0xb6, 0x5b, 0xab, 0xf4, 0xa9, 0x75}},
+       { // 33
+               []byte{
+                       0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0x93, 0xc9, 0xb6, 0x40, 0x42, 0xea, 0xa2, 0x40}},
+       { // 34
+               []byte{
+                       0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01},
+               nil,
+               []byte{0x55, 0x70, 0x53, 0x08, 0x29, 0x70, 0x55, 0x92}},
+       { // 35
+               []byte{
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01},
+               nil,
+               []byte{0x86, 0x38, 0x80, 0x9e, 0x87, 0x87, 0x87, 0xa0}},
+       { // 36
+               []byte{
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01},
+               nil,
+               []byte{0x41, 0xb9, 0xa7, 0x9a, 0xf7, 0x9a, 0xc2, 0x08}},
+       { // 37
+               []byte{
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01},
+               nil,
+               []byte{0x7a, 0x9b, 0xe4, 0x2f, 0x20, 0x09, 0xa8, 0x92}},
+       { // 38
+               []byte{
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01},
+               nil,
+               []byte{0x29, 0x03, 0x8d, 0x56, 0xba, 0x6d, 0x27, 0x45}},
+       { // 39
+               []byte{
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01},
+               nil,
+               []byte{0x54, 0x95, 0xc6, 0xab, 0xf1, 0xe5, 0xdf, 0x51}},
+       { // 40
+               []byte{
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01},
+               nil,
+               []byte{0xae, 0x13, 0xdb, 0xd5, 0x61, 0x48, 0x89, 0x33}},
+       { // 41
+               []byte{
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01},
+               nil,
+               []byte{0x02, 0x4d, 0x1f, 0xfa, 0x89, 0x04, 0xe3, 0x89}},
+       { // 42
+               []byte{
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01},
+               nil,
+               []byte{0xd1, 0x39, 0x97, 0x12, 0xf9, 0x9b, 0xf0, 0x2e}},
+       { // 43
+               []byte{
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01},
+               nil,
+               []byte{0x14, 0xc1, 0xd7, 0xc1, 0xcf, 0xfe, 0xc7, 0x9e}},
+       { // 44
+               []byte{
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01},
+               nil,
+               []byte{0x1d, 0xe5, 0x27, 0x9d, 0xae, 0x3b, 0xed, 0x6f}},
+       { // 45
+               []byte{
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01},
+               nil,
+               []byte{0xe9, 0x41, 0xa3, 0x3f, 0x85, 0x50, 0x13, 0x03}},
+       { // 46
+               []byte{
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01},
+               nil,
+               []byte{0xda, 0x99, 0xdb, 0xbc, 0x9a, 0x03, 0xf3, 0x79}},
+       { // 47
+               []byte{
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01},
+               nil,
+               []byte{0xb7, 0xfc, 0x92, 0xf9, 0x1d, 0x8e, 0x92, 0xe9}},
+       { // 48
+               []byte{
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01},
+               nil,
+               []byte{0xae, 0x8e, 0x5c, 0xaa, 0x3c, 0xa0, 0x4e, 0x85}},
+       { // 49
+               []byte{
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80},
+               nil,
+               []byte{0x9c, 0xc6, 0x2d, 0xf4, 0x3b, 0x6e, 0xed, 0x74}},
+       { // 50
+               []byte{
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40},
+               nil,
+               []byte{0xd8, 0x63, 0xdb, 0xb5, 0xc5, 0x9a, 0x91, 0xa0}},
+       { // 50
+               []byte{
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20},
+               nil,
+               []byte{0xa1, 0xab, 0x21, 0x90, 0x54, 0x5b, 0x91, 0xd7}},
+       { // 52
+               []byte{
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10},
+               nil,
+               []byte{0x08, 0x75, 0x04, 0x1e, 0x64, 0xc5, 0x70, 0xf7}},
+       { // 53
+               []byte{
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08},
+               nil,
+               []byte{0x5a, 0x59, 0x45, 0x28, 0xbe, 0xbe, 0xf1, 0xcc}},
+       { // 54
+               []byte{
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04},
+               nil,
+               []byte{0xfc, 0xdb, 0x32, 0x91, 0xde, 0x21, 0xf0, 0xc0}},
+       { // 55
+               []byte{
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+                       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02},
+               nil,
+               []byte{0x86, 0x9e, 0xfd, 0x7f, 0x9f, 0x26, 0x5a, 0x09}},
+}
+
+// Plaintext for use with Table A.3 tests
+var tableA3Plaintext = []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+
+// Table A.3 Values To Be Used for the Permutation Operation Known Answer Test
+var tableA3Tests = []CryptTest{
+       { // 0
+               []byte{
+                       0x10, 0x46, 0x91, 0x34, 0x89, 0x98, 0x01, 0x31,
+                       0x10, 0x46, 0x91, 0x34, 0x89, 0x98, 0x01, 0x31,
+                       0x10, 0x46, 0x91, 0x34, 0x89, 0x98, 0x01, 0x31,
+               },
+               nil,
+               []byte{0x88, 0xd5, 0x5e, 0x54, 0xf5, 0x4c, 0x97, 0xb4}},
+       { // 1
+               []byte{
+                       0x10, 0x07, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20,
+                       0x10, 0x07, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20,
+                       0x10, 0x07, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20,
+               },
+               nil,
+               []byte{0x0c, 0x0c, 0xc0, 0x0c, 0x83, 0xea, 0x48, 0xfd}},
+       { // 2
+               []byte{
+                       0x10, 0x07, 0x10, 0x34, 0xc8, 0x98, 0x01, 0x20,
+                       0x10, 0x07, 0x10, 0x34, 0xc8, 0x98, 0x01, 0x20,
+                       0x10, 0x07, 0x10, 0x34, 0xc8, 0x98, 0x01, 0x20,
+               },
+               nil,
+               []byte{0x83, 0xbc, 0x8e, 0xf3, 0xa6, 0x57, 0x01, 0x83}},
+       { // 3
+               []byte{
+                       0x10, 0x46, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20,
+                       0x10, 0x46, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20,
+                       0x10, 0x46, 0x10, 0x34, 0x89, 0x98, 0x80, 0x20,
+               },
+               nil,
+               []byte{0xdf, 0x72, 0x5d, 0xca, 0xd9, 0x4e, 0xa2, 0xe9}},
+       { // 4
+               []byte{
+                       0x10, 0x86, 0x91, 0x15, 0x19, 0x19, 0x01, 0x01,
+                       0x10, 0x86, 0x91, 0x15, 0x19, 0x19, 0x01, 0x01,
+                       0x10, 0x86, 0x91, 0x15, 0x19, 0x19, 0x01, 0x01,
+               },
+               nil,
+               []byte{0xe6, 0x52, 0xb5, 0x3b, 0x55, 0x0b, 0xe8, 0xb0}},
+       { // 5
+               []byte{
+                       0x10, 0x86, 0x91, 0x15, 0x19, 0x58, 0x01, 0x01,
+                       0x10, 0x86, 0x91, 0x15, 0x19, 0x58, 0x01, 0x01,
+                       0x10, 0x86, 0x91, 0x15, 0x19, 0x58, 0x01, 0x01,
+               },
+               nil,
+               []byte{0xaf, 0x52, 0x71, 0x20, 0xc4, 0x85, 0xcb, 0xb0}},
+       { // 6
+               []byte{
+                       0x51, 0x07, 0xb0, 0x15, 0x19, 0x58, 0x01, 0x01,
+                       0x51, 0x07, 0xb0, 0x15, 0x19, 0x58, 0x01, 0x01,
+                       0x51, 0x07, 0xb0, 0x15, 0x19, 0x58, 0x01, 0x01,
+               },
+               nil,
+               []byte{0x0f, 0x04, 0xce, 0x39, 0x3d, 0xb9, 0x26, 0xd5}},
+       { // 7
+               []byte{
+                       0x10, 0x07, 0xb0, 0x15, 0x19, 0x19, 0x01, 0x01,
+                       0x10, 0x07, 0xb0, 0x15, 0x19, 0x19, 0x01, 0x01,
+                       0x10, 0x07, 0xb0, 0x15, 0x19, 0x19, 0x01, 0x01,
+               },
+               nil,
+               []byte{0xc9, 0xf0, 0x0f, 0xfc, 0x74, 0x07, 0x90, 0x67}},
+       { // 8
+               []byte{
+                       0x31, 0x07, 0x91, 0x54, 0x98, 0x08, 0x01, 0x01,
+                       0x31, 0x07, 0x91, 0x54, 0x98, 0x08, 0x01, 0x01,
+                       0x31, 0x07, 0x91, 0x54, 0x98, 0x08, 0x01, 0x01,
+               },
+               nil,
+               []byte{0x7c, 0xfd, 0x82, 0xa5, 0x93, 0x25, 0x2b, 0x4e}},
+       { // 9
+               []byte{
+                       0x31, 0x07, 0x91, 0x94, 0x98, 0x08, 0x01, 0x01,
+                       0x31, 0x07, 0x91, 0x94, 0x98, 0x08, 0x01, 0x01,
+                       0x31, 0x07, 0x91, 0x94, 0x98, 0x08, 0x01, 0x01,
+               },
+               nil,
+               []byte{0xcb, 0x49, 0xa2, 0xf9, 0xe9, 0x13, 0x63, 0xe3}},
+       { // 10
+               []byte{
+                       0x10, 0x07, 0x91, 0x15, 0xb9, 0x08, 0x01, 0x40,
+                       0x10, 0x07, 0x91, 0x15, 0xb9, 0x08, 0x01, 0x40,
+                       0x10, 0x07, 0x91, 0x15, 0xb9, 0x08, 0x01, 0x40,
+               },
+               nil,
+               []byte{0x00, 0xb5, 0x88, 0xbe, 0x70, 0xd2, 0x3f, 0x56}},
+       { // 11
+               []byte{
+                       0x31, 0x07, 0x91, 0x15, 0x98, 0x08, 0x01, 0x40,
+                       0x31, 0x07, 0x91, 0x15, 0x98, 0x08, 0x01, 0x40,
+                       0x31, 0x07, 0x91, 0x15, 0x98, 0x08, 0x01, 0x40,
+               },
+               nil,
+               []byte{0x40, 0x6a, 0x9a, 0x6a, 0xb4, 0x33, 0x99, 0xae}},
+       { // 12
+               []byte{
+                       0x10, 0x07, 0xd0, 0x15, 0x89, 0x98, 0x01, 0x01,
+                       0x10, 0x07, 0xd0, 0x15, 0x89, 0x98, 0x01, 0x01,
+                       0x10, 0x07, 0xd0, 0x15, 0x89, 0x98, 0x01, 0x01,
+               },
+               nil,
+               []byte{0x6c, 0xb7, 0x73, 0x61, 0x1d, 0xca, 0x9a, 0xda}},
+       { // 13
+               []byte{
+                       0x91, 0x07, 0x91, 0x15, 0x89, 0x98, 0x01, 0x01,
+                       0x91, 0x07, 0x91, 0x15, 0x89, 0x98, 0x01, 0x01,
+                       0x91, 0x07, 0x91, 0x15, 0x89, 0x98, 0x01, 0x01,
+               },
+               nil,
+               []byte{0x67, 0xfd, 0x21, 0xc1, 0x7d, 0xbb, 0x5d, 0x70}},
+       { // 14
+               []byte{
+                       0x91, 0x07, 0xd0, 0x15, 0x89, 0x19, 0x01, 0x01,
+                       0x91, 0x07, 0xd0, 0x15, 0x89, 0x19, 0x01, 0x01,
+                       0x91, 0x07, 0xd0, 0x15, 0x89, 0x19, 0x01, 0x01,
+               },
+               nil,
+               []byte{0x95, 0x92, 0xcb, 0x41, 0x10, 0x43, 0x07, 0x87}},
+       { // 15
+               []byte{
+                       0x10, 0x07, 0xd0, 0x15, 0x98, 0x98, 0x01, 0x20,
+                       0x10, 0x07, 0xd0, 0x15, 0x98, 0x98, 0x01, 0x20,
+                       0x10, 0x07, 0xd0, 0x15, 0x98, 0x98, 0x01, 0x20,
+               },
+               nil,
+               []byte{0xa6, 0xb7, 0xff, 0x68, 0xa3, 0x18, 0xdd, 0xd3}},
+       { // 16
+               []byte{
+                       0x10, 0x07, 0x94, 0x04, 0x98, 0x19, 0x01, 0x01,
+                       0x10, 0x07, 0x94, 0x04, 0x98, 0x19, 0x01, 0x01,
+                       0x10, 0x07, 0x94, 0x04, 0x98, 0x19, 0x01, 0x01,
+               },
+               nil,
+               []byte{0x4d, 0x10, 0x21, 0x96, 0xc9, 0x14, 0xca, 0x16}},
+       { // 17
+               []byte{
+                       0x01, 0x07, 0x91, 0x04, 0x91, 0x19, 0x04, 0x01,
+                       0x01, 0x07, 0x91, 0x04, 0x91, 0x19, 0x04, 0x01,
+                       0x01, 0x07, 0x91, 0x04, 0x91, 0x19, 0x04, 0x01,
+               },
+               nil,
+               []byte{0x2d, 0xfa, 0x9f, 0x45, 0x73, 0x59, 0x49, 0x65}},
+       { // 18
+               []byte{
+                       0x01, 0x07, 0x91, 0x04, 0x91, 0x19, 0x01, 0x01,
+                       0x01, 0x07, 0x91, 0x04, 0x91, 0x19, 0x01, 0x01,
+                       0x01, 0x07, 0x91, 0x04, 0x91, 0x19, 0x01, 0x01,
+               },
+               nil,
+               []byte{0xb4, 0x66, 0x04, 0x81, 0x6c, 0x0e, 0x07, 0x74}},
+       { // 19
+               []byte{
+                       0x01, 0x07, 0x94, 0x04, 0x91, 0x19, 0x04, 0x01,
+                       0x01, 0x07, 0x94, 0x04, 0x91, 0x19, 0x04, 0x01,
+                       0x01, 0x07, 0x94, 0x04, 0x91, 0x19, 0x04, 0x01,
+               },
+               nil,
+               []byte{0x6e, 0x7e, 0x62, 0x21, 0xa4, 0xf3, 0x4e, 0x87}},
+       { // 20
+               []byte{
+                       0x19, 0x07, 0x92, 0x10, 0x98, 0x1a, 0x01, 0x01,
+                       0x19, 0x07, 0x92, 0x10, 0x98, 0x1a, 0x01, 0x01,
+                       0x19, 0x07, 0x92, 0x10, 0x98, 0x1a, 0x01, 0x01,
+               },
+               nil,
+               []byte{0xaa, 0x85, 0xe7, 0x46, 0x43, 0x23, 0x31, 0x99}},
+       { // 21
+               []byte{
+                       0x10, 0x07, 0x91, 0x19, 0x98, 0x19, 0x08, 0x01,
+                       0x10, 0x07, 0x91, 0x19, 0x98, 0x19, 0x08, 0x01,
+                       0x10, 0x07, 0x91, 0x19, 0x98, 0x19, 0x08, 0x01,
+               },
+               nil,
+               []byte{0x2e, 0x5a, 0x19, 0xdb, 0x4d, 0x19, 0x62, 0xd6}},
+       { // 22
+               []byte{
+                       0x10, 0x07, 0x91, 0x19, 0x98, 0x1a, 0x08, 0x01,
+                       0x10, 0x07, 0x91, 0x19, 0x98, 0x1a, 0x08, 0x01,
+                       0x10, 0x07, 0x91, 0x19, 0x98, 0x1a, 0x08, 0x01,
+               },
+               nil,
+               []byte{0x23, 0xa8, 0x66, 0xa8, 0x09, 0xd3, 0x08, 0x94}},
+       { // 23
+               []byte{
+                       0x10, 0x07, 0x92, 0x10, 0x98, 0x19, 0x01, 0x01,
+                       0x10, 0x07, 0x92, 0x10, 0x98, 0x19, 0x01, 0x01,
+                       0x10, 0x07, 0x92, 0x10, 0x98, 0x19, 0x01, 0x01,
+               },
+               nil,
+               []byte{0xd8, 0x12, 0xd9, 0x61, 0xf0, 0x17, 0xd3, 0x20}},
+       { // 24
+               []byte{
+                       0x10, 0x07, 0x91, 0x15, 0x98, 0x19, 0x01, 0x0b,
+                       0x10, 0x07, 0x91, 0x15, 0x98, 0x19, 0x01, 0x0b,
+                       0x10, 0x07, 0x91, 0x15, 0x98, 0x19, 0x01, 0x0b,
+               },
+               nil,
+               []byte{0x05, 0x56, 0x05, 0x81, 0x6e, 0x58, 0x60, 0x8f}},
+       { // 25
+               []byte{
+                       0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x01,
+                       0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x01,
+                       0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x01,
+               },
+               nil,
+               []byte{0xab, 0xd8, 0x8e, 0x8b, 0x1b, 0x77, 0x16, 0xf1}},
+       { // 26
+               []byte{
+                       0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x02,
+                       0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x02,
+                       0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x02,
+               },
+               nil,
+               []byte{0x53, 0x7a, 0xc9, 0x5b, 0xe6, 0x9d, 0xa1, 0xe1}},
+       { // 27
+               []byte{
+                       0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x08,
+                       0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x08,
+                       0x10, 0x04, 0x80, 0x15, 0x98, 0x19, 0x01, 0x08,
+               },
+               nil,
+               []byte{0xae, 0xd0, 0xf6, 0xae, 0x3c, 0x25, 0xcd, 0xd8}},
+       { // 28
+               []byte{
+                       0x10, 0x02, 0x91, 0x15, 0x98, 0x10, 0x01, 0x04,
+                       0x10, 0x02, 0x91, 0x15, 0x98, 0x10, 0x01, 0x04,
+                       0x10, 0x02, 0x91, 0x15, 0x98, 0x10, 0x01, 0x04,
+               },
+               nil,
+               []byte{0xb3, 0xe3, 0x5a, 0x5e, 0xe5, 0x3e, 0x7b, 0x8d}},
+       { // 29
+               []byte{
+                       0x10, 0x02, 0x91, 0x15, 0x98, 0x19, 0x01, 0x04,
+                       0x10, 0x02, 0x91, 0x15, 0x98, 0x19, 0x01, 0x04,
+                       0x10, 0x02, 0x91, 0x15, 0x98, 0x19, 0x01, 0x04,
+               },
+               nil,
+               []byte{0x61, 0xc7, 0x9c, 0x71, 0x92, 0x1a, 0x2e, 0xf8}},
+       { // 30
+               []byte{
+                       0x10, 0x02, 0x91, 0x15, 0x98, 0x10, 0x02, 0x01,
+                       0x10, 0x02, 0x91, 0x15, 0x98, 0x10, 0x02, 0x01,
+                       0x10, 0x02, 0x91, 0x15, 0x98, 0x10, 0x02, 0x01,
+               },
+               nil,
+               []byte{0xe2, 0xf5, 0x72, 0x8f, 0x09, 0x95, 0x01, 0x3c}},
+       { // 31
+               []byte{
+                       0x10, 0x02, 0x91, 0x16, 0x98, 0x10, 0x01, 0x01,
+                       0x10, 0x02, 0x91, 0x16, 0x98, 0x10, 0x01, 0x01,
+                       0x10, 0x02, 0x91, 0x16, 0x98, 0x10, 0x01, 0x01,
+               },
+               nil,
+               []byte{0x1a, 0xea, 0xc3, 0x9a, 0x61, 0xf0, 0xa4, 0x64}},
+}
+
+// Table A.4 Values To Be Used for the Substitution Table Known Answer Test
+var tableA4Tests = []CryptTest{
+       { // 0
+               []byte{
+                       0x7c, 0xa1, 0x10, 0x45, 0x4a, 0x1a, 0x6e, 0x57,
+                       0x7c, 0xa1, 0x10, 0x45, 0x4a, 0x1a, 0x6e, 0x57,
+                       0x7c, 0xa1, 0x10, 0x45, 0x4a, 0x1a, 0x6e, 0x57},
+               []byte{0x01, 0xa1, 0xd6, 0xd0, 0x39, 0x77, 0x67, 0x42},
+               []byte{0x69, 0x0f, 0x5b, 0x0d, 0x9a, 0x26, 0x93, 0x9b}},
+       { // 1
+               []byte{
+                       0x01, 0x31, 0xd9, 0x61, 0x9d, 0xc1, 0x37, 0x6e,
+                       0x01, 0x31, 0xd9, 0x61, 0x9d, 0xc1, 0x37, 0x6e,
+                       0x01, 0x31, 0xd9, 0x61, 0x9d, 0xc1, 0x37, 0x6e},
+               []byte{0x5c, 0xd5, 0x4c, 0xa8, 0x3d, 0xef, 0x57, 0xda},
+               []byte{0x7a, 0x38, 0x9d, 0x10, 0x35, 0x4b, 0xd2, 0x71}},
+       { // 2
+               []byte{
+                       0x07, 0xa1, 0x13, 0x3e, 0x4a, 0x0b, 0x26, 0x86,
+                       0x07, 0xa1, 0x13, 0x3e, 0x4a, 0x0b, 0x26, 0x86,
+                       0x07, 0xa1, 0x13, 0x3e, 0x4a, 0x0b, 0x26, 0x86},
+               []byte{0x02, 0x48, 0xd4, 0x38, 0x06, 0xf6, 0x71, 0x72},
+               []byte{0x86, 0x8e, 0xbb, 0x51, 0xca, 0xb4, 0x59, 0x9a}},
+       { // 3
+               []byte{
+                       0x38, 0x49, 0x67, 0x4c, 0x26, 0x02, 0x31, 0x9e,
+                       0x38, 0x49, 0x67, 0x4c, 0x26, 0x02, 0x31, 0x9e,
+                       0x38, 0x49, 0x67, 0x4c, 0x26, 0x02, 0x31, 0x9e},
+               []byte{0x51, 0x45, 0x4b, 0x58, 0x2d, 0xdf, 0x44, 0x0a},
+               []byte{0x71, 0x78, 0x87, 0x6e, 0x01, 0xf1, 0x9b, 0x2a}},
+       { // 4
+               []byte{
+                       0x04, 0xb9, 0x15, 0xba, 0x43, 0xfe, 0xb5, 0xb6,
+                       0x04, 0xb9, 0x15, 0xba, 0x43, 0xfe, 0xb5, 0xb6,
+                       0x04, 0xb9, 0x15, 0xba, 0x43, 0xfe, 0xb5, 0xb6},
+               []byte{0x42, 0xfd, 0x44, 0x30, 0x59, 0x57, 0x7f, 0xa2},
+               []byte{0xaf, 0x37, 0xfb, 0x42, 0x1f, 0x8c, 0x40, 0x95}},
+       { // 5
+               []byte{
+                       0x01, 0x13, 0xb9, 0x70, 0xfd, 0x34, 0xf2, 0xce,
+                       0x01, 0x13, 0xb9, 0x70, 0xfd, 0x34, 0xf2, 0xce,
+                       0x01, 0x13, 0xb9, 0x70, 0xfd, 0x34, 0xf2, 0xce},
+               []byte{0x05, 0x9b, 0x5e, 0x08, 0x51, 0xcf, 0x14, 0x3a},
+               []byte{0x86, 0xa5, 0x60, 0xf1, 0x0e, 0xc6, 0xd8, 0x5b}},
+       { // 6
+               []byte{
+                       0x01, 0x70, 0xf1, 0x75, 0x46, 0x8f, 0xb5, 0xe6,
+                       0x01, 0x70, 0xf1, 0x75, 0x46, 0x8f, 0xb5, 0xe6,
+                       0x01, 0x70, 0xf1, 0x75, 0x46, 0x8f, 0xb5, 0xe6},
+               []byte{0x07, 0x56, 0xd8, 0xe0, 0x77, 0x47, 0x61, 0xd2},
+               []byte{0x0c, 0xd3, 0xda, 0x02, 0x00, 0x21, 0xdc, 0x09}},
+       { // 7
+               []byte{
+                       0x43, 0x29, 0x7f, 0xad, 0x38, 0xe3, 0x73, 0xfe,
+                       0x43, 0x29, 0x7f, 0xad, 0x38, 0xe3, 0x73, 0xfe,
+                       0x43, 0x29, 0x7f, 0xad, 0x38, 0xe3, 0x73, 0xfe},
+               []byte{0x76, 0x25, 0x14, 0xb8, 0x29, 0xbf, 0x48, 0x6a},
+               []byte{0xea, 0x67, 0x6b, 0x2c, 0xb7, 0xdb, 0x2b, 0x7a}},
+       { // 8
+               []byte{
+                       0x07, 0xa7, 0x13, 0x70, 0x45, 0xda, 0x2a, 0x16,
+                       0x07, 0xa7, 0x13, 0x70, 0x45, 0xda, 0x2a, 0x16,
+                       0x07, 0xa7, 0x13, 0x70, 0x45, 0xda, 0x2a, 0x16},
+               []byte{0x3b, 0xdd, 0x11, 0x90, 0x49, 0x37, 0x28, 0x02},
+               []byte{0xdf, 0xd6, 0x4a, 0x81, 0x5c, 0xaf, 0x1a, 0x0f}},
+       { // 9
+               []byte{
+                       0x04, 0x68, 0x91, 0x04, 0xc2, 0xfd, 0x3b, 0x2f,
+                       0x04, 0x68, 0x91, 0x04, 0xc2, 0xfd, 0x3b, 0x2f,
+                       0x04, 0x68, 0x91, 0x04, 0xc2, 0xfd, 0x3b, 0x2f},
+               []byte{0x26, 0x95, 0x5f, 0x68, 0x35, 0xaf, 0x60, 0x9a},
+               []byte{0x5c, 0x51, 0x3c, 0x9c, 0x48, 0x86, 0xc0, 0x88}},
+       { // 10
+               []byte{
+                       0x37, 0xd0, 0x6b, 0xb5, 0x16, 0xcb, 0x75, 0x46,
+                       0x37, 0xd0, 0x6b, 0xb5, 0x16, 0xcb, 0x75, 0x46,
+                       0x37, 0xd0, 0x6b, 0xb5, 0x16, 0xcb, 0x75, 0x46},
+               []byte{0x16, 0x4d, 0x5e, 0x40, 0x4f, 0x27, 0x52, 0x32},
+               []byte{0x0a, 0x2a, 0xee, 0xae, 0x3f, 0xf4, 0xab, 0x77}},
+       { // 11
+               []byte{
+                       0x1f, 0x08, 0x26, 0x0d, 0x1a, 0xc2, 0x46, 0x5e,
+                       0x1f, 0x08, 0x26, 0x0d, 0x1a, 0xc2, 0x46, 0x5e,
+                       0x1f, 0x08, 0x26, 0x0d, 0x1a, 0xc2, 0x46, 0x5e},
+               []byte{0x6b, 0x05, 0x6e, 0x18, 0x75, 0x9f, 0x5c, 0xca},
+               []byte{0xef, 0x1b, 0xf0, 0x3e, 0x5d, 0xfa, 0x57, 0x5a}},
+       { // 12
+               []byte{
+                       0x58, 0x40, 0x23, 0x64, 0x1a, 0xba, 0x61, 0x76,
+                       0x58, 0x40, 0x23, 0x64, 0x1a, 0xba, 0x61, 0x76,
+                       0x58, 0x40, 0x23, 0x64, 0x1a, 0xba, 0x61, 0x76},
+               []byte{0x00, 0x4b, 0xd6, 0xef, 0x09, 0x17, 0x60, 0x62},
+               []byte{0x88, 0xbf, 0x0d, 0xb6, 0xd7, 0x0d, 0xee, 0x56}},
+       { // 13
+               []byte{
+                       0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xb0, 0x07,
+                       0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xb0, 0x07,
+                       0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xb0, 0x07},
+               []byte{0x48, 0x0d, 0x39, 0x00, 0x6e, 0xe7, 0x62, 0xf2},
+               []byte{0xa1, 0xf9, 0x91, 0x55, 0x41, 0x02, 0x0b, 0x56}},
+       { // 14
+               []byte{
+                       0x49, 0x79, 0x3e, 0xbc, 0x79, 0xb3, 0x25, 0x8f,
+                       0x49, 0x79, 0x3e, 0xbc, 0x79, 0xb3, 0x25, 0x8f,
+                       0x49, 0x79, 0x3e, 0xbc, 0x79, 0xb3, 0x25, 0x8f},
+               []byte{0x43, 0x75, 0x40, 0xc8, 0x69, 0x8f, 0x3c, 0xfa},
+               []byte{0x6f, 0xbf, 0x1c, 0xaf, 0xcf, 0xfd, 0x05, 0x56}},
+       { // 15
+               []byte{
+                       0x4f, 0xb0, 0x5e, 0x15, 0x15, 0xab, 0x73, 0xa7,
+                       0x4f, 0xb0, 0x5e, 0x15, 0x15, 0xab, 0x73, 0xa7,
+                       0x4f, 0xb0, 0x5e, 0x15, 0x15, 0xab, 0x73, 0xa7},
+               []byte{0x07, 0x2d, 0x43, 0xa0, 0x77, 0x07, 0x52, 0x92},
+               []byte{0x2f, 0x22, 0xe4, 0x9b, 0xab, 0x7c, 0xa1, 0xac}},
+       { // 16
+               []byte{
+                       0x49, 0xe9, 0x5d, 0x6d, 0x4c, 0xa2, 0x29, 0xbf,
+                       0x49, 0xe9, 0x5d, 0x6d, 0x4c, 0xa2, 0x29, 0xbf,
+                       0x49, 0xe9, 0x5d, 0x6d, 0x4c, 0xa2, 0x29, 0xbf},
+               []byte{0x02, 0xfe, 0x55, 0x77, 0x81, 0x17, 0xf1, 0x2a},
+               []byte{0x5a, 0x6b, 0x61, 0x2c, 0xc2, 0x6c, 0xce, 0x4a}},
+       { // 17
+               []byte{
+                       0x01, 0x83, 0x10, 0xdc, 0x40, 0x9b, 0x26, 0xd6,
+                       0x01, 0x83, 0x10, 0xdc, 0x40, 0x9b, 0x26, 0xd6,
+                       0x01, 0x83, 0x10, 0xdc, 0x40, 0x9b, 0x26, 0xd6},
+               []byte{0x1d, 0x9d, 0x5c, 0x50, 0x18, 0xf7, 0x28, 0xc2},
+               []byte{0x5f, 0x4c, 0x03, 0x8e, 0xd1, 0x2b, 0x2e, 0x41}},
+       { // 18
+               []byte{
+                       0x1c, 0x58, 0x7f, 0x1c, 0x13, 0x92, 0x4f, 0xef,
+                       0x1c, 0x58, 0x7f, 0x1c, 0x13, 0x92, 0x4f, 0xef,
+                       0x1c, 0x58, 0x7f, 0x1c, 0x13, 0x92, 0x4f, 0xef},
+               []byte{0x30, 0x55, 0x32, 0x28, 0x6d, 0x6f, 0x29, 0x5a},
+               []byte{0x63, 0xfa, 0xc0, 0xd0, 0x34, 0xd9, 0xf7, 0x93}},
+}
+
+// Use the known weak keys to test DES implementation
+func TestWeakKeys(t *testing.T) {
+       for i, tt := range weakKeyTests {
+               var encrypt = func(in []byte) (out []byte) {
+                       c, _ := NewCipher(tt.key)
+                       out = make([]byte, len(in))
+                       encryptBlock(c.subkeys[:], out, in)
+                       return
+               }
+
+               // Encrypting twice with a DES weak
+               // key should reproduce the original input
+               result := encrypt(tt.in)
+               result = encrypt(result)
+
+               if !bytes.Equal(result, tt.in) {
+                       t.Errorf("#%d: result: %x want: %x", i, result, tt.in)
+               }
+       }
+}
+
+// Use the known semi-weak key pairs to test DES implementation
+func TestSemiWeakKeyPairs(t *testing.T) {
+       for i, tt := range semiWeakKeyTests {
+               var encrypt = func(key, in []byte) (out []byte) {
+                       c, _ := NewCipher(key)
+                       out = make([]byte, len(in))
+                       encryptBlock(c.subkeys[:], out, in)
+                       return
+               }
+
+               // Encrypting with one member of the semi-weak pair
+               // and then encrypting the result with the other member
+               // should reproduce the original input.
+               result := encrypt(tt.key, tt.in)
+               result = encrypt(tt.out, result)
+
+               if !bytes.Equal(result, tt.in) {
+                       t.Errorf("#%d: result: %x want: %x", i, result, tt.in)
+               }
+       }
+}
+
+func TestDESEncryptBlock(t *testing.T) {
+       for i, tt := range encryptDESTests {
+               c, _ := NewCipher(tt.key)
+               out := make([]byte, len(tt.in))
+               encryptBlock(c.subkeys[:], out, tt.in)
+
+               if !bytes.Equal(out, tt.out) {
+                       t.Errorf("#%d: result: %x want: %x", i, out, tt.out)
+               }
+       }
+}
+
+func TestDESDecryptBlock(t *testing.T) {
+       for i, tt := range encryptDESTests {
+               c, _ := NewCipher(tt.key)
+               plain := make([]byte, len(tt.in))
+               decryptBlock(c.subkeys[:], plain, tt.out)
+
+               if !bytes.Equal(plain, tt.in) {
+                       t.Errorf("#%d: result: %x want: %x", i, plain, tt.in)
+               }
+       }
+}
+
+func TestEncryptTripleDES(t *testing.T) {
+       for i, tt := range encryptTripleDESTests {
+               c, _ := NewTripleDESCipher(tt.key)
+               out := make([]byte, len(tt.in))
+               c.Encrypt(out, tt.in)
+
+               if !bytes.Equal(out, tt.out) {
+                       t.Errorf("#%d: result: %x want: %x", i, out, tt.out)
+               }
+       }
+}
+
+func TestDecryptTripleDES(t *testing.T) {
+       for i, tt := range encryptTripleDESTests {
+               c, _ := NewTripleDESCipher(tt.key)
+
+               plain := make([]byte, len(tt.in))
+               c.Decrypt(plain, tt.out)
+
+               if !bytes.Equal(plain, tt.in) {
+                       t.Errorf("#%d: result: %x want: %x", i, plain, tt.in)
+               }
+       }
+}
+
+// Defined in Pub 800-20
+func TestVariablePlaintextKnownAnswer(t *testing.T) {
+       for i, tt := range tableA1Tests {
+               c, _ := NewTripleDESCipher(tableA1Key)
+
+               out := make([]byte, len(tt.in))
+               c.Encrypt(out, tt.in)
+
+               if !bytes.Equal(out, tt.out) {
+                       t.Errorf("#%d: result: %x want: %x", i, out, tt.out)
+               }
+       }
+}
+
+// Defined in Pub 800-20
+func TestVariableCiphertextKnownAnswer(t *testing.T) {
+       for i, tt := range tableA1Tests {
+               c, _ := NewTripleDESCipher(tableA1Key)
+
+               plain := make([]byte, len(tt.out))
+               c.Decrypt(plain, tt.out)
+
+               if !bytes.Equal(plain, tt.in) {
+                       t.Errorf("#%d: result: %x want: %x", i, plain, tt.in)
+               }
+       }
+}
+
+// Defined in Pub 800-20
+// Encrypting the Table A.1 ciphertext with the
+// 0x01... key produces the original plaintext
+func TestInversePermutationKnownAnswer(t *testing.T) {
+       for i, tt := range tableA1Tests {
+               c, _ := NewTripleDESCipher(tableA1Key)
+
+               plain := make([]byte, len(tt.in))
+               c.Encrypt(plain, tt.out)
+
+               if !bytes.Equal(plain, tt.in) {
+                       t.Errorf("#%d: result: %x want: %x", i, plain, tt.in)
+               }
+       }
+}
+
+// Defined in Pub 800-20
+// Decrypting the Table A.1 plaintext with the
+// 0x01... key produces the corresponding ciphertext
+func TestInitialPermutationKnownAnswer(t *testing.T) {
+       for i, tt := range tableA1Tests {
+               c, _ := NewTripleDESCipher(tableA1Key)
+
+               out := make([]byte, len(tt.in))
+               c.Decrypt(out, tt.in)
+
+               if !bytes.Equal(out, tt.out) {
+                       t.Errorf("#%d: result: %x want: %x", i, out, tt.out)
+               }
+       }
+}
+
+// Defined in Pub 800-20
+func TestVariableKeyKnownAnswerEncrypt(t *testing.T) {
+       for i, tt := range tableA2Tests {
+               c, _ := NewTripleDESCipher(tt.key)
+
+               out := make([]byte, len(tableA2Plaintext))
+               c.Encrypt(out, tableA2Plaintext)
+
+               if !bytes.Equal(out, tt.out) {
+                       t.Errorf("#%d: result: %x want: %x", i, out, tt.out)
+               }
+       }
+}
+
+// Defined in Pub 800-20
+func TestVariableKeyKnownAnswerDecrypt(t *testing.T) {
+       for i, tt := range tableA2Tests {
+               c, _ := NewTripleDESCipher(tt.key)
+
+               out := make([]byte, len(tt.out))
+               c.Decrypt(out, tt.out)
+
+               if !bytes.Equal(out, tableA2Plaintext) {
+                       t.Errorf("#%d: result: %x want: %x", i, out, tableA2Plaintext)
+               }
+       }
+}
+
+// Defined in Pub 800-20
+func TestPermutationOperationKnownAnswerEncrypt(t *testing.T) {
+       for i, tt := range tableA3Tests {
+               c, _ := NewTripleDESCipher(tt.key)
+
+               out := make([]byte, len(tableA3Plaintext))
+               c.Encrypt(out, tableA3Plaintext)
+
+               if !bytes.Equal(out, tt.out) {
+                       t.Errorf("#%d: result: %x want: %x", i, out, tt.out)
+               }
+       }
+}
+
+// Defined in Pub 800-20
+func TestPermutationOperationKnownAnswerDecrypt(t *testing.T) {
+       for i, tt := range tableA3Tests {
+               c, _ := NewTripleDESCipher(tt.key)
+
+               out := make([]byte, len(tt.out))
+               c.Decrypt(out, tt.out)
+
+               if !bytes.Equal(out, tableA3Plaintext) {
+                       t.Errorf("#%d: result: %x want: %x", i, out, tableA3Plaintext)
+               }
+       }
+}
+
+// Defined in Pub 800-20
+func TestSubstitutionTableKnownAnswerEncrypt(t *testing.T) {
+       for i, tt := range tableA4Tests {
+               c, _ := NewTripleDESCipher(tt.key)
+
+               out := make([]byte, len(tt.in))
+               c.Encrypt(out, tt.in)
+
+               if !bytes.Equal(out, tt.out) {
+                       t.Errorf("#%d: result: %x want: %x", i, out, tt.out)
+               }
+       }
+}
+
+// Defined in Pub 800-20
+func TestSubstitutionTableKnownAnswerDecrypt(t *testing.T) {
+       for i, tt := range tableA4Tests {
+               c, _ := NewTripleDESCipher(tt.key)
+
+               out := make([]byte, len(tt.out))
+               c.Decrypt(out, tt.out)
+
+               if !bytes.Equal(out, tt.in) {
+                       t.Errorf("#%d: result: %x want: %x", i, out, tt.in)
+               }
+       }
+}
index 1f37849c5d5ee1b467e8e297f6a0a3d03202ea3d..7bce1bc967538102504bba204ec6d9a5b0017ddf 100644 (file)
@@ -37,7 +37,7 @@ var one = new(big.Int).SetInt64(1)
 // curve using the procedure given in [NSA] A.2.1.
 func randFieldElement(c *elliptic.Curve, rand io.Reader) (k *big.Int, err os.Error) {
        b := make([]byte, c.BitSize/8+8)
-       _, err = rand.Read(b)
+       _, err = io.ReadFull(rand, b)
        if err != nil {
                return
        }
index 66b72c07662f78915d3dd0b0d96f26c5883b7dcf..3a06aa8b148954a4301d47084391de05de94291a 100644 (file)
@@ -32,7 +32,7 @@ func (r *devReader) Read(b []byte) (n int, err os.Error) {
        r.mu.Lock()
        defer r.mu.Unlock()
        if r.f == nil {
-               f, err := os.Open(r.name, os.O_RDONLY, 0)
+               f, err := os.Open(r.name)
                if f == nil {
                        return 0, err
                }
index 2eaadee24c2e964d042e1d94109d5a4fc1ff3762..9a7184127db0689533a87351623524ee50b75eef 100644 (file)
@@ -127,7 +127,7 @@ func nonZeroRandomBytes(s []byte, rand io.Reader) (err os.Error) {
 
        for i := 0; i < len(s); i++ {
                for s[i] == 0 {
-                       _, err = rand.Read(s[i : i+1])
+                       _, err = io.ReadFull(rand, s[i:i+1])
                        if err != nil {
                                return
                        }
index faf914991d06310b54d6c2ddfbfc1d0680128a3c..b3b212c2066ca9bb0f4e4cb884f947a646047a8b 100644 (file)
@@ -13,6 +13,7 @@ import (
        "hash"
        "io"
        "os"
+       "sync"
 )
 
 var bigZero = big.NewInt(0)
@@ -91,15 +92,21 @@ type PublicKey struct {
 type PrivateKey struct {
        PublicKey          // public part.
        D         *big.Int // private exponent
-       P, Q      *big.Int // prime factors of N
+       P, Q, R   *big.Int // prime factors of N (R may be nil)
+
+       rwMutex    sync.RWMutex // protects the following
+       dP, dQ, dR *big.Int     // D mod (P-1) (or mod Q-1 etc) 
+       qInv       *big.Int     // q^-1 mod p
+       pq         *big.Int     // P*Q
+       tr         *big.Int     // pq·tr ≡ 1 mod r
 }
 
 // Validate performs basic sanity checks on the key.
 // It returns nil if the key is valid, or else an os.Error describing a problem.
 
-func (priv PrivateKey) Validate() os.Error {
-       // Check that p and q are prime. Note that this is just a sanity
-       // check. Since the random witnesses chosen by ProbablyPrime are
+func (priv *PrivateKey) Validate() os.Error {
+       // Check that p, q and, maybe, r are prime. Note that this is just a
+       // sanity check. Since the random witnesses chosen by ProbablyPrime are
        // deterministic, given the candidate number, it's easy for an attack
        // to generate composites that pass this test.
        if !big.ProbablyPrime(priv.P, 20) {
@@ -108,16 +115,26 @@ func (priv PrivateKey) Validate() os.Error {
        if !big.ProbablyPrime(priv.Q, 20) {
                return os.ErrorString("Q is composite")
        }
+       if priv.R != nil && !big.ProbablyPrime(priv.R, 20) {
+               return os.ErrorString("R is composite")
+       }
 
-       // Check that p*q == n.
+       // Check that p*q*r == n.
        modulus := new(big.Int).Mul(priv.P, priv.Q)
+       if priv.R != nil {
+               modulus.Mul(modulus, priv.R)
+       }
        if modulus.Cmp(priv.N) != 0 {
                return os.ErrorString("invalid modulus")
        }
-       // Check that e and totient(p, q) are coprime.
+       // Check that e and totient(p, q, r) are coprime.
        pminus1 := new(big.Int).Sub(priv.P, bigOne)
        qminus1 := new(big.Int).Sub(priv.Q, bigOne)
        totient := new(big.Int).Mul(pminus1, qminus1)
+       if priv.R != nil {
+               rminus1 := new(big.Int).Sub(priv.R, bigOne)
+               totient.Mul(totient, rminus1)
+       }
        e := big.NewInt(int64(priv.E))
        gcd := new(big.Int)
        x := new(big.Int)
@@ -126,7 +143,7 @@ func (priv PrivateKey) Validate() os.Error {
        if gcd.Cmp(bigOne) != 0 {
                return os.ErrorString("invalid public exponent E")
        }
-       // Check that de ≡ 1 (mod totient(p, q))
+       // Check that de ≡ 1 (mod totient(p, q, r))
        de := new(big.Int).Mul(priv.D, e)
        de.Mod(de, totient)
        if de.Cmp(bigOne) != 0 {
@@ -135,7 +152,7 @@ func (priv PrivateKey) Validate() os.Error {
        return nil
 }
 
-// GenerateKeyPair generates an RSA keypair of the given bit size.
+// GenerateKey generates an RSA keypair of the given bit size.
 func GenerateKey(rand io.Reader, bits int) (priv *PrivateKey, err os.Error) {
        priv = new(PrivateKey)
        // Smaller public exponents lead to faster public key
@@ -191,6 +208,77 @@ func GenerateKey(rand io.Reader, bits int) (priv *PrivateKey, err os.Error) {
        return
 }
 
+// Generate3PrimeKey generates a 3-prime RSA keypair of the given bit size, as
+// suggested in [1]. Although the public keys are compatible (actually,
+// indistinguishable) from the 2-prime case, the private keys are not. Thus it
+// may not be possible to export 3-prime private keys in certain formats or to
+// subsequently import them into other code.
+//
+// Table 1 in [2] suggests that size should be >= 1024 when using 3 primes.
+//
+// [1] US patent 4405829 (1972, expired)
+// [2] http://www.cacr.math.uwaterloo.ca/techreports/2006/cacr2006-16.pdf
+func Generate3PrimeKey(rand io.Reader, bits int) (priv *PrivateKey, err os.Error) {
+       priv = new(PrivateKey)
+       priv.E = 3
+
+       pminus1 := new(big.Int)
+       qminus1 := new(big.Int)
+       rminus1 := new(big.Int)
+       totient := new(big.Int)
+
+       for {
+               p, err := randomPrime(rand, bits/3)
+               if err != nil {
+                       return nil, err
+               }
+
+               todo := bits - p.BitLen()
+               q, err := randomPrime(rand, todo/2)
+               if err != nil {
+                       return nil, err
+               }
+
+               todo -= q.BitLen()
+               r, err := randomPrime(rand, todo)
+               if err != nil {
+                       return nil, err
+               }
+
+               if p.Cmp(q) == 0 ||
+                       q.Cmp(r) == 0 ||
+                       r.Cmp(p) == 0 {
+                       continue
+               }
+
+               n := new(big.Int).Mul(p, q)
+               n.Mul(n, r)
+               pminus1.Sub(p, bigOne)
+               qminus1.Sub(q, bigOne)
+               rminus1.Sub(r, bigOne)
+               totient.Mul(pminus1, qminus1)
+               totient.Mul(totient, rminus1)
+
+               g := new(big.Int)
+               priv.D = new(big.Int)
+               y := new(big.Int)
+               e := big.NewInt(int64(priv.E))
+               big.GcdInt(g, priv.D, y, e, totient)
+
+               if g.Cmp(bigOne) == 0 {
+                       priv.D.Add(priv.D, totient)
+                       priv.P = p
+                       priv.Q = q
+                       priv.R = r
+                       priv.N = n
+
+                       break
+               }
+       }
+
+       return
+}
+
 // incCounter increments a four byte, big-endian counter.
 func incCounter(c *[4]byte) {
        if c[3]++; c[3] != 0 {
@@ -321,6 +409,26 @@ func modInverse(a, n *big.Int) (ia *big.Int, ok bool) {
        return x, true
 }
 
+// precompute performs some calculations that speed up private key operations
+// in the future.
+func (priv *PrivateKey) precompute() {
+       priv.dP = new(big.Int).Sub(priv.P, bigOne)
+       priv.dP.Mod(priv.D, priv.dP)
+
+       priv.dQ = new(big.Int).Sub(priv.Q, bigOne)
+       priv.dQ.Mod(priv.D, priv.dQ)
+
+       priv.qInv = new(big.Int).ModInverse(priv.Q, priv.P)
+
+       if priv.R != nil {
+               priv.dR = new(big.Int).Sub(priv.R, bigOne)
+               priv.dR.Mod(priv.D, priv.dR)
+
+               priv.pq = new(big.Int).Mul(priv.P, priv.Q)
+               priv.tr = new(big.Int).ModInverse(priv.pq, priv.R)
+       }
+}
+
 // decrypt performs an RSA decryption, resulting in a plaintext integer. If a
 // random source is given, RSA blinding is used.
 func decrypt(rand io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err os.Error) {
@@ -359,7 +467,48 @@ func decrypt(rand io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err os.E
                c.Mod(c, priv.N)
        }
 
-       m = new(big.Int).Exp(c, priv.D, priv.N)
+       priv.rwMutex.RLock()
+
+       if priv.dP == nil && priv.P != nil {
+               priv.rwMutex.RUnlock()
+               priv.rwMutex.Lock()
+               if priv.dP == nil && priv.P != nil {
+                       priv.precompute()
+               }
+               priv.rwMutex.Unlock()
+               priv.rwMutex.RLock()
+       }
+
+       if priv.dP == nil {
+               m = new(big.Int).Exp(c, priv.D, priv.N)
+       } else {
+               // We have the precalculated values needed for the CRT.
+               m = new(big.Int).Exp(c, priv.dP, priv.P)
+               m2 := new(big.Int).Exp(c, priv.dQ, priv.Q)
+               m.Sub(m, m2)
+               if m.Sign() < 0 {
+                       m.Add(m, priv.P)
+               }
+               m.Mul(m, priv.qInv)
+               m.Mod(m, priv.P)
+               m.Mul(m, priv.Q)
+               m.Add(m, m2)
+
+               if priv.dR != nil {
+                       // 3-prime CRT.
+                       m2.Exp(c, priv.dR, priv.R)
+                       m2.Sub(m2, m)
+                       m2.Mul(m2, priv.tr)
+                       m2.Mod(m2, priv.R)
+                       if m2.Sign() < 0 {
+                               m2.Add(m2, priv.R)
+                       }
+                       m2.Mul(m2, priv.pq)
+                       m.Add(m, m2)
+               }
+       }
+
+       priv.rwMutex.RUnlock()
 
        if ir != nil {
                // Unblind.
index bf7c05137a38a4e75b6d7c60bd39407326fb0e27..d8a936eb68f03739abd511360e4d0145e14677a1 100644 (file)
@@ -13,28 +13,48 @@ import (
 )
 
 func TestKeyGeneration(t *testing.T) {
-       random := rand.Reader
-
        size := 1024
        if testing.Short() {
                size = 128
        }
-       priv, err := GenerateKey(random, size)
+       priv, err := GenerateKey(rand.Reader, size)
+       if err != nil {
+               t.Errorf("failed to generate key")
+       }
+       testKeyBasics(t, priv)
+}
+
+func Test3PrimeKeyGeneration(t *testing.T) {
+       if testing.Short() {
+               return
+       }
+
+       size := 768
+       priv, err := Generate3PrimeKey(rand.Reader, size)
        if err != nil {
                t.Errorf("failed to generate key")
        }
+       testKeyBasics(t, priv)
+}
+
+func testKeyBasics(t *testing.T, priv *PrivateKey) {
+       if err := priv.Validate(); err != nil {
+               t.Errorf("Validate() failed: %s", err)
+       }
+
        pub := &priv.PublicKey
        m := big.NewInt(42)
        c := encrypt(new(big.Int), pub, m)
        m2, err := decrypt(nil, priv, c)
        if err != nil {
                t.Errorf("error while decrypting: %s", err)
+               return
        }
        if m.Cmp(m2) != 0 {
-               t.Errorf("got:%v, want:%v (%s)", m2, m, priv)
+               t.Errorf("got:%v, want:%v (%+v)", m2, m, priv)
        }
 
-       m3, err := decrypt(random, priv, c)
+       m3, err := decrypt(rand.Reader, priv, c)
        if err != nil {
                t.Errorf("error while decrypting (blind): %s", err)
        }
@@ -43,6 +63,57 @@ func TestKeyGeneration(t *testing.T) {
        }
 }
 
+func fromBase10(base10 string) *big.Int {
+       i := new(big.Int)
+       i.SetString(base10, 10)
+       return i
+}
+
+func BenchmarkRSA2048Decrypt(b *testing.B) {
+       b.StopTimer()
+       priv := &PrivateKey{
+               PublicKey: PublicKey{
+                       N: fromBase10("14314132931241006650998084889274020608918049032671858325988396851334124245188214251956198731333464217832226406088020736932173064754214329009979944037640912127943488972644697423190955557435910767690712778463524983667852819010259499695177313115447116110358524558307947613422897787329221478860907963827160223559690523660574329011927531289655711860504630573766609239332569210831325633840174683944553667352219670930408593321661375473885147973879086994006440025257225431977751512374815915392249179976902953721486040787792801849818254465486633791826766873076617116727073077821584676715609985777563958286637185868165868520557"),
+                       E: 3,
+               },
+               D: fromBase10("9542755287494004433998723259516013739278699355114572217325597900889416163458809501304132487555642811888150937392013824621448709836142886006653296025093941418628992648429798282127303704957273845127141852309016655778568546006839666463451542076964744073572349705538631742281931858219480985907271975884773482372966847639853897890615456605598071088189838676728836833012254065983259638538107719766738032720239892094196108713378822882383694456030043492571063441943847195939549773271694647657549658603365629458610273821292232646334717612674519997533901052790334279661754176490593041941863932308687197618671528035670452762731"),
+               P: fromBase10("130903255182996722426771613606077755295583329135067340152947172868415809027537376306193179624298874215608270802054347609836776473930072411958753044562214537013874103802006369634761074377213995983876788718033850153719421695468704276694983032644416930879093914927146648402139231293035971427838068945045019075433"),
+               Q: fromBase10("109348945610485453577574767652527472924289229538286649661240938988020367005475727988253438647560958573506159449538793540472829815903949343191091817779240101054552748665267574271163617694640513549693841337820602726596756351006149518830932261246698766355347898158548465400674856021497190430791824869615170301029"),
+       }
+       priv.precompute()
+
+       c := fromBase10("1000")
+
+       b.StartTimer()
+
+       for i := 0; i < b.N; i++ {
+               decrypt(nil, priv, c)
+       }
+}
+
+func Benchmark3PrimeRSA2048Decrypt(b *testing.B) {
+       b.StopTimer()
+       priv := &PrivateKey{
+               PublicKey: PublicKey{
+                       N: fromBase10("16346378922382193400538269749936049106320265317511766357599732575277382844051791096569333808598921852351577762718529818072849191122419410612033592401403764925096136759934497687765453905884149505175426053037420486697072448609022753683683718057795566811401938833367954642951433473337066311978821180526439641496973296037000052546108507805269279414789035461158073156772151892452251106173507240488993608650881929629163465099476849643165682709047462010581308719577053905787496296934240246311806555924593059995202856826239801816771116902778517096212527979497399966526283516447337775509777558018145573127308919204297111496233"),
+                       E: 3,
+               },
+               D: fromBase10("10897585948254795600358846499957366070880176878341177571733155050184921896034527397712889205732614568234385175145686545381899460748279607074689061600935843283397424506622998458510302603922766336783617368686090042765718290914099334449154829375179958369993407724946186243249568928237086215759259909861748642124071874879861299389874230489928271621259294894142840428407196932444474088857746123104978617098858619445675532587787023228852383149557470077802718705420275739737958953794088728369933811184572620857678792001136676902250566845618813972833750098806496641114644760255910789397593428910198080271317419213080834885003"),
+               P: fromBase10("1025363189502892836833747188838978207017355117492483312747347695538428729137306368764177201532277413433182799108299960196606011786562992097313508180436744488171474690412562218914213688661311117337381958560443"),
+               Q: fromBase10("3467903426626310123395340254094941045497208049900750380025518552334536945536837294961497712862519984786362199788654739924501424784631315081391467293694361474867825728031147665777546570788493758372218019373"),
+               R: fromBase10("4597024781409332673052708605078359346966325141767460991205742124888960305710298765592730135879076084498363772408626791576005136245060321874472727132746643162385746062759369754202494417496879741537284589047"),
+       }
+       priv.precompute()
+
+       c := fromBase10("1000")
+
+       b.StartTimer()
+
+       for i := 0; i < b.N; i++ {
+               decrypt(nil, priv, c)
+       }
+}
+
 type testEncryptOAEPMessage struct {
        in   []byte
        seed []byte
@@ -85,10 +156,12 @@ func TestDecryptOAEP(t *testing.T) {
        for i, test := range testEncryptOAEPData {
                n.SetString(test.modulus, 16)
                d.SetString(test.d, 16)
-               private := PrivateKey{PublicKey{n, test.e}, d, nil, nil}
+               private := new(PrivateKey)
+               private.PublicKey = PublicKey{n, test.e}
+               private.D = d
 
                for j, message := range test.msgs {
-                       out, err := DecryptOAEP(sha1, nil, &private, message.out, nil)
+                       out, err := DecryptOAEP(sha1, nil, private, message.out, nil)
                        if err != nil {
                                t.Errorf("#%d,%d error: %s", i, j, err)
                        } else if bytes.Compare(out, message.in) != 0 {
@@ -96,7 +169,7 @@ func TestDecryptOAEP(t *testing.T) {
                        }
 
                        // Decrypt with blinding.
-                       out, err = DecryptOAEP(sha1, random, &private, message.out, nil)
+                       out, err = DecryptOAEP(sha1, random, private, message.out, nil)
                        if err != nil {
                                t.Errorf("#%d,%d (blind) error: %s", i, j, err)
                        } else if bytes.Compare(out, message.in) != 0 {
index ee77f949fc038b4d01d3d053a0e775c98b5b8ede..5b8c700e5f909bf949280d1f2f2187ede8ae1dbb 100644 (file)
@@ -50,7 +50,7 @@ func main() {
                return
        }
 
-       certOut, err := os.Open("cert.pem", os.O_WRONLY|os.O_CREAT, 0644)
+       certOut, err := os.Create("cert.pem")
        if err != nil {
                log.Fatalf("failed to open cert.pem for writing: %s", err)
                return
@@ -59,7 +59,7 @@ func main() {
        certOut.Close()
        log.Print("written cert.pem\n")
 
-       keyOut, err := os.Open("key.pem", os.O_WRONLY|os.O_CREAT, 0600)
+       keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREAT|os.O_TRUNC, 0600)
        if err != nil {
                log.Print("failed to open key.pem for writing:", err)
                return
index f66449c822535f15839a2c376f4256552615a752..7de44bbd244df80afe6451ef0d8754e22e60f4d7 100644 (file)
@@ -124,7 +124,16 @@ func LoadX509KeyPair(certFile string, keyFile string) (cert Certificate, err os.
        if err != nil {
                return
        }
+       keyPEMBlock, err := ioutil.ReadFile(keyFile)
+       if err != nil {
+               return
+       }
+       return X509KeyPair(certPEMBlock, keyPEMBlock)
+}
 
+// X509KeyPair parses a public/private key pair from a pair of
+// PEM encoded data.
+func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (cert Certificate, err os.Error) {
        var certDERBlock *pem.Block
        for {
                certDERBlock, certPEMBlock = pem.Decode(certPEMBlock)
@@ -141,11 +150,6 @@ func LoadX509KeyPair(certFile string, keyFile string) (cert Certificate, err os.
                return
        }
 
-       keyPEMBlock, err := ioutil.ReadFile(keyFile)
-       if err != nil {
-               return
-       }
-
        keyDERBlock, _ := pem.Decode(keyPEMBlock)
        if keyDERBlock == nil {
                err = os.ErrorString("crypto/tls: failed to parse key PEM data")
index 853bcde9ad8053bbdd8eaab05b886968928f38c9..6825030d6f97063fb5e9e60a96bc51cd49409351 100644 (file)
@@ -54,20 +54,21 @@ func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err os.Error) {
                return
        }
 
-       key = &rsa.PrivateKey{
-               PublicKey: rsa.PublicKey{
-                       E: priv.E,
-                       N: new(big.Int).SetBytes(priv.N.Bytes),
-               },
-               D: new(big.Int).SetBytes(priv.D.Bytes),
-               P: new(big.Int).SetBytes(priv.P.Bytes),
-               Q: new(big.Int).SetBytes(priv.Q.Bytes),
+       key = new(rsa.PrivateKey)
+       key.PublicKey = rsa.PublicKey{
+               E: priv.E,
+               N: new(big.Int).SetBytes(priv.N.Bytes),
        }
 
+       key.D = new(big.Int).SetBytes(priv.D.Bytes)
+       key.P = new(big.Int).SetBytes(priv.P.Bytes)
+       key.Q = new(big.Int).SetBytes(priv.Q.Bytes)
+
        err = key.Validate()
        if err != nil {
                return nil, err
        }
+
        return
 }
 
index 57889e7e12201dc2bd961695051a63496c8d278c..d9511b863fbbdfad3ccf3aaaa1e084cddcb5d748 100644 (file)
@@ -11,7 +11,6 @@ import (
        "crypto/rsa"
        "encoding/hex"
        "encoding/pem"
-       "reflect"
        "testing"
        "time"
 )
@@ -22,7 +21,11 @@ func TestParsePKCS1PrivateKey(t *testing.T) {
        if err != nil {
                t.Errorf("Failed to parse private key: %s", err)
        }
-       if !reflect.DeepEqual(priv, rsaPrivateKey) {
+       if priv.PublicKey.N.Cmp(rsaPrivateKey.PublicKey.N) != 0 ||
+               priv.PublicKey.E != rsaPrivateKey.PublicKey.E ||
+               priv.D.Cmp(rsaPrivateKey.D) != 0 ||
+               priv.P.Cmp(rsaPrivateKey.P) != 0 ||
+               priv.Q.Cmp(rsaPrivateKey.Q) != 0 {
                t.Errorf("got:%+v want:%+v", priv, rsaPrivateKey)
        }
 }
index e69317a75faf62dfb37b7c9cfb97aaee01a442f0..6fdcda6d485faf4b6f3db39c79c5b45353e953b1 100644 (file)
@@ -144,7 +144,7 @@ func (e *FormatError) String() string {
 
 // Open opens the named file using os.Open and prepares it for use as an ELF binary.
 func Open(name string) (*File, os.Error) {
-       f, err := os.Open(name, os.O_RDONLY, 0)
+       f, err := os.Open(name)
        if err != nil {
                return nil, err
        }
@@ -228,7 +228,7 @@ func NewFile(r io.ReaderAt) (*File, os.Error) {
        switch f.Class {
        case ELFCLASS32:
                hdr := new(Header32)
-               sr.Seek(0, 0)
+               sr.Seek(0, os.SEEK_SET)
                if err := binary.Read(sr, f.ByteOrder, hdr); err != nil {
                        return nil, err
                }
@@ -243,7 +243,7 @@ func NewFile(r io.ReaderAt) (*File, os.Error) {
                shstrndx = int(hdr.Shstrndx)
        case ELFCLASS64:
                hdr := new(Header64)
-               sr.Seek(0, 0)
+               sr.Seek(0, os.SEEK_SET)
                if err := binary.Read(sr, f.ByteOrder, hdr); err != nil {
                        return nil, err
                }
@@ -269,7 +269,7 @@ func NewFile(r io.ReaderAt) (*File, os.Error) {
        names := make([]uint32, shnum)
        for i := 0; i < shnum; i++ {
                off := shoff + int64(i)*int64(shentsize)
-               sr.Seek(off, 0)
+               sr.Seek(off, os.SEEK_SET)
                s := new(Section)
                switch f.Class {
                case ELFCLASS32:
index fd8da9449ad0bd1765c06eebcc33bf10228a9d40..a777d873cf2cd2e47eb90e9683e81d7545c2fae3 100644 (file)
@@ -159,7 +159,7 @@ func (e *FormatError) String() string {
 
 // Open opens the named file using os.Open and prepares it for use as a Mach-O binary.
 func Open(name string) (*File, os.Error) {
-       f, err := os.Open(name, os.O_RDONLY, 0)
+       f, err := os.Open(name)
        if err != nil {
                return nil, err
        }
index 1bcbdc5e9a5706af9af14d09b14b255ca94b33f7..6a14e50f9609b8da4be68f8170aa8a82860b27db 100644 (file)
@@ -87,7 +87,7 @@ func (e *FormatError) String() string {
 
 // Open opens the named file using os.Open and prepares it for use as a PE binary.
 func Open(name string) (*File, os.Error) {
-       f, err := os.Open(name, os.O_RDONLY, 0)
+       f, err := os.Open(name)
        if err != nil {
                return nil, err
        }
@@ -132,7 +132,7 @@ func NewFile(r io.ReaderAt) (*File, os.Error) {
        } else {
                base = int64(0)
        }
-       sr.Seek(base, 0)
+       sr.Seek(base, os.SEEK_SET)
        if err := binary.Read(sr, binary.LittleEndian, &f.FileHeader); err != nil {
                return nil, err
        }
@@ -140,7 +140,7 @@ func NewFile(r io.ReaderAt) (*File, os.Error) {
                return nil, os.NewError("Invalid PE File Format.")
        }
        // get symbol string table
-       sr.Seek(int64(f.FileHeader.PointerToSymbolTable+18*f.FileHeader.NumberOfSymbols), 0)
+       sr.Seek(int64(f.FileHeader.PointerToSymbolTable+18*f.FileHeader.NumberOfSymbols), os.SEEK_SET)
        var l uint32
        if err := binary.Read(sr, binary.LittleEndian, &l); err != nil {
                return nil, err
@@ -149,9 +149,9 @@ func NewFile(r io.ReaderAt) (*File, os.Error) {
        if _, err := r.ReadAt(ss, int64(f.FileHeader.PointerToSymbolTable+18*f.FileHeader.NumberOfSymbols)); err != nil {
                return nil, err
        }
-       sr.Seek(base, 0)
+       sr.Seek(base, os.SEEK_SET)
        binary.Read(sr, binary.LittleEndian, &f.FileHeader)
-       sr.Seek(int64(f.FileHeader.SizeOfOptionalHeader), 1) //Skip OptionalHeader
+       sr.Seek(int64(f.FileHeader.SizeOfOptionalHeader), os.SEEK_CUR) //Skip OptionalHeader
        f.Sections = make([]*Section, f.FileHeader.NumberOfSections)
        for i := 0; i < int(f.FileHeader.NumberOfSections); i++ {
                sh := new(SectionHeader32)
index 6890a2221ef4b3496c6d7b3f32963afac8b906f6..17c8fa529f53aad2cb85d62bb57c8819962a77c9 100644 (file)
@@ -1184,7 +1184,7 @@ func (p *process) attachThread(tid int) (*thread, os.Error) {
 // attachAllThreads attaches to all threads in a process.
 func (p *process) attachAllThreads() os.Error {
        taskPath := "/proc/" + strconv.Itoa(p.pid) + "/task"
-       taskDir, err := os.Open(taskPath, os.O_RDONLY, 0)
+       taskDir, err := os.Open(taskPath)
        if err != nil {
                return err
        }
index 44e3b65bec87f24c18e6d5733785a657c41d8809..5398eb8e0ca35b4f908725f9e479f65bdb307dca 100644 (file)
@@ -2,9 +2,13 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// The exec package runs external commands.
+// The exec package runs external commands. It wraps os.StartProcess
+// to make it easier to remap stdin and stdout, connect I/O with pipes,
+// and do other adjustments.
 package exec
 
+// BUG(r): This package should be made even easier to use or merged into os.
+
 import (
        "os"
        "strconv"
@@ -49,7 +53,7 @@ func modeToFiles(mode, fd int) (*os.File, *os.File, os.Error) {
                if fd == 0 {
                        rw = os.O_RDONLY
                }
-               f, err := os.Open(os.DevNull, rw, 0)
+               f, err := os.OpenFile(os.DevNull, rw, 0)
                return f, nil, err
        case PassThrough:
                switch fd {
index 896dedf05c75880fe030ab6cb88662d711043cfd..d48936ac178a865b9e5de82287e60036c5ca36c7 100644 (file)
@@ -53,7 +53,7 @@ func readAuth(displayStr string) (name, data string, err os.Error) {
                }
                fn = home + "/.Xauthority"
        }
-       r, err := os.Open(fn, os.O_RDONLY, 0444)
+       r, err := os.Open(fn)
        if err != nil {
                return
        }
index ba056e88bafc021bb4d5a8363dceeaee0d3abbf5..813d3a875a6c85ed93d1dfee82ebff38e13f2e7a 100644 (file)
@@ -170,7 +170,7 @@ func cmdLoad(args []byte) os.Error {
        }
 
        // Get symbols
-       f, err := os.Open(fname, os.O_RDONLY, 0)
+       f, err := os.Open(fname)
        if err != nil {
                tproc.Detach()
                return err
index 4d308ac342dea8371f877f1d4363244b837bc3d2..3766c838a91009c44fb0ed188eaaf7a488fd163f 100644 (file)
@@ -139,7 +139,17 @@ var fmttests = []struct {
        {"%5s", "abc", "  abc"},
        {"%2s", "\u263a", " \u263a"},
        {"%-5s", "abc", "abc  "},
+       {"%-8q", "abc", `"abc"   `},
        {"%05s", "abc", "00abc"},
+       {"%08q", "abc", `000"abc"`},
+       {"%5s", "abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz"},
+       {"%.5s", "abcdefghijklmnopqrstuvwxyz", "abcde"},
+       {"%.5s", "日本語日本語", "日本語日本"},
+       {"%.5s", []byte("日本語日本語"), "日本語日本"},
+       {"%.5q", "abcdefghijklmnopqrstuvwxyz", `"abcde"`},
+       {"%.3q", "日本語日本語", `"\u65e5\u672c\u8a9e"`},
+       {"%.3q", []byte("日本語日本語"), `"\u65e5\u672c\u8a9e"`},
+       {"%10.1q", "日本語日本語", `  "\u65e5"`},
 
        // integers
        {"%d", 12345, "12345"},
index caaa7ac1a8af36ed2fb0ac13ef69911f33971954..f9d2b4fcaf6b177425d769c7f2fc62aef9ccc7dc 100644 (file)
@@ -235,13 +235,24 @@ func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) {
        f.pad(buf[i:])
 }
 
-// fmt_s formats a string.
-func (f *fmt) fmt_s(s string) {
-       if f.precPresent {
-               if f.prec < len(s) {
-                       s = s[0:f.prec]
+// truncate truncates the string to the specified precision, if present.
+func (f *fmt) truncate(s string) string {
+       if f.precPresent && f.prec < utf8.RuneCountInString(s) {
+               n := f.prec
+               for i := range s {
+                       if n == 0 {
+                               s = s[:i]
+                               break
+                       }
+                       n--
                }
        }
+       return s
+}
+
+// fmt_s formats a string.
+func (f *fmt) fmt_s(s string) {
+       s = f.truncate(s)
        f.padString(s)
 }
 
@@ -275,6 +286,7 @@ func (f *fmt) fmt_sX(s string) {
 
 // fmt_q formats a string as a double-quoted, escaped Go string constant.
 func (f *fmt) fmt_q(s string) {
+       s = f.truncate(s)
        var quoted string
        if f.sharp && strconv.CanBackquote(s) {
                quoted = "`" + s + "`"
index 4e14fdaa4a7436f0672110df1889a9ca5dac9119..4b68051188a031cd253d6eda917e328eed6933f9 100644 (file)
@@ -520,12 +520,14 @@ func (p *pp) fmtBytes(v []byte, verb int, goSyntax bool, depth int, value interf
 }
 
 func (p *pp) fmtPointer(field interface{}, value reflect.Value, verb int, goSyntax bool) {
-       v, ok := value.(uintptrGetter)
-       if !ok { // reflect.PtrValue is a uintptrGetter, so failure means it's not a pointer at all.
+       var u uintptr
+       switch value.(type) {
+       case *reflect.ChanValue, *reflect.FuncValue, *reflect.MapValue, *reflect.PtrValue, *reflect.SliceValue, *reflect.UnsafePointerValue:
+               u = value.(uintptrGetter).Get()
+       default:
                p.badVerb(verb, field)
                return
        }
-       u := v.Get()
        if goSyntax {
                p.add('(')
                p.buf.WriteString(reflect.Typeof(field).String())
@@ -534,7 +536,7 @@ func (p *pp) fmtPointer(field interface{}, value reflect.Value, verb int, goSynt
                if u == 0 {
                        p.buf.Write(nilBytes)
                } else {
-                       p.fmt0x64(uint64(v.Get()), true)
+                       p.fmt0x64(uint64(u), true)
                }
                p.add(')')
        } else {
@@ -811,7 +813,7 @@ BigSwitch:
                        break
                }
                p.fmt0x64(uint64(v), true)
-       case uintptrGetter:
+       case *reflect.ChanValue, *reflect.FuncValue, *reflect.UnsafePointerValue:
                p.fmtPointer(field, value, verb, goSyntax)
        default:
                p.unknownType(f)
index fc4ae094394b4b850875087a2293601e8cd84efb..b4780e05784f7cd992a2260e2f1152d2dd1e99ee 100644 (file)
@@ -183,7 +183,7 @@ func ParseFiles(fset *token.FileSet, filenames []string, mode uint) (pkgs map[st
 // error are returned.
 //
 func ParseDir(fset *token.FileSet, path string, filter func(*os.FileInfo) bool, mode uint) (map[string]*ast.Package, os.Error) {
-       fd, err := os.Open(path, os.O_RDONLY, 0)
+       fd, err := os.Open(path)
        if err != nil {
                return nil, err
        }
index ad7e4cdcf2e2856ef798df8e01c75517350b86a8..84a0da6ae7bddd6693e93bcb6464d2bd38d966c5 100644 (file)
@@ -332,7 +332,7 @@ func (p *parser) next() {
                var endline int
 
                if p.file.Line(p.pos) == line {
-                       // The comment is on same line as previous token; it
+                       // The comment is on same line as the previous token; it
                        // cannot be a lead comment but may be a line comment.
                        comment, endline = p.consumeCommentGroup()
                        if p.file.Line(p.pos) != endline {
@@ -2016,16 +2016,18 @@ func parseTypeSpec(p *parser, doc *ast.CommentGroup, _ int) ast.Spec {
        }
 
        ident := p.parseIdent()
-       typ := p.parseType()
-       p.expectSemi() // call before accessing p.linecomment
 
        // Go spec: The scope of a type identifier declared inside a function begins
        // at the identifier in the TypeSpec and ends at the end of the innermost
        // containing block.
        // (Global identifiers are resolved in a separate phase after parsing.)
-       spec := &ast.TypeSpec{doc, ident, typ, p.lineComment}
+       spec := &ast.TypeSpec{doc, ident, nil, nil}
        p.declare(spec, p.topScope, ast.Typ, ident)
 
+       spec.Type = p.parseType()
+       p.expectSemi() // call before accessing p.linecomment
+       spec.Comment = p.lineComment
+
        return spec
 }
 
@@ -2207,6 +2209,9 @@ func (p *parser) parseFile() *ast.File {
        // Go spec: The package clause is not a declaration;
        // the package name does not appear in any scope.
        ident := p.parseIdent()
+       if ident.Name == "_" {
+               p.error(p.pos, "invalid package name _")
+       }
        p.expectSemi()
 
        var decls []ast.Decl
index d153533b588b45c7882ead30bc38da7876d982b1..fe955436c8a4bd609ed3443f4f0b558e73798eeb 100644 (file)
@@ -28,7 +28,7 @@ func pipeErr(err os.Error) io.Reader {
 }
 
 func readDat(filename string, c chan io.Reader) {
-       f, err := os.Open("testdata/webkit/"+filename, os.O_RDONLY, 0600)
+       f, err := os.Open("testdata/webkit/" + filename)
        if err != nil {
                c <- pipeErr(err)
                return
index 8b5c4770c49b2fab5927eea67ed79b0f283640d8..c5efffca9cdb0ae0989b6172a18d190e38fdd800 100644 (file)
@@ -72,7 +72,7 @@ func serveFile(w ResponseWriter, r *Request, name string, redirect bool) {
                return
        }
 
-       f, err := os.Open(name, os.O_RDONLY, 0)
+       f, err := os.Open(name)
        if err != nil {
                // TODO expose actual error?
                NotFound(w, r)
@@ -113,7 +113,7 @@ func serveFile(w ResponseWriter, r *Request, name string, redirect bool) {
        // use contents of index.html for directory, if present
        if d.IsDirectory() {
                index := name + filepath.FromSlash(indexPage)
-               ff, err := os.Open(index, os.O_RDONLY, 0)
+               ff, err := os.Open(index)
                if err == nil {
                        defer ff.Close()
                        dd, err := ff.Stat()
@@ -134,21 +134,23 @@ func serveFile(w ResponseWriter, r *Request, name string, redirect bool) {
        size := d.Size
        code := StatusOK
 
-       // use extension to find content type.
-       ext := filepath.Ext(name)
-       if ctype := mime.TypeByExtension(ext); ctype != "" {
-               w.Header().Set("Content-Type", ctype)
-       } else {
-               // read first chunk to decide between utf-8 text and binary
-               var buf [1024]byte
-               n, _ := io.ReadFull(f, buf[:])
-               b := buf[:n]
-               if isText(b) {
-                       w.Header().Set("Content-Type", "text-plain; charset=utf-8")
-               } else {
-                       w.Header().Set("Content-Type", "application/octet-stream") // generic binary
+       // If Content-Type isn't set, use the file's extension to find it.
+       if w.Header().Get("Content-Type") == "" {
+               ctype := mime.TypeByExtension(filepath.Ext(name))
+               if ctype == "" {
+                       // read a chunk to decide between utf-8 text and binary
+                       var buf [1024]byte
+                       n, _ := io.ReadFull(f, buf[:])
+                       b := buf[:n]
+                       if isText(b) {
+                               ctype = "text-plain; charset=utf-8"
+                       } else {
+                               // generic binary
+                               ctype = "application/octet-stream"
+                       }
+                       f.Seek(0, os.SEEK_SET) // rewind to output whole file
                }
-               f.Seek(0, 0) // rewind to output whole file
+               w.Header().Set("Content-Type", ctype)
        }
 
        // handle Content-Range header.
@@ -163,7 +165,7 @@ func serveFile(w ResponseWriter, r *Request, name string, redirect bool) {
        }
        if len(ranges) == 1 {
                ra := ranges[0]
-               if _, err := f.Seek(ra.start, 0); err != nil {
+               if _, err := f.Seek(ra.start, os.SEEK_SET); err != nil {
                        Error(w, err.String(), StatusRequestedRangeNotSatisfiable)
                        return
                }
index a89c76d0bfb5c90b267f7c4e25bdb459b4e47d0d..692b9863e82fdc9ba4ec85a4d11d764c47c64869 100644 (file)
@@ -85,6 +85,30 @@ func TestServeFile(t *testing.T) {
        }
 }
 
+func TestServeFileContentType(t *testing.T) {
+       const ctype = "icecream/chocolate"
+       override := false
+       ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+               if override {
+                       w.Header().Set("Content-Type", ctype)
+               }
+               ServeFile(w, r, "testdata/file")
+       }))
+       defer ts.Close()
+       get := func(want string) {
+               resp, _, err := Get(ts.URL)
+               if err != nil {
+                       t.Fatal(err)
+               }
+               if h := resp.Header.Get("Content-Type"); h != want {
+                       t.Errorf("Content-Type mismatch: got %q, want %q", h, want)
+               }
+       }
+       get("text-plain; charset=utf-8")
+       override = true
+       get(ctype)
+}
+
 func getBody(t *testing.T, req Request) (*Response, []byte) {
        r, err := DefaultClient.Do(&req)
        if err != nil {
index 6e825a890d19382122f768161fa0f685839ec9ae..8e385d045a1a64b95c3ee5270738209da92d445d 100644 (file)
@@ -7,10 +7,13 @@
 package httptest
 
 import (
+       "crypto/rand"
+       "crypto/tls"
        "fmt"
        "http"
-       "os"
        "net"
+       "os"
+       "time"
 )
 
 // A Server is an HTTP server listening on a system-chosen port on the
@@ -18,6 +21,7 @@ import (
 type Server struct {
        URL      string // base URL of form http://ipaddr:port with no trailing slash
        Listener net.Listener
+       TLS      *tls.Config // nil if not using using TLS
 }
 
 // historyListener keeps track of all connections that it's ever
@@ -35,16 +39,21 @@ func (hs *historyListener) Accept() (c net.Conn, err os.Error) {
        return
 }
 
-// NewServer starts and returns a new Server.
-// The caller should call Close when finished, to shut it down.
-func NewServer(handler http.Handler) *Server {
-       ts := new(Server)
+func newLocalListener() net.Listener {
        l, err := net.Listen("tcp", "127.0.0.1:0")
        if err != nil {
                if l, err = net.Listen("tcp6", "[::1]:0"); err != nil {
                        panic(fmt.Sprintf("httptest: failed to listen on a port: %v", err))
                }
        }
+       return l
+}
+
+// NewServer starts and returns a new Server.
+// The caller should call Close when finished, to shut it down.
+func NewServer(handler http.Handler) *Server {
+       ts := new(Server)
+       l := newLocalListener()
        ts.Listener = &historyListener{l, make([]net.Conn, 0)}
        ts.URL = "http://" + l.Addr().String()
        server := &http.Server{Handler: handler}
@@ -52,6 +61,32 @@ func NewServer(handler http.Handler) *Server {
        return ts
 }
 
+// NewTLSServer starts and returns a new Server using TLS.
+// The caller should call Close when finished, to shut it down.
+func NewTLSServer(handler http.Handler) *Server {
+       l := newLocalListener()
+       ts := new(Server)
+
+       cert, err := tls.X509KeyPair(localhostCert, localhostKey)
+       if err != nil {
+               panic(fmt.Sprintf("httptest: NewTLSServer: %v", err))
+       }
+
+       ts.TLS = &tls.Config{
+               Rand:         rand.Reader,
+               Time:         time.Seconds,
+               NextProtos:   []string{"http/1.1"},
+               Certificates: []tls.Certificate{cert},
+       }
+       tlsListener := tls.NewListener(l, ts.TLS)
+
+       ts.Listener = &historyListener{tlsListener, make([]net.Conn, 0)}
+       ts.URL = "https://" + l.Addr().String()
+       server := &http.Server{Handler: handler}
+       go server.Serve(ts.Listener)
+       return ts
+}
+
 // Close shuts down the server.
 func (s *Server) Close() {
        s.Listener.Close()
@@ -68,3 +103,34 @@ func (s *Server) CloseClientConnections() {
                conn.Close()
        }
 }
+
+// localhostCert is a PEM-encoded TLS cert with SAN DNS names
+// "127.0.0.1" and "[::1]", expiring at the last second of 2049 (the end
+// of ASN.1 time).
+var localhostCert = []byte(`-----BEGIN CERTIFICATE-----
+MIIBwTCCASugAwIBAgIBADALBgkqhkiG9w0BAQUwADAeFw0xMTAzMzEyMDI1MDda
+Fw00OTEyMzEyMzU5NTlaMAAwggCdMAsGCSqGSIb3DQEBAQOCAIwAMIIAhwKCAIB6
+oy4iT42G6qk+GGn5VL5JlnJT6ZG5cqaMNFaNGlIxNb6CPUZLKq2sM3gRaimsktIw
+nNAcNwQGHpe1tZo+J/Pl04JTt71Y/TTAxy7OX27aZf1Rpt0SjdZ7vTPnFDPNsHGe
+KBKvPt55l2+YKjkZmV7eRevsVbpkNvNGB+T5d4Ge/wIBA6NPME0wDgYDVR0PAQH/
+BAQDAgCgMA0GA1UdDgQGBAQBAgMEMA8GA1UdIwQIMAaABAECAwQwGwYDVR0RBBQw
+EoIJMTI3LjAuMC4xggVbOjoxXTALBgkqhkiG9w0BAQUDggCBAHC3gbdvc44vs+wD
+g2kONiENnx8WKc0UTGg/TOXS3gaRb+CUIQtHWja65l8rAfclEovjHgZ7gx8brO0W
+JuC6p3MUAKsgOssIrrRIx2rpnfcmFVMzguCmrMNVmKUAalw18Yp0F72xYAIitVQl
+kJrLdIhBajcJRYu/YGltHQRaXuVt
+-----END CERTIFICATE-----
+`)
+
+// localhostKey is the private key for localhostCert.
+var localhostKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
+MIIBkgIBAQKCAIB6oy4iT42G6qk+GGn5VL5JlnJT6ZG5cqaMNFaNGlIxNb6CPUZL
+Kq2sM3gRaimsktIwnNAcNwQGHpe1tZo+J/Pl04JTt71Y/TTAxy7OX27aZf1Rpt0S
+jdZ7vTPnFDPNsHGeKBKvPt55l2+YKjkZmV7eRevsVbpkNvNGB+T5d4Ge/wIBAwKC
+AIBRwh7Bil5Z8cYpZZv7jdQxDvbim7Z7ocRdeDmzZuF2I9RW04QyHHPIIlALnBvI
+YeF1veASz1gEFGUjzmbUGqKYSbCoTzXoev+F4bmbRxcX9sOmtslqvhMSHRSzA5NH
+aDVI3Hn4wvBVD8gePu8ACWqvPGbCiql11OKCMfjlPn2uuwJAx/24/F5DjXZ6hQQ7
+HxScOxKrpx5WnA9r1wZTltOTZkhRRzuLc21WJeE3M15QUdWi3zZxCKRFoth65HEs
+jy9YHQJAnPueRI44tz79b5QqVbeaOMUr7ZCb1Kp0uo6G+ANPLdlfliAupwij2eIz
+mHRJOWk0jBtXfRft1McH2H51CpXAyw==
+-----END RSA PRIVATE KEY-----
+`)
index bf63ccb9e9655a5c12869e35d61fa3e67184ba80..ef67fdd2dc374ec1d82412b75d4694813616cb95 100644 (file)
@@ -164,6 +164,28 @@ var respTests = []respTest{
                "Body here\n",
        },
 
+       // Chunked response in response to a HEAD request (the "chunked" should
+       // be ignored, as HEAD responses never have bodies)
+       {
+               "HTTP/1.0 200 OK\r\n" +
+                       "Transfer-Encoding: chunked\r\n" +
+                       "\r\n",
+
+               Response{
+                       Status:        "200 OK",
+                       StatusCode:    200,
+                       Proto:         "HTTP/1.0",
+                       ProtoMajor:    1,
+                       ProtoMinor:    0,
+                       RequestMethod: "HEAD",
+                       Header:        Header{},
+                       Close:         true,
+                       ContentLength: 0,
+               },
+
+               "",
+       },
+
        // Status line without a Reason-Phrase, but trailing space.
        // (permitted by RFC 2616)
        {
index b0e26e533596b423d0f7ffb61fa2ef6970c62967..cf889553fb7852f25d64efc9d7bcfa5fcbfb574d 100644 (file)
@@ -507,3 +507,30 @@ func TestHeadResponses(t *testing.T) {
                t.Errorf("got unexpected body %q", string(body))
        }
 }
+
+func TestTLSServer(t *testing.T) {
+       ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+               fmt.Fprintf(w, "tls=%v", r.TLS != nil)
+       }))
+       defer ts.Close()
+       if !strings.HasPrefix(ts.URL, "https://") {
+               t.Fatalf("expected test TLS server to start with https://, got %q", ts.URL)
+       }
+       res, _, err := Get(ts.URL)
+       if err != nil {
+               t.Error(err)
+       }
+       if res == nil {
+               t.Fatalf("got nil Response")
+       }
+       if res.Body == nil {
+               t.Fatalf("got nil Response.Body")
+       }
+       body, err := ioutil.ReadAll(res.Body)
+       if err != nil {
+               t.Error(err)
+       }
+       if e, g := "tls=true", string(body); e != g {
+               t.Errorf("expected body %q; got %q", e, g)
+       }
+}
index 996e2897325384355aba1b1e20f020c3b55fb773..41614f144fe3ac999ba8338a2fdea81e97be0a4b 100644 (file)
@@ -215,7 +215,7 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err os.Error) {
        }
 
        // Transfer encoding, content length
-       t.TransferEncoding, err = fixTransferEncoding(t.Header)
+       t.TransferEncoding, err = fixTransferEncoding(t.RequestMethod, t.Header)
        if err != nil {
                return err
        }
@@ -289,13 +289,20 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err os.Error) {
 func chunked(te []string) bool { return len(te) > 0 && te[0] == "chunked" }
 
 // Sanitize transfer encoding
-func fixTransferEncoding(header Header) ([]string, os.Error) {
+func fixTransferEncoding(requestMethod string, header Header) ([]string, os.Error) {
        raw, present := header["Transfer-Encoding"]
        if !present {
                return nil, nil
        }
 
        header["Transfer-Encoding"] = nil, false
+
+       // Head responses have no bodies, so the transfer encoding
+       // should be ignored.
+       if requestMethod == "HEAD" {
+               return nil, nil
+       }
+
        encodings := strings.Split(raw[0], ",", -1)
        te := make([]string, 0, len(encodings))
        // TODO: Even though we only support "identity" and "chunked"
index ed7843bc713c0f6d0ca4fb35af614e0185283bca..797d134aa8511b645783d4c62807fb14e4f509d1 100644 (file)
@@ -24,6 +24,10 @@ import (
 // environment variables.
 var DefaultTransport RoundTripper = &Transport{}
 
+// DefaultMaxIdleConnsPerHost is the default value of Transport's
+// MaxIdleConnsPerHost.
+const DefaultMaxIdleConnsPerHost = 2
+
 // Transport is an implementation of RoundTripper that supports http,
 // https, and http proxies (for either http or https with CONNECT).
 // Transport can also cache connections for future re-use.
@@ -31,11 +35,17 @@ type Transport struct {
        lk       sync.Mutex
        idleConn map[string][]*persistConn
 
-       // TODO: tunables on max cached connections (total, per-server), duration
+       // TODO: tunable on global max cached connections
+       // TODO: tunable on timeout on cached connections
        // TODO: optional pipelining
 
        IgnoreEnvironment bool // don't look at environment variables for proxy configuration
        DisableKeepAlives bool
+
+       // MaxIdleConnsPerHost, if non-zero, controls the maximum idle
+       // (keep-alive) to keep to keep per-host.  If zero,
+       // DefaultMaxIdleConnsPerHost is used.
+       MaxIdleConnsPerHost int
 }
 
 // RoundTrip implements the RoundTripper interface.
@@ -147,7 +157,7 @@ func (cm *connectMethod) proxyAuth() string {
 func (t *Transport) putIdleConn(pconn *persistConn) {
        t.lk.Lock()
        defer t.lk.Unlock()
-       if t.DisableKeepAlives {
+       if t.DisableKeepAlives || t.MaxIdleConnsPerHost < 0 {
                pconn.close()
                return
        }
@@ -155,6 +165,14 @@ func (t *Transport) putIdleConn(pconn *persistConn) {
                return
        }
        key := pconn.cacheKey
+       max := t.MaxIdleConnsPerHost
+       if max == 0 {
+               max = DefaultMaxIdleConnsPerHost
+       }
+       if len(t.idleConn[key]) >= max {
+               pconn.close()
+               return
+       }
        t.idleConn[key] = append(t.idleConn[key], pconn)
 }
 
@@ -406,24 +424,37 @@ func (pc *persistConn) readLoop() {
 
                rc := <-pc.reqch
                resp, err := pc.cc.Read(rc.req)
-               if err == nil && !rc.req.Close {
-                       pc.t.putIdleConn(pc)
-               }
+
                if err == ErrPersistEOF {
                        // Succeeded, but we can't send any more
                        // persistent connections on this again.  We
                        // hide this error to upstream callers.
                        alive = false
                        err = nil
-               } else if err != nil {
+               } else if err != nil || rc.req.Close {
                        alive = false
                }
+
+               hasBody := resp != nil && resp.ContentLength != 0
+               var waitForBodyRead chan bool
+               if alive {
+                       if hasBody {
+                               waitForBodyRead = make(chan bool)
+                               resp.Body.(*bodyEOFSignal).fn = func() {
+                                       pc.t.putIdleConn(pc)
+                                       waitForBodyRead <- true
+                               }
+                       } else {
+                               pc.t.putIdleConn(pc)
+                       }
+               }
+
                rc.ch <- responseAndError{resp, err}
 
                // Wait for the just-returned response body to be fully consumed
                // before we race and peek on the underlying bufio reader.
-               if alive {
-                       <-resp.Body.(*bodyEOFSignal).ch
+               if waitForBodyRead != nil {
+                       <-waitForBodyRead
                }
        }
 }
@@ -494,34 +525,34 @@ func responseIsKeepAlive(res *Response) bool {
 // the response body with a bodyEOFSignal-wrapped version.
 func readResponseWithEOFSignal(r *bufio.Reader, requestMethod string) (resp *Response, err os.Error) {
        resp, err = ReadResponse(r, requestMethod)
-       if err == nil {
-               resp.Body = &bodyEOFSignal{resp.Body, make(chan bool, 1), false}
+       if err == nil && resp.ContentLength != 0 {
+               resp.Body = &bodyEOFSignal{resp.Body, nil}
        }
        return
 }
 
-// bodyEOFSignal wraps a ReadCloser but sends on ch once once
-// the wrapped ReadCloser is fully consumed (including on Close)
+// bodyEOFSignal wraps a ReadCloser but runs fn (if non-nil) at most
+// once, right before the final Read() or Close() call returns, but after
+// EOF has been seen.
 type bodyEOFSignal struct {
        body io.ReadCloser
-       ch   chan bool
-       done bool
+       fn   func()
 }
 
 func (es *bodyEOFSignal) Read(p []byte) (n int, err os.Error) {
        n, err = es.body.Read(p)
-       if err == os.EOF && !es.done {
-               es.ch <- true
-               es.done = true
+       if err == os.EOF && es.fn != nil {
+               es.fn()
+               es.fn = nil
        }
        return
 }
 
 func (es *bodyEOFSignal) Close() (err os.Error) {
        err = es.body.Close()
-       if err == nil && !es.done {
-               es.ch <- true
-               es.done = true
+       if err == nil && es.fn != nil {
+               es.fn()
+               es.fn = nil
        }
        return
 }
index 5c3e1cdb582a92d0a2b11c2719e710646e1f7ba1..e46f830c82841a0bed2f40247671e2aaba8c6c01 100644 (file)
@@ -85,6 +85,7 @@ func TestTransportConnectionCloseOnResponse(t *testing.T) {
                                t.Fatalf("error in connectionClose=%v, req #%d, Do: %v", connectionClose, n, err)
                        }
                        body, err := ioutil.ReadAll(res.Body)
+                       defer res.Body.Close()
                        if err != nil {
                                t.Fatalf("error in connectionClose=%v, req #%d, ReadAll: %v", connectionClose, n, err)
                        }
@@ -154,9 +155,11 @@ func TestTransportIdleCacheKeys(t *testing.T) {
                t.Errorf("After CloseIdleConnections expected %d idle conn cache keys; got %d", e, g)
        }
 
-       if _, _, err := c.Get(ts.URL); err != nil {
+       resp, _, err := c.Get(ts.URL)
+       if err != nil {
                t.Error(err)
        }
+       ioutil.ReadAll(resp.Body)
 
        keys := tr.IdleConnKeysForTesting()
        if e, g := 1, len(keys); e != g {
@@ -164,7 +167,7 @@ func TestTransportIdleCacheKeys(t *testing.T) {
        }
 
        if e := "|http|" + ts.Listener.Addr().String(); keys[0] != e {
-               t.Logf("Expected idle cache key %q; got %q", e, keys[0])
+               t.Errorf("Expected idle cache key %q; got %q", e, keys[0])
        }
 
        tr.CloseIdleConnections()
@@ -173,6 +176,62 @@ func TestTransportIdleCacheKeys(t *testing.T) {
        }
 }
 
+func TestTransportMaxPerHostIdleConns(t *testing.T) {
+       ch := make(chan string)
+       ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+               fmt.Fprintf(w, "%s", <-ch)
+       }))
+       defer ts.Close()
+       maxIdleConns := 2
+       tr := &Transport{DisableKeepAlives: false, MaxIdleConnsPerHost: maxIdleConns}
+       c := &Client{Transport: tr}
+
+       // Start 3 outstanding requests (will hang until we write to
+       // ch)
+       donech := make(chan bool)
+       doReq := func() {
+               resp, _, err := c.Get(ts.URL)
+               if err != nil {
+                       t.Error(err)
+               }
+               ioutil.ReadAll(resp.Body)
+               donech <- true
+       }
+       go doReq()
+       go doReq()
+       go doReq()
+
+       if e, g := 0, len(tr.IdleConnKeysForTesting()); e != g {
+               t.Fatalf("Before writes, expected %d idle conn cache keys; got %d", e, g)
+       }
+
+       ch <- "res1"
+       <-donech
+       keys := tr.IdleConnKeysForTesting()
+       if e, g := 1, len(keys); e != g {
+               t.Fatalf("after first response, expected %d idle conn cache keys; got %d", e, g)
+       }
+       cacheKey := "|http|" + ts.Listener.Addr().String()
+       if keys[0] != cacheKey {
+               t.Fatalf("Expected idle cache key %q; got %q", cacheKey, keys[0])
+       }
+       if e, g := 1, tr.IdleConnCountForTesting(cacheKey); e != g {
+               t.Errorf("after first response, expected %d idle conns; got %d", e, g)
+       }
+
+       ch <- "res2"
+       <-donech
+       if e, g := 2, tr.IdleConnCountForTesting(cacheKey); e != g {
+               t.Errorf("after second response, expected %d idle conns; got %d", e, g)
+       }
+
+       ch <- "res3"
+       <-donech
+       if e, g := maxIdleConns, tr.IdleConnCountForTesting(cacheKey); e != g {
+               t.Errorf("after third response, still expected %d idle conns; got %d", e, g)
+       }
+}
+
 func TestTransportServerClosingUnexpectedly(t *testing.T) {
        ts := httptest.NewServer(hostPortHandler)
        defer ts.Close()
@@ -209,6 +268,63 @@ func TestTransportServerClosingUnexpectedly(t *testing.T) {
        }
 }
 
+// TestTransportHeadResponses verifies that we deal with Content-Lengths
+// with no bodies properly
+func TestTransportHeadResponses(t *testing.T) {
+       ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+               if r.Method != "HEAD" {
+                       panic("expected HEAD; got " + r.Method)
+               }
+               w.Header().Set("Content-Length", "123")
+               w.WriteHeader(200)
+       }))
+       defer ts.Close()
+
+       tr := &Transport{DisableKeepAlives: false}
+       c := &Client{Transport: tr}
+       for i := 0; i < 2; i++ {
+               res, err := c.Head(ts.URL)
+               if err != nil {
+                       t.Errorf("error on loop %d: %v", i, err)
+               }
+               if e, g := "123", res.Header.Get("Content-Length"); e != g {
+                       t.Errorf("loop %d: expected Content-Length header of %q, got %q", e, g)
+               }
+               if e, g := int64(0), res.ContentLength; e != g {
+                       t.Errorf("loop %d: expected res.ContentLength of %v, got %v", e, g)
+               }
+       }
+}
+
+// TestTransportHeadChunkedResponse verifies that we ignore chunked transfer-encoding
+// on responses to HEAD requests.
+func TestTransportHeadChunkedResponse(t *testing.T) {
+       ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+               if r.Method != "HEAD" {
+                       panic("expected HEAD; got " + r.Method)
+               }
+               w.Header().Set("Transfer-Encoding", "chunked") // client should ignore
+               w.Header().Set("x-client-ipport", r.RemoteAddr)
+               w.WriteHeader(200)
+       }))
+       defer ts.Close()
+
+       tr := &Transport{DisableKeepAlives: false}
+       c := &Client{Transport: tr}
+
+       res1, err := c.Head(ts.URL)
+       if err != nil {
+               t.Fatalf("request 1 error: %v", err)
+       }
+       res2, err := c.Head(ts.URL)
+       if err != nil {
+               t.Fatalf("request 2 error: %v", err)
+       }
+       if v1, v2 := res1.Header.Get("x-client-ipport"), res2.Header.Get("x-client-ipport"); v1 != v2 {
+               t.Errorf("ip/ports differed between head requests: %q vs %q", v1, v2)
+       }
+}
+
 func TestTransportNilURL(t *testing.T) {
        ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
                fmt.Fprintf(w, "Hi")
index efd90d81eb187f101062000f38fe02f0c54b85af..0fc0cb2d76ee2703ca244f890879e6b33373dbef 100644 (file)
@@ -213,8 +213,8 @@ func urlEscape(s string, mode encoding) string {
                        j++
                case shouldEscape(c, mode):
                        t[j] = '%'
-                       t[j+1] = "0123456789abcdef"[c>>4]
-                       t[j+2] = "0123456789abcdef"[c&15]
+                       t[j+1] = "0123456789ABCDEF"[c>>4]
+                       t[j+2] = "0123456789ABCDEF"[c&15]
                        j += 3
                default:
                        t[j] = s[i]
index 0801f7ff3e82ab55d593c1cfb8e05f9a8f32e1cf..d8863f3d3b5751ad0bd695ef5c70a1a6647dbc95 100644 (file)
@@ -490,7 +490,7 @@ var escapeTests = []URLEscapeTest{
        },
        {
                " ?&=#+%!<>#\"{}|\\^[]`☺\t",
-               "+%3f%26%3d%23%2b%25!%3c%3e%23%22%7b%7d%7c%5c%5e%5b%5d%60%e2%98%ba%09",
+               "+%3F%26%3D%23%2B%25!%3C%3E%23%22%7B%7D%7C%5C%5E%5B%5D%60%E2%98%BA%09",
                nil,
        },
 }
@@ -519,7 +519,7 @@ type UserinfoTest struct {
 var userinfoTests = []UserinfoTest{
        {"user", "password", "user:password"},
        {"foo:bar", "~!@#$%^&*()_+{}|[]\\-=`:;'\"<>?,./",
-               "foo%3abar:~!%40%23$%25%5e&*()_+%7b%7d%7c%5b%5d%5c-=%60%3a;'%22%3c%3e?,.%2f"},
+               "foo%3Abar:~!%40%23$%25%5E&*()_+%7B%7D%7C%5B%5D%5C-=%60%3A;'%22%3C%3E?,.%2F"},
 }
 
 func TestEscapeUserinfo(t *testing.T) {
index 5b87344c50aecffad48ec1258625eb3ba0fa6f93..0716ad9055b85ec56b3b898f1dc06f45516cfcec 100644 (file)
@@ -34,7 +34,7 @@ var imageTests = []imageTest{
 }
 
 func decode(filename string) (image.Image, string, os.Error) {
-       f, err := os.Open(filename, os.O_RDONLY, 0400)
+       f, err := os.Open(filename)
        if err != nil {
                return nil, "", err
        }
index 0b2058d51a2b378a79e8a1f7d36e633b66a1f0e9..efa6336d792f979c6f958fa915ee345d453be1ca 100644 (file)
@@ -41,7 +41,7 @@ var filenamesShort = []string{
 }
 
 func readPng(filename string) (image.Image, os.Error) {
-       f, err := os.Open(filename, os.O_RDONLY, 0444)
+       f, err := os.Open(filename)
        if err != nil {
                return nil, err
        }
@@ -191,7 +191,7 @@ func TestReader(t *testing.T) {
                defer piper.Close()
 
                // Read the .sng file.
-               sf, err := os.Open("testdata/pngsuite/"+fn+".sng", os.O_RDONLY, 0444)
+               sf, err := os.Open("testdata/pngsuite/" + fn + ".sng")
                if err != nil {
                        t.Error(fn, err)
                        continue
index ed6c310eb44c7e57e633b670cfcc428d876844d9..57d797e851cf89b227733d8af637a83e3f795195 100644 (file)
@@ -28,7 +28,7 @@ func ReadAll(r io.Reader) ([]byte, os.Error) {
 
 // ReadFile reads the file named by filename and returns the contents.
 func ReadFile(filename string) ([]byte, os.Error) {
-       f, err := os.Open(filename, os.O_RDONLY, 0)
+       f, err := os.Open(filename)
        if err != nil {
                return nil, err
        }
@@ -52,7 +52,7 @@ func ReadFile(filename string) ([]byte, os.Error) {
 // If the file does not exist, WriteFile creates it with permissions perm;
 // otherwise WriteFile truncates it before writing.
 func WriteFile(filename string, data []byte, perm uint32) os.Error {
-       f, err := os.Open(filename, os.O_WRONLY|os.O_CREAT|os.O_TRUNC, perm)
+       f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
        if err != nil {
                return err
        }
@@ -74,7 +74,7 @@ func (f fileInfoList) Swap(i, j int)      { f[i], f[j] = f[j], f[i] }
 // ReadDir reads the directory named by dirname and returns
 // a list of sorted directory entries.
 func ReadDir(dirname string) ([]*os.FileInfo, os.Error) {
-       f, err := os.Open(dirname, os.O_RDONLY, 0)
+       f, err := os.Open(dirname)
        if err != nil {
                return nil, err
        }
index 62f8849c0a0b74c964fe59a513c16fac3107293c..8e681bdc3bce55fb04efe0ce6657cd43c757bd92 100644 (file)
@@ -48,7 +48,7 @@ func TempFile(dir, prefix string) (f *os.File, err os.Error) {
        nconflict := 0
        for i := 0; i < 10000; i++ {
                name := filepath.Join(dir, prefix+nextSuffix())
-               f, err = os.Open(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
+               f, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
                if pe, ok := err.(*os.PathError); ok && pe.Error == os.EEXIST {
                        if nconflict++; nconflict > 10 {
                                rand = reseed()
index 658e3bd94b1b3b8835e860f37bfdf2a305d9063c..33140ee08afa08e358a2d100645bd1b330c6e69e 100644 (file)
@@ -28,11 +28,12 @@ const (
        // order they appear (the order listed here) or the format they present (as
        // described in the comments).  A colon appears after these items:
        //      2009/0123 01:23:23.123123 /a/b/c/d.go:23: message
-       Ldate         = 1 << iota // the date: 2009/0123
-       Ltime                     // the time: 01:23:23
-       Lmicroseconds             // microsecond resolution: 01:23:23.123123.  assumes Ltime.
-       Llongfile                 // full file name and line number: /a/b/c/d.go:23
-       Lshortfile                // final file name element and line number: d.go:23. overrides Llongfile
+       Ldate         = 1 << iota     // the date: 2009/0123
+       Ltime                         // the time: 01:23:23
+       Lmicroseconds                 // microsecond resolution: 01:23:23.123123.  assumes Ltime.
+       Llongfile                     // full file name and line number: /a/b/c/d.go:23
+       Lshortfile                    // final file name element and line number: d.go:23. overrides Llongfile
+       LstdFlags     = Ldate | Ltime // initial values for the standard logger
 )
 
 // A Logger represents an active logging object that generates lines of
@@ -40,10 +41,11 @@ const (
 // the Writer's Write method.  A Logger can be used simultaneously from
 // multiple goroutines; it guarantees to serialize access to the Writer.
 type Logger struct {
-       mu     sync.Mutex // ensures atomic writes
-       out    io.Writer  // destination for output
-       prefix string     // prefix to write at beginning of each line
-       flag   int        // properties
+       prefix string       // prefix to write at beginning of each line
+       flag   int          // properties
+       mu     sync.Mutex   // ensures atomic writes; protects the following fields
+       out    io.Writer    // destination for output
+       buf    bytes.Buffer // for accumulating text to write
 }
 
 // New creates a new Logger.   The out variable sets the
@@ -54,7 +56,7 @@ func New(out io.Writer, prefix string, flag int) *Logger {
        return &Logger{out: out, prefix: prefix, flag: flag}
 }
 
-var std = New(os.Stderr, "", Ldate|Ltime)
+var std = New(os.Stderr, "", LstdFlags)
 
 // Cheap integer to fixed-width decimal ASCII.  Give a negative width to avoid zero-padding.
 // Knows the buffer has capacity.
@@ -81,7 +83,7 @@ func itoa(buf *bytes.Buffer, i int, wid int) {
        }
 }
 
-func (l *Logger) formatHeader(buf *bytes.Buffer, ns int64, calldepth int) {
+func (l *Logger) formatHeader(buf *bytes.Buffer, ns int64, file string, line int) {
        buf.WriteString(l.prefix)
        if l.flag&(Ldate|Ltime|Lmicroseconds) != 0 {
                t := time.SecondsToLocalTime(ns / 1e9)
@@ -107,21 +109,15 @@ func (l *Logger) formatHeader(buf *bytes.Buffer, ns int64, calldepth int) {
                }
        }
        if l.flag&(Lshortfile|Llongfile) != 0 {
-               _, file, line, ok := runtime.Caller(calldepth)
-               if ok {
-                       if l.flag&Lshortfile != 0 {
-                               short := file
-                               for i := len(file) - 1; i > 0; i-- {
-                                       if file[i] == '/' {
-                                               short = file[i+1:]
-                                               break
-                                       }
+               if l.flag&Lshortfile != 0 {
+                       short := file
+                       for i := len(file) - 1; i > 0; i-- {
+                               if file[i] == '/' {
+                                       short = file[i+1:]
+                                       break
                                }
-                               file = short
                        }
-               } else {
-                       file = "???"
-                       line = 0
+                       file = short
                }
                buf.WriteString(file)
                buf.WriteByte(':')
@@ -138,15 +134,26 @@ func (l *Logger) formatHeader(buf *bytes.Buffer, ns int64, calldepth int) {
 // paths it will be 2.
 func (l *Logger) Output(calldepth int, s string) os.Error {
        now := time.Nanoseconds() // get this early.
-       buf := new(bytes.Buffer)
-       l.formatHeader(buf, now, calldepth+1)
-       buf.WriteString(s)
-       if len(s) > 0 && s[len(s)-1] != '\n' {
-               buf.WriteByte('\n')
+       // get caller info (if required) before locking - it's expensive.
+       var file string
+       var line int
+       if l.flag&(Lshortfile|Llongfile) != 0 {
+               var ok bool
+               _, file, line, ok = runtime.Caller(calldepth)
+               if !ok {
+                       file = "???"
+                       line = 0
+               }
        }
        l.mu.Lock()
        defer l.mu.Unlock()
-       _, err := l.out.Write(buf.Bytes())
+       l.buf.Reset()
+       l.formatHeader(&l.buf, now, file, line)
+       l.buf.WriteString(s)
+       if len(s) > 0 && s[len(s)-1] != '\n' {
+               l.buf.WriteByte('\n')
+       }
+       _, err := l.out.Write(l.buf.Bytes())
        return err
 }
 
@@ -203,19 +210,49 @@ func (l *Logger) Panicln(v ...interface{}) {
        panic(s)
 }
 
+// Flags returns the output flags for the logger.
+func (l *Logger) Flags() int {
+       return l.flag
+}
+
+// SetFlags sets the output flags for the logger.
+func (l *Logger) SetFlags(flag int) {
+       l.flag = flag
+}
+
+// Prefix returns the output prefix for the logger.
+func (l *Logger) Prefix() string {
+       return l.prefix
+}
+
+// SetPrefix sets the output prefix for the logger.
+func (l *Logger) SetPrefix(prefix string) {
+       l.prefix = prefix
+}
+
 // SetOutput sets the output destination for the standard logger.
 func SetOutput(w io.Writer) {
        std.out = w
 }
 
+// Flags returns the output flags for the standard logger.
+func Flags() int {
+       return std.Flags()
+}
+
 // SetFlags sets the output flags for the standard logger.
 func SetFlags(flag int) {
-       std.flag = flag
+       std.SetFlags(flag)
+}
+
+// Prefix returns the output prefix for the standard logger.
+func Prefix() string {
+       return std.Prefix()
 }
 
 // SetPrefix sets the output prefix for the standard logger.
 func SetPrefix(prefix string) {
-       std.prefix = prefix
+       std.SetPrefix(prefix)
 }
 
 // These functions write to the standard logger.
index bd4d1a9c583b2a1b659f84545021f599fde70ce3..72ebf398eda2b879cd156a41bd6751e3c2ab6858 100644 (file)
@@ -84,3 +84,36 @@ func TestOutput(t *testing.T) {
                t.Errorf("log output should match %q is %q", expect, b.String())
        }
 }
+
+func TestFlagAndPrefixSetting(t *testing.T) {
+       var b bytes.Buffer
+       l := New(&b, "Test:", LstdFlags)
+       f := l.Flags()
+       if f != LstdFlags {
+               t.Errorf("Flags 1: expected %x got %x", LstdFlags, f)
+       }
+       l.SetFlags(f | Lmicroseconds)
+       f = l.Flags()
+       if f != LstdFlags|Lmicroseconds {
+               t.Errorf("Flags 2: expected %x got %x", LstdFlags|Lmicroseconds, f)
+       }
+       p := l.Prefix()
+       if p != "Test:" {
+               t.Errorf(`Prefix: expected "Test:" got %q`, p)
+       }
+       l.SetPrefix("Reality:")
+       p = l.Prefix()
+       if p != "Reality:" {
+               t.Errorf(`Prefix: expected "Reality:" got %q`, p)
+       }
+       // Verify a log message looks right, with our prefix and microseconds present.
+       l.Print("hello")
+       pattern := "^Reality:" + Rdate + " " + Rtime + Rmicroseconds + " hello\n"
+       matched, err := regexp.Match(pattern, b.Bytes())
+       if err != nil {
+               t.Fatalf("pattern %q did not compile: %s", pattern, err)
+       }
+       if !matched {
+               t.Error("message did not match pattern")
+       }
+}
index a10b780ae95c94d0bf68128c7d26daf9d2d46127..6fe0ed5fd5e0584cf4c819bf83a69cf7a032fbca 100644 (file)
@@ -33,7 +33,7 @@ var mimeTypes = map[string]string{
 var mimeLock sync.RWMutex
 
 func loadMimeFile(filename string) {
-       f, err := os.Open(filename, os.O_RDONLY, 0666)
+       f, err := os.Open(filename)
        if err != nil {
                return
        }
index 8525f578d74457af6e80752eeb3194b9907fe05d..d75e9e038a6791360b4f1a1cb49c850015726e7c 100644 (file)
@@ -59,7 +59,7 @@ func readHosts() {
        }
 }
 
-// lookupStaticHosts looks up the addresses for the given host from /etc/hosts.
+// lookupStaticHost looks up the addresses for the given host from /etc/hosts.
 func lookupStaticHost(host string) []string {
        hosts.Lock()
        defer hosts.Unlock()
@@ -72,7 +72,7 @@ func lookupStaticHost(host string) []string {
        return nil
 }
 
-// rlookupStaticHosts looks up the hosts for the given address from /etc/hosts.
+// lookupStaticAddr looks up the hosts for the given address from /etc/hosts.
 func lookupStaticAddr(addr string) []string {
        hosts.Lock()
        defer hosts.Unlock()
index 2bc0db4655a2fe3f4cd0d44264bd4e7c173858cf..de46830d2928d09f231d699ee9005485e12fd68b 100644 (file)
@@ -63,7 +63,7 @@ func (f *file) readLine() (s string, ok bool) {
 }
 
 func open(name string) (*file, os.Error) {
-       fd, err := os.Open(name, os.O_RDONLY, 0)
+       fd, err := os.Open(name)
        if err != nil {
                return nil, err
        }
index 2b7784eee2d24bfef3a7a2f454f59f9cec9d91cb..226f354d300604be7b7a308021e7599a21479239 100644 (file)
@@ -18,7 +18,7 @@ func TestReadLine(t *testing.T) {
        }
        filename := "/etc/services" // a nice big file
 
-       fd, err := os.Open(filename, os.O_RDONLY, 0)
+       fd, err := os.Open(filename)
        if err != nil {
                t.Fatalf("open %s: %v", filename, err)
        }
index f3d854ff253ba00a0a234819270e5d77af01e316..000c3065911fa07918e63c898fc7820b18c86e9d 100644 (file)
@@ -14,26 +14,51 @@ import (
 var hostentLock sync.Mutex
 var serventLock sync.Mutex
 
-func LookupHost(name string) (cname string, addrs []string, err os.Error) {
+func goLookupHost(name string) (addrs []string, err os.Error) {
+       ips, err := goLookupIP(name)
+       if err != nil {
+               return
+       }
+       addrs = make([]string, 0, len(ips))
+       for _, ip := range ips {
+               addrs = append(addrs, ip.String())
+       }
+       return
+}
+
+func goLookupIP(name string) (addrs []IP, err os.Error) {
        hostentLock.Lock()
        defer hostentLock.Unlock()
        h, e := syscall.GetHostByName(name)
        if e != 0 {
-               return "", nil, os.NewSyscallError("GetHostByName", e)
+               return nil, os.NewSyscallError("GetHostByName", e)
        }
-       cname = name
        switch h.AddrType {
        case syscall.AF_INET:
                i := 0
-               addrs = make([]string, 100) // plenty of room to grow
+               addrs = make([]IP, 100) // plenty of room to grow
                for p := (*[100](*[4]byte))(unsafe.Pointer(h.AddrList)); i < cap(addrs) && p[i] != nil; i++ {
-                       addrs[i] = IPv4(p[i][0], p[i][1], p[i][2], p[i][3]).String()
+                       addrs[i] = IPv4(p[i][0], p[i][1], p[i][2], p[i][3])
                }
                addrs = addrs[0:i]
        default: // TODO(vcc): Implement non IPv4 address lookups.
-               return "", nil, os.NewSyscallError("LookupHost", syscall.EWINDOWS)
+               return nil, os.NewSyscallError("LookupHost", syscall.EWINDOWS)
+       }
+       return addrs, nil
+}
+
+func LookupCNAME(name string) (cname string, err os.Error) {
+       var r *syscall.DNSRecord
+       e := syscall.DnsQuery(name, syscall.DNS_TYPE_CNAME, 0, nil, &r, nil)
+       if int(e) != 0 {
+               return "", os.NewSyscallError("LookupCNAME", int(e))
+       }
+       defer syscall.DnsRecordListFree(r, 1)
+       if r != nil && r.Type == syscall.DNS_TYPE_CNAME {
+               v := (*syscall.DNSPTRData)(unsafe.Pointer(&r.Data[0]))
+               cname = syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.Host))[:]) + "."
        }
-       return cname, addrs, nil
+       return
 }
 
 type SRV struct {
@@ -62,7 +87,7 @@ func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err os.
        return name, addrs, nil
 }
 
-func LookupPort(network, service string) (port int, err os.Error) {
+func goLookupPort(network, service string) (port int, err os.Error) {
        switch network {
        case "tcp4", "tcp6":
                network = "tcp"
diff --git a/libgo/go/os/dir_plan9.go b/libgo/go/os/dir_plan9.go
new file mode 100644 (file)
index 0000000..7bb0642
--- /dev/null
@@ -0,0 +1,300 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package os
+
+import (
+       "syscall"
+)
+
+type dirInfo int
+
+var markDirectory dirInfo = ^0
+
+// Readdir reads the contents of the directory associated with file and
+// returns an array of up to count FileInfo structures, as would be returned
+// by Lstat, in directory order.  Subsequent calls on the same file will yield
+// further FileInfos. A negative count means to read the entire directory.
+// Readdir returns the array and an Error, if any.
+func (file *File) Readdir(count int) (fi []FileInfo, err Error) {
+       // If this file has no dirinfo, create one.
+       if file.dirinfo == nil {
+               file.dirinfo = &markDirectory
+       }
+
+       size := count
+       if size < 0 {
+               size = 100
+       }
+
+       result := make([]FileInfo, 0, size)
+       var buf [syscall.STATMAX]byte
+
+       for {
+               n, e := file.Read(buf[:])
+
+               if e != nil {
+                       if e == EOF {
+                               break
+                       }
+
+                       return []FileInfo{}, &PathError{"readdir", file.name, e}
+               }
+
+               if n < syscall.STATFIXLEN {
+                       return []FileInfo{}, &PathError{"readdir", file.name, Eshortstat}
+               }
+
+               for i := 0; i < n; {
+                       m, _ := gbit16(buf[i:])
+                       m += 2
+
+                       if m < syscall.STATFIXLEN {
+                               return []FileInfo{}, &PathError{"readdir", file.name, Eshortstat}
+                       }
+
+                       d, e := UnmarshalDir(buf[i : i+int(m)])
+
+                       if e != nil {
+                               return []FileInfo{}, &PathError{"readdir", file.name, e}
+                       }
+
+                       var f FileInfo
+                       fileInfoFromStat(&f, d)
+
+                       result = append(result, f)
+
+                       // a negative count means to read until EOF.
+                       if count > 0 && len(result) >= count {
+                               break
+                       }
+
+                       i += int(m)
+               }
+       }
+
+       return result, nil
+}
+
+// Readdirnames returns an array of up to count file names residing in the 
+// directory associated with file. A negative count will return all of them.
+// Readdir returns the array and an Error, if any.
+func (file *File) Readdirnames(count int) (names []string, err Error) {
+       fi, e := file.Readdir(count)
+
+       if e != nil {
+               return []string{}, e
+       }
+
+       names = make([]string, len(fi))
+       err = nil
+
+       for i, _ := range fi {
+               names[i] = fi[i].Name
+       }
+
+       return
+}
+
+type Dir struct {
+       // system-modified data
+       Type uint16 // server type
+       Dev  uint32 // server subtype
+       // file data
+       Qid    Qid    // unique id from server
+       Mode   uint32 // permissions
+       Atime  uint32 // last read time
+       Mtime  uint32 // last write time
+       Length uint64 // file length
+       Name   string // last element of path
+       Uid    string // owner name
+       Gid    string // group name
+       Muid   string // last modifier name
+}
+
+type Qid struct {
+       Path uint64 // the file server's unique identification for the file
+       Vers uint32 // version number for given Path
+       Type uint8  // the type of the file (syscall.QTDIR for example)
+}
+
+var nullDir = Dir{
+       ^uint16(0),
+       ^uint32(0),
+       Qid{^uint64(0), ^uint32(0), ^uint8(0)},
+       ^uint32(0),
+       ^uint32(0),
+       ^uint32(0),
+       ^uint64(0),
+       "",
+       "",
+       "",
+       "",
+}
+
+// Null assigns members of d with special "don't care" values indicating
+// they should not be written by syscall.Wstat. 
+func (d *Dir) Null() {
+       *d = nullDir
+}
+
+// pdir appends a 9P Stat message based on the contents of Dir d to a byte slice b.
+func pdir(b []byte, d *Dir) []byte {
+       n := len(b)
+       b = pbit16(b, 0) // length, filled in later     
+       b = pbit16(b, d.Type)
+       b = pbit32(b, d.Dev)
+       b = pqid(b, d.Qid)
+       b = pbit32(b, d.Mode)
+       b = pbit32(b, d.Atime)
+       b = pbit32(b, d.Mtime)
+       b = pbit64(b, d.Length)
+       b = pstring(b, d.Name)
+       b = pstring(b, d.Uid)
+       b = pstring(b, d.Gid)
+       b = pstring(b, d.Muid)
+       pbit16(b[0:n], uint16(len(b)-(n+2)))
+       return b
+}
+
+// UnmarshalDir reads a 9P Stat message from a 9P protocol message strored in b,
+// returning the corresponding Dir struct.
+func UnmarshalDir(b []byte) (d *Dir, err Error) {
+       n := uint16(0)
+       n, b = gbit16(b)
+
+       if int(n) != len(b) {
+               return nil, Ebadstat
+       }
+
+       d = new(Dir)
+       d.Type, b = gbit16(b)
+       d.Dev, b = gbit32(b)
+       d.Qid, b = gqid(b)
+       d.Mode, b = gbit32(b)
+       d.Atime, b = gbit32(b)
+       d.Mtime, b = gbit32(b)
+       d.Length, b = gbit64(b)
+       d.Name, b = gstring(b)
+       d.Uid, b = gstring(b)
+       d.Gid, b = gstring(b)
+       d.Muid, b = gstring(b)
+
+       if len(b) != 0 {
+               return nil, Ebadstat
+       }
+
+       return d, nil
+}
+
+// gqid reads the qid part of a 9P Stat message from a 9P protocol message strored in b,
+// returning the corresponding Qid struct and the remaining slice of b.
+func gqid(b []byte) (Qid, []byte) {
+       var q Qid
+       q.Path, b = gbit64(b)
+       q.Vers, b = gbit32(b)
+       q.Type, b = gbit8(b)
+       return q, b
+}
+
+// pqid appends a Qid struct q to a 9P message b.
+func pqid(b []byte, q Qid) []byte {
+       b = pbit64(b, q.Path)
+       b = pbit32(b, q.Vers)
+       b = pbit8(b, q.Type)
+       return b
+}
+
+// gbit8 reads a byte-sized numeric value from a 9P protocol message strored in b,
+// returning the value and the remaining slice of b.
+func gbit8(b []byte) (uint8, []byte) {
+       return uint8(b[0]), b[1:]
+}
+
+// gbit16 reads a 16-bit numeric value from a 9P protocol message strored in b,
+// returning the value and the remaining slice of b.
+func gbit16(b []byte) (uint16, []byte) {
+       return uint16(b[0]) | uint16(b[1])<<8, b[2:]
+}
+
+// gbit32 reads a 32-bit numeric value from a 9P protocol message strored in b,
+// returning the value and the remaining slice of b.
+func gbit32(b []byte) (uint32, []byte) {
+       return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24, b[4:]
+}
+
+// gbit64 reads a 64-bit numeric value from a 9P protocol message strored in b,
+// returning the value and the remaining slice of b.
+func gbit64(b []byte) (uint64, []byte) {
+       lo, b := gbit32(b)
+       hi, b := gbit32(b)
+       return uint64(hi)<<32 | uint64(lo), b
+}
+
+// gstring reads a string from a 9P protocol message strored in b,
+// returning the value as a Go string and the remaining slice of b.
+func gstring(b []byte) (string, []byte) {
+       n, b := gbit16(b)
+       return string(b[0:n]), b[n:]
+}
+
+// pbit8 appends a byte-sized numeric value x to a 9P message b.
+func pbit8(b []byte, x uint8) []byte {
+       n := len(b)
+       if n+1 > cap(b) {
+               nb := make([]byte, n, 100+2*cap(b))
+               copy(nb, b)
+               b = nb
+       }
+       b = b[0 : n+1]
+       b[n] = x
+       return b
+}
+
+// pbit16 appends a 16-bit numeric value x to a 9P message b.
+func pbit16(b []byte, x uint16) []byte {
+       n := len(b)
+       if n+2 > cap(b) {
+               nb := make([]byte, n, 100+2*cap(b))
+               copy(nb, b)
+               b = nb
+       }
+       b = b[0 : n+2]
+       b[n] = byte(x)
+       b[n+1] = byte(x >> 8)
+       return b
+}
+
+// pbit32 appends a 32-bit numeric value x to a 9P message b.
+func pbit32(b []byte, x uint32) []byte {
+       n := len(b)
+       if n+4 > cap(b) {
+               nb := make([]byte, n, 100+2*cap(b))
+               copy(nb, b)
+               b = nb
+       }
+       b = b[0 : n+4]
+       b[n] = byte(x)
+       b[n+1] = byte(x >> 8)
+       b[n+2] = byte(x >> 16)
+       b[n+3] = byte(x >> 24)
+       return b
+}
+
+// pbit64 appends a 64-bit numeric value x to a 9P message b.
+func pbit64(b []byte, x uint64) []byte {
+       b = pbit32(b, uint32(x))
+       b = pbit32(b, uint32(x>>32))
+       return b
+}
+
+// pstring appends a Go string s to a 9P message b.
+func pstring(b []byte, s string) []byte {
+       if len(s) >= 1<<16 {
+               panic(NewError("string too long"))
+       }
+       b = pbit16(b, uint16(len(s)))
+       b = append(b, []byte(s)...)
+       return b
+}
diff --git a/libgo/go/os/dir_unix.go b/libgo/go/os/dir_unix.go
new file mode 100644 (file)
index 0000000..f5b8223
--- /dev/null
@@ -0,0 +1,54 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package os
+
+import (
+       "syscall"
+)
+
+const (
+       blockSize = 4096
+)
+
+// Readdirnames reads the contents of the directory associated with file and
+// returns an array of up to count names, in directory order.  Subsequent
+// calls on the same file will yield further names.
+// A negative count means to read until EOF.
+// Readdirnames returns the array and an Error, if any.
+func (file *File) Readdirnames(count int) (names []string, err Error) {
+       // If this file has no dirinfo, create one.
+       if file.dirinfo == nil {
+               file.dirinfo = new(dirInfo)
+               // The buffer must be at least a block long.
+               file.dirinfo.buf = make([]byte, blockSize)
+       }
+       d := file.dirinfo
+       size := count
+       if size < 0 {
+               size = 100
+       }
+       names = make([]string, 0, size) // Empty with room to grow.
+       for count != 0 {
+               // Refill the buffer if necessary
+               if d.bufp >= d.nbuf {
+                       d.bufp = 0
+                       var errno int
+                       d.nbuf, errno = syscall.ReadDirent(file.fd, d.buf)
+                       if errno != 0 {
+                               return names, NewSyscallError("readdirent", errno)
+                       }
+                       if d.nbuf <= 0 {
+                               break // EOF
+                       }
+               }
+
+               // Drain the buffer
+               var nb, nc int
+               nb, nc, names = syscall.ParseDirent(d.buf[d.bufp:d.nbuf], count, names)
+               d.bufp += nb
+               count -= nc
+       }
+       return names, nil
+}
diff --git a/libgo/go/os/env_plan9.go b/libgo/go/os/env_plan9.go
new file mode 100644 (file)
index 0000000..14df55e
--- /dev/null
@@ -0,0 +1,91 @@
+// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Plan 9 environment variables.
+
+package os
+
+import "syscall"
+
+// ENOENV is the Error indicating that an environment variable does not exist.
+var ENOENV = NewError("no such environment variable")
+
+// Getenverror retrieves the value of the environment variable named by the key.
+// It returns the value and an error, if any.
+func Getenverror(key string) (value string, err Error) {
+       if len(key) == 0 {
+               return "", EINVAL
+       }
+       f, e := Open("/env/" + key)
+       if iserror(e) {
+               return "", ENOENV
+       }
+       defer f.Close()
+
+       var buf [4096]byte
+       n, e := f.Read(buf[:len(buf)-1])
+       if iserror(e) {
+               return "", ENOENV
+       }
+       buf[n] = 0
+       return string(buf[0:n]), nil
+}
+
+// Getenv retrieves the value of the environment variable named by the key.
+// It returns the value, which will be empty if the variable is not present.
+func Getenv(key string) string {
+       v, _ := Getenverror(key)
+       return v
+}
+
+// Setenv sets the value of the environment variable named by the key.
+// It returns an Error, if any.
+func Setenv(key, value string) Error {
+       if len(key) == 0 {
+               return EINVAL
+       }
+
+       f, e := Create("/env/" + key)
+       if iserror(e) {
+               return e
+       }
+       defer f.Close()
+
+       _, e = f.Write(syscall.StringByteSlice(value))
+       return nil
+}
+
+// Clearenv deletes all environment variables.
+func Clearenv() {
+       syscall.RawSyscall(syscall.SYS_RFORK, syscall.RFCENVG, 0, 0)
+}
+
+// Environ returns an array of strings representing the environment,
+// in the form "key=value".
+func Environ() []string {
+       env := make([]string, 0, 100)
+
+       f, e := Open("/env")
+       if iserror(e) {
+               panic(e)
+       }
+       defer f.Close()
+
+       names, e := f.Readdirnames(-1)
+       if iserror(e) {
+               panic(e)
+       }
+
+       for _, k := range names {
+               if v, e := Getenverror(k); !iserror(e) {
+                       env = append(env, k+"="+v)
+               }
+       }
+       return env[0:len(env)]
+}
+
+// TempDir returns the default directory to use for temporary files.
+func TempDir() string {
+       return "/tmp"
+}
index 635a3fe50aa350213d1a37bd274a3f230fe7f935..2c4516ca7dae79c5743820918e5b369b6b4d1ca8 100644 (file)
@@ -4,8 +4,6 @@
 
 package os
 
-import syscall "syscall"
-
 // An Error can represent any printable error condition.
 type Error interface {
        String() string
@@ -26,63 +24,6 @@ func (e ErrorString) Timeout() bool   { return false }
 // NewError converts s to an ErrorString, which satisfies the Error interface.
 func NewError(s string) Error { return ErrorString(s) }
 
-// Errno is the Unix error number.  Names such as EINVAL are simple
-// wrappers to convert the error number into an Error.
-type Errno int64
-
-func (e Errno) String() string { return syscall.Errstr(int(e)) }
-
-func (e Errno) Temporary() bool {
-       return e == Errno(syscall.EINTR) || e.Timeout()
-}
-
-func (e Errno) Timeout() bool {
-       return e == Errno(syscall.EAGAIN) || e == Errno(syscall.EWOULDBLOCK) || e == Errno(syscall.ETIMEDOUT)
-}
-
-// Commonly known Unix errors.
-var (
-       EPERM        Error = Errno(syscall.EPERM)
-       ENOENT       Error = Errno(syscall.ENOENT)
-       ESRCH        Error = Errno(syscall.ESRCH)
-       EINTR        Error = Errno(syscall.EINTR)
-       EIO          Error = Errno(syscall.EIO)
-       ENXIO        Error = Errno(syscall.ENXIO)
-       E2BIG        Error = Errno(syscall.E2BIG)
-       ENOEXEC      Error = Errno(syscall.ENOEXEC)
-       EBADF        Error = Errno(syscall.EBADF)
-       ECHILD       Error = Errno(syscall.ECHILD)
-       EDEADLK      Error = Errno(syscall.EDEADLK)
-       ENOMEM       Error = Errno(syscall.ENOMEM)
-       EACCES       Error = Errno(syscall.EACCES)
-       EFAULT       Error = Errno(syscall.EFAULT)
-       EBUSY        Error = Errno(syscall.EBUSY)
-       EEXIST       Error = Errno(syscall.EEXIST)
-       EXDEV        Error = Errno(syscall.EXDEV)
-       ENODEV       Error = Errno(syscall.ENODEV)
-       ENOTDIR      Error = Errno(syscall.ENOTDIR)
-       EISDIR       Error = Errno(syscall.EISDIR)
-       EINVAL       Error = Errno(syscall.EINVAL)
-       ENFILE       Error = Errno(syscall.ENFILE)
-       EMFILE       Error = Errno(syscall.EMFILE)
-       ENOTTY       Error = Errno(syscall.ENOTTY)
-       EFBIG        Error = Errno(syscall.EFBIG)
-       ENOSPC       Error = Errno(syscall.ENOSPC)
-       ESPIPE       Error = Errno(syscall.ESPIPE)
-       EROFS        Error = Errno(syscall.EROFS)
-       EMLINK       Error = Errno(syscall.EMLINK)
-       EPIPE        Error = Errno(syscall.EPIPE)
-       EAGAIN       Error = Errno(syscall.EAGAIN)
-       EDOM         Error = Errno(syscall.EDOM)
-       ERANGE       Error = Errno(syscall.ERANGE)
-       EADDRINUSE   Error = Errno(syscall.EADDRINUSE)
-       ECONNREFUSED Error = Errno(syscall.ECONNREFUSED)
-       ENAMETOOLONG Error = Errno(syscall.ENAMETOOLONG)
-       EAFNOSUPPORT Error = Errno(syscall.EAFNOSUPPORT)
-       ETIMEDOUT    Error = Errno(syscall.ETIMEDOUT)
-       ENOTCONN     Error = Errno(syscall.ENOTCONN)
-)
-
 // PathError records an error and the operation and file path that caused it.
 type PathError struct {
        Op    string
@@ -91,25 +32,3 @@ type PathError struct {
 }
 
 func (e *PathError) String() string { return e.Op + " " + e.Path + ": " + e.Error.String() }
-
-// SyscallError records an error from a specific system call.
-type SyscallError struct {
-       Syscall string
-       Errno   Errno
-}
-
-func (e *SyscallError) String() string { return e.Syscall + ": " + e.Errno.String() }
-
-// Note: If the name of the function NewSyscallError changes,
-// pkg/go/doc/doc.go should be adjusted since it hardwires
-// this name in a heuristic.
-
-// NewSyscallError returns, as an Error, a new SyscallError
-// with the given system call name and error number.
-// As a convenience, if errno is 0, NewSyscallError returns nil.
-func NewSyscallError(syscall string, errno int) Error {
-       if errno == 0 {
-               return nil
-       }
-       return &SyscallError{syscall, Errno(errno)}
-}
diff --git a/libgo/go/os/error_plan9.go b/libgo/go/os/error_plan9.go
new file mode 100644 (file)
index 0000000..d657586
--- /dev/null
@@ -0,0 +1,57 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package os
+
+import syscall "syscall"
+
+// SyscallError records an error from a specific system call.
+type SyscallError struct {
+       Syscall string
+       Err     string
+}
+
+func (e *SyscallError) String() string { return e.Syscall + ": " + e.Err }
+
+// Note: If the name of the function NewSyscallError changes,
+// pkg/go/doc/doc.go should be adjusted since it hardwires
+// this name in a heuristic.
+
+// NewSyscallError returns, as an Error, a new SyscallError
+// with the given system call name and error details.
+// As a convenience, if err is nil, NewSyscallError returns nil.
+func NewSyscallError(syscall string, err syscall.Error) Error {
+       if err == nil {
+               return nil
+       }
+       return &SyscallError{syscall, err.String()}
+}
+
+var (
+       Eshortstat = NewError("stat buffer too small")
+       Ebadstat   = NewError("malformed stat buffer")
+       Ebadfd     = NewError("fd out of range or not open")
+       Ebadarg    = NewError("bad arg in system call")
+       Enotdir    = NewError("not a directory")
+       Enonexist  = NewError("file does not exist")
+       Eexist     = NewError("file already exists")
+       Eio        = NewError("i/o error")
+
+       EINVAL  = Ebadarg
+       ENOTDIR = Enotdir
+       ENOENT  = Enonexist
+       EEXIST  = Eexist
+       EIO     = Eio
+
+       ENAMETOOLONG = NewError("file name too long")
+       ERANGE       = NewError("math result not representable")
+       EPIPE        = NewError("Broken Pipe")
+       EPLAN9       = NewError("not supported by plan 9")
+)
+
+func iserror(err syscall.Error) bool {
+       return err != nil
+}
+
+func Errno(e syscall.Error) syscall.Error { return e }
diff --git a/libgo/go/os/error_posix.go b/libgo/go/os/error_posix.go
new file mode 100644 (file)
index 0000000..0ee34e4
--- /dev/null
@@ -0,0 +1,90 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package os
+
+import syscall "syscall"
+
+// Errno is the Unix error number.  Names such as EINVAL are simple
+// wrappers to convert the error number into an Error.
+type Errno int64
+
+func (e Errno) String() string { return syscall.Errstr(int(e)) }
+
+func (e Errno) Temporary() bool {
+       return e == Errno(syscall.EINTR) || e.Timeout()
+}
+
+func (e Errno) Timeout() bool {
+       return e == Errno(syscall.EAGAIN) || e == Errno(syscall.EWOULDBLOCK) || e == Errno(syscall.ETIMEDOUT)
+}
+
+// Commonly known Unix errors.
+var (
+       EPERM        Error = Errno(syscall.EPERM)
+       ENOENT       Error = Errno(syscall.ENOENT)
+       ESRCH        Error = Errno(syscall.ESRCH)
+       EINTR        Error = Errno(syscall.EINTR)
+       EIO          Error = Errno(syscall.EIO)
+       ENXIO        Error = Errno(syscall.ENXIO)
+       E2BIG        Error = Errno(syscall.E2BIG)
+       ENOEXEC      Error = Errno(syscall.ENOEXEC)
+       EBADF        Error = Errno(syscall.EBADF)
+       ECHILD       Error = Errno(syscall.ECHILD)
+       EDEADLK      Error = Errno(syscall.EDEADLK)
+       ENOMEM       Error = Errno(syscall.ENOMEM)
+       EACCES       Error = Errno(syscall.EACCES)
+       EFAULT       Error = Errno(syscall.EFAULT)
+       EBUSY        Error = Errno(syscall.EBUSY)
+       EEXIST       Error = Errno(syscall.EEXIST)
+       EXDEV        Error = Errno(syscall.EXDEV)
+       ENODEV       Error = Errno(syscall.ENODEV)
+       ENOTDIR      Error = Errno(syscall.ENOTDIR)
+       EISDIR       Error = Errno(syscall.EISDIR)
+       EINVAL       Error = Errno(syscall.EINVAL)
+       ENFILE       Error = Errno(syscall.ENFILE)
+       EMFILE       Error = Errno(syscall.EMFILE)
+       ENOTTY       Error = Errno(syscall.ENOTTY)
+       EFBIG        Error = Errno(syscall.EFBIG)
+       ENOSPC       Error = Errno(syscall.ENOSPC)
+       ESPIPE       Error = Errno(syscall.ESPIPE)
+       EROFS        Error = Errno(syscall.EROFS)
+       EMLINK       Error = Errno(syscall.EMLINK)
+       EPIPE        Error = Errno(syscall.EPIPE)
+       EAGAIN       Error = Errno(syscall.EAGAIN)
+       EDOM         Error = Errno(syscall.EDOM)
+       ERANGE       Error = Errno(syscall.ERANGE)
+       EADDRINUSE   Error = Errno(syscall.EADDRINUSE)
+       ECONNREFUSED Error = Errno(syscall.ECONNREFUSED)
+       ENAMETOOLONG Error = Errno(syscall.ENAMETOOLONG)
+       EAFNOSUPPORT Error = Errno(syscall.EAFNOSUPPORT)
+       ETIMEDOUT    Error = Errno(syscall.ETIMEDOUT)
+       ENOTCONN     Error = Errno(syscall.ENOTCONN)
+)
+
+// SyscallError records an error from a specific system call.
+type SyscallError struct {
+       Syscall string
+       Errno   Errno
+}
+
+func (e *SyscallError) String() string { return e.Syscall + ": " + e.Errno.String() }
+
+// Note: If the name of the function NewSyscallError changes,
+// pkg/go/doc/doc.go should be adjusted since it hardwires
+// this name in a heuristic.
+
+// NewSyscallError returns, as an Error, a new SyscallError
+// with the given system call name and error details.
+// As a convenience, if errno is 0, NewSyscallError returns nil.
+func NewSyscallError(syscall string, errno int) Error {
+       if errno == 0 {
+               return nil
+       }
+       return &SyscallError{syscall, Errno(errno)}
+}
+
+func iserror(errno int) bool {
+       return errno != 0
+}
index 9d80ccfbed464d65564cec40b65e73318b9268d3..f62caf9a069b15b8fa7b10b24f92925a3b3a17d0 100644 (file)
@@ -39,126 +39,6 @@ type ProcAttr struct {
        Files []*File
 }
 
-// StartProcess starts a new process with the program, arguments and attributes
-// specified by name, argv and attr.
-func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err Error) {
-       sysattr := &syscall.ProcAttr{
-               Dir: attr.Dir,
-               Env: attr.Env,
-       }
-       if sysattr.Env == nil {
-               sysattr.Env = Environ()
-       }
-       // Create array of integer (system) fds.
-       intfd := make([]int, len(attr.Files))
-       for i, f := range attr.Files {
-               if f == nil {
-                       intfd[i] = -1
-               } else {
-                       intfd[i] = f.Fd()
-               }
-       }
-       sysattr.Files = intfd
-
-       pid, h, e := syscall.StartProcess(name, argv, sysattr)
-       if e != 0 {
-               return nil, &PathError{"fork/exec", name, Errno(e)}
-       }
-       return newProcess(pid, h), nil
-}
-
-// Exec replaces the current process with an execution of the
-// named binary, with arguments argv and environment envv.
-// If successful, Exec never returns.  If it fails, it returns an Error.
-// StartProcess is almost always a better way to execute a program.
-func Exec(name string, argv []string, envv []string) Error {
-       if envv == nil {
-               envv = Environ()
-       }
-       e := syscall.Exec(name, argv, envv)
-       if e != 0 {
-               return &PathError{"exec", name, Errno(e)}
-       }
-       return nil
-}
-
-// TODO(rsc): Should os implement its own syscall.WaitStatus
-// wrapper with the methods, or is exposing the underlying one enough?
-//
-// TODO(rsc): Certainly need to have Rusage struct,
-// since syscall one might have different field types across
-// different OS.
-
-// Waitmsg stores the information about an exited process as reported by Wait.
-type Waitmsg struct {
-       Pid                int             // The process's id.
-       syscall.WaitStatus                 // System-dependent status info.
-       Rusage             *syscall.Rusage // System-dependent resource usage info.
-}
-
-// Wait waits for process pid to exit or stop, and then returns a
-// Waitmsg describing its status and an Error, if any. The options
-// (WNOHANG etc.) affect the behavior of the Wait call.
-// Wait is equivalent to calling FindProcess and then Wait
-// and Release on the result.
-func Wait(pid int, options int) (w *Waitmsg, err Error) {
-       p, e := FindProcess(pid)
-       if e != nil {
-               return nil, e
-       }
-       defer p.Release()
-       return p.Wait(options)
-}
-
-// Convert i to decimal string.
-func itod(i int) string {
-       if i == 0 {
-               return "0"
-       }
-
-       u := uint64(i)
-       if i < 0 {
-               u = -u
-       }
-
-       // Assemble decimal in reverse order.
-       var b [32]byte
-       bp := len(b)
-       for ; u > 0; u /= 10 {
-               bp--
-               b[bp] = byte(u%10) + '0'
-       }
-
-       if i < 0 {
-               bp--
-               b[bp] = '-'
-       }
-
-       return string(b[bp:])
-}
-
-func (w Waitmsg) String() string {
-       // TODO(austin) Use signal names when possible?
-       res := ""
-       switch {
-       case w.Exited():
-               res = "exit status " + itod(w.ExitStatus())
-       case w.Signaled():
-               res = "signal " + itod(w.Signal())
-       case w.Stopped():
-               res = "stop signal " + itod(w.StopSignal())
-               if w.StopSignal() == syscall.SIGTRAP && w.TrapCause() != 0 {
-                       res += " (trap " + itod(w.TrapCause()) + ")"
-               }
-       case w.Continued():
-               res = "continued"
-       }
-       if w.CoreDump() {
-               res += " (core dumped)"
-       }
-       return res
-}
-
 // Getpid returns the process id of the caller.
 func Getpid() int { return syscall.Getpid() }
 
diff --git a/libgo/go/os/exec_plan9.go b/libgo/go/os/exec_plan9.go
new file mode 100644 (file)
index 0000000..11874ab
--- /dev/null
@@ -0,0 +1,114 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package os
+
+import (
+       "runtime"
+       "syscall"
+)
+
+// StartProcess starts a new process with the program, arguments and attributes
+// specified by name, argv and attr.
+func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err Error) {
+       sysattr := &syscall.ProcAttr{
+               Dir: attr.Dir,
+               Env: attr.Env,
+       }
+
+       // Create array of integer (system) fds.
+       intfd := make([]int, len(attr.Files))
+       for i, f := range attr.Files {
+               if f == nil {
+                       intfd[i] = -1
+               } else {
+                       intfd[i] = f.Fd()
+               }
+       }
+
+       sysattr.Files = intfd
+
+       pid, h, e := syscall.StartProcess(name, argv, sysattr)
+       if iserror(e) {
+               return nil, &PathError{"fork/exec", name, e}
+       }
+
+       return newProcess(pid, h), nil
+}
+
+// Exec replaces the current process with an execution of the
+// named binary, with arguments argv and environment envv.
+// If successful, Exec never returns.  If it fails, it returns an Error.
+// ForkExec is almost always a better way to execute a program.
+func Exec(name string, argv []string, envv []string) Error {
+       e := syscall.Exec(name, argv, envv)
+       if iserror(e) {
+               return &PathError{"exec", name, e}
+       }
+
+       return nil
+}
+
+// Waitmsg stores the information about an exited process as reported by Wait.
+type Waitmsg syscall.Waitmsg
+
+// Wait waits for the Process to exit or stop, and then returns a
+// Waitmsg describing its status and an Error, if any. The options
+// (WNOHANG etc.) affect the behavior of the Wait call.
+func (p *Process) Wait(options int) (w *Waitmsg, err Error) {
+       var waitmsg syscall.Waitmsg
+
+       if p.Pid == -1 {
+               return nil, EINVAL
+       }
+
+       for true {
+               err = syscall.Await(&waitmsg)
+
+               if iserror(err) {
+                       return nil, NewSyscallError("wait", err)
+               }
+
+               if waitmsg.Pid == p.Pid {
+                       break
+               }
+       }
+
+       return (*Waitmsg)(&waitmsg), nil
+}
+
+// Wait waits for process pid to exit or stop, and then returns a
+// Waitmsg describing its status and an Error, if any. The options
+// (WNOHANG etc.) affect the behavior of the Wait call.
+// Wait is equivalent to calling FindProcess and then Wait
+// and Release on the result.
+func Wait(pid int, options int) (w *Waitmsg, err Error) {
+       p, e := FindProcess(pid)
+       if e != nil {
+               return nil, e
+       }
+       defer p.Release()
+       return p.Wait(options)
+}
+
+// Release releases any resources associated with the Process.
+func (p *Process) Release() Error {
+       // NOOP for Plan 9.
+       p.Pid = -1
+       // no need for a finalizer anymore
+       runtime.SetFinalizer(p, nil)
+       return nil
+}
+
+// FindProcess looks for a running process by its pid.
+// The Process it returns can be used to obtain information
+// about the underlying operating system process.
+func FindProcess(pid int) (p *Process, err Error) {
+       // NOOP for Plan 9.
+       return newProcess(pid, 0), nil
+}
+
+func (w Waitmsg) String() string {
+       return "exit status: " + w.Msg
+}
diff --git a/libgo/go/os/exec_posix.go b/libgo/go/os/exec_posix.go
new file mode 100644 (file)
index 0000000..9102dc0
--- /dev/null
@@ -0,0 +1,127 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package os
+
+import "syscall"
+
+// StartProcess starts a new process with the program, arguments and attributes
+// specified by name, argv and attr.
+func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err Error) {
+       sysattr := &syscall.ProcAttr{
+               Dir: attr.Dir,
+               Env: attr.Env,
+       }
+       if sysattr.Env == nil {
+               sysattr.Env = Environ()
+       }
+       // Create array of integer (system) fds.
+       intfd := make([]int, len(attr.Files))
+       for i, f := range attr.Files {
+               if f == nil {
+                       intfd[i] = -1
+               } else {
+                       intfd[i] = f.Fd()
+               }
+       }
+       sysattr.Files = intfd
+
+       pid, h, e := syscall.StartProcess(name, argv, sysattr)
+       if iserror(e) {
+               return nil, &PathError{"fork/exec", name, Errno(e)}
+       }
+       return newProcess(pid, h), nil
+}
+
+// Exec replaces the current process with an execution of the
+// named binary, with arguments argv and environment envv.
+// If successful, Exec never returns.  If it fails, it returns an Error.
+// StartProcess is almost always a better way to execute a program.
+func Exec(name string, argv []string, envv []string) Error {
+       if envv == nil {
+               envv = Environ()
+       }
+       e := syscall.Exec(name, argv, envv)
+       if iserror(e) {
+               return &PathError{"exec", name, Errno(e)}
+       }
+       return nil
+}
+
+// TODO(rsc): Should os implement its own syscall.WaitStatus
+// wrapper with the methods, or is exposing the underlying one enough?
+//
+// TODO(rsc): Certainly need to have Rusage struct,
+// since syscall one might have different field types across
+// different OS.
+
+// Waitmsg stores the information about an exited process as reported by Wait.
+type Waitmsg struct {
+       Pid                int             // The process's id.
+       syscall.WaitStatus                 // System-dependent status info.
+       Rusage             *syscall.Rusage // System-dependent resource usage info.
+}
+
+// Wait waits for process pid to exit or stop, and then returns a
+// Waitmsg describing its status and an Error, if any. The options
+// (WNOHANG etc.) affect the behavior of the Wait call.
+// Wait is equivalent to calling FindProcess and then Wait
+// and Release on the result.
+func Wait(pid int, options int) (w *Waitmsg, err Error) {
+       p, e := FindProcess(pid)
+       if e != nil {
+               return nil, e
+       }
+       defer p.Release()
+       return p.Wait(options)
+}
+
+// Convert i to decimal string.
+func itod(i int) string {
+       if i == 0 {
+               return "0"
+       }
+
+       u := uint64(i)
+       if i < 0 {
+               u = -u
+       }
+
+       // Assemble decimal in reverse order.
+       var b [32]byte
+       bp := len(b)
+       for ; u > 0; u /= 10 {
+               bp--
+               b[bp] = byte(u%10) + '0'
+       }
+
+       if i < 0 {
+               bp--
+               b[bp] = '-'
+       }
+
+       return string(b[bp:])
+}
+
+func (w Waitmsg) String() string {
+       // TODO(austin) Use signal names when possible?
+       res := ""
+       switch {
+       case w.Exited():
+               res = "exit status " + itod(w.ExitStatus())
+       case w.Signaled():
+               res = "signal " + itod(w.Signal())
+       case w.Stopped():
+               res = "stop signal " + itod(w.StopSignal())
+               if w.StopSignal() == syscall.SIGTRAP && w.TrapCause() != 0 {
+                       res += " (trap " + itod(w.TrapCause()) + ")"
+               }
+       case w.Continued():
+               res = "continued"
+       }
+       if w.CoreDump() {
+               res += " (core dumped)"
+       }
+       return res
+}
index 3f73f1dffef6f9da90dd0feb7e1d7f5c2c8815dd..3aad8023453358517fdede659574941e625af93a 100644 (file)
@@ -51,14 +51,20 @@ const (
        O_RDWR     int = syscall.O_RDWR     // open the file read-write.
        O_APPEND   int = syscall.O_APPEND   // append data to the file when writing.
        O_ASYNC    int = syscall.O_ASYNC    // generate a signal when I/O is available.
-       O_CREAT    int = syscall.O_CREAT    // create a new file if none exists.
-       O_EXCL     int = syscall.O_EXCL     // used with O_CREAT, file must not exist
+       O_CREATE   int = syscall.O_CREAT    // create a new file if none exists.
+       O_EXCL     int = syscall.O_EXCL     // used with O_CREATE, file must not exist
        O_NOCTTY   int = syscall.O_NOCTTY   // do not make file the controlling tty.
        O_NONBLOCK int = syscall.O_NONBLOCK // open in non-blocking mode.
        O_NDELAY   int = O_NONBLOCK         // synonym for O_NONBLOCK
        O_SYNC     int = syscall.O_SYNC     // open for synchronous I/O.
        O_TRUNC    int = syscall.O_TRUNC    // if possible, truncate file when opened.
-       O_CREATE   int = O_CREAT            // create a new file if none exists.
+)
+
+// Seek whence values.
+const (
+       SEEK_SET int = 0 // seek relative to the origin of the file
+       SEEK_CUR int = 1 // seek relative to the current offset
+       SEEK_END int = 2 // seek relative to the end
 )
 
 type eofError int
@@ -83,10 +89,10 @@ func (file *File) Read(b []byte) (n int, err Error) {
        if n < 0 {
                n = 0
        }
-       if n == 0 && e == 0 {
+       if n == 0 && !iserror(e) {
                return 0, EOF
        }
-       if e != 0 {
+       if iserror(e) {
                err = &PathError{"read", file.name, Errno(e)}
        }
        return n, err
@@ -102,10 +108,10 @@ func (file *File) ReadAt(b []byte, off int64) (n int, err Error) {
        }
        for len(b) > 0 {
                m, e := syscall.Pread(file.fd, b, off)
-               if m == 0 && e == 0 {
+               if m == 0 && !iserror(e) {
                        return n, EOF
                }
-               if e != 0 {
+               if iserror(e) {
                        err = &PathError{"read", file.name, Errno(e)}
                        break
                }
@@ -127,15 +133,10 @@ func (file *File) Write(b []byte) (n int, err Error) {
        if n < 0 {
                n = 0
        }
-       if e == syscall.EPIPE {
-               file.nepipe++
-               if file.nepipe >= 10 {
-                       Exit(syscall.EPIPE)
-               }
-       } else {
-               file.nepipe = 0
-       }
-       if e != 0 {
+
+       epipecheck(file, e)
+
+       if iserror(e) {
                err = &PathError{"write", file.name, Errno(e)}
        }
        return n, err
@@ -150,7 +151,7 @@ func (file *File) WriteAt(b []byte, off int64) (n int, err Error) {
        }
        for len(b) > 0 {
                m, e := syscall.Pwrite(file.fd, b, off)
-               if e != 0 {
+               if iserror(e) {
                        err = &PathError{"write", file.name, Errno(e)}
                        break
                }
@@ -167,10 +168,10 @@ func (file *File) WriteAt(b []byte, off int64) (n int, err Error) {
 // It returns the new offset and an Error, if any.
 func (file *File) Seek(offset int64, whence int) (ret int64, err Error) {
        r, e := syscall.Seek(file.fd, offset, whence)
-       if e == 0 && file.dirinfo != nil && r != 0 {
+       if !iserror(e) && file.dirinfo != nil && r != 0 {
                e = syscall.EISDIR
        }
-       if e != 0 {
+       if iserror(e) {
                return 0, &PathError{"seek", file.name, Errno(e)}
        }
        return r, nil
@@ -187,71 +188,19 @@ func (file *File) WriteString(s string) (ret int, err Error) {
        return file.Write(b)
 }
 
-// Pipe returns a connected pair of Files; reads from r return bytes written to w.
-// It returns the files and an Error, if any.
-func Pipe() (r *File, w *File, err Error) {
-       var p [2]int
-
-       // See ../syscall/exec.go for description of lock.
-       syscall.ForkLock.RLock()
-       e := syscall.Pipe(p[0:])
-       if e != 0 {
-               syscall.ForkLock.RUnlock()
-               return nil, nil, NewSyscallError("pipe", e)
-       }
-       syscall.CloseOnExec(p[0])
-       syscall.CloseOnExec(p[1])
-       syscall.ForkLock.RUnlock()
-
-       return NewFile(p[0], "|0"), NewFile(p[1], "|1"), nil
-}
-
 // Mkdir creates a new directory with the specified name and permission bits.
 // It returns an error, if any.
 func Mkdir(name string, perm uint32) Error {
        e := syscall.Mkdir(name, perm)
-       if e != 0 {
+       if iserror(e) {
                return &PathError{"mkdir", name, Errno(e)}
        }
        return nil
 }
 
-// Stat returns a FileInfo structure describing the named file and an error, if any.
-// If name names a valid symbolic link, the returned FileInfo describes
-// the file pointed at by the link and has fi.FollowedSymlink set to true.
-// If name names an invalid symbolic link, the returned FileInfo describes
-// the link itself and has fi.FollowedSymlink set to false.
-func Stat(name string) (fi *FileInfo, err Error) {
-       var lstat, stat syscall.Stat_t
-       e := syscall.Lstat(name, &lstat)
-       if e != 0 {
-               return nil, &PathError{"stat", name, Errno(e)}
-       }
-       statp := &lstat
-       if lstat.Mode&syscall.S_IFMT == syscall.S_IFLNK {
-               e := syscall.Stat(name, &stat)
-               if e == 0 {
-                       statp = &stat
-               }
-       }
-       return fileInfoFromStat(name, new(FileInfo), &lstat, statp), nil
-}
-
-// Lstat returns the FileInfo structure describing the named file and an
-// error, if any.  If the file is a symbolic link, the returned FileInfo
-// describes the symbolic link.  Lstat makes no attempt to follow the link.
-func Lstat(name string) (fi *FileInfo, err Error) {
-       var stat syscall.Stat_t
-       e := syscall.Lstat(name, &stat)
-       if e != 0 {
-               return nil, &PathError{"lstat", name, Errno(e)}
-       }
-       return fileInfoFromStat(name, new(FileInfo), &stat, &stat), nil
-}
-
 // Chdir changes the current working directory to the named directory.
 func Chdir(dir string) Error {
-       if e := syscall.Chdir(dir); e != 0 {
+       if e := syscall.Chdir(dir); iserror(e) {
                return &PathError{"chdir", dir, Errno(e)}
        }
        return nil
@@ -260,179 +209,25 @@ func Chdir(dir string) Error {
 // Chdir changes the current working directory to the file,
 // which must be a directory.
 func (f *File) Chdir() Error {
-       if e := syscall.Fchdir(f.fd); e != 0 {
+       if e := syscall.Fchdir(f.fd); iserror(e) {
                return &PathError{"chdir", f.name, Errno(e)}
        }
        return nil
 }
 
-// Remove removes the named file or directory.
-func Remove(name string) Error {
-       // System call interface forces us to know
-       // whether name is a file or directory.
-       // Try both: it is cheaper on average than
-       // doing a Stat plus the right one.
-       e := syscall.Unlink(name)
-       if e == 0 {
-               return nil
-       }
-       e1 := syscall.Rmdir(name)
-       if e1 == 0 {
-               return nil
-       }
-
-       // Both failed: figure out which error to return.
-       // OS X and Linux differ on whether unlink(dir)
-       // returns EISDIR, so can't use that.  However,
-       // both agree that rmdir(file) returns ENOTDIR,
-       // so we can use that to decide which error is real.
-       // Rmdir might also return ENOTDIR if given a bad
-       // file path, like /etc/passwd/foo, but in that case,
-       // both errors will be ENOTDIR, so it's okay to
-       // use the error from unlink.
-       // For windows syscall.ENOTDIR is set
-       // to syscall.ERROR_DIRECTORY, hopefully it should
-       // do the trick.
-       if e1 != syscall.ENOTDIR {
-               e = e1
-       }
-       return &PathError{"remove", name, Errno(e)}
-}
-
-// LinkError records an error during a link or symlink or rename
-// system call and the paths that caused it.
-type LinkError struct {
-       Op    string
-       Old   string
-       New   string
-       Error Error
-}
-
-func (e *LinkError) String() string {
-       return e.Op + " " + e.Old + " " + e.New + ": " + e.Error.String()
+// Open opens the named file for reading.  If successful, methods on
+// the returned file can be used for reading; the associated file
+// descriptor has mode O_RDONLY.
+// It returns the File and an Error, if any.
+func Open(name string) (file *File, err Error) {
+       return OpenFile(name, O_RDONLY, 0)
 }
 
-// Link creates a hard link.
-func Link(oldname, newname string) Error {
-       e := syscall.Link(oldname, newname)
-       if e != 0 {
-               return &LinkError{"link", oldname, newname, Errno(e)}
-       }
-       return nil
-}
-
-// Symlink creates a symbolic link.
-func Symlink(oldname, newname string) Error {
-       e := syscall.Symlink(oldname, newname)
-       if e != 0 {
-               return &LinkError{"symlink", oldname, newname, Errno(e)}
-       }
-       return nil
-}
-
-// Readlink reads the contents of a symbolic link: the destination of
-// the link.  It returns the contents and an Error, if any.
-func Readlink(name string) (string, Error) {
-       for len := 128; ; len *= 2 {
-               b := make([]byte, len)
-               n, e := syscall.Readlink(name, b)
-               if e != 0 {
-                       return "", &PathError{"readlink", name, Errno(e)}
-               }
-               if n < len {
-                       return string(b[0:n]), nil
-               }
-       }
-       // Silence 6g.
-       return "", nil
-}
-
-// Rename renames a file.
-func Rename(oldname, newname string) Error {
-       e := syscall.Rename(oldname, newname)
-       if e != 0 {
-               return &LinkError{"rename", oldname, newname, Errno(e)}
-       }
-       return nil
-}
-
-// Chmod changes the mode of the named file to mode.
-// If the file is a symbolic link, it changes the mode of the link's target.
-func Chmod(name string, mode uint32) Error {
-       if e := syscall.Chmod(name, mode); e != 0 {
-               return &PathError{"chmod", name, Errno(e)}
-       }
-       return nil
-}
-
-// Chmod changes the mode of the file to mode.
-func (f *File) Chmod(mode uint32) Error {
-       if e := syscall.Fchmod(f.fd, mode); e != 0 {
-               return &PathError{"chmod", f.name, Errno(e)}
-       }
-       return nil
-}
-
-// Chown changes the numeric uid and gid of the named file.
-// If the file is a symbolic link, it changes the uid and gid of the link's target.
-func Chown(name string, uid, gid int) Error {
-       if e := syscall.Chown(name, uid, gid); e != 0 {
-               return &PathError{"chown", name, Errno(e)}
-       }
-       return nil
-}
-
-// Lchown changes the numeric uid and gid of the named file.
-// If the file is a symbolic link, it changes the uid and gid of the link itself.
-func Lchown(name string, uid, gid int) Error {
-       if e := syscall.Lchown(name, uid, gid); e != 0 {
-               return &PathError{"lchown", name, Errno(e)}
-       }
-       return nil
-}
-
-// Chown changes the numeric uid and gid of the named file.
-func (f *File) Chown(uid, gid int) Error {
-       if e := syscall.Fchown(f.fd, uid, gid); e != 0 {
-               return &PathError{"chown", f.name, Errno(e)}
-       }
-       return nil
-}
-
-// Truncate changes the size of the file.
-// It does not change the I/O offset.
-func (f *File) Truncate(size int64) Error {
-       if e := syscall.Ftruncate(f.fd, size); e != 0 {
-               return &PathError{"truncate", f.name, Errno(e)}
-       }
-       return nil
-}
-
-// Sync commits the current contents of the file to stable storage.
-// Typically, this means flushing the file system's in-memory copy
-// of recently written data to disk.
-func (file *File) Sync() (err Error) {
-       if file == nil {
-               return EINVAL
-       }
-       if e := syscall.Fsync(file.fd); e != 0 {
-               return NewSyscallError("fsync", e)
-       }
-       return nil
-}
-
-// Chtimes changes the access and modification times of the named
-// file, similar to the Unix utime() or utimes() functions.
-//
-// The argument times are in nanoseconds, although the underlying
-// filesystem may truncate or round the values to a more
-// coarse time unit.
-func Chtimes(name string, atime_ns int64, mtime_ns int64) Error {
-       var utimes [2]syscall.Timeval
-       utimes[0] = syscall.NsecToTimeval(atime_ns)
-       utimes[1] = syscall.NsecToTimeval(mtime_ns)
-       if e := syscall.Utimes(name, utimes[0:]); e != 0 {
-               return &PathError{"chtimes", name, Errno(e)}
-       }
-       return nil
+// Create creates the named file mode 0666 (before umask), truncating
+// it if it already exists.  If successful, methods on the returned
+// File can be used for I/O; the associated file descriptor has mode
+// O_RDWR.
+// It returns the File and an Error, if any.
+func Create(name string) (file *File, err Error) {
+       return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
 }
diff --git a/libgo/go/os/file_plan9.go b/libgo/go/os/file_plan9.go
new file mode 100644 (file)
index 0000000..b79256c
--- /dev/null
@@ -0,0 +1,233 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package os
+
+import (
+       "runtime"
+       "syscall"
+)
+
+func epipecheck(file *File, e syscall.Error) {
+}
+
+
+// DevNull is the name of the operating system's ``null device.''
+// On Unix-like systems, it is "/dev/null"; on Windows, "NUL".
+const DevNull = "/dev/null"
+
+// OpenFile is the generalized open call; most users will use Open
+// or Create instead.  It opens the named file with specified flag
+// (O_RDONLY etc.) and perm, (0666 etc.) if applicable.  If successful,
+// methods on the returned File can be used for I/O.
+// It returns the File and an Error, if any.
+func OpenFile(name string, flag int, perm uint32) (file *File, err Error) {
+       var fd int
+       var e syscall.Error
+
+       syscall.ForkLock.RLock()
+       if flag&O_CREATE == O_CREATE {
+               fd, e = syscall.Create(name, flag & ^O_CREATE, perm)
+       } else {
+               fd, e = syscall.Open(name, flag)
+       }
+       syscall.ForkLock.RUnlock()
+
+       if e != nil {
+               return nil, &PathError{"open", name, e}
+       }
+
+       return NewFile(fd, name), nil
+}
+
+// Close closes the File, rendering it unusable for I/O.
+// It returns an Error, if any.
+func (file *File) Close() Error {
+       if file == nil || file.fd < 0 {
+               return Ebadfd
+       }
+       var err Error
+       syscall.ForkLock.RLock()
+       if e := syscall.Close(file.fd); e != nil {
+               err = &PathError{"close", file.name, e}
+       }
+       syscall.ForkLock.RUnlock()
+       file.fd = -1 // so it can't be closed again
+
+       // no need for a finalizer anymore
+       runtime.SetFinalizer(file, nil)
+       return err
+}
+
+// Stat returns the FileInfo structure describing file.
+// It returns the FileInfo and an error, if any.
+func (file *File) Stat() (fi *FileInfo, err Error) {
+       return dirstat(file)
+}
+
+// Truncate changes the size of the file.
+// It does not change the I/O offset.
+func (f *File) Truncate(size int64) Error {
+       var d Dir
+       d.Null()
+
+       d.Length = uint64(size)
+
+       if e := syscall.Fwstat(f.fd, pdir(nil, &d)); iserror(e) {
+               return &PathError{"truncate", f.name, e}
+       }
+       return nil
+}
+
+// Chmod changes the mode of the file to mode.
+func (f *File) Chmod(mode uint32) Error {
+       var d Dir
+       d.Null()
+
+       d.Mode = mode & 0777
+
+       if e := syscall.Fwstat(f.fd, pdir(nil, &d)); iserror(e) {
+               return &PathError{"chmod", f.name, e}
+       }
+       return nil
+}
+
+// Sync commits the current contents of the file to stable storage.
+// Typically, this means flushing the file system's in-memory copy
+// of recently written data to disk.
+func (f *File) Sync() (err Error) {
+       if f == nil {
+               return EINVAL
+       }
+
+       var d Dir
+       d.Null()
+
+       if e := syscall.Fwstat(f.fd, pdir(nil, &d)); iserror(e) {
+               return NewSyscallError("fsync", e)
+       }
+       return nil
+}
+
+// Truncate changes the size of the named file.
+// If the file is a symbolic link, it changes the size of the link's target.
+func Truncate(name string, size int64) Error {
+       var d Dir
+       d.Null()
+
+       d.Length = uint64(size)
+
+       if e := syscall.Wstat(name, pdir(nil, &d)); iserror(e) {
+               return &PathError{"truncate", name, e}
+       }
+       return nil
+}
+
+// Remove removes the named file or directory.
+func Remove(name string) Error {
+       if e := syscall.Remove(name); iserror(e) {
+               return &PathError{"remove", name, e}
+       }
+       return nil
+}
+
+// Rename renames a file.
+func Rename(oldname, newname string) Error {
+       var d Dir
+       d.Null()
+
+       d.Name = newname
+
+       if e := syscall.Wstat(oldname, pdir(nil, &d)); iserror(e) {
+               return &PathError{"rename", oldname, e}
+       }
+       return nil
+}
+
+// Chmod changes the mode of the named file to mode.
+func Chmod(name string, mode uint32) Error {
+       var d Dir
+       d.Null()
+
+       d.Mode = mode & 0777
+
+       if e := syscall.Wstat(name, pdir(nil, &d)); iserror(e) {
+               return &PathError{"chmod", name, e}
+       }
+       return nil
+}
+
+// ChownPlan9 changes the uid and gid strings of the named file.
+func ChownPlan9(name, uid, gid string) Error {
+       var d Dir
+       d.Null()
+
+       d.Uid = uid
+       d.Gid = gid
+
+       if e := syscall.Wstat(name, pdir(nil, &d)); iserror(e) {
+               return &PathError{"chown_plan9", name, e}
+       }
+       return nil
+}
+
+// Chtimes changes the access and modification times of the named
+// file, similar to the Unix utime() or utimes() functions.
+//
+// The argument times are in nanoseconds, although the underlying
+// filesystem may truncate or round the values to a more
+// coarse time unit.
+func Chtimes(name string, atimeNs int64, mtimeNs int64) Error {
+       var d Dir
+       d.Null()
+
+       d.Atime = uint32(atimeNs / 1e9)
+       d.Mtime = uint32(mtimeNs / 1e9)
+
+       if e := syscall.Wstat(name, pdir(nil, &d)); iserror(e) {
+               return &PathError{"chtimes", name, e}
+       }
+       return nil
+}
+
+func Pipe() (r *File, w *File, err Error) {
+       var p [2]int
+
+       syscall.ForkLock.RLock()
+       if e := syscall.Pipe(p[0:]); iserror(e) {
+               syscall.ForkLock.RUnlock()
+               return nil, nil, NewSyscallError("pipe", e)
+       }
+       syscall.ForkLock.RUnlock()
+
+       return NewFile(p[0], "|0"), NewFile(p[1], "|1"), nil
+}
+
+
+// not supported on Plan 9
+
+// Link creates a hard link.
+func Link(oldname, newname string) Error {
+       return EPLAN9
+}
+
+func Symlink(oldname, newname string) Error {
+       return EPLAN9
+}
+
+func Readlink(name string) (string, Error) {
+       return "", EPLAN9
+}
+
+func Chown(name string, uid, gid int) Error {
+       return EPLAN9
+}
+
+func Lchown(name string, uid, gid int) Error {
+       return EPLAN9
+}
+
+func (f *File) Chown(uid, gid int) Error {
+       return EPLAN9
+}
diff --git a/libgo/go/os/file_posix.go b/libgo/go/os/file_posix.go
new file mode 100644 (file)
index 0000000..5151df4
--- /dev/null
@@ -0,0 +1,246 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// The os package provides a platform-independent interface to operating
+// system functionality.  The design is Unix-like.
+package os
+
+import (
+       "syscall"
+)
+
+func epipecheck(file *File, e int) {
+       if e == syscall.EPIPE {
+               file.nepipe++
+               if file.nepipe >= 10 {
+                       Exit(syscall.EPIPE)
+               }
+       } else {
+               file.nepipe = 0
+       }
+}
+
+
+// Pipe returns a connected pair of Files; reads from r return bytes written to w.
+// It returns the files and an Error, if any.
+func Pipe() (r *File, w *File, err Error) {
+       var p [2]int
+
+       // See ../syscall/exec.go for description of lock.
+       syscall.ForkLock.RLock()
+       e := syscall.Pipe(p[0:])
+       if iserror(e) {
+               syscall.ForkLock.RUnlock()
+               return nil, nil, NewSyscallError("pipe", e)
+       }
+       syscall.CloseOnExec(p[0])
+       syscall.CloseOnExec(p[1])
+       syscall.ForkLock.RUnlock()
+
+       return NewFile(p[0], "|0"), NewFile(p[1], "|1"), nil
+}
+
+// Stat returns a FileInfo structure describing the named file and an error, if any.
+// If name names a valid symbolic link, the returned FileInfo describes
+// the file pointed at by the link and has fi.FollowedSymlink set to true.
+// If name names an invalid symbolic link, the returned FileInfo describes
+// the link itself and has fi.FollowedSymlink set to false.
+func Stat(name string) (fi *FileInfo, err Error) {
+       var lstat, stat syscall.Stat_t
+       e := syscall.Lstat(name, &lstat)
+       if iserror(e) {
+               return nil, &PathError{"stat", name, Errno(e)}
+       }
+       statp := &lstat
+       if lstat.Mode&syscall.S_IFMT == syscall.S_IFLNK {
+               e := syscall.Stat(name, &stat)
+               if !iserror(e) {
+                       statp = &stat
+               }
+       }
+       return fileInfoFromStat(name, new(FileInfo), &lstat, statp), nil
+}
+
+// Lstat returns the FileInfo structure describing the named file and an
+// error, if any.  If the file is a symbolic link, the returned FileInfo
+// describes the symbolic link.  Lstat makes no attempt to follow the link.
+func Lstat(name string) (fi *FileInfo, err Error) {
+       var stat syscall.Stat_t
+       e := syscall.Lstat(name, &stat)
+       if iserror(e) {
+               return nil, &PathError{"lstat", name, Errno(e)}
+       }
+       return fileInfoFromStat(name, new(FileInfo), &stat, &stat), nil
+}
+
+// Remove removes the named file or directory.
+func Remove(name string) Error {
+       // System call interface forces us to know
+       // whether name is a file or directory.
+       // Try both: it is cheaper on average than
+       // doing a Stat plus the right one.
+       e := syscall.Unlink(name)
+       if !iserror(e) {
+               return nil
+       }
+       e1 := syscall.Rmdir(name)
+       if !iserror(e1) {
+               return nil
+       }
+
+       // Both failed: figure out which error to return.
+       // OS X and Linux differ on whether unlink(dir)
+       // returns EISDIR, so can't use that.  However,
+       // both agree that rmdir(file) returns ENOTDIR,
+       // so we can use that to decide which error is real.
+       // Rmdir might also return ENOTDIR if given a bad
+       // file path, like /etc/passwd/foo, but in that case,
+       // both errors will be ENOTDIR, so it's okay to
+       // use the error from unlink.
+       // For windows syscall.ENOTDIR is set
+       // to syscall.ERROR_DIRECTORY, hopefully it should
+       // do the trick.
+       if e1 != syscall.ENOTDIR {
+               e = e1
+       }
+       return &PathError{"remove", name, Errno(e)}
+}
+
+// LinkError records an error during a link or symlink or rename
+// system call and the paths that caused it.
+type LinkError struct {
+       Op    string
+       Old   string
+       New   string
+       Error Error
+}
+
+func (e *LinkError) String() string {
+       return e.Op + " " + e.Old + " " + e.New + ": " + e.Error.String()
+}
+
+// Link creates a hard link.
+func Link(oldname, newname string) Error {
+       e := syscall.Link(oldname, newname)
+       if iserror(e) {
+               return &LinkError{"link", oldname, newname, Errno(e)}
+       }
+       return nil
+}
+
+// Symlink creates a symbolic link.
+func Symlink(oldname, newname string) Error {
+       e := syscall.Symlink(oldname, newname)
+       if iserror(e) {
+               return &LinkError{"symlink", oldname, newname, Errno(e)}
+       }
+       return nil
+}
+
+// Readlink reads the contents of a symbolic link: the destination of
+// the link.  It returns the contents and an Error, if any.
+func Readlink(name string) (string, Error) {
+       for len := 128; ; len *= 2 {
+               b := make([]byte, len)
+               n, e := syscall.Readlink(name, b)
+               if iserror(e) {
+                       return "", &PathError{"readlink", name, Errno(e)}
+               }
+               if n < len {
+                       return string(b[0:n]), nil
+               }
+       }
+       // Silence 6g.
+       return "", nil
+}
+
+// Rename renames a file.
+func Rename(oldname, newname string) Error {
+       e := syscall.Rename(oldname, newname)
+       if iserror(e) {
+               return &LinkError{"rename", oldname, newname, Errno(e)}
+       }
+       return nil
+}
+
+// Chmod changes the mode of the named file to mode.
+// If the file is a symbolic link, it changes the mode of the link's target.
+func Chmod(name string, mode uint32) Error {
+       if e := syscall.Chmod(name, mode); iserror(e) {
+               return &PathError{"chmod", name, Errno(e)}
+       }
+       return nil
+}
+
+// Chmod changes the mode of the file to mode.
+func (f *File) Chmod(mode uint32) Error {
+       if e := syscall.Fchmod(f.fd, mode); iserror(e) {
+               return &PathError{"chmod", f.name, Errno(e)}
+       }
+       return nil
+}
+
+// Chown changes the numeric uid and gid of the named file.
+// If the file is a symbolic link, it changes the uid and gid of the link's target.
+func Chown(name string, uid, gid int) Error {
+       if e := syscall.Chown(name, uid, gid); iserror(e) {
+               return &PathError{"chown", name, Errno(e)}
+       }
+       return nil
+}
+
+// Lchown changes the numeric uid and gid of the named file.
+// If the file is a symbolic link, it changes the uid and gid of the link itself.
+func Lchown(name string, uid, gid int) Error {
+       if e := syscall.Lchown(name, uid, gid); iserror(e) {
+               return &PathError{"lchown", name, Errno(e)}
+       }
+       return nil
+}
+
+// Chown changes the numeric uid and gid of the named file.
+func (f *File) Chown(uid, gid int) Error {
+       if e := syscall.Fchown(f.fd, uid, gid); iserror(e) {
+               return &PathError{"chown", f.name, Errno(e)}
+       }
+       return nil
+}
+
+// Truncate changes the size of the file.
+// It does not change the I/O offset.
+func (f *File) Truncate(size int64) Error {
+       if e := syscall.Ftruncate(f.fd, size); iserror(e) {
+               return &PathError{"truncate", f.name, Errno(e)}
+       }
+       return nil
+}
+
+// Sync commits the current contents of the file to stable storage.
+// Typically, this means flushing the file system's in-memory copy
+// of recently written data to disk.
+func (file *File) Sync() (err Error) {
+       if file == nil {
+               return EINVAL
+       }
+       if e := syscall.Fsync(file.fd); iserror(e) {
+               return NewSyscallError("fsync", e)
+       }
+       return nil
+}
+
+// Chtimes changes the access and modification times of the named
+// file, similar to the Unix utime() or utimes() functions.
+//
+// The argument times are in nanoseconds, although the underlying
+// filesystem may truncate or round the values to a more
+// coarse time unit.
+func Chtimes(name string, atime_ns int64, mtime_ns int64) Error {
+       var utimes [2]syscall.Timeval
+       utimes[0] = syscall.NsecToTimeval(atime_ns)
+       utimes[1] = syscall.NsecToTimeval(mtime_ns)
+       if e := syscall.Utimes(name, utimes[0:]); iserror(e) {
+               return &PathError{"chtimes", name, Errno(e)}
+       }
+       return nil
+}
index 01268e53a78b7033e07881853ceb2cae83144dd5..f80f1d538ef59ed2fc696e2d4b7f052036d6441d 100644 (file)
@@ -19,10 +19,12 @@ type dirInfo struct {
 // On Unix-like systems, it is "/dev/null"; on Windows, "NUL".
 const DevNull = "/dev/null"
 
-// Open opens the named file with specified flag (O_RDONLY etc.) and perm, (0666 etc.)
-// if applicable.  If successful, methods on the returned File can be used for I/O.
+// OpenFile is the generalized open call; most users will use Open
+// or Create instead.  It opens the named file with specified flag
+// (O_RDONLY etc.) and perm, (0666 etc.) if applicable.  If successful,
+// methods on the returned File can be used for I/O.
 // It returns the File and an Error, if any.
-func Open(name string, flag int, perm uint32) (file *File, err Error) {
+func OpenFile(name string, flag int, perm uint32) (file *File, err Error) {
        r, e := syscall.Open(name, flag|syscall.O_CLOEXEC, perm)
        if e != 0 {
                return nil, &PathError{"open", name, Errno(e)}
index 49aaea865f2274f7dec9d3a587c7cd0f4a6a3447..4c142ad3abbf453b7ec9a8cbe2d4355f6b3ad35b 100644 (file)
@@ -54,7 +54,7 @@ func Getwd() (string, Error) {
                if len(parent) >= 1024 { // Sanity check
                        return "", ENAMETOOLONG
                }
-               fd, err := Open(parent, O_RDONLY, 0)
+               fd, err := Open(parent)
                if err != nil {
                        return "", err
                }
index 79c3bfa36e489e8af75fbc29f3fd57033e080058..f5d1f8384df5533fdff33c18803658b20f80ef07 100644 (file)
@@ -51,7 +51,7 @@ func TestInotifyEvents(t *testing.T) {
 
        // Create a file
        // This should add at least one event to the inotify event queue
-       _, err = os.Open(testFile, os.O_WRONLY|os.O_CREAT, 0666)
+       _, err = os.OpenFile(testFile, os.O_WRONLY|os.O_CREATE, 0666)
        if err != nil {
                t.Fatalf("creating test file failed: %s", err)
        }
index bb1b8e31893150aa0a7d0774dfc956ce6f63baf2..607a11be334f0da1733d497ee2f220ff9ff06df9 100644 (file)
@@ -17,6 +17,7 @@ import (
 )
 
 var dot = []string{
+       "dir_unix.go",
        "env_unix.go",
        "error.go",
        "file.go",
@@ -56,7 +57,7 @@ var sysdir = func() (sd *sysDir) {
 }()
 
 func size(name string, t *testing.T) int64 {
-       file, err := Open(name, O_RDONLY, 0)
+       file, err := Open(name)
        defer file.Close()
        if err != nil {
                t.Fatal("open failed:", err)
@@ -121,7 +122,7 @@ func TestStat(t *testing.T) {
 
 func TestFstat(t *testing.T) {
        path := sfdir + "/" + sfname
-       file, err1 := Open(path, O_RDONLY, 0)
+       file, err1 := Open(path)
        defer file.Close()
        if err1 != nil {
                t.Fatal("open failed:", err1)
@@ -155,7 +156,7 @@ func TestLstat(t *testing.T) {
 }
 
 func testReaddirnames(dir string, contents []string, t *testing.T) {
-       file, err := Open(dir, O_RDONLY, 0)
+       file, err := Open(dir)
        defer file.Close()
        if err != nil {
                t.Fatalf("open %q failed: %v", dir, err)
@@ -184,7 +185,7 @@ func testReaddirnames(dir string, contents []string, t *testing.T) {
 }
 
 func testReaddir(dir string, contents []string, t *testing.T) {
-       file, err := Open(dir, O_RDONLY, 0)
+       file, err := Open(dir)
        defer file.Close()
        if err != nil {
                t.Fatalf("open %q failed: %v", dir, err)
@@ -245,7 +246,7 @@ func TestReaddirnamesOneAtATime(t *testing.T) {
        if syscall.OS == "windows" {
                dir = Getenv("SystemRoot") + "\\system32"
        }
-       file, err := Open(dir, O_RDONLY, 0)
+       file, err := Open(dir)
        defer file.Close()
        if err != nil {
                t.Fatalf("open %q failed: %v", dir, err)
@@ -254,7 +255,7 @@ func TestReaddirnamesOneAtATime(t *testing.T) {
        if err1 != nil {
                t.Fatalf("readdirnames %q failed: %v", dir, err1)
        }
-       file1, err2 := Open(dir, O_RDONLY, 0)
+       file1, err2 := Open(dir)
        if err2 != nil {
                t.Fatalf("open %q failed: %v", dir, err2)
        }
@@ -273,7 +274,7 @@ func TestHardLink(t *testing.T) {
        }
        from, to := "hardlinktestfrom", "hardlinktestto"
        Remove(from) // Just in case.
-       file, err := Open(to, O_CREAT|O_WRONLY, 0666)
+       file, err := Create(to)
        if err != nil {
                t.Fatalf("open %q failed: %v", to, err)
        }
@@ -306,7 +307,7 @@ func TestSymLink(t *testing.T) {
        }
        from, to := "symlinktestfrom", "symlinktestto"
        Remove(from) // Just in case.
-       file, err := Open(to, O_CREAT|O_WRONLY, 0666)
+       file, err := Create(to)
        if err != nil {
                t.Fatalf("open %q failed: %v", to, err)
        }
@@ -354,7 +355,7 @@ func TestSymLink(t *testing.T) {
        if s != to {
                t.Fatalf("after symlink %q != %q", s, to)
        }
-       file, err = Open(from, O_RDONLY, 0)
+       file, err = Open(from)
        if err != nil {
                t.Fatalf("open %q failed: %v", from, err)
        }
@@ -388,7 +389,7 @@ func TestLongSymlink(t *testing.T) {
 func TestRename(t *testing.T) {
        from, to := "renamefrom", "renameto"
        Remove(to) // Just in case.
-       file, err := Open(from, O_CREAT|O_WRONLY, 0666)
+       file, err := Create(from)
        if err != nil {
                t.Fatalf("open %q failed: %v", to, err)
        }
@@ -615,7 +616,7 @@ func TestChdirAndGetwd(t *testing.T) {
        if syscall.OS == "windows" {
                return
        }
-       fd, err := Open(".", O_RDONLY, 0)
+       fd, err := Open(".")
        if err != nil {
                t.Fatalf("Open .: %s", err)
        }
@@ -627,7 +628,7 @@ func TestChdirAndGetwd(t *testing.T) {
                        if mode == 0 {
                                err = Chdir(d)
                        } else {
-                               fd1, err := Open(d, O_RDONLY, 0)
+                               fd1, err := Open(d)
                                if err != nil {
                                        t.Errorf("Open %s: %s", d, err)
                                        continue
@@ -736,7 +737,7 @@ var openErrorTests = []openErrorTest{
 
 func TestOpenError(t *testing.T) {
        for _, tt := range openErrorTests {
-               f, err := Open(tt.path, tt.mode, 0)
+               f, err := OpenFile(tt.path, tt.mode, 0)
                if err == nil {
                        t.Errorf("Open(%q, %d) succeeded", tt.path, tt.mode)
                        f.Close()
@@ -842,7 +843,7 @@ func TestWriteAt(t *testing.T) {
 }
 
 func writeFile(t *testing.T, fname string, flag int, text string) string {
-       f, err := Open(fname, flag, 0666)
+       f, err := OpenFile(fname, flag, 0666)
        if err != nil {
                t.Fatalf("Open: %v", err)
        }
@@ -861,7 +862,7 @@ func writeFile(t *testing.T, fname string, flag int, text string) string {
 func TestAppend(t *testing.T) {
        const f = "append.txt"
        defer Remove(f)
-       s := writeFile(t, f, O_CREAT|O_TRUNC|O_RDWR, "new")
+       s := writeFile(t, f, O_CREATE|O_TRUNC|O_RDWR, "new")
        if s != "new" {
                t.Fatalf("writeFile: have %q want %q", s, "new")
        }
index b762971d9cf986e5bd1c1c281042df475c7ce5a1..0eb3ee50369b98d1f986915181065c811e018304 100644 (file)
@@ -33,7 +33,7 @@ func MkdirAll(path string, perm uint32) Error {
                j--
        }
 
-       if j > 0 {
+       if j > 1 {
                // Create parent
                err = MkdirAll(path[0:j-1], perm)
                if err != nil {
@@ -80,7 +80,7 @@ func RemoveAll(path string) Error {
        }
 
        // Directory.
-       fd, err := Open(path, O_RDONLY, 0)
+       fd, err := Open(path)
        if err != nil {
                return err
        }
index 799e3ec2fa7a231f5ee3450154953e03cdfa4f3a..483bb639535ddbc748c0b366d249a70fd8e3c23f 100644 (file)
@@ -29,7 +29,7 @@ func TestMkdirAll(t *testing.T) {
 
        // Make file.
        fpath := path + "/file"
-       _, err = Open(fpath, O_WRONLY|O_CREAT, 0666)
+       _, err = Create(fpath)
        if err != nil {
                t.Fatalf("create %q: %s", fpath, err)
        }
@@ -72,7 +72,7 @@ func TestRemoveAll(t *testing.T) {
        if err := MkdirAll(path, 0777); err != nil {
                t.Fatalf("MkdirAll %q: %s", path, err)
        }
-       fd, err := Open(fpath, O_WRONLY|O_CREAT, 0666)
+       fd, err := Create(fpath)
        if err != nil {
                t.Fatalf("create %q: %s", fpath, err)
        }
@@ -88,12 +88,12 @@ func TestRemoveAll(t *testing.T) {
        if err = MkdirAll(dpath, 0777); err != nil {
                t.Fatalf("MkdirAll %q: %s", dpath, err)
        }
-       fd, err = Open(fpath, O_WRONLY|O_CREAT, 0666)
+       fd, err = Create(fpath)
        if err != nil {
                t.Fatalf("create %q: %s", fpath, err)
        }
        fd.Close()
-       fd, err = Open(dpath+"/file", O_WRONLY|O_CREAT, 0666)
+       fd, err = Create(dpath + "/file")
        if err != nil {
                t.Fatalf("create %q: %s", fpath, err)
        }
@@ -121,7 +121,7 @@ func TestRemoveAll(t *testing.T) {
                }
 
                for _, s := range []string{fpath, dpath + "/file1", path + "/zzz"} {
-                       fd, err = Open(s, O_WRONLY|O_CREAT, 0666)
+                       fd, err = Create(s)
                        if err != nil {
                                t.Fatalf("create %q: %s", s, err)
                        }
@@ -179,3 +179,20 @@ func TestMkdirAllWithSymlink(t *testing.T) {
                t.Errorf("MkdirAll %q: %s", path, err)
        }
 }
+
+func TestMkdirAllAtSlash(t *testing.T) {
+       if runtime.GOOS == "windows" {
+               return
+       }
+       RemoveAll("/_go_os_test")
+       err := MkdirAll("/_go_os_test/dir", 0777)
+       if err != nil {
+               pathErr, ok := err.(*PathError)
+               // common for users not to be able to write to /
+               if ok && pathErr.Error == EACCES {
+                       return
+               }
+               t.Fatalf(`MkdirAll "/_go_os_test/dir": %v`, err)
+       }
+       RemoveAll("/_go_os_test")
+}
index dfddab6cb8f04b11358d98459423e8826536e6e2..481ef603371b407586264bd7f27f4b7c6de5ea74 100644 (file)
@@ -26,8 +26,8 @@ func Getegid() int { return syscall.Getegid() }
 
 // Getgroups returns a list of the numeric ids of groups that the caller belongs to.
 func Getgroups() ([]int, Error) {
-       gids, errno := syscall.Getgroups()
-       return gids, NewSyscallError("getgroups", errno)
+       gids, e := syscall.Getgroups()
+       return gids, NewSyscallError("getgroups", e)
 }
 
 // Exit causes the current program to exit with the given status code.
diff --git a/libgo/go/os/stat_plan9.go b/libgo/go/os/stat_plan9.go
new file mode 100644 (file)
index 0000000..e96749d
--- /dev/null
@@ -0,0 +1,84 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package os
+
+import "syscall"
+
+func fileInfoFromStat(fi *FileInfo, d *Dir) *FileInfo {
+       fi.Dev = uint64(d.Qid.Vers) | uint64(d.Qid.Type<<32)
+       fi.Ino = d.Qid.Path
+
+       fi.Mode = uint32(d.Mode) & 0777
+       if (d.Mode & syscall.DMDIR) == syscall.DMDIR {
+               fi.Mode |= syscall.S_IFDIR
+       } else {
+               fi.Mode |= syscall.S_IFREG
+       }
+
+       fi.Size = int64(d.Length)
+       fi.Atime_ns = 1e9 * int64(d.Atime)
+       fi.Mtime_ns = 1e9 * int64(d.Mtime)
+       fi.Name = d.Name
+       fi.FollowedSymlink = false
+       return fi
+}
+
+// arg is an open *File or a path string. 
+func dirstat(arg interface{}) (fi *FileInfo, err Error) {
+       var name string
+       nd := syscall.STATFIXLEN + 16*4
+
+       for i := 0; i < 2; i++ { /* should work by the second try */
+               buf := make([]byte, nd)
+
+               var n int
+               var e syscall.Error
+
+               switch syscallArg := arg.(type) {
+               case *File:
+                       name = syscallArg.name
+                       n, e = syscall.Fstat(syscallArg.fd, buf)
+               case string:
+                       name = syscallArg
+                       n, e = syscall.Stat(name, buf)
+               }
+
+               if e != nil {
+                       return nil, &PathError{"stat", name, e}
+               }
+
+               if n < syscall.STATFIXLEN {
+                       return nil, &PathError{"stat", name, Eshortstat}
+               }
+
+               ntmp, _ := gbit16(buf)
+               nd = int(ntmp)
+
+               if nd <= n {
+                       d, e := UnmarshalDir(buf[:n])
+
+                       if e != nil {
+                               return nil, &PathError{"stat", name, e}
+                       }
+
+                       return fileInfoFromStat(new(FileInfo), d), nil
+               }
+       }
+
+       return nil, &PathError{"stat", name, Ebadstat}
+}
+
+
+// Stat returns a FileInfo structure describing the named file and an error, if any.
+func Stat(name string) (fi *FileInfo, err Error) {
+       return dirstat(name)
+}
+
+// Lstat returns the FileInfo structure describing the named file and an
+// error, if any.  If the file is a symbolic link (though Plan 9 does not have symbolic links), 
+// the returned FileInfo describes the symbolic link.  Lstat makes no attempt to follow the link.
+func Lstat(name string) (fi *FileInfo, err Error) {
+       return dirstat(name)
+}
index b82d295d3d6c33d43399d40d59bc69b50a754ba8..408d667c7cf1e2d5425fabe580208260a6fcb372 100644 (file)
@@ -9,7 +9,7 @@ package os
 
 // Hostname returns the host name reported by the kernel.
 func Hostname() (name string, err Error) {
-       f, err := Open("/proc/sys/kernel/hostname", O_RDONLY, 0)
+       f, err := Open("/proc/sys/kernel/hostname")
        if err != nil {
                return "", err
        }
diff --git a/libgo/go/os/sys_plan9.go b/libgo/go/os/sys_plan9.go
new file mode 100644 (file)
index 0000000..f6af28b
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Plan 9-specific
+
+package os
+
+
+func Hostname() (name string, err Error) {
+       f, err := Open("#c/sysname")
+       if err != nil {
+               return "", err
+       }
+       defer f.Close()
+
+       var buf [128]byte
+       n, err := f.Read(buf[:len(buf)-1])
+
+       if err != nil {
+               return "", err
+       }
+       if n > 0 {
+               buf[n] = 0
+       }
+       return string(buf[0:n]), nil
+}
index 380345f1b1ec60840b2fb2474e2093834cf64e08..8e87a49e1627171c3a43fba5f93decdcc2d1004a 100644 (file)
@@ -13,8 +13,8 @@ import "syscall"
 // time is the Unix epoch.
 func Time() (sec int64, nsec int64, err Error) {
        var tv syscall.Timeval
-       if errno := syscall.Gettimeofday(&tv); errno != 0 {
-               return 0, 0, NewSyscallError("gettimeofday", errno)
+       if e := syscall.Gettimeofday(&tv); iserror(e) {
+               return 0, 0, NewSyscallError("gettimeofday", e)
        }
        return int64(tv.Sec), int64(tv.Usec) * 1000, err
 }
index ad4053fa242a64ed50bd331e1b79f18d208225e5..a05bb5f7e71d6c050cb3df885b7545653b8085ed 100644 (file)
@@ -32,7 +32,7 @@ var ErrBadPattern = os.NewError("syntax error in pattern")
 //             lo '-' hi   matches character c for lo <= c <= hi
 //
 // Match requires pattern to match all of name, not just a substring.
-// The only possible error return is when pattern is malformed.
+// The only possible error return occurs when the pattern is malformed.
 //
 func Match(pattern, name string) (matched bool, err os.Error) {
 Pattern:
@@ -211,13 +211,14 @@ func getEsc(chunk string) (r int, nchunk string, err os.Error) {
 // if there is no matching file. The syntax of patterns is the same
 // as in Match. The pattern may describe hierarchical names such as
 // /usr/*/bin/ed (assuming the Separator is '/').
+// The only possible error return occurs when the pattern is malformed.
 //
-func Glob(pattern string) (matches []string) {
+func Glob(pattern string) (matches []string, err os.Error) {
        if !hasMeta(pattern) {
-               if _, err := os.Stat(pattern); err == nil {
-                       return []string{pattern}
+               if _, err = os.Stat(pattern); err != nil {
+                       return
                }
-               return nil
+               return []string{pattern}, nil
        }
 
        dir, file := Split(pattern)
@@ -230,48 +231,60 @@ func Glob(pattern string) (matches []string) {
                dir = dir[0 : len(dir)-1] // chop off trailing separator
        }
 
-       if hasMeta(dir) {
-               for _, d := range Glob(dir) {
-                       matches = glob(d, file, matches)
-               }
-       } else {
+       if !hasMeta(dir) {
                return glob(dir, file, nil)
        }
-       return matches
+
+       var m []string
+       m, err = Glob(dir)
+       if err != nil {
+               return
+       }
+       for _, d := range m {
+               matches, err = glob(d, file, matches)
+               if err != nil {
+                       return
+               }
+       }
+       return
 }
 
 // glob searches for files matching pattern in the directory dir
-// and appends them to matches.
-func glob(dir, pattern string, matches []string) []string {
+// and appends them to matches. If the directory cannot be
+// opened, it returns the existing matches. New matches are
+// added in lexicographical order.
+// The only possible error return occurs when the pattern is malformed.
+func glob(dir, pattern string, matches []string) (m []string, e os.Error) {
+       m = matches
        fi, err := os.Stat(dir)
        if err != nil {
-               return nil
+               return
        }
        if !fi.IsDirectory() {
-               return matches
+               return
        }
-       d, err := os.Open(dir, os.O_RDONLY, 0666)
+       d, err := os.Open(dir)
        if err != nil {
-               return nil
+               return
        }
        defer d.Close()
 
        names, err := d.Readdirnames(-1)
        if err != nil {
-               return nil
+               return
        }
        sort.SortStrings(names)
 
        for _, n := range names {
                matched, err := Match(pattern, n)
                if err != nil {
-                       return matches
+                       return m, err
                }
                if matched {
-                       matches = append(matches, Join(dir, n))
+                       m = append(m, Join(dir, n))
                }
        }
-       return matches
+       return
 }
 
 // hasMeta returns true if path contains any of the magic characters
index a1e631647e51e50fb1714c784b10f1b27e64aba8..0b594fa66e295c7be5ae4f9253aaa49ea6098006 100644 (file)
@@ -6,7 +6,7 @@ package filepath_test
 
 import (
        "os"
-       "path/filepath"
+       "path/filepath"
        "testing"
        "runtime"
 )
@@ -56,16 +56,16 @@ var matchTests = []MatchTest{
        {"[\\-x]", "x", true, nil},
        {"[\\-x]", "-", true, nil},
        {"[\\-x]", "a", false, nil},
-       {"[]a]", "]", false, filepath.ErrBadPattern},
-       {"[-]", "-", false, filepath.ErrBadPattern},
-       {"[x-]", "x", false, filepath.ErrBadPattern},
-       {"[x-]", "-", false, filepath.ErrBadPattern},
-       {"[x-]", "z", false, filepath.ErrBadPattern},
-       {"[-x]", "x", false, filepath.ErrBadPattern},
-       {"[-x]", "-", false, filepath.ErrBadPattern},
-       {"[-x]", "a", false, filepath.ErrBadPattern},
-       {"\\", "a", false, filepath.ErrBadPattern},
-       {"[a-b-c]", "a", false, filepath.ErrBadPattern},
+       {"[]a]", "]", false, ErrBadPattern},
+       {"[-]", "-", false, ErrBadPattern},
+       {"[x-]", "x", false, ErrBadPattern},
+       {"[x-]", "-", false, ErrBadPattern},
+       {"[x-]", "z", false, ErrBadPattern},
+       {"[-x]", "x", false, ErrBadPattern},
+       {"[-x]", "-", false, ErrBadPattern},
+       {"[-x]", "a", false, ErrBadPattern},
+       {"\\", "a", false, ErrBadPattern},
+       {"[a-b-c]", "a", false, ErrBadPattern},
        {"*x", "xxx", true, nil},
 }
 
@@ -75,7 +75,7 @@ func TestMatch(t *testing.T) {
                return
        }
        for _, tt := range matchTests {
-               ok, err := filepath.Match(tt.pattern, tt.s)
+               ok, err := Match(tt.pattern, tt.s)
                if ok != tt.match || err != tt.err {
                        t.Errorf("Match(%#q, %#q) = %v, %v want %v, nil", tt.pattern, tt.s, ok, err, tt.match)
                }
@@ -84,7 +84,7 @@ func TestMatch(t *testing.T) {
 
 // contains returns true if vector contains the string s.
 func contains(vector []string, s string) bool {
-       s = filepath.ToSlash(s)
+       s = ToSlash(s)
        for _, elem := range vector {
                if elem == s {
                        return true
@@ -109,9 +109,20 @@ func TestGlob(t *testing.T) {
                return
        }
        for _, tt := range globTests {
-               matches := filepath.Glob(tt.pattern)
+               matches, err := Glob(tt.pattern)
+               if err != nil {
+                       t.Errorf("Glob error for %q: %s", tt.pattern, err)
+                       continue
+               }
                if !contains(matches, tt.result) {
                        t.Errorf("Glob(%#q) = %#v want %v", tt.pattern, matches, tt.result)
                }
        }
 }
+
+func TestGlobError(t *testing.T) {
+       _, err := Glob("[7]")
+       if err != nil {
+               t.Error("expected error for bad pattern; got none")
+       }
+}
index 6cd6cf2ab094034a4ac55ad8befbbae83c6a185a..de673a7257725cf0d3e266af206f393794bad87d 100644 (file)
@@ -231,6 +231,21 @@ func EvalSymlinks(path string) (string, os.Error) {
        return Clean(b.String()), nil
 }
 
+// Abs returns an absolute representation of path.
+// If the path is not absolute it will be joined with the current
+// working directory to turn it into an absolute path.  The absolute
+// path name for a given file is not guaranteed to be unique.
+func Abs(path string) (string, os.Error) {
+       if IsAbs(path) {
+               return path, nil
+       }
+       wd, err := os.Getwd()
+       if err != nil {
+               return "", err
+       }
+       return Join(wd, path), nil
+}
+
 // Visitor methods are invoked for corresponding file tree entries
 // visited by Walk. The parameter path is the full path of f relative
 // to root.
@@ -265,7 +280,7 @@ func walk(path string, f *os.FileInfo, v Visitor, errors chan<- os.Error) {
 // a list of sorted directory entries.
 // Copied from io/ioutil to avoid the circular import.
 func readDir(dirname string) ([]*os.FileInfo, os.Error) {
-       f, err := os.Open(dirname, os.O_RDONLY, 0)
+       f, err := os.Open(dirname)
        if err != nil {
                return nil, err
        }
diff --git a/libgo/go/path/filepath/path_plan9.go b/libgo/go/path/filepath/path_plan9.go
new file mode 100644 (file)
index 0000000..e400083
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package filepath
+
+import "strings"
+
+const (
+       Separator     = '/' // OS-specific path separator
+       ListSeparator = 0   // OS-specific path list separator
+)
+
+// isSeparator returns true if c is a directory separator character.
+func isSeparator(c uint8) bool {
+       return Separator == c
+}
+
+// IsAbs returns true if the path is absolute.
+func IsAbs(path string) bool {
+       return strings.HasPrefix(path, "/") || strings.HasPrefix(path, "#")
+}
+
+// volumeName returns the leading volume name on Windows.
+// It returns "" elsewhere
+func volumeName(path string) string {
+       return ""
+}
index 0249af4d87c20cb74baf32a9e1cd377d44c8e110..37078f63af979b55f94a26ff288465933d0a67c0 100644 (file)
@@ -248,7 +248,7 @@ func walkTree(n *Node, path string, f func(path string, n *Node)) {
 func makeTree(t *testing.T) {
        walkTree(tree, tree.name, func(path string, n *Node) {
                if n.entries == nil {
-                       fd, err := os.Open(path, os.O_CREAT, 0660)
+                       fd, err := os.Create(path)
                        if err != nil {
                                t.Errorf("makeTree: %v", err)
                        }
@@ -459,9 +459,9 @@ func TestEvalSymlinks(t *testing.T) {
        // relative
        for _, d := range EvalSymlinksTests {
                if p, err := filepath.EvalSymlinks(d.path); err != nil {
-                       t.Errorf("EvalSymlinks(%v) error: %v", d.path, err)
+                       t.Errorf("EvalSymlinks(%q) error: %v", d.path, err)
                } else if p != d.dest {
-                       t.Errorf("EvalSymlinks(%v)=%v, want %v", d.path, p, d.dest)
+                       t.Errorf("EvalSymlinks(%q)=%q, want %q", d.path, p, d.dest)
                }
        }
        // absolute
@@ -477,10 +477,54 @@ func TestEvalSymlinks(t *testing.T) {
                        filepath.Join(testroot, d.dest),
                }
                if p, err := filepath.EvalSymlinks(a.path); err != nil {
-                       t.Errorf("EvalSymlinks(%v) error: %v", a.path, err)
+                       t.Errorf("EvalSymlinks(%q) error: %v", a.path, err)
                } else if p != a.dest {
-                       t.Errorf("EvalSymlinks(%v)=%v, want %v", a.path, p, a.dest)
+                       t.Errorf("EvalSymlinks(%q)=%q, want %q", a.path, p, a.dest)
                }
        }
 */
 }
+
+/* These tests do not work in the gccgo test environment.
+
+// Test paths relative to $GOROOT/src
+var abstests = []string{
+       "../AUTHORS",
+       "pkg/../../AUTHORS",
+       "Make.pkg",
+       "pkg/Makefile",
+
+       // Already absolute
+       "$GOROOT/src/Make.pkg",
+}
+
+func TestAbs(t *testing.T) {
+       oldwd, err := os.Getwd()
+       if err != nil {
+               t.Fatal("Getwd failed: " + err.String())
+       }
+       defer os.Chdir(oldwd)
+       goroot := os.Getenv("GOROOT")
+       cwd := filepath.Join(goroot, "src")
+       os.Chdir(cwd)
+       for _, path := range abstests {
+               path = strings.Replace(path, "$GOROOT", goroot, -1)
+               abspath, err := filepath.Abs(path)
+               if err != nil {
+                       t.Errorf("Abs(%q) error: %v", path, err)
+               }
+               info, err := os.Stat(path)
+               if err != nil {
+                       t.Errorf("%s: %s", path, err)
+               }
+               absinfo, err := os.Stat(abspath)
+               if err != nil || absinfo.Ino != info.Ino {
+                       t.Errorf("Abs(%q)=%q, not the same file", path, abspath)
+               }
+               if !filepath.IsAbs(abspath) {
+                       t.Errorf("Abs(%q)=%q, not an absolute path", path, abspath)
+               }
+       }
+}
+
+*/
index 1bb21ec7d92a1184b42b5e30ce1d7920c8569ee4..f8ac248fbb973cc114a1d5d2c6a3047bbd373720 100644 (file)
@@ -22,7 +22,7 @@ func IsAbs(path string) bool {
 }
 
 // volumeName returns the leading volume name on Windows.
-// It returns "" on Unix.
+// It returns "" elsewhere.
 func volumeName(path string) string {
        return ""
 }
index 2396cdd9a190591a6ccf19512d2e98108a0a9e47..560e595b45a82cab0740dfd20e38ac2f85913f2d 100644 (file)
@@ -331,7 +331,7 @@ func (s *Scanner) error(msg string) {
                s.Error(s, msg)
                return
        }
-       fmt.Fprintf(os.Stderr, "%s: %s", s.Position, msg)
+       fmt.Fprintf(os.Stderr, "%s: %s\n", s.Position, msg)
 }
 
 
@@ -503,41 +503,32 @@ func (s *Scanner) scanChar() {
 }
 
 
-func (s *Scanner) scanLineComment() {
-       ch := s.next() // read character after "//"
-       for ch != '\n' {
-               if ch < 0 {
-                       s.error("comment not terminated")
-                       return
+func (s *Scanner) scanComment(ch int) int {
+       // ch == '/' || ch == '*'
+       if ch == '/' {
+               // line comment
+               ch = s.next() // read character after "//"
+               for ch != '\n' && ch >= 0 {
+                       ch = s.next()
                }
-               ch = s.next()
+               return ch
        }
-}
-
 
-func (s *Scanner) scanGeneralComment() {
-       ch := s.next() // read character after "/*"
+       // general comment
+       ch = s.next() // read character after "/*"
        for {
                if ch < 0 {
                        s.error("comment not terminated")
-                       return
+                       break
                }
                ch0 := ch
                ch = s.next()
                if ch0 == '*' && ch == '/' {
+                       ch = s.next()
                        break
                }
        }
-}
-
-
-func (s *Scanner) scanComment(ch int) {
-       // ch == '/' || ch == '*'
-       if ch == '/' {
-               s.scanLineComment()
-               return
-       }
-       s.scanGeneralComment()
+       return ch
 }
 
 
@@ -619,13 +610,11 @@ redo:
                        if (ch == '/' || ch == '*') && s.Mode&ScanComments != 0 {
                                if s.Mode&SkipComments != 0 {
                                        s.tokPos = -1 // don't collect token text
-                                       s.scanComment(ch)
-                                       ch = s.next()
+                                       ch = s.scanComment(ch)
                                        goto redo
                                }
-                               s.scanComment(ch)
+                               ch = s.scanComment(ch)
                                tok = Comment
-                               ch = s.next()
                        }
                case '`':
                        if s.Mode&ScanRawStrings != 0 {
index 002252de8a8d1255191b502b76aafdfd074d2d5d..cf9ad01111f387ce212642124a2ccd487e8005fc 100644 (file)
@@ -77,15 +77,15 @@ type token struct {
 var f100 = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
 
 var tokenList = []token{
-       {Comment, "// line comments\n"},
-       {Comment, "//\n"},
-       {Comment, "////\n"},
-       {Comment, "// comment\n"},
-       {Comment, "// /* comment */\n"},
-       {Comment, "// // comment //\n"},
-       {Comment, "//" + f100 + "\n"},
-
-       {Comment, "// general comments\n"},
+       {Comment, "// line comments"},
+       {Comment, "//"},
+       {Comment, "////"},
+       {Comment, "// comment"},
+       {Comment, "// /* comment */"},
+       {Comment, "// // comment //"},
+       {Comment, "//" + f100},
+
+       {Comment, "// general comments"},
        {Comment, "/**/"},
        {Comment, "/***/"},
        {Comment, "/* comment */"},
@@ -94,7 +94,7 @@ var tokenList = []token{
        {Comment, "/*\n comment\n*/"},
        {Comment, "/*" + f100 + "*/"},
 
-       {Comment, "// identifiers\n"},
+       {Comment, "// identifiers"},
        {Ident, "a"},
        {Ident, "a0"},
        {Ident, "foobar"},
@@ -116,21 +116,21 @@ var tokenList = []token{
        {Ident, "bar9876"},
        {Ident, f100},
 
-       {Comment, "// decimal ints\n"},
+       {Comment, "// decimal ints"},
        {Int, "0"},
        {Int, "1"},
        {Int, "9"},
        {Int, "42"},
        {Int, "1234567890"},
 
-       {Comment, "// octal ints\n"},
+       {Comment, "// octal ints"},
        {Int, "00"},
        {Int, "01"},
        {Int, "07"},
        {Int, "042"},
        {Int, "01234567"},
 
-       {Comment, "// hexadecimal ints\n"},
+       {Comment, "// hexadecimal ints"},
        {Int, "0x0"},
        {Int, "0x1"},
        {Int, "0xf"},
@@ -144,7 +144,7 @@ var tokenList = []token{
        {Int, "0X123456789abcDEF"},
        {Int, "0X" + f100},
 
-       {Comment, "// floats\n"},
+       {Comment, "// floats"},
        {Float, "0."},
        {Float, "1."},
        {Float, "42."},
@@ -174,7 +174,7 @@ var tokenList = []token{
        {Float, "42E+10"},
        {Float, "01234567890E-10"},
 
-       {Comment, "// chars\n"},
+       {Comment, "// chars"},
        {Char, `' '`},
        {Char, `'a'`},
        {Char, `'本'`},
@@ -195,7 +195,7 @@ var tokenList = []token{
        {Char, `'\U00000000'`},
        {Char, `'\U0000ffAB'`},
 
-       {Comment, "// strings\n"},
+       {Comment, "// strings"},
        {String, `" "`},
        {String, `"a"`},
        {String, `"本"`},
@@ -217,13 +217,13 @@ var tokenList = []token{
        {String, `"\U0000ffAB"`},
        {String, `"` + f100 + `"`},
 
-       {Comment, "// raw strings\n"},
+       {Comment, "// raw strings"},
        {String, "``"},
        {String, "`\\`"},
        {String, "`" + "\n\n/* foobar */\n\n" + "`"},
        {String, "`" + f100 + "`"},
 
-       {Comment, "// individual characters\n"},
+       {Comment, "// individual characters"},
        // NUL character is not allowed
        {'\x01', "\x01"},
        {' ' - 1, string(' ' - 1)},
@@ -276,7 +276,7 @@ func countNewlines(s string) int {
 
 
 func testScan(t *testing.T, mode uint) {
-       s := new(Scanner).Init(makeSource(" \t%s\t\n\r"))
+       s := new(Scanner).Init(makeSource(" \t%s\n"))
        s.Mode = mode
        tok := s.Scan()
        line := 1
@@ -287,7 +287,7 @@ func testScan(t *testing.T, mode uint) {
                }
                line += countNewlines(k.text) + 1 // each token is on a new line
        }
-       checkTok(t, s, line, tok, -1, "")
+       checkTok(t, s, line, tok, EOF, "")
 }
 
 
@@ -317,6 +317,10 @@ func TestPosition(t *testing.T) {
                pos.Line += countNewlines(k.text) + 1 // each token is on a new line
                s.Scan()
        }
+       // make sure there were no token-internal errors reported by scanner
+       if s.ErrorCount != 0 {
+               t.Errorf("%d errors", s.ErrorCount)
+       }
 }
 
 
@@ -336,6 +340,9 @@ func TestScanZeroMode(t *testing.T) {
        if tok != EOF {
                t.Fatalf("tok = %s, want EOF", TokenString(tok))
        }
+       if s.ErrorCount != 0 {
+               t.Errorf("%d errors", s.ErrorCount)
+       }
 }
 
 
@@ -350,6 +357,9 @@ func testScanSelectedMode(t *testing.T, mode uint, class int) {
                }
                tok = s.Scan()
        }
+       if s.ErrorCount != 0 {
+               t.Errorf("%d errors", s.ErrorCount)
+       }
 }
 
 
@@ -367,7 +377,7 @@ func TestScanSelectedMask(t *testing.T) {
 
 
 func TestScanNext(t *testing.T) {
-       s := new(Scanner).Init(bytes.NewBufferString("if a == bcd /* comment */ {\n\ta += c\n}"))
+       s := new(Scanner).Init(bytes.NewBufferString("if a == bcd /* comment */ {\n\ta += c\n} // line comment ending in eof"))
        checkTok(t, s, 1, s.Scan(), Ident, "if")
        checkTok(t, s, 1, s.Scan(), Ident, "a")
        checkTok(t, s, 1, s.Scan(), '=', "=")
@@ -382,6 +392,9 @@ func TestScanNext(t *testing.T) {
        checkTok(t, s, 2, s.Scan(), Ident, "c")
        checkTok(t, s, 3, s.Scan(), '}', "}")
        checkTok(t, s, 3, s.Scan(), -1, "")
+       if s.ErrorCount != 0 {
+               t.Errorf("%d errors", s.ErrorCount)
+       }
 }
 
 
@@ -441,7 +454,6 @@ func TestError(t *testing.T) {
        testError(t, `"\'"`, "illegal char escape", String)
        testError(t, `"abc`, "literal not terminated", String)
        testError(t, "`abc", "literal not terminated", String)
-       testError(t, `//`, "comment not terminated", EOF)
        testError(t, `/*/`, "comment not terminated", EOF)
        testError(t, `"abc`+"\x00"+`def"`, "illegal character NUL", String)
        testError(t, `"abc`+"\xff"+`def"`, "illegal UTF-8 encoding", String)
@@ -493,6 +505,9 @@ func TestPos(t *testing.T) {
        for i := 10; i > 0; i-- {
                checkScanPos(t, s, 1, 2, 1, EOF)
        }
+       if s.ErrorCount != 0 {
+               t.Errorf("%d errors", s.ErrorCount)
+       }
 
        // corner case: source with only a single character
        s = new(Scanner).Init(bytes.NewBufferString("本"))
@@ -502,6 +517,9 @@ func TestPos(t *testing.T) {
        for i := 10; i > 0; i-- {
                checkScanPos(t, s, 3, 1, 2, EOF)
        }
+       if s.ErrorCount != 0 {
+               t.Errorf("%d errors", s.ErrorCount)
+       }
 
        // positions after calling Next
        s = new(Scanner).Init(bytes.NewBufferString("  foo६४  \n\n本語\n"))
@@ -524,6 +542,9 @@ func TestPos(t *testing.T) {
        for i := 10; i > 0; i-- {
                checkScanPos(t, s, 22, 4, 1, EOF)
        }
+       if s.ErrorCount != 0 {
+               t.Errorf("%d errors", s.ErrorCount)
+       }
 
        // positions after calling Scan
        s = new(Scanner).Init(bytes.NewBufferString("abc\n本語\n\nx"))
@@ -543,4 +564,7 @@ func TestPos(t *testing.T) {
        for i := 10; i > 0; i-- {
                checkScanPos(t, s, 13, 4, 2, EOF)
        }
+       if s.ErrorCount != 0 {
+               t.Errorf("%d errors", s.ErrorCount)
+       }
 }
index 305adcc0c41068b0df134f7ed22cb671eabaf691..34baeee39b3360a7dcc35d41e3a42c038a74e6d3 100644 (file)
@@ -94,7 +94,7 @@ func myatof32(s string) (f float32, ok bool) {
 }
 
 func TestFp(t *testing.T) {
-       f, err := os.Open("testfp.txt", os.O_RDONLY, 0)
+       f, err := os.Open("testfp.txt")
        if err != nil {
                t.Fatal("testfp: open testfp.txt:", err.String())
        }
index 6d303cc6f2cd86de8a6f2e45ad1ed8fed0da8c05..1e65528ef9689dee95d41b652f9006ed69fd6eb6 100644 (file)
@@ -212,7 +212,7 @@ func before() {
                runtime.MemProfileRate = *memProfileRate
        }
        if *cpuProfile != "" {
-               f, err := os.Open(*cpuProfile, os.O_WRONLY|os.O_CREAT|os.O_TRUNC, 0666)
+               f, err := os.Create(*cpuProfile)
                if err != nil {
                        fmt.Fprintf(os.Stderr, "testing: %s", err)
                        return
@@ -233,7 +233,7 @@ func after() {
                pprof.StopCPUProfile() // flushes profile to disk
        }
        if *memProfile != "" {
-               f, err := os.Open(*memProfile, os.O_WRONLY|os.O_CREAT|os.O_TRUNC, 0666)
+               f, err := os.Create(*memProfile)
                if err != nil {
                        fmt.Fprintf(os.Stderr, "testing: %s", err)
                        return
index 77d699e75a5dd8cc659ea3d7912c5ae195c2fbaf..05f4af01ab323b38b7b145fe1e42d218c6a33552 100755 (executable)
@@ -57,6 +57,9 @@ cat > sysinfo.c <<EOF
 #if defined(HAVE_SYS_EPOLL_H)
 #include <sys/epoll.h>
 #endif
+#if defined(HAVE_SYS_MMAN_H)
+#include <sys/mman.h>
+#endif
 #if defined(HAVE_SYS_PTRACE_H)
 #include <sys/ptrace.h>
 #endif
@@ -131,6 +134,12 @@ grep '^const _SYS_' gen-sysinfo.go | \
 grep '^const _S_' gen-sysinfo.go | \
   sed -e 's/^\(const \)_\(S_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
 
+# Mmap constants.
+grep '^const _PROT_' gen-sysinfo.go | \
+  sed -e 's/^\(const \)_\(PROT_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+grep '^const _MAP_' gen-sysinfo.go | \
+  sed -e 's/^\(const \)_\(MAP_[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+
 # Process status constants.
 grep '^const _W' gen-sysinfo.go |
   sed -e 's/^\(const \)_\(W[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
index fa7d9d0683e2454bf5c7871a9a9cbfca44948814..8c7a7ba5fee18ac3700358a290ba9a038a95cf38 100644 (file)
 // the manuals for the appropriate operating system.
 package syscall
 
-import "unsafe"
+import (
+       "sync"
+       "unsafe"
+)
 
 func libc_syscall32(trap int32, a1, a2, a3, a4, a5, a6 int32) int32 __asm__ ("syscall");
 func libc_syscall64(trap int64, a1, a2, a3, a4, a5, a6 int64) int64 __asm__ ("syscall");
@@ -46,3 +49,63 @@ func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
   }
   return r, 0, uintptr(GetErrno());
 }
+
+// Mmap manager, for use by operating system-specific implementations.
+
+type mmapper struct {
+       sync.Mutex
+       active map[*byte][]byte // active mappings; key is last byte in mapping
+       mmap   func(addr, length uintptr, prot, flags, fd int, offset int64) (uintptr, int)
+       munmap func(addr uintptr, length uintptr) int
+}
+
+func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, errno int) {
+       if length <= 0 {
+               return nil, EINVAL
+       }
+
+       // Map the requested memory.
+       addr, errno := m.mmap(0, uintptr(length), prot, flags, fd, offset)
+       if errno != 0 {
+               return nil, errno
+       }
+
+       // Slice memory layout
+       var sl = struct {
+               addr uintptr
+               len  int
+               cap  int
+       }{addr, length, length}
+
+       // Use unsafe to turn sl into a []byte.
+       b := *(*[]byte)(unsafe.Pointer(&sl))
+
+       // Register mapping in m and return it.
+       p := &b[cap(b)-1]
+       m.Lock()
+       defer m.Unlock()
+       m.active[p] = b
+       return b, 0
+}
+
+func (m *mmapper) Munmap(data []byte) (errno int) {
+       if len(data) == 0 || len(data) != cap(data) {
+               return EINVAL
+       }
+
+       // Find the base of the mapping.
+       p := &data[cap(data)-1]
+       m.Lock()
+       defer m.Unlock()
+       b := m.active[p]
+       if b == nil || &b[0] != &data[0] {
+               return EINVAL
+       }
+
+       // Unmap the memory and update m.
+       if errno := m.munmap(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))); errno != 0 {
+               return errno
+       }
+       m.active[p] = nil, false
+       return 0
+}
index a29b6b54bfbbc53b08b5b1a781a859757fc6c54b..b5a660e93d1b6ef35c553bd55580090a9867a55d 100644 (file)
@@ -4,6 +4,8 @@
 
 package syscall
 
+import "unsafe"
+
 var (
        Stdin  = 0
        Stdout = 1
@@ -22,3 +24,35 @@ func Uname(buf *Utsname) (errno int) {
        }
        return
 }
+
+var mapper = &mmapper{
+       active: make(map[*byte][]byte),
+       mmap:   mmap,
+       munmap: munmap,
+}
+
+func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, errno int) {
+       return mapper.Mmap(fd, offset, length, prot, flags)
+}
+
+func Munmap(b []byte) (errno int) {
+       return mapper.Munmap(b)
+}
+
+func libc_munmap(*byte, Size_t) int __asm__ ("munmap")
+
+func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, errno int) {
+       r0 := libc_mmap((*byte)(unsafe.Pointer(addr)), Size_t(length), prot, flag, fd, Offset_t(pos))
+       ret = uintptr(unsafe.Pointer(r0))
+       if ret + 1 == 0 {
+               errno = GetErrno()
+       }
+       return
+}
+
+func munmap(addr uintptr, length uintptr) (errno int) {
+       if libc_munmap((*byte)(unsafe.Pointer(addr)), Size_t(length)) < 0 {
+               errno = GetErrno()
+       }
+       return
+}
index 963a624bd88087f4dfb41974525d2c7bf99a9df9..c0c4e555e63a1e8102a1160dad260d99e7e31b76 100644 (file)
@@ -11,3 +11,4 @@ func libc_pwrite(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t __asm
 func libc_lseek(int, Offset_t, int) Offset_t __asm__ ("lseek64")
 func libc_truncate(path *byte, length Offset_t) int __asm__ ("truncate64")
 func libc_ftruncate(fd int, length Offset_t) int __asm__ ("ftruncate64")
+func libc_mmap(*byte, Size_t, int, int, int, Offset_t) *byte __asm__ ("mmap64")
index 731c59c97b09609f806425ef95186b434c61bf13..fcbf254dc0e3238c39ca0671a419d0653f00e319 100644 (file)
@@ -11,3 +11,4 @@ func libc_pwrite(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t __asm
 func libc_lseek(int, Offset_t, int) Offset_t __asm__ ("lseek")
 func libc_truncate(path *byte, length Offset_t) int __asm__ ("truncate")
 func libc_ftruncate(fd int, length Offset_t) int __asm__ ("ftruncate")
+func libc_mmap(*byte, Size_t, int, int, int, Offset_t) *byte __asm__ ("mmap")
This page took 0.361951 seconds and 5 git commands to generate.