Update to current version of Go library (revision 94d654be2064).

From-SVN: r171076
This commit is contained in:
Ian Lance Taylor 2011-03-16 23:05:44 +00:00
parent f617201f55
commit 5133f00ef8
293 changed files with 16312 additions and 4920 deletions

View File

@ -1078,7 +1078,7 @@ Type::make_type_descriptor_type()
bloc);
Struct_type* type_descriptor_type =
Type::make_builtin_struct_type(9,
Type::make_builtin_struct_type(10,
"Kind", uint8_type,
"align", uint8_type,
"fieldAlign", uint8_type,
@ -1087,7 +1087,9 @@ Type::make_type_descriptor_type()
"hashfn", hashfn_type,
"equalfn", equalfn_type,
"string", pointer_string_type,
"", pointer_uncommon_type);
"", pointer_uncommon_type,
"ptrToThis",
pointer_type_descriptor_type);
Named_type* named = Type::make_builtin_named_type("commonType",
type_descriptor_type);
@ -1259,6 +1261,16 @@ Type::type_descriptor_constructor(Gogo* gogo, int runtime_type_kind,
only_value_methods));
}
++p;
gcc_assert(p->field_name() == "ptrToThis");
if (name == NULL)
vals->push_back(Expression::make_nil(bloc));
else
{
Type* pt = Type::make_pointer_type(name);
vals->push_back(Expression::make_type_descriptor(pt, bloc));
}
++p;
gcc_assert(p == fields->end());

View File

@ -1,4 +1,4 @@
559f12e8fcd5
94d654be2064
The first line of this file holds the Mercurial revision number of the
last merge done from the master library sources.

View File

@ -105,6 +105,7 @@ toolexeclibgo_DATA = \
bufio.gox \
bytes.gox \
cmath.gox \
crypto.gox \
ebnf.gox \
exec.gox \
expvar.gox \
@ -158,8 +159,10 @@ toolexeclibgoarchive_DATA = \
toolexeclibgocompressdir = $(toolexeclibgodir)/compress
toolexeclibgocompress_DATA = \
compress/bzip2.gox \
compress/flate.gox \
compress/gzip.gox \
compress/lzw.gox \
compress/zlib.gox
toolexeclibgocontainerdir = $(toolexeclibgodir)/container
@ -178,11 +181,13 @@ toolexeclibgocrypto_DATA = \
crypto/blowfish.gox \
crypto/cast5.gox \
crypto/cipher.gox \
crypto/dsa.gox \
crypto/elliptic.gox \
crypto/hmac.gox \
crypto/md4.gox \
crypto/md5.gox \
crypto/ocsp.gox \
crypto/openpgp.gox \
crypto/rand.gox \
crypto/rc4.gox \
crypto/ripemd160.gox \
@ -201,6 +206,7 @@ toolexeclibgocryptoopenpgpdir = $(toolexeclibgocryptodir)/openpgp
toolexeclibgocryptoopenpgp_DATA = \
crypto/openpgp/armor.gox \
crypto/openpgp/error.gox \
crypto/openpgp/packet.gox \
crypto/openpgp/s2k.gox
toolexeclibgodebugdir = $(toolexeclibgodir)/debug
@ -306,6 +312,11 @@ toolexeclibgoruntime_DATA = \
runtime/debug.gox \
runtime/pprof.gox
toolexeclibgosyncdir = $(toolexeclibgodir)/sync
toolexeclibgosync_DATA = \
sync/atomic.gox
toolexeclibgotestingdir = $(toolexeclibgodir)/testing
toolexeclibgotesting_DATA = \
@ -411,8 +422,6 @@ runtime_files = \
runtime/mfixalloc.c \
runtime/mgc0.c \
runtime/mheap.c \
runtime/mheapmap32.c \
runtime/mheapmap64.c \
runtime/msize.c \
runtime/proc.c \
runtime/thread.c \
@ -489,6 +498,9 @@ go_cmath_files = \
go/cmath/sqrt.go \
go/cmath/tan.go
go_crypto_files = \
go/crypto/crypto.go
go_ebnf_files = \
go/ebnf/ebnf.go \
go/ebnf/parser.go
@ -533,6 +545,7 @@ go_http_files = \
go/http/client.go \
go/http/dump.go \
go/http/fs.go \
go/http/header.go \
go/http/lex.go \
go/http/persist.go \
go/http/request.go \
@ -540,6 +553,7 @@ go_http_files = \
go/http/server.go \
go/http/status.go \
go/http/transfer.go \
go/http/transport.go \
go/http/url.go
go_image_files = \
@ -693,6 +707,7 @@ go_os_files = \
go/os/env_unix.go \
go/os/error.go \
go/os/exec.go \
go/os/exec_unix.go \
go/os/file.go \
go/os/file_unix.go \
go/os/getwd.go \
@ -738,8 +753,6 @@ go_runtime_files = \
go/runtime/debug.go \
go/runtime/error.go \
go/runtime/extern.go \
go/runtime/malloc_defs.go \
go/runtime/runtime_defs.go \
go/runtime/sig.go \
go/runtime/softfloat64.go \
go/runtime/type.go \
@ -781,11 +794,11 @@ go_strings_files = \
go/strings/strings.go
go_sync_files = \
go/sync/cond.go \
go/sync/mutex.go \
go/sync/once.go \
go/sync/rwmutex.go
go_sync_c_files = \
go/sync/cas.c
go/sync/rwmutex.go \
go/sync/waitgroup.go
if LIBGO_IS_SOLARIS
go_syslog_file = go/syslog/syslog_solaris.go
@ -851,6 +864,12 @@ go_archive_zip_files = \
go/archive/zip/reader.go \
go/archive/zip/struct.go
go_compress_bzip2_files = \
go/compress/bzip2/bit_reader.go \
go/compress/bzip2/bzip2.go \
go/compress/bzip2/huffman.go \
go/compress/bzip2/move_to_front.go
go_compress_flate_files = \
go/compress/flate/deflate.go \
go/compress/flate/huffman_bit_writer.go \
@ -864,6 +883,10 @@ go_compress_gzip_files = \
go/compress/gzip/gzip.go \
go/compress/gzip/gunzip.go
go_compress_lzw_files = \
go/compress/lzw/reader.go \
go/compress/lzw/writer.go
go_compress_zlib_files = \
go/compress/zlib/reader.go \
go/compress/zlib/writer.go
@ -911,6 +934,8 @@ go_crypto_cipher_files = \
go/crypto/cipher/io.go \
go/crypto/cipher/ocfb.go \
go/crypto/cipher/ofb.go
go_crypto_dsa_files = \
go/crypto/dsa/dsa.go
go_crypto_elliptic_files = \
go/crypto/elliptic/elliptic.go
go_crypto_hmac_files = \
@ -923,6 +948,11 @@ go_crypto_md5_files = \
go/crypto/md5/md5block.go
go_crypto_ocsp_files = \
go/crypto/ocsp/ocsp.go
go_crypto_openpgp_files = \
go/crypto/openpgp/canonical_text.go \
go/crypto/openpgp/keys.go \
go/crypto/openpgp/read.go \
go/crypto/openpgp/write.go
go_crypto_rand_files = \
go/crypto/rand/rand.go \
go/crypto/rand/rand_unix.go
@ -970,6 +1000,19 @@ go_crypto_openpgp_armor_files = \
go/crypto/openpgp/armor/encode.go
go_crypto_openpgp_error_files = \
go/crypto/openpgp/error/error.go
go_crypto_openpgp_packet_files = \
go/crypto/openpgp/packet/compressed.go \
go/crypto/openpgp/packet/encrypted_key.go \
go/crypto/openpgp/packet/literal.go \
go/crypto/openpgp/packet/one_pass_signature.go \
go/crypto/openpgp/packet/packet.go \
go/crypto/openpgp/packet/private_key.go \
go/crypto/openpgp/packet/public_key.go \
go/crypto/openpgp/packet/reader.go \
go/crypto/openpgp/packet/signature.go \
go/crypto/openpgp/packet/symmetric_key_encrypted.go \
go/crypto/openpgp/packet/symmetrically_encrypted.go \
go/crypto/openpgp/packet/userid.go
go_crypto_openpgp_s2k_files = \
go/crypto/openpgp/s2k/s2k.go
@ -1095,6 +1138,7 @@ go_net_dict_files = \
go/net/dict/dict.go
go_net_textproto_files = \
go/net/textproto/header.go \
go/net/textproto/pipeline.go \
go/net/textproto/reader.go \
go/net/textproto/textproto.go \
@ -1116,6 +1160,11 @@ go_runtime_debug_files = \
go_runtime_pprof_files = \
go/runtime/pprof/pprof.go
go_sync_atomic_files = \
go/sync/atomic/doc.go
go_sync_atomic_c_files = \
go/sync/atomic/atomic.c
go_testing_iotest_files = \
go/testing/iotest/logger.go \
go/testing/iotest/reader.go \
@ -1268,6 +1317,7 @@ libgo_go_objs = \
bytes/bytes.lo \
bytes/index.lo \
cmath/cmath.lo \
crypto/crypto.lo \
ebnf/ebnf.lo \
exec/exec.lo \
expvar/expvar.lo \
@ -1298,8 +1348,7 @@ libgo_go_objs = \
sort/sort.lo \
strconv/strconv.lo \
strings/strings.lo \
sync/mutex.lo \
sync/cas.lo \
sync/sync.lo \
syslog/syslog.lo \
syslog/syslog_c.lo \
tabwriter/tabwriter.lo \
@ -1313,8 +1362,10 @@ libgo_go_objs = \
xml/xml.lo \
archive/tar.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 \
@ -1325,11 +1376,13 @@ libgo_go_objs = \
crypto/blowfish.lo \
crypto/cast5.lo \
crypto/cipher.lo \
crypto/dsa.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 \
@ -1344,6 +1397,7 @@ libgo_go_objs = \
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 \
@ -1385,6 +1439,8 @@ libgo_go_objs = \
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 \
@ -1500,6 +1556,12 @@ cmath/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: cmath/check
crypto/crypto.lo: $(go_crypto_files) hash.gox
$(BUILDPACKAGE)
crypto/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: crypto/check
ebnf/ebnf.lo: $(go_ebnf_files) container/vector.gox go/scanner.gox \
go/token.gox os.gox strconv.gox unicode.gox utf8.gox
$(BUILDPACKAGE)
@ -1507,7 +1569,7 @@ ebnf/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: ebnf/check
exec/exec.lo: $(go_exec_files) os.gox strings.gox
exec/exec.lo: $(go_exec_files) os.gox strconv.gox strings.gox
$(BUILDPACKAGE)
exec/check: $(CHECK_DEPS)
$(CHECK)
@ -1526,8 +1588,8 @@ flag/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: flag/check
fmt/fmt.lo: $(go_fmt_files) bytes.gox io.gox os.gox reflect.gox strconv.gox \
strings.gox unicode.gox utf8.gox
fmt/fmt.lo: $(go_fmt_files) bytes.gox io.gox math.gox os.gox reflect.gox \
strconv.gox strings.gox unicode.gox utf8.gox
$(BUILDPACKAGE)
fmt/check: $(CHECK_DEPS)
$(CHECK)
@ -1554,10 +1616,10 @@ html/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: html/check
http/http.lo: $(go_http_files) bufio.gox bytes.gox container/list.gox \
container/vector.gox crypto/rand.gox crypto/tls.gox \
encoding/base64.gox fmt.gox io.gox io/ioutil.gox log.gox \
mime.gox mime/multipart.gox net.gox os.gox path.gox sort.gox \
http/http.lo: $(go_http_files) bufio.gox bytes.gox container/vector.gox \
crypto/rand.gox crypto/tls.gox encoding/base64.gox fmt.gox \
io.gox io/ioutil.gox log.gox mime.gox mime/multipart.gox \
net.gox net/textproto.gox os.gox path.gox sort.gox \
strconv.gox strings.gox sync.gox time.gox utf8.gox
$(BUILDPACKAGE)
http/check: $(CHECK_DEPS)
@ -1576,9 +1638,10 @@ io/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: io/check
json/json.lo: $(go_json_files) bytes.gox container/vector.gox fmt.gox io.gox \
math.gox os.gox reflect.gox runtime.gox strconv.gox \
strings.gox unicode.gox utf16.gox utf8.gox
json/json.lo: $(go_json_files) bytes.gox container/vector.gox \
encoding/base64.gox fmt.gox io.gox math.gox os.gox \
reflect.gox runtime.gox strconv.gox strings.gox unicode.gox \
utf16.gox utf8.gox
$(BUILDPACKAGE)
json/check: $(CHECK_DEPS)
$(CHECK)
@ -1611,14 +1674,14 @@ net/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: net/check
netchan/netchan.lo: $(go_netchan_files) gob.gox log.gox net.gox os.gox \
netchan/netchan.lo: $(go_netchan_files) gob.gox io.gox log.gox net.gox os.gox \
reflect.gox strconv.gox sync.gox time.gox
$(BUILDPACKAGE)
netchan/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: netchan/check
os/os.lo: $(go_os_files) sync.gox syscall.gox
os/os.lo: $(go_os_files) runtime.gox sync.gox syscall.gox
$(BUILDPACKAGE)
os/check: $(CHECK_DEPS)
$(CHECK)
@ -1706,10 +1769,8 @@ strings/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: strings/check
sync/mutex.lo: $(go_sync_files) runtime.gox
sync/sync.lo: $(go_sync_files) runtime.gox sync/atomic.gox
$(BUILDPACKAGE)
sync/cas.lo: $(go_sync_c_files) sync/mutex.lo
$(LTCOMPILE) -c -o sync/cas.lo $(srcdir)/go/sync/cas.c
sync/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: sync/check
@ -1806,6 +1867,13 @@ archive/zip/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: archive/zip/check
compress/bzip2.lo: $(go_compress_bzip2_files) bufio.gox io.gox os.gox sort.gox
$(BUILDPACKAGE)
compress/bzip2/check: $(CHECK_DEPS)
@$(MKDIR_P) compress/bzip2
$(CHECK)
.PHONY: compress/bzip2/check
compress/flate.lo: $(go_compress_flate_files) bufio.gox io.gox math.gox \
os.gox sort.gox strconv.gox
$(BUILDPACKAGE)
@ -1822,6 +1890,13 @@ compress/gzip/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: compress/gzip/check
compress/lzw.lo: $(go_compress_lzw_files) bufio.gox fmt.gox io.gox os.gox
$(BUILDPACKAGE)
compress/lzw/check: $(CHECK_DEPS)
@$(MKDIR_P) compress/lzw
$(CHECK)
.PHONY: compress/lzw/check
compress/zlib.lo: $(go_compress_zlib_files) bufio.gox compress/flate.gox \
hash.gox hash/adler32.gox io.gox os.gox
$(BUILDPACKAGE)
@ -1893,6 +1968,13 @@ crypto/cipher/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: crypto/cipher/check
crypto/dsa.lo: $(go_crypto_dsa_files) big.gox io.gox os.gox
$(BUILDPACKAGE)
crypto/dsa/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/dsa
$(CHECK)
.PHONY: crypto/dsa/check
crypto/elliptic.lo: $(go_crypto_elliptic_files) big.gox io.gox os.gox sync.gox
$(BUILDPACKAGE)
crypto/elliptic/check: $(CHECK_DEPS)
@ -1908,21 +1990,21 @@ crypto/hmac/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: crypto/hmac/check
crypto/md4.lo: $(go_crypto_md4_files) hash.gox os.gox
crypto/md4.lo: $(go_crypto_md4_files) crypto.gox hash.gox os.gox
$(BUILDPACKAGE)
crypto/md4/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/md4
$(CHECK)
.PHONY: crypto/md4/check
crypto/md5.lo: $(go_crypto_md5_files) hash.gox os.gox
crypto/md5.lo: $(go_crypto_md5_files) crypto.gox hash.gox os.gox
$(BUILDPACKAGE)
crypto/md5/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/md5
$(CHECK)
.PHONY: crypto/md5/check
crypto/ocsp.lo: $(go_crypto_ocsp_files) asn1.gox crypto/rsa.gox \
crypto/ocsp.lo: $(go_crypto_ocsp_files) asn1.gox crypto.gox crypto/rsa.gox \
crypto/sha1.gox crypto/x509.gox os.gox time.gox
$(BUILDPACKAGE)
crypto/ocsp/check: $(CHECK_DEPS)
@ -1930,8 +2012,18 @@ crypto/ocsp/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: crypto/ocsp/check
crypto/rand.lo: $(go_crypto_rand_files) crypto/aes.gox io.gox os.gox sync.gox \
time.gox
crypto/openpgp.lo: $(go_crypto_openpgp_files) crypto.gox \
crypto/openpgp/armor.gox crypto/openpgp/error.gox \
crypto/openpgp/packet.gox crypto/rsa.gox crypto/sha256.gox \
hash.gox io.gox os.gox strconv.gox time.gox
$(BUILDPACKAGE)
crypto/openpgp/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/openpgp
$(CHECK)
.PHONY: crypto/openpgp/check
crypto/rand.lo: $(go_crypto_rand_files) bufio.gox crypto/aes.gox io.gox \
os.gox sync.gox time.gox
$(BUILDPACKAGE)
crypto/rand/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/rand
@ -1945,14 +2037,14 @@ crypto/rc4/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: crypto/rc4/check
crypto/ripemd160.lo: $(go_crypto_ripemd160_files) hash.gox os.gox
crypto/ripemd160.lo: $(go_crypto_ripemd160_files) crypto.gox hash.gox os.gox
$(BUILDPACKAGE)
crypto/ripemd160/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/ripemd160
$(CHECK)
.PHONY: crypto/ripemd160/check
crypto/rsa.lo: $(go_crypto_rsa_files) big.gox crypto/sha1.gox \
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
$(BUILDPACKAGE)
crypto/rsa/check: $(CHECK_DEPS)
@ -1960,21 +2052,21 @@ crypto/rsa/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: crypto/rsa/check
crypto/sha1.lo: $(go_crypto_sha1_files) hash.gox os.gox
crypto/sha1.lo: $(go_crypto_sha1_files) crypto.gox hash.gox os.gox
$(BUILDPACKAGE)
crypto/sha1/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/sha1
$(CHECK)
.PHONY: crypto/sha1/check
crypto/sha256.lo: $(go_crypto_sha256_files) hash.gox os.gox
crypto/sha256.lo: $(go_crypto_sha256_files) crypto.gox hash.gox os.gox
$(BUILDPACKAGE)
crypto/sha256/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/sha256
$(CHECK)
.PHONY: crypto/sha256/check
crypto/sha512.lo: $(go_crypto_sha512_files) hash.gox os.gox
crypto/sha512.lo: $(go_crypto_sha512_files) crypto.gox hash.gox os.gox
$(BUILDPACKAGE)
crypto/sha512/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/sha512
@ -1989,7 +2081,7 @@ crypto/subtle/check: $(CHECK_DEPS)
.PHONY: crypto/subtle/check
crypto/tls.lo: $(go_crypto_tls_files) big.gox bufio.gox bytes.gox \
container/list.gox crypto/aes.gox crypto/cipher.gox \
container/list.gox crypto.gox crypto/aes.gox crypto/cipher.gox \
crypto/elliptic.gox crypto/hmac.gox crypto/md5.gox \
crypto/rc4.gox crypto/rand.gox crypto/rsa.gox crypto/sha1.gox \
crypto/subtle.gox crypto/rsa.gox crypto/sha1.gox \
@ -2009,8 +2101,8 @@ crypto/twofish/check: $(CHECK_DEPS)
.PHONY: crypto/twofish/check
crypto/x509.lo: $(go_crypto_x509_files) asn1.gox big.gox container/vector.gox \
crypto/rsa.gox crypto/sha1.gox hash.gox os.gox strings.gox \
time.gox
crypto.gox crypto/rsa.gox crypto/sha1.gox hash.gox os.gox \
strings.gox time.gox
$(BUILDPACKAGE)
crypto/x509/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/x509
@ -2033,16 +2125,30 @@ crypto/openpgp/armor/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: crypto/openpgp/armor/check
crypto/openpgp/error.lo: $(go_crypto_openpgp_error_files)
crypto/openpgp/error.lo: $(go_crypto_openpgp_error_files) strconv.gox
$(BUILDPACKAGE)
crypto/openpgp/error/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/openpgp/error
$(CHECK)
.PHONY: crypto/openpgp/error/check
crypto/openpgp/s2k.lo: $(go_crypto_openpgp_s2k_files) crypto/md5.gox \
crypto/openpgp/error.gox crypto/ripemd160.gox crypto/sha1.gox \
crypto/sha256.gox crypto/sha512.gox hash.gox io.gox os.gox
crypto/openpgp/packet.lo: $(go_crypto_openpgp_packet_files) big.gox bytes.gox \
compress/flate.gox compress/zlib.gox crypto.gox \
crypto/aes.gox crypto/cast5.gox crypto/cipher.gox \
crypto/openpgp/error.gox crypto/openpgp/s2k.gox \
crypto/rand.gox crypto/rsa.gox crypto/sha1.gox \
crypto/subtle.gox encoding/binary.gox hash.gox io.gox \
io/ioutil.gox os.gox strconv.gox strings.gox
$(BUILDPACKAGE)
crypto/openpgp/packet/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/openpgp/packet
$(CHECK)
.PHONY: crypto/openpgp/packet/check
crypto/openpgp/s2k.lo: $(go_crypto_openpgp_s2k_files) crypto.gox \
crypto/md5.gox crypto/openpgp/error.gox crypto/ripemd160.gox \
crypto/sha1.gox crypto/sha256.gox crypto/sha512.gox hash.gox \
io.gox os.gox
$(BUILDPACKAGE)
crypto/openpgp/s2k/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/openpgp/s2k
@ -2361,6 +2467,15 @@ runtime/pprof/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: runtime/pprof/check
sync/atomic.lo: $(go_sync_atomic_files)
$(BUILDPACKAGE)
sync/atomic_c.lo: $(go_sync_atomic_c_files) sync/atomic.lo
$(LTCOMPILE) -c -o $@ $(srcdir)/go/sync/atomic/atomic.c
sync/atomic/check: $(CHECK_DEPS)
@$(MKDIR_P) sync/atomic
$(CHECK)
.PHONY: sync/atomic/check
testing/iotest.lo: $(go_testing_iotest_files) io.gox log.gox os.gox
$(BUILDPACKAGE)
testing/iotest/check: $(CHECK_DEPS)
@ -2410,6 +2525,8 @@ bytes.gox: bytes/bytes.lo
$(BUILDGOX)
cmath.gox: cmath/cmath.lo
$(BUILDGOX)
crypto.gox: crypto/crypto.lo
$(BUILDGOX)
ebnf.gox: ebnf/ebnf.lo
$(BUILDGOX)
exec.gox: exec/exec.lo
@ -2470,7 +2587,7 @@ strconv.gox: strconv/strconv.lo
$(BUILDGOX)
strings.gox: strings/strings.lo
$(BUILDGOX)
sync.gox: sync/mutex.lo
sync.gox: sync/sync.lo
$(BUILDGOX)
syslog.gox: syslog/syslog.lo
$(BUILDGOX)
@ -2502,10 +2619,14 @@ archive/tar.gox: archive/tar.lo
archive/zip.gox: archive/zip.lo
$(BUILDGOX)
compress/bzip2.gox: compress/bzip2.lo
$(BUILDGOX)
compress/flate.gox: compress/flate.lo
$(BUILDGOX)
compress/gzip.gox: compress/gzip.lo
$(BUILDGOX)
compress/lzw.gox: compress/lzw.lo
$(BUILDGOX)
compress/zlib.gox: compress/zlib.lo
$(BUILDGOX)
@ -2528,6 +2649,8 @@ crypto/cast5.gox: crypto/cast5.lo
$(BUILDGOX)
crypto/cipher.gox: crypto/cipher.lo
$(BUILDGOX)
crypto/dsa.gox: crypto/dsa.lo
$(BUILDGOX)
crypto/elliptic.gox: crypto/elliptic.lo
$(BUILDGOX)
crypto/hmac.gox: crypto/hmac.lo
@ -2538,6 +2661,8 @@ crypto/md5.gox: crypto/md5.lo
$(BUILDGOX)
crypto/ocsp.gox: crypto/ocsp.lo
$(BUILDGOX)
crypto/openpgp.gox: crypto/openpgp.lo
$(BUILDGOX)
crypto/rand.gox: crypto/rand.lo
$(BUILDGOX)
crypto/rc4.gox: crypto/rc4.lo
@ -2567,6 +2692,8 @@ crypto/openpgp/armor.gox: crypto/openpgp/armor.lo
$(BUILDGOX)
crypto/openpgp/error.gox: crypto/openpgp/error.lo
$(BUILDGOX)
crypto/openpgp/packet.gox: crypto/openpgp/packet.lo
$(BUILDGOX)
crypto/openpgp/s2k.gox: crypto/openpgp/s2k.lo
$(BUILDGOX)
@ -2664,6 +2791,9 @@ runtime/debug.gox: runtime/debug.lo
runtime/pprof.gox: runtime/pprof.lo
$(BUILDGOX)
sync/atomic.gox: sync/atomic.lo
$(BUILDGOX)
testing/iotest.gox: testing/iotest.lo
$(BUILDGOX)
testing/quick.gox: testing/quick.lo
@ -2725,8 +2855,10 @@ TEST_PACKAGES = \
xml/check \
archive/tar/check \
archive/zip/check \
compress/bzip2/check \
compress/flate/check \
compress/gzip/check \
compress/lzw/check \
compress/zlib/check \
container/heap/check \
container/list/check \
@ -2737,11 +2869,13 @@ TEST_PACKAGES = \
crypto/blowfish/check \
crypto/cast5/check \
crypto/cipher/check \
crypto/dsa/check \
crypto/elliptic/check \
crypto/hmac/check \
crypto/md4/check \
crypto/md5/check \
crypto/ocsp/check \
crypto/openpgp/check \
crypto/rand/check \
crypto/rc4/check \
crypto/ripemd160/check \
@ -2755,6 +2889,7 @@ TEST_PACKAGES = \
crypto/x509/check \
crypto/xtea/check \
crypto/openpgp/armor/check \
crypto/openpgp/packet/check \
crypto/openpgp/s2k/check \
debug/dwarf/check \
debug/elf/check \
@ -2787,6 +2922,7 @@ TEST_PACKAGES = \
$(os_inotify_check) \
os/signal/check \
rpc/jsonrpc/check \
sync/atomic/check \
testing/quick/check \
testing/script/check

View File

@ -112,6 +112,7 @@ am__installdirs = "$(DESTDIR)$(toolexeclibdir)" \
"$(DESTDIR)$(toolexeclibgoosdir)" \
"$(DESTDIR)$(toolexeclibgorpcdir)" \
"$(DESTDIR)$(toolexeclibgoruntimedir)" \
"$(DESTDIR)$(toolexeclibgosyncdir)" \
"$(DESTDIR)$(toolexeclibgotestingdir)"
LIBRARIES = $(toolexeclib_LIBRARIES)
ARFLAGS = cru
@ -122,43 +123,45 @@ libgobegin_a_OBJECTS = $(am_libgobegin_a_OBJECTS)
LTLIBRARIES = $(toolexeclib_LTLIBRARIES)
am__DEPENDENCIES_1 =
am__DEPENDENCIES_2 = asn1/asn1.lo big/big.lo bufio/bufio.lo \
bytes/bytes.lo bytes/index.lo cmath/cmath.lo ebnf/ebnf.lo \
exec/exec.lo expvar/expvar.lo flag/flag.lo fmt/fmt.lo \
gob/gob.lo hash/hash.lo html/html.lo http/http.lo \
bytes/bytes.lo bytes/index.lo cmath/cmath.lo crypto/crypto.lo \
ebnf/ebnf.lo exec/exec.lo expvar/expvar.lo flag/flag.lo \
fmt/fmt.lo gob/gob.lo hash/hash.lo html/html.lo http/http.lo \
image/image.lo io/io.lo json/json.lo log/log.lo math/math.lo \
mime/mime.lo net/net.lo netchan/netchan.lo os/os.lo \
patch/patch.lo path/path.lo rand/rand.lo reflect/reflect.lo \
regexp/regexp.lo rpc/rpc.lo runtime/runtime.lo \
scanner/scanner.lo smtp/smtp.lo sort/sort.lo \
strconv/strconv.lo strings/strings.lo sync/mutex.lo \
sync/cas.lo syslog/syslog.lo syslog/syslog_c.lo \
tabwriter/tabwriter.lo template/template.lo time/time.lo \
try/try.lo unicode/unicode.lo utf16/utf16.lo utf8/utf8.lo \
strconv/strconv.lo strings/strings.lo sync/sync.lo \
syslog/syslog.lo syslog/syslog_c.lo tabwriter/tabwriter.lo \
template/template.lo time/time.lo try/try.lo \
unicode/unicode.lo utf16/utf16.lo utf8/utf8.lo \
websocket/websocket.lo xml/xml.lo archive/tar.lo \
archive/zip.lo compress/flate.lo compress/gzip.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/elliptic.lo crypto/hmac.lo \
crypto/md4.lo crypto/md5.lo crypto/ocsp.lo crypto/rand.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/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/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 http/pprof.lo image/jpeg.lo \
image/png.lo index/suffixarray.lo io/ioutil.lo \
mime/multipart.lo net/dict.lo net/textproto.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 \
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 rpc/jsonrpc.lo \
runtime/debug.lo runtime/pprof.lo syscalls/syscall.lo \
syscalls/errno.lo testing/testing.lo testing/iotest.lo \
testing/quick.lo testing/script.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)
@ -204,8 +207,7 @@ am__libgo_la_SOURCES_DIST = runtime/go-append.c runtime/go-assert.c \
runtime/mcache.c runtime/mcentral.c \
runtime/mem_posix_memalign.c runtime/mem.c runtime/mfinal.c \
runtime/mfixalloc.c runtime/mgc0.c runtime/mheap.c \
runtime/mheapmap32.c runtime/mheapmap64.c runtime/msize.c \
runtime/proc.c runtime/thread.c \
runtime/msize.c runtime/proc.c runtime/thread.c \
runtime/rtems-task-variable-add.c chan.c iface.c malloc.c \
map.c mprof.c reflect.c sigqueue.c string.c
@HAVE_SYS_MMAN_H_FALSE@am__objects_1 = mem_posix_memalign.lo
@ -237,9 +239,8 @@ am__objects_3 = go-append.lo go-assert.lo go-assert-interface.lo \
go-unreflect.lo go-unsafe-new.lo go-unsafe-newarray.lo \
go-unsafe-pointer.lo go-unwind.lo mcache.lo mcentral.lo \
$(am__objects_1) mfinal.lo mfixalloc.lo mgc0.lo mheap.lo \
mheapmap32.lo mheapmap64.lo msize.lo proc.lo thread.lo \
$(am__objects_2) chan.lo iface.lo malloc.lo map.lo mprof.lo \
reflect.lo sigqueue.lo string.lo
msize.lo proc.lo thread.lo $(am__objects_2) chan.lo iface.lo \
malloc.lo map.lo mprof.lo reflect.lo sigqueue.lo string.lo
am_libgo_la_OBJECTS = $(am__objects_3)
libgo_la_OBJECTS = $(am_libgo_la_OBJECTS)
DEFAULT_INCLUDES = -I.@am__isrc@
@ -280,7 +281,7 @@ DATA = $(toolexeclibgo_DATA) $(toolexeclibgoarchive_DATA) \
$(toolexeclibgoio_DATA) $(toolexeclibgomime_DATA) \
$(toolexeclibgonet_DATA) $(toolexeclibgoos_DATA) \
$(toolexeclibgorpc_DATA) $(toolexeclibgoruntime_DATA) \
$(toolexeclibgotesting_DATA)
$(toolexeclibgosync_DATA) $(toolexeclibgotesting_DATA)
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
distclean-recursive maintainer-clean-recursive
AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
@ -546,6 +547,7 @@ toolexeclibgo_DATA = \
bufio.gox \
bytes.gox \
cmath.gox \
crypto.gox \
ebnf.gox \
exec.gox \
expvar.gox \
@ -597,8 +599,10 @@ toolexeclibgoarchive_DATA = \
toolexeclibgocompressdir = $(toolexeclibgodir)/compress
toolexeclibgocompress_DATA = \
compress/bzip2.gox \
compress/flate.gox \
compress/gzip.gox \
compress/lzw.gox \
compress/zlib.gox
toolexeclibgocontainerdir = $(toolexeclibgodir)/container
@ -615,11 +619,13 @@ toolexeclibgocrypto_DATA = \
crypto/blowfish.gox \
crypto/cast5.gox \
crypto/cipher.gox \
crypto/dsa.gox \
crypto/elliptic.gox \
crypto/hmac.gox \
crypto/md4.gox \
crypto/md5.gox \
crypto/ocsp.gox \
crypto/openpgp.gox \
crypto/rand.gox \
crypto/rc4.gox \
crypto/ripemd160.gox \
@ -637,6 +643,7 @@ toolexeclibgocryptoopenpgpdir = $(toolexeclibgocryptodir)/openpgp
toolexeclibgocryptoopenpgp_DATA = \
crypto/openpgp/armor.gox \
crypto/openpgp/error.gox \
crypto/openpgp/packet.gox \
crypto/openpgp/s2k.gox
toolexeclibgodebugdir = $(toolexeclibgodir)/debug
@ -725,6 +732,10 @@ toolexeclibgoruntime_DATA = \
runtime/debug.gox \
runtime/pprof.gox
toolexeclibgosyncdir = $(toolexeclibgodir)/sync
toolexeclibgosync_DATA = \
sync/atomic.gox
toolexeclibgotestingdir = $(toolexeclibgodir)/testing
toolexeclibgotesting_DATA = \
testing/iotest.gox \
@ -821,8 +832,6 @@ runtime_files = \
runtime/mfixalloc.c \
runtime/mgc0.c \
runtime/mheap.c \
runtime/mheapmap32.c \
runtime/mheapmap64.c \
runtime/msize.c \
runtime/proc.c \
runtime/thread.c \
@ -874,6 +883,9 @@ go_cmath_files = \
go/cmath/sqrt.go \
go/cmath/tan.go
go_crypto_files = \
go/crypto/crypto.go
go_ebnf_files = \
go/ebnf/ebnf.go \
go/ebnf/parser.go
@ -918,6 +930,7 @@ go_http_files = \
go/http/client.go \
go/http/dump.go \
go/http/fs.go \
go/http/header.go \
go/http/lex.go \
go/http/persist.go \
go/http/request.go \
@ -925,6 +938,7 @@ go_http_files = \
go/http/server.go \
go/http/status.go \
go/http/transfer.go \
go/http/transport.go \
go/http/url.go
go_image_files = \
@ -1051,6 +1065,7 @@ go_os_files = \
go/os/env_unix.go \
go/os/error.go \
go/os/exec.go \
go/os/exec_unix.go \
go/os/file.go \
go/os/file_unix.go \
go/os/getwd.go \
@ -1096,8 +1111,6 @@ go_runtime_files = \
go/runtime/debug.go \
go/runtime/error.go \
go/runtime/extern.go \
go/runtime/malloc_defs.go \
go/runtime/runtime_defs.go \
go/runtime/sig.go \
go/runtime/softfloat64.go \
go/runtime/type.go \
@ -1128,12 +1141,11 @@ go_strings_files = \
go/strings/strings.go
go_sync_files = \
go/sync/cond.go \
go/sync/mutex.go \
go/sync/once.go \
go/sync/rwmutex.go
go_sync_c_files = \
go/sync/cas.c
go/sync/rwmutex.go \
go/sync/waitgroup.go
@LIBGO_IS_SOLARIS_FALSE@go_syslog_file = go/syslog/syslog_unix.go
@LIBGO_IS_SOLARIS_TRUE@go_syslog_file = go/syslog/syslog_solaris.go
@ -1196,6 +1208,12 @@ go_archive_zip_files = \
go/archive/zip/reader.go \
go/archive/zip/struct.go
go_compress_bzip2_files = \
go/compress/bzip2/bit_reader.go \
go/compress/bzip2/bzip2.go \
go/compress/bzip2/huffman.go \
go/compress/bzip2/move_to_front.go
go_compress_flate_files = \
go/compress/flate/deflate.go \
go/compress/flate/huffman_bit_writer.go \
@ -1209,6 +1227,10 @@ go_compress_gzip_files = \
go/compress/gzip/gzip.go \
go/compress/gzip/gunzip.go
go_compress_lzw_files = \
go/compress/lzw/reader.go \
go/compress/lzw/writer.go
go_compress_zlib_files = \
go/compress/zlib/reader.go \
go/compress/zlib/writer.go
@ -1261,6 +1283,9 @@ go_crypto_cipher_files = \
go/crypto/cipher/ocfb.go \
go/crypto/cipher/ofb.go
go_crypto_dsa_files = \
go/crypto/dsa/dsa.go
go_crypto_elliptic_files = \
go/crypto/elliptic/elliptic.go
@ -1278,6 +1303,12 @@ go_crypto_md5_files = \
go_crypto_ocsp_files = \
go/crypto/ocsp/ocsp.go
go_crypto_openpgp_files = \
go/crypto/openpgp/canonical_text.go \
go/crypto/openpgp/keys.go \
go/crypto/openpgp/read.go \
go/crypto/openpgp/write.go
go_crypto_rand_files = \
go/crypto/rand/rand.go \
go/crypto/rand/rand_unix.go
@ -1338,6 +1369,20 @@ go_crypto_openpgp_armor_files = \
go_crypto_openpgp_error_files = \
go/crypto/openpgp/error/error.go
go_crypto_openpgp_packet_files = \
go/crypto/openpgp/packet/compressed.go \
go/crypto/openpgp/packet/encrypted_key.go \
go/crypto/openpgp/packet/literal.go \
go/crypto/openpgp/packet/one_pass_signature.go \
go/crypto/openpgp/packet/packet.go \
go/crypto/openpgp/packet/private_key.go \
go/crypto/openpgp/packet/public_key.go \
go/crypto/openpgp/packet/reader.go \
go/crypto/openpgp/packet/signature.go \
go/crypto/openpgp/packet/symmetric_key_encrypted.go \
go/crypto/openpgp/packet/symmetrically_encrypted.go \
go/crypto/openpgp/packet/userid.go
go_crypto_openpgp_s2k_files = \
go/crypto/openpgp/s2k/s2k.go
@ -1484,6 +1529,7 @@ go_net_dict_files = \
go/net/dict/dict.go
go_net_textproto_files = \
go/net/textproto/header.go \
go/net/textproto/pipeline.go \
go/net/textproto/reader.go \
go/net/textproto/textproto.go \
@ -1506,6 +1552,12 @@ go_runtime_debug_files = \
go_runtime_pprof_files = \
go/runtime/pprof/pprof.go
go_sync_atomic_files = \
go/sync/atomic/doc.go
go_sync_atomic_c_files = \
go/sync/atomic/atomic.c
go_testing_iotest_files = \
go/testing/iotest/logger.go \
go/testing/iotest/reader.go \
@ -1606,6 +1658,7 @@ libgo_go_objs = \
bytes/bytes.lo \
bytes/index.lo \
cmath/cmath.lo \
crypto/crypto.lo \
ebnf/ebnf.lo \
exec/exec.lo \
expvar/expvar.lo \
@ -1636,8 +1689,7 @@ libgo_go_objs = \
sort/sort.lo \
strconv/strconv.lo \
strings/strings.lo \
sync/mutex.lo \
sync/cas.lo \
sync/sync.lo \
syslog/syslog.lo \
syslog/syslog_c.lo \
tabwriter/tabwriter.lo \
@ -1651,8 +1703,10 @@ libgo_go_objs = \
xml/xml.lo \
archive/tar.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 \
@ -1663,11 +1717,13 @@ libgo_go_objs = \
crypto/blowfish.lo \
crypto/cast5.lo \
crypto/cipher.lo \
crypto/dsa.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 \
@ -1682,6 +1738,7 @@ libgo_go_objs = \
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 \
@ -1723,6 +1780,8 @@ libgo_go_objs = \
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 \
@ -1857,8 +1916,10 @@ TEST_PACKAGES = \
xml/check \
archive/tar/check \
archive/zip/check \
compress/bzip2/check \
compress/flate/check \
compress/gzip/check \
compress/lzw/check \
compress/zlib/check \
container/heap/check \
container/list/check \
@ -1869,11 +1930,13 @@ TEST_PACKAGES = \
crypto/blowfish/check \
crypto/cast5/check \
crypto/cipher/check \
crypto/dsa/check \
crypto/elliptic/check \
crypto/hmac/check \
crypto/md4/check \
crypto/md5/check \
crypto/ocsp/check \
crypto/openpgp/check \
crypto/rand/check \
crypto/rc4/check \
crypto/ripemd160/check \
@ -1887,6 +1950,7 @@ TEST_PACKAGES = \
crypto/x509/check \
crypto/xtea/check \
crypto/openpgp/armor/check \
crypto/openpgp/packet/check \
crypto/openpgp/s2k/check \
debug/dwarf/check \
debug/elf/check \
@ -1919,6 +1983,7 @@ TEST_PACKAGES = \
$(os_inotify_check) \
os/signal/check \
rpc/jsonrpc/check \
sync/atomic/check \
testing/quick/check \
testing/script/check
@ -2146,8 +2211,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mfixalloc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mgc0.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mheap.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mheapmap32.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mheapmap64.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mprof.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msize.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc.Plo@am__quote@
@ -2794,20 +2857,6 @@ mheap.lo: runtime/mheap.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mheap.lo `test -f 'runtime/mheap.c' || echo '$(srcdir)/'`runtime/mheap.c
mheapmap32.lo: runtime/mheapmap32.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mheapmap32.lo -MD -MP -MF $(DEPDIR)/mheapmap32.Tpo -c -o mheapmap32.lo `test -f 'runtime/mheapmap32.c' || echo '$(srcdir)/'`runtime/mheapmap32.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/mheapmap32.Tpo $(DEPDIR)/mheapmap32.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/mheapmap32.c' object='mheapmap32.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mheapmap32.lo `test -f 'runtime/mheapmap32.c' || echo '$(srcdir)/'`runtime/mheapmap32.c
mheapmap64.lo: runtime/mheapmap64.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mheapmap64.lo -MD -MP -MF $(DEPDIR)/mheapmap64.Tpo -c -o mheapmap64.lo `test -f 'runtime/mheapmap64.c' || echo '$(srcdir)/'`runtime/mheapmap64.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/mheapmap64.Tpo $(DEPDIR)/mheapmap64.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/mheapmap64.c' object='mheapmap64.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mheapmap64.lo `test -f 'runtime/mheapmap64.c' || echo '$(srcdir)/'`runtime/mheapmap64.c
msize.lo: runtime/msize.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT msize.lo -MD -MP -MF $(DEPDIR)/msize.Tpo -c -o msize.lo `test -f 'runtime/msize.c' || echo '$(srcdir)/'`runtime/msize.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/msize.Tpo $(DEPDIR)/msize.Plo
@ -3261,6 +3310,26 @@ uninstall-toolexeclibgoruntimeDATA:
test -n "$$files" || exit 0; \
echo " ( cd '$(DESTDIR)$(toolexeclibgoruntimedir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(toolexeclibgoruntimedir)" && rm -f $$files
install-toolexeclibgosyncDATA: $(toolexeclibgosync_DATA)
@$(NORMAL_INSTALL)
test -z "$(toolexeclibgosyncdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgosyncdir)"
@list='$(toolexeclibgosync_DATA)'; test -n "$(toolexeclibgosyncdir)" || list=; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
done | $(am__base_list) | \
while read files; do \
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgosyncdir)'"; \
$(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgosyncdir)" || exit $$?; \
done
uninstall-toolexeclibgosyncDATA:
@$(NORMAL_UNINSTALL)
@list='$(toolexeclibgosync_DATA)'; test -n "$(toolexeclibgosyncdir)" || list=; \
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
test -n "$$files" || exit 0; \
echo " ( cd '$(DESTDIR)$(toolexeclibgosyncdir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(toolexeclibgosyncdir)" && rm -f $$files
install-toolexeclibgotestingDATA: $(toolexeclibgotesting_DATA)
@$(NORMAL_INSTALL)
test -z "$(toolexeclibgotestingdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgotestingdir)"
@ -3598,7 +3667,7 @@ all-am: Makefile $(LIBRARIES) $(LTLIBRARIES) all-multi $(DATA) \
config.h
installdirs: installdirs-recursive
installdirs-am:
for dir in "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibgodir)" "$(DESTDIR)$(toolexeclibgoarchivedir)" "$(DESTDIR)$(toolexeclibgocompressdir)" "$(DESTDIR)$(toolexeclibgocontainerdir)" "$(DESTDIR)$(toolexeclibgocryptodir)" "$(DESTDIR)$(toolexeclibgocryptoopenpgpdir)" "$(DESTDIR)$(toolexeclibgodebugdir)" "$(DESTDIR)$(toolexeclibgoencodingdir)" "$(DESTDIR)$(toolexeclibgoexpdir)" "$(DESTDIR)$(toolexeclibgogodir)" "$(DESTDIR)$(toolexeclibgohashdir)" "$(DESTDIR)$(toolexeclibgohttpdir)" "$(DESTDIR)$(toolexeclibgoimagedir)" "$(DESTDIR)$(toolexeclibgoindexdir)" "$(DESTDIR)$(toolexeclibgoiodir)" "$(DESTDIR)$(toolexeclibgomimedir)" "$(DESTDIR)$(toolexeclibgonetdir)" "$(DESTDIR)$(toolexeclibgoosdir)" "$(DESTDIR)$(toolexeclibgorpcdir)" "$(DESTDIR)$(toolexeclibgoruntimedir)" "$(DESTDIR)$(toolexeclibgotestingdir)"; do \
for dir in "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibgodir)" "$(DESTDIR)$(toolexeclibgoarchivedir)" "$(DESTDIR)$(toolexeclibgocompressdir)" "$(DESTDIR)$(toolexeclibgocontainerdir)" "$(DESTDIR)$(toolexeclibgocryptodir)" "$(DESTDIR)$(toolexeclibgocryptoopenpgpdir)" "$(DESTDIR)$(toolexeclibgodebugdir)" "$(DESTDIR)$(toolexeclibgoencodingdir)" "$(DESTDIR)$(toolexeclibgoexpdir)" "$(DESTDIR)$(toolexeclibgogodir)" "$(DESTDIR)$(toolexeclibgohashdir)" "$(DESTDIR)$(toolexeclibgohttpdir)" "$(DESTDIR)$(toolexeclibgoimagedir)" "$(DESTDIR)$(toolexeclibgoindexdir)" "$(DESTDIR)$(toolexeclibgoiodir)" "$(DESTDIR)$(toolexeclibgomimedir)" "$(DESTDIR)$(toolexeclibgonetdir)" "$(DESTDIR)$(toolexeclibgoosdir)" "$(DESTDIR)$(toolexeclibgorpcdir)" "$(DESTDIR)$(toolexeclibgoruntimedir)" "$(DESTDIR)$(toolexeclibgosyncdir)" "$(DESTDIR)$(toolexeclibgotestingdir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-recursive
@ -3672,7 +3741,7 @@ install-exec-am: install-multi install-toolexeclibLIBRARIES \
install-toolexeclibgoindexDATA install-toolexeclibgoioDATA \
install-toolexeclibgomimeDATA install-toolexeclibgonetDATA \
install-toolexeclibgoosDATA install-toolexeclibgorpcDATA \
install-toolexeclibgoruntimeDATA \
install-toolexeclibgoruntimeDATA install-toolexeclibgosyncDATA \
install-toolexeclibgotestingDATA
install-html: install-html-recursive
@ -3732,6 +3801,7 @@ uninstall-am: uninstall-toolexeclibLIBRARIES \
uninstall-toolexeclibgomimeDATA uninstall-toolexeclibgonetDATA \
uninstall-toolexeclibgoosDATA uninstall-toolexeclibgorpcDATA \
uninstall-toolexeclibgoruntimeDATA \
uninstall-toolexeclibgosyncDATA \
uninstall-toolexeclibgotestingDATA
.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all all-multi \
@ -3766,7 +3836,7 @@ uninstall-am: uninstall-toolexeclibLIBRARIES \
install-toolexeclibgoindexDATA install-toolexeclibgoioDATA \
install-toolexeclibgomimeDATA install-toolexeclibgonetDATA \
install-toolexeclibgoosDATA install-toolexeclibgorpcDATA \
install-toolexeclibgoruntimeDATA \
install-toolexeclibgoruntimeDATA install-toolexeclibgosyncDATA \
install-toolexeclibgotestingDATA installcheck installcheck-am \
installdirs installdirs-am maintainer-clean \
maintainer-clean-generic maintainer-clean-multi mostlyclean \
@ -3790,6 +3860,7 @@ uninstall-am: uninstall-toolexeclibLIBRARIES \
uninstall-toolexeclibgomimeDATA uninstall-toolexeclibgonetDATA \
uninstall-toolexeclibgoosDATA uninstall-toolexeclibgorpcDATA \
uninstall-toolexeclibgoruntimeDATA \
uninstall-toolexeclibgosyncDATA \
uninstall-toolexeclibgotestingDATA
@ -3872,6 +3943,12 @@ cmath/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: cmath/check
crypto/crypto.lo: $(go_crypto_files) hash.gox
$(BUILDPACKAGE)
crypto/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: crypto/check
ebnf/ebnf.lo: $(go_ebnf_files) container/vector.gox go/scanner.gox \
go/token.gox os.gox strconv.gox unicode.gox utf8.gox
$(BUILDPACKAGE)
@ -3879,7 +3956,7 @@ ebnf/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: ebnf/check
exec/exec.lo: $(go_exec_files) os.gox strings.gox
exec/exec.lo: $(go_exec_files) os.gox strconv.gox strings.gox
$(BUILDPACKAGE)
exec/check: $(CHECK_DEPS)
$(CHECK)
@ -3898,8 +3975,8 @@ flag/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: flag/check
fmt/fmt.lo: $(go_fmt_files) bytes.gox io.gox os.gox reflect.gox strconv.gox \
strings.gox unicode.gox utf8.gox
fmt/fmt.lo: $(go_fmt_files) bytes.gox io.gox math.gox os.gox reflect.gox \
strconv.gox strings.gox unicode.gox utf8.gox
$(BUILDPACKAGE)
fmt/check: $(CHECK_DEPS)
$(CHECK)
@ -3926,10 +4003,10 @@ html/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: html/check
http/http.lo: $(go_http_files) bufio.gox bytes.gox container/list.gox \
container/vector.gox crypto/rand.gox crypto/tls.gox \
encoding/base64.gox fmt.gox io.gox io/ioutil.gox log.gox \
mime.gox mime/multipart.gox net.gox os.gox path.gox sort.gox \
http/http.lo: $(go_http_files) bufio.gox bytes.gox container/vector.gox \
crypto/rand.gox crypto/tls.gox encoding/base64.gox fmt.gox \
io.gox io/ioutil.gox log.gox mime.gox mime/multipart.gox \
net.gox net/textproto.gox os.gox path.gox sort.gox \
strconv.gox strings.gox sync.gox time.gox utf8.gox
$(BUILDPACKAGE)
http/check: $(CHECK_DEPS)
@ -3948,9 +4025,10 @@ io/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: io/check
json/json.lo: $(go_json_files) bytes.gox container/vector.gox fmt.gox io.gox \
math.gox os.gox reflect.gox runtime.gox strconv.gox \
strings.gox unicode.gox utf16.gox utf8.gox
json/json.lo: $(go_json_files) bytes.gox container/vector.gox \
encoding/base64.gox fmt.gox io.gox math.gox os.gox \
reflect.gox runtime.gox strconv.gox strings.gox unicode.gox \
utf16.gox utf8.gox
$(BUILDPACKAGE)
json/check: $(CHECK_DEPS)
$(CHECK)
@ -3983,14 +4061,14 @@ net/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: net/check
netchan/netchan.lo: $(go_netchan_files) gob.gox log.gox net.gox os.gox \
netchan/netchan.lo: $(go_netchan_files) gob.gox io.gox log.gox net.gox os.gox \
reflect.gox strconv.gox sync.gox time.gox
$(BUILDPACKAGE)
netchan/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: netchan/check
os/os.lo: $(go_os_files) sync.gox syscall.gox
os/os.lo: $(go_os_files) runtime.gox sync.gox syscall.gox
$(BUILDPACKAGE)
os/check: $(CHECK_DEPS)
$(CHECK)
@ -4078,10 +4156,8 @@ strings/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: strings/check
sync/mutex.lo: $(go_sync_files) runtime.gox
sync/sync.lo: $(go_sync_files) runtime.gox sync/atomic.gox
$(BUILDPACKAGE)
sync/cas.lo: $(go_sync_c_files) sync/mutex.lo
$(LTCOMPILE) -c -o sync/cas.lo $(srcdir)/go/sync/cas.c
sync/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: sync/check
@ -4178,6 +4254,13 @@ archive/zip/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: archive/zip/check
compress/bzip2.lo: $(go_compress_bzip2_files) bufio.gox io.gox os.gox sort.gox
$(BUILDPACKAGE)
compress/bzip2/check: $(CHECK_DEPS)
@$(MKDIR_P) compress/bzip2
$(CHECK)
.PHONY: compress/bzip2/check
compress/flate.lo: $(go_compress_flate_files) bufio.gox io.gox math.gox \
os.gox sort.gox strconv.gox
$(BUILDPACKAGE)
@ -4194,6 +4277,13 @@ compress/gzip/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: compress/gzip/check
compress/lzw.lo: $(go_compress_lzw_files) bufio.gox fmt.gox io.gox os.gox
$(BUILDPACKAGE)
compress/lzw/check: $(CHECK_DEPS)
@$(MKDIR_P) compress/lzw
$(CHECK)
.PHONY: compress/lzw/check
compress/zlib.lo: $(go_compress_zlib_files) bufio.gox compress/flate.gox \
hash.gox hash/adler32.gox io.gox os.gox
$(BUILDPACKAGE)
@ -4265,6 +4355,13 @@ crypto/cipher/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: crypto/cipher/check
crypto/dsa.lo: $(go_crypto_dsa_files) big.gox io.gox os.gox
$(BUILDPACKAGE)
crypto/dsa/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/dsa
$(CHECK)
.PHONY: crypto/dsa/check
crypto/elliptic.lo: $(go_crypto_elliptic_files) big.gox io.gox os.gox sync.gox
$(BUILDPACKAGE)
crypto/elliptic/check: $(CHECK_DEPS)
@ -4280,21 +4377,21 @@ crypto/hmac/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: crypto/hmac/check
crypto/md4.lo: $(go_crypto_md4_files) hash.gox os.gox
crypto/md4.lo: $(go_crypto_md4_files) crypto.gox hash.gox os.gox
$(BUILDPACKAGE)
crypto/md4/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/md4
$(CHECK)
.PHONY: crypto/md4/check
crypto/md5.lo: $(go_crypto_md5_files) hash.gox os.gox
crypto/md5.lo: $(go_crypto_md5_files) crypto.gox hash.gox os.gox
$(BUILDPACKAGE)
crypto/md5/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/md5
$(CHECK)
.PHONY: crypto/md5/check
crypto/ocsp.lo: $(go_crypto_ocsp_files) asn1.gox crypto/rsa.gox \
crypto/ocsp.lo: $(go_crypto_ocsp_files) asn1.gox crypto.gox crypto/rsa.gox \
crypto/sha1.gox crypto/x509.gox os.gox time.gox
$(BUILDPACKAGE)
crypto/ocsp/check: $(CHECK_DEPS)
@ -4302,8 +4399,18 @@ crypto/ocsp/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: crypto/ocsp/check
crypto/rand.lo: $(go_crypto_rand_files) crypto/aes.gox io.gox os.gox sync.gox \
time.gox
crypto/openpgp.lo: $(go_crypto_openpgp_files) crypto.gox \
crypto/openpgp/armor.gox crypto/openpgp/error.gox \
crypto/openpgp/packet.gox crypto/rsa.gox crypto/sha256.gox \
hash.gox io.gox os.gox strconv.gox time.gox
$(BUILDPACKAGE)
crypto/openpgp/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/openpgp
$(CHECK)
.PHONY: crypto/openpgp/check
crypto/rand.lo: $(go_crypto_rand_files) bufio.gox crypto/aes.gox io.gox \
os.gox sync.gox time.gox
$(BUILDPACKAGE)
crypto/rand/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/rand
@ -4317,14 +4424,14 @@ crypto/rc4/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: crypto/rc4/check
crypto/ripemd160.lo: $(go_crypto_ripemd160_files) hash.gox os.gox
crypto/ripemd160.lo: $(go_crypto_ripemd160_files) crypto.gox hash.gox os.gox
$(BUILDPACKAGE)
crypto/ripemd160/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/ripemd160
$(CHECK)
.PHONY: crypto/ripemd160/check
crypto/rsa.lo: $(go_crypto_rsa_files) big.gox crypto/sha1.gox \
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
$(BUILDPACKAGE)
crypto/rsa/check: $(CHECK_DEPS)
@ -4332,21 +4439,21 @@ crypto/rsa/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: crypto/rsa/check
crypto/sha1.lo: $(go_crypto_sha1_files) hash.gox os.gox
crypto/sha1.lo: $(go_crypto_sha1_files) crypto.gox hash.gox os.gox
$(BUILDPACKAGE)
crypto/sha1/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/sha1
$(CHECK)
.PHONY: crypto/sha1/check
crypto/sha256.lo: $(go_crypto_sha256_files) hash.gox os.gox
crypto/sha256.lo: $(go_crypto_sha256_files) crypto.gox hash.gox os.gox
$(BUILDPACKAGE)
crypto/sha256/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/sha256
$(CHECK)
.PHONY: crypto/sha256/check
crypto/sha512.lo: $(go_crypto_sha512_files) hash.gox os.gox
crypto/sha512.lo: $(go_crypto_sha512_files) crypto.gox hash.gox os.gox
$(BUILDPACKAGE)
crypto/sha512/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/sha512
@ -4361,7 +4468,7 @@ crypto/subtle/check: $(CHECK_DEPS)
.PHONY: crypto/subtle/check
crypto/tls.lo: $(go_crypto_tls_files) big.gox bufio.gox bytes.gox \
container/list.gox crypto/aes.gox crypto/cipher.gox \
container/list.gox crypto.gox crypto/aes.gox crypto/cipher.gox \
crypto/elliptic.gox crypto/hmac.gox crypto/md5.gox \
crypto/rc4.gox crypto/rand.gox crypto/rsa.gox crypto/sha1.gox \
crypto/subtle.gox crypto/rsa.gox crypto/sha1.gox \
@ -4381,8 +4488,8 @@ crypto/twofish/check: $(CHECK_DEPS)
.PHONY: crypto/twofish/check
crypto/x509.lo: $(go_crypto_x509_files) asn1.gox big.gox container/vector.gox \
crypto/rsa.gox crypto/sha1.gox hash.gox os.gox strings.gox \
time.gox
crypto.gox crypto/rsa.gox crypto/sha1.gox hash.gox os.gox \
strings.gox time.gox
$(BUILDPACKAGE)
crypto/x509/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/x509
@ -4405,16 +4512,30 @@ crypto/openpgp/armor/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: crypto/openpgp/armor/check
crypto/openpgp/error.lo: $(go_crypto_openpgp_error_files)
crypto/openpgp/error.lo: $(go_crypto_openpgp_error_files) strconv.gox
$(BUILDPACKAGE)
crypto/openpgp/error/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/openpgp/error
$(CHECK)
.PHONY: crypto/openpgp/error/check
crypto/openpgp/s2k.lo: $(go_crypto_openpgp_s2k_files) crypto/md5.gox \
crypto/openpgp/error.gox crypto/ripemd160.gox crypto/sha1.gox \
crypto/sha256.gox crypto/sha512.gox hash.gox io.gox os.gox
crypto/openpgp/packet.lo: $(go_crypto_openpgp_packet_files) big.gox bytes.gox \
compress/flate.gox compress/zlib.gox crypto.gox \
crypto/aes.gox crypto/cast5.gox crypto/cipher.gox \
crypto/openpgp/error.gox crypto/openpgp/s2k.gox \
crypto/rand.gox crypto/rsa.gox crypto/sha1.gox \
crypto/subtle.gox encoding/binary.gox hash.gox io.gox \
io/ioutil.gox os.gox strconv.gox strings.gox
$(BUILDPACKAGE)
crypto/openpgp/packet/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/openpgp/packet
$(CHECK)
.PHONY: crypto/openpgp/packet/check
crypto/openpgp/s2k.lo: $(go_crypto_openpgp_s2k_files) crypto.gox \
crypto/md5.gox crypto/openpgp/error.gox crypto/ripemd160.gox \
crypto/sha1.gox crypto/sha256.gox crypto/sha512.gox hash.gox \
io.gox os.gox
$(BUILDPACKAGE)
crypto/openpgp/s2k/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/openpgp/s2k
@ -4733,6 +4854,15 @@ runtime/pprof/check: $(CHECK_DEPS)
$(CHECK)
.PHONY: runtime/pprof/check
sync/atomic.lo: $(go_sync_atomic_files)
$(BUILDPACKAGE)
sync/atomic_c.lo: $(go_sync_atomic_c_files) sync/atomic.lo
$(LTCOMPILE) -c -o $@ $(srcdir)/go/sync/atomic/atomic.c
sync/atomic/check: $(CHECK_DEPS)
@$(MKDIR_P) sync/atomic
$(CHECK)
.PHONY: sync/atomic/check
testing/iotest.lo: $(go_testing_iotest_files) io.gox log.gox os.gox
$(BUILDPACKAGE)
testing/iotest/check: $(CHECK_DEPS)
@ -4777,6 +4907,8 @@ bytes.gox: bytes/bytes.lo
$(BUILDGOX)
cmath.gox: cmath/cmath.lo
$(BUILDGOX)
crypto.gox: crypto/crypto.lo
$(BUILDGOX)
ebnf.gox: ebnf/ebnf.lo
$(BUILDGOX)
exec.gox: exec/exec.lo
@ -4837,7 +4969,7 @@ strconv.gox: strconv/strconv.lo
$(BUILDGOX)
strings.gox: strings/strings.lo
$(BUILDGOX)
sync.gox: sync/mutex.lo
sync.gox: sync/sync.lo
$(BUILDGOX)
syslog.gox: syslog/syslog.lo
$(BUILDGOX)
@ -4869,10 +5001,14 @@ archive/tar.gox: archive/tar.lo
archive/zip.gox: archive/zip.lo
$(BUILDGOX)
compress/bzip2.gox: compress/bzip2.lo
$(BUILDGOX)
compress/flate.gox: compress/flate.lo
$(BUILDGOX)
compress/gzip.gox: compress/gzip.lo
$(BUILDGOX)
compress/lzw.gox: compress/lzw.lo
$(BUILDGOX)
compress/zlib.gox: compress/zlib.lo
$(BUILDGOX)
@ -4895,6 +5031,8 @@ crypto/cast5.gox: crypto/cast5.lo
$(BUILDGOX)
crypto/cipher.gox: crypto/cipher.lo
$(BUILDGOX)
crypto/dsa.gox: crypto/dsa.lo
$(BUILDGOX)
crypto/elliptic.gox: crypto/elliptic.lo
$(BUILDGOX)
crypto/hmac.gox: crypto/hmac.lo
@ -4905,6 +5043,8 @@ crypto/md5.gox: crypto/md5.lo
$(BUILDGOX)
crypto/ocsp.gox: crypto/ocsp.lo
$(BUILDGOX)
crypto/openpgp.gox: crypto/openpgp.lo
$(BUILDGOX)
crypto/rand.gox: crypto/rand.lo
$(BUILDGOX)
crypto/rc4.gox: crypto/rc4.lo
@ -4934,6 +5074,8 @@ crypto/openpgp/armor.gox: crypto/openpgp/armor.lo
$(BUILDGOX)
crypto/openpgp/error.gox: crypto/openpgp/error.lo
$(BUILDGOX)
crypto/openpgp/packet.gox: crypto/openpgp/packet.lo
$(BUILDGOX)
crypto/openpgp/s2k.gox: crypto/openpgp/s2k.lo
$(BUILDGOX)
@ -5031,6 +5173,9 @@ runtime/debug.gox: runtime/debug.lo
runtime/pprof.gox: runtime/pprof.lo
$(BUILDGOX)
sync/atomic.gox: sync/atomic.lo
$(BUILDGOX)
testing/iotest.gox: testing/iotest.lo
$(BUILDGOX)
testing/quick.gox: testing/quick.lo

View File

@ -42,6 +42,10 @@ type File struct {
bodyOffset int64
}
func (f *File) hasDataDescriptor() bool {
return f.Flags&0x8 != 0
}
// 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)
@ -93,7 +97,16 @@ func (f *File) Open() (rc io.ReadCloser, err os.Error) {
return
}
}
r := io.NewSectionReader(f.zipr, off+f.bodyOffset, int64(f.CompressedSize))
size := int64(f.CompressedSize)
if f.hasDataDescriptor() {
if size == 0 {
// permit SectionReader to see the rest of the file
size = f.zipsize - (off + f.bodyOffset)
} else {
size += dataDescriptorLen
}
}
r := io.NewSectionReader(f.zipr, off+f.bodyOffset, size)
switch f.Method {
case 0: // store (no compression)
rc = nopCloser{r}
@ -103,7 +116,7 @@ func (f *File) Open() (rc io.ReadCloser, err os.Error) {
err = UnsupportedMethod
}
if rc != nil {
rc = &checksumReader{rc, crc32.NewIEEE(), f.CRC32}
rc = &checksumReader{rc, crc32.NewIEEE(), f, r}
}
return
}
@ -111,7 +124,8 @@ func (f *File) Open() (rc io.ReadCloser, err os.Error) {
type checksumReader struct {
rc io.ReadCloser
hash hash.Hash32
sum uint32
f *File
zipr io.Reader // for reading the data descriptor
}
func (r *checksumReader) Read(b []byte) (n int, err os.Error) {
@ -120,7 +134,12 @@ func (r *checksumReader) Read(b []byte) (n int, err os.Error) {
if err != os.EOF {
return
}
if r.hash.Sum32() != r.sum {
if r.f.hasDataDescriptor() {
if err = readDataDescriptor(r.zipr, r.f); err != nil {
return
}
}
if r.hash.Sum32() != r.f.CRC32 {
err = ChecksumError
}
return
@ -205,6 +224,18 @@ func readDirectoryHeader(f *File, r io.Reader) (err os.Error) {
return
}
func readDataDescriptor(r io.Reader, f *File) (err os.Error) {
defer func() {
if rerr, ok := recover().(os.Error); ok {
err = rerr
}
}()
read(r, &f.CRC32)
read(r, &f.CompressedSize)
read(r, &f.UncompressedSize)
return
}
func readDirectoryEnd(r io.ReaderAt, size int64) (d *directoryEnd, err os.Error) {
// look for directoryEndSignature in the last 1k, then in the last 65k
var b []byte

View File

@ -52,6 +52,15 @@ var tests = []ZipTest{
},
{Name: "readme.zip"},
{Name: "readme.notzip", Error: FormatError},
{
Name: "dd.zip",
File: []ZipTestFile{
{
Name: "filename",
Content: []byte("This is a test textfile.\n"),
},
},
},
}
func TestReader(t *testing.T) {
@ -102,16 +111,18 @@ func readTestZip(t *testing.T, zt ZipTest) {
}
// test invalid checksum
z.File[0].CRC32++ // invalidate
r, err := z.File[0].Open()
if err != nil {
t.Error(err)
return
}
var b bytes.Buffer
_, err = io.Copy(&b, r)
if err != ChecksumError {
t.Errorf("%s: copy error=%v, want %v", z.File[0].Name, err, ChecksumError)
if !z.File[0].hasDataDescriptor() { // skip test when crc32 in dd
z.File[0].CRC32++ // invalidate
r, err := z.File[0].Open()
if err != nil {
t.Error(err)
return
}
var b bytes.Buffer
_, err = io.Copy(&b, r)
if err != ChecksumError {
t.Errorf("%s: copy error=%v, want %v", z.File[0].Name, err, ChecksumError)
}
}
}

View File

@ -4,6 +4,7 @@ const (
fileHeaderSignature = 0x04034b50
directoryHeaderSignature = 0x02014b50
directoryEndSignature = 0x06054b50
dataDescriptorLen = 12
)
type FileHeader struct {

View File

@ -317,7 +317,7 @@ func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameter
switch v := value.(type) {
case *reflect.BoolValue:
if v.Get() {
return out.WriteByte(1)
return out.WriteByte(255)
} else {
return out.WriteByte(0)
}

View File

@ -286,7 +286,8 @@ func (b *Reader) ReadSlice(delim byte) (line []byte, err os.Error) {
// returning a slice containing the data up to and including the delimiter.
// If ReadBytes encounters an error before finding a delimiter,
// it returns the data read before the error and the error itself (often os.EOF).
// ReadBytes returns err != nil if and only if line does not end in delim.
// ReadBytes returns err != nil if and only if the returned data does not end in
// delim.
func (b *Reader) ReadBytes(delim byte) (line []byte, err os.Error) {
// Use ReadSlice to look for array,
// accumulating full buffers.
@ -332,7 +333,8 @@ func (b *Reader) ReadBytes(delim byte) (line []byte, err os.Error) {
// returning a string containing the data up to and including the delimiter.
// If ReadString encounters an error before finding a delimiter,
// it returns the data read before the error and the error itself (often os.EOF).
// ReadString returns err != nil if and only if line does not end in delim.
// ReadString returns err != nil if and only if the returned data does not end in
// delim.
func (b *Reader) ReadString(delim byte) (line string, err os.Error) {
bytes, e := b.ReadBytes(delim)
return string(bytes), e
@ -383,6 +385,9 @@ func (b *Writer) Flush() os.Error {
if b.err != nil {
return b.err
}
if b.n == 0 {
return nil
}
n, e := b.wr.Write(b.buf[0:b.n])
if n < b.n && e == nil {
e = io.ErrShortWrite

View File

@ -154,17 +154,20 @@ func (b *Buffer) ReadFrom(r io.Reader) (n int64, err os.Error) {
}
// WriteTo writes data to w until the buffer is drained or an error
// occurs. The return value n is the number of bytes written.
// occurs. The return value n is the number of bytes written; it always
// fits into an int, but it is int64 to match the io.WriterTo interface.
// Any error encountered during the write is also returned.
func (b *Buffer) WriteTo(w io.Writer) (n int64, err os.Error) {
b.lastRead = opInvalid
for b.off < len(b.buf) {
if b.off < len(b.buf) {
m, e := w.Write(b.buf[b.off:])
n += int64(m)
b.off += m
n = int64(m)
if e != nil {
return n, e
}
// otherwise all bytes were written, by definition of
// Write method in io.Writer
}
// Buffer is now empty; reset.
b.Truncate(0)
@ -301,6 +304,36 @@ func (b *Buffer) UnreadByte() os.Error {
return nil
}
// ReadBytes reads until the first occurrence of delim in the input,
// returning a slice containing the data up to and including the delimiter.
// If ReadBytes encounters an error before finding a delimiter,
// it returns the data read before the error and the error itself (often os.EOF).
// ReadBytes returns err != nil if and only if the returned data does not end in
// delim.
func (b *Buffer) ReadBytes(delim byte) (line []byte, err os.Error) {
i := IndexByte(b.buf[b.off:], delim)
size := i + 1
if i < 0 {
size = len(b.buf) - b.off
err = os.EOF
}
line = make([]byte, size)
copy(line, b.buf[b.off:])
b.off += size
return
}
// ReadString reads until the first occurrence of delim in the input,
// returning a string containing the data up to and including the delimiter.
// If ReadString encounters an error before finding a delimiter,
// it returns the data read before the error and the error itself (often os.EOF).
// ReadString returns err != nil if and only if the returned data does not end
// in delim.
func (b *Buffer) ReadString(delim byte) (line string, err os.Error) {
bytes, err := b.ReadBytes(delim)
return string(bytes), err
}
// NewBuffer creates and initializes a new Buffer using buf as its initial
// contents. It is intended to prepare a Buffer to read existing data. It
// can also be used to size the internal buffer for writing. To do that,

View File

@ -6,6 +6,7 @@ package bytes_test
import (
. "bytes"
"os"
"rand"
"testing"
"utf8"
@ -238,7 +239,7 @@ func TestMixedReadsAndWrites(t *testing.T) {
func TestNil(t *testing.T) {
var b *Buffer
if b.String() != "<nil>" {
t.Errorf("expcted <nil>; got %q", b.String())
t.Errorf("expected <nil>; got %q", b.String())
}
}
@ -347,3 +348,38 @@ func TestNext(t *testing.T) {
}
}
}
var readBytesTests = []struct {
buffer string
delim byte
expected []string
err os.Error
}{
{"", 0, []string{""}, os.EOF},
{"a\x00", 0, []string{"a\x00"}, nil},
{"abbbaaaba", 'b', []string{"ab", "b", "b", "aaab"}, nil},
{"hello\x01world", 1, []string{"hello\x01"}, nil},
{"foo\nbar", 0, []string{"foo\nbar"}, os.EOF},
{"alpha\nbeta\ngamma\n", '\n', []string{"alpha\n", "beta\n", "gamma\n"}, nil},
{"alpha\nbeta\ngamma", '\n', []string{"alpha\n", "beta\n", "gamma"}, os.EOF},
}
func TestReadBytes(t *testing.T) {
for _, test := range readBytesTests {
buf := NewBufferString(test.buffer)
var err os.Error
for _, expected := range test.expected {
var bytes []byte
bytes, err = buf.ReadBytes(test.delim)
if string(bytes) != expected {
t.Errorf("expected %q, got %q", expected, bytes)
}
if err != nil {
break
}
}
if err != test.err {
t.Errorf("expected error %v, got %v", test.err, err)
}
}
}

View File

@ -0,0 +1,88 @@
// 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 bzip2
import (
"bufio"
"io"
"os"
)
// bitReader wraps an io.Reader and provides the ability to read values,
// bit-by-bit, from it. Its Read* methods don't return the usual os.Error
// because the error handling was verbose. Instead, any error is kept and can
// be checked afterwards.
type bitReader struct {
r byteReader
n uint64
bits uint
err os.Error
}
// bitReader needs to read bytes from an io.Reader. We attempt to cast the
// given io.Reader to this interface and, if it doesn't already fit, we wrap in
// a bufio.Reader.
type byteReader interface {
ReadByte() (byte, os.Error)
}
func newBitReader(r io.Reader) bitReader {
byter, ok := r.(byteReader)
if !ok {
byter = bufio.NewReader(r)
}
return bitReader{r: byter}
}
// ReadBits64 reads the given number of bits and returns them in the
// least-significant part of a uint64. In the event of an error, it returns 0
// and the error can be obtained by calling Error().
func (br *bitReader) ReadBits64(bits uint) (n uint64) {
for bits > br.bits {
b, err := br.r.ReadByte()
if err == os.EOF {
err = io.ErrUnexpectedEOF
}
if err != nil {
br.err = err
return 0
}
br.n <<= 8
br.n |= uint64(b)
br.bits += 8
}
// br.n looks like this (assuming that br.bits = 14 and bits = 6):
// Bit: 111111
// 5432109876543210
//
// (6 bits, the desired output)
// |-----|
// V V
// 0101101101001110
// ^ ^
// |------------|
// br.bits (num valid bits)
//
// This the next line right shifts the desired bits into the
// least-significant places and masks off anything above.
n = (br.n >> (br.bits - bits)) & ((1 << bits) - 1)
br.bits -= bits
return
}
func (br *bitReader) ReadBits(bits uint) (n int) {
n64 := br.ReadBits64(bits)
return int(n64)
}
func (br *bitReader) ReadBit() bool {
n := br.ReadBits(1)
return n != 0
}
func (br *bitReader) Error() os.Error {
return br.err
}

View File

@ -0,0 +1,390 @@
// 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 bzip2 implements bzip2 decompression.
package bzip2
import (
"io"
"os"
)
// There's no RFC for bzip2. I used the Wikipedia page for reference and a lot
// of guessing: http://en.wikipedia.org/wiki/Bzip2
// The source code to pyflate was useful for debugging:
// http://www.paul.sladen.org/projects/pyflate
// A StructuralError is returned when the bzip2 data is found to be
// syntactically invalid.
type StructuralError string
func (s StructuralError) String() string {
return "bzip2 data invalid: " + string(s)
}
// A reader decompresses bzip2 compressed data.
type reader struct {
br bitReader
setupDone bool // true if we have parsed the bzip2 header.
blockSize int // blockSize in bytes, i.e. 900 * 1024.
eof bool
buf []byte // stores Burrows-Wheeler transformed data.
c [256]uint // the `C' array for the inverse BWT.
tt []uint32 // mirrors the `tt' array in the bzip2 source and contains the P array in the upper 24 bits.
tPos uint32 // Index of the next output byte in tt.
preRLE []uint32 // contains the RLE data still to be processed.
preRLEUsed int // number of entries of preRLE used.
lastByte int // the last byte value seen.
byteRepeats uint // the number of repeats of lastByte seen.
repeats uint // the number of copies of lastByte to output.
}
// NewReader returns an io.Reader which decompresses bzip2 data from r.
func NewReader(r io.Reader) io.Reader {
bz2 := new(reader)
bz2.br = newBitReader(r)
return bz2
}
const bzip2FileMagic = 0x425a // "BZ"
const bzip2BlockMagic = 0x314159265359
const bzip2FinalMagic = 0x177245385090
// setup parses the bzip2 header.
func (bz2 *reader) setup() os.Error {
br := &bz2.br
magic := br.ReadBits(16)
if magic != bzip2FileMagic {
return StructuralError("bad magic value")
}
t := br.ReadBits(8)
if t != 'h' {
return StructuralError("non-Huffman entropy encoding")
}
level := br.ReadBits(8)
if level < '1' || level > '9' {
return StructuralError("invalid compression level")
}
bz2.blockSize = 100 * 1024 * (int(level) - '0')
bz2.tt = make([]uint32, bz2.blockSize)
return nil
}
func (bz2 *reader) Read(buf []byte) (n int, err os.Error) {
if bz2.eof {
return 0, os.EOF
}
if !bz2.setupDone {
err = bz2.setup()
brErr := bz2.br.Error()
if brErr != nil {
err = brErr
}
if err != nil {
return 0, err
}
bz2.setupDone = true
}
n, err = bz2.read(buf)
brErr := bz2.br.Error()
if brErr != nil {
err = brErr
}
return
}
func (bz2 *reader) read(buf []byte) (n int, err os.Error) {
// bzip2 is a block based compressor, except that it has a run-length
// preprocessing step. The block based nature means that we can
// preallocate fixed-size buffers and reuse them. However, the RLE
// preprocessing would require allocating huge buffers to store the
// maximum expansion. Thus we process blocks all at once, except for
// the RLE which we decompress as required.
for (bz2.repeats > 0 || bz2.preRLEUsed < len(bz2.preRLE)) && n < len(buf) {
// We have RLE data pending.
// The run-length encoding works like this:
// Any sequence of four equal bytes is followed by a length
// byte which contains the number of repeats of that byte to
// include. (The number of repeats can be zero.) Because we are
// decompressing on-demand our state is kept in the reader
// object.
if bz2.repeats > 0 {
buf[n] = byte(bz2.lastByte)
n++
bz2.repeats--
if bz2.repeats == 0 {
bz2.lastByte = -1
}
continue
}
bz2.tPos = bz2.preRLE[bz2.tPos]
b := byte(bz2.tPos)
bz2.tPos >>= 8
bz2.preRLEUsed++
if bz2.byteRepeats == 3 {
bz2.repeats = uint(b)
bz2.byteRepeats = 0
continue
}
if bz2.lastByte == int(b) {
bz2.byteRepeats++
} else {
bz2.byteRepeats = 0
}
bz2.lastByte = int(b)
buf[n] = b
n++
}
if n > 0 {
return
}
// No RLE data is pending so we need to read a block.
br := &bz2.br
magic := br.ReadBits64(48)
if magic == bzip2FinalMagic {
br.ReadBits64(32) // ignored CRC
bz2.eof = true
return 0, os.EOF
} else if magic != bzip2BlockMagic {
return 0, StructuralError("bad magic value found")
}
err = bz2.readBlock()
if err != nil {
return 0, err
}
return bz2.read(buf)
}
// readBlock reads a bzip2 block. The magic number should already have been consumed.
func (bz2 *reader) readBlock() (err os.Error) {
br := &bz2.br
br.ReadBits64(32) // skip checksum. TODO: check it if we can figure out what it is.
randomized := br.ReadBits(1)
if randomized != 0 {
return StructuralError("deprecated randomized files")
}
origPtr := uint(br.ReadBits(24))
// If not every byte value is used in the block (i.e., it's text) then
// the symbol set is reduced. The symbols used are stored as a
// two-level, 16x16 bitmap.
symbolRangeUsedBitmap := br.ReadBits(16)
symbolPresent := make([]bool, 256)
numSymbols := 0
for symRange := uint(0); symRange < 16; symRange++ {
if symbolRangeUsedBitmap&(1<<(15-symRange)) != 0 {
bits := br.ReadBits(16)
for symbol := uint(0); symbol < 16; symbol++ {
if bits&(1<<(15-symbol)) != 0 {
symbolPresent[16*symRange+symbol] = true
numSymbols++
}
}
}
}
// A block uses between two and six different Huffman trees.
numHuffmanTrees := br.ReadBits(3)
if numHuffmanTrees < 2 || numHuffmanTrees > 6 {
return StructuralError("invalid number of Huffman trees")
}
// The Huffman tree can switch every 50 symbols so there's a list of
// tree indexes telling us which tree to use for each 50 symbol block.
numSelectors := br.ReadBits(15)
treeIndexes := make([]uint8, numSelectors)
// The tree indexes are move-to-front transformed and stored as unary
// numbers.
mtfTreeDecoder := newMTFDecoderWithRange(numHuffmanTrees)
for i := range treeIndexes {
c := 0
for {
inc := br.ReadBits(1)
if inc == 0 {
break
}
c++
}
if c >= numHuffmanTrees {
return StructuralError("tree index too large")
}
treeIndexes[i] = uint8(mtfTreeDecoder.Decode(c))
}
// The list of symbols for the move-to-front transform is taken from
// the previously decoded symbol bitmap.
symbols := make([]byte, numSymbols)
nextSymbol := 0
for i := 0; i < 256; i++ {
if symbolPresent[i] {
symbols[nextSymbol] = byte(i)
nextSymbol++
}
}
mtf := newMTFDecoder(symbols)
numSymbols += 2 // to account for RUNA and RUNB symbols
huffmanTrees := make([]huffmanTree, numHuffmanTrees)
// Now we decode the arrays of code-lengths for each tree.
lengths := make([]uint8, numSymbols)
for i := 0; i < numHuffmanTrees; i++ {
// The code lengths are delta encoded from a 5-bit base value.
length := br.ReadBits(5)
for j := 0; j < numSymbols; j++ {
for {
if !br.ReadBit() {
break
}
if br.ReadBit() {
length--
} else {
length++
}
}
if length < 0 || length > 20 {
return StructuralError("Huffman length out of range")
}
lengths[j] = uint8(length)
}
huffmanTrees[i], err = newHuffmanTree(lengths)
if err != nil {
return err
}
}
selectorIndex := 1 // the next tree index to use
currentHuffmanTree := huffmanTrees[treeIndexes[0]]
bufIndex := 0 // indexes bz2.buf, the output buffer.
// The output of the move-to-front transform is run-length encoded and
// we merge the decoding into the Huffman parsing loop. These two
// variables accumulate the repeat count. See the Wikipedia page for
// details.
repeat := 0
repeat_power := 0
// The `C' array (used by the inverse BWT) needs to be zero initialised.
for i := range bz2.c {
bz2.c[i] = 0
}
decoded := 0 // counts the number of symbols decoded by the current tree.
for {
if decoded == 50 {
currentHuffmanTree = huffmanTrees[treeIndexes[selectorIndex]]
selectorIndex++
decoded = 0
}
v := currentHuffmanTree.Decode(br)
decoded++
if v < 2 {
// This is either the RUNA or RUNB symbol.
if repeat == 0 {
repeat_power = 1
}
repeat += repeat_power << v
repeat_power <<= 1
// This limit of 2 million comes from the bzip2 source
// code. It prevents repeat from overflowing.
if repeat > 2*1024*1024 {
return StructuralError("repeat count too large")
}
continue
}
if repeat > 0 {
// We have decoded a complete run-length so we need to
// replicate the last output symbol.
for i := 0; i < repeat; i++ {
b := byte(mtf.First())
bz2.tt[bufIndex] = uint32(b)
bz2.c[b]++
bufIndex++
}
repeat = 0
}
if int(v) == numSymbols-1 {
// This is the EOF symbol. Because it's always at the
// end of the move-to-front list, and nevers gets moved
// to the front, it has this unique value.
break
}
// Since two metasymbols (RUNA and RUNB) have values 0 and 1,
// one would expect |v-2| to be passed to the MTF decoder.
// However, the front of the MTF list is never referenced as 0,
// it's always referenced with a run-length of 1. Thus 0
// doesn't need to be encoded and we have |v-1| in the next
// line.
b := byte(mtf.Decode(int(v - 1)))
bz2.tt[bufIndex] = uint32(b)
bz2.c[b]++
bufIndex++
}
if origPtr >= uint(bufIndex) {
return StructuralError("origPtr out of bounds")
}
// We have completed the entropy decoding. Now we can perform the
// inverse BWT and setup the RLE buffer.
bz2.preRLE = bz2.tt[:bufIndex]
bz2.preRLEUsed = 0
bz2.tPos = inverseBWT(bz2.preRLE, origPtr, bz2.c[:])
bz2.lastByte = -1
bz2.byteRepeats = 0
bz2.repeats = 0
return nil
}
// inverseBWT implements the inverse Burrows-Wheeler transform as described in
// http://www.hpl.hp.com/techreports/Compaq-DEC/SRC-RR-124.pdf, section 4.2.
// In that document, origPtr is called `I' and c is the `C' array after the
// first pass over the data. It's an argument here because we merge the first
// pass with the Huffman decoding.
//
// This also implements the `single array' method from the bzip2 source code
// which leaves the output, still shuffled, in the bottom 8 bits of tt with the
// index of the next byte in the top 24-bits. The index of the first byte is
// returned.
func inverseBWT(tt []uint32, origPtr uint, c []uint) uint32 {
sum := uint(0)
for i := 0; i < 256; i++ {
sum += c[i]
c[i] = sum - c[i]
}
for i := range tt {
b := tt[i] & 0xff
tt[c[b]] |= uint32(i) << 8
c[b]++
}
return tt[origPtr] >> 8
}

View File

@ -0,0 +1,158 @@
// 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 bzip2
import (
"bytes"
"encoding/hex"
"io"
"io/ioutil"
"os"
"testing"
)
func TestBitReader(t *testing.T) {
buf := bytes.NewBuffer([]byte{0xaa})
br := newBitReader(buf)
if n := br.ReadBits(1); n != 1 {
t.Errorf("read 1 wrong")
}
if n := br.ReadBits(1); n != 0 {
t.Errorf("read 2 wrong")
}
if n := br.ReadBits(1); n != 1 {
t.Errorf("read 3 wrong")
}
if n := br.ReadBits(1); n != 0 {
t.Errorf("read 4 wrong")
}
}
func TestBitReaderLarge(t *testing.T) {
buf := bytes.NewBuffer([]byte{0x12, 0x34, 0x56, 0x78})
br := newBitReader(buf)
if n := br.ReadBits(32); n != 0x12345678 {
t.Errorf("got: %x want: %x", n, 0x12345678)
}
}
func readerFromHex(s string) io.Reader {
data, err := hex.DecodeString(s)
if err != nil {
panic("readerFromHex: bad input")
}
return bytes.NewBuffer(data)
}
func decompressHex(s string) (out []byte, err os.Error) {
r := NewReader(readerFromHex(s))
return ioutil.ReadAll(r)
}
func TestHelloWorldBZ2(t *testing.T) {
out, err := decompressHex(helloWorldBZ2Hex)
if err != nil {
t.Errorf("error from Read: %s", err)
return
}
if !bytes.Equal(helloWorld, out) {
t.Errorf("got %x, want %x", out, helloWorld)
}
}
func testZeros(t *testing.T, inHex string, n int) {
out, err := decompressHex(inHex)
if err != nil {
t.Errorf("error from Read: %s", err)
return
}
expected := make([]byte, n)
if !bytes.Equal(expected, out) {
allZeros := true
for _, b := range out {
if b != 0 {
allZeros = false
break
}
}
t.Errorf("incorrect result, got %d bytes (allZeros: %t)", len(out), allZeros)
}
}
func Test32Zeros(t *testing.T) {
testZeros(t, thirtyTwoZerosBZ2Hex, 32)
}
func Test1MBZeros(t *testing.T) {
testZeros(t, oneMBZerosBZ2Hex, 1024*1024)
}
func testRandomData(t *testing.T, compressedHex, uncompressedHex string) {
out, err := decompressHex(compressedHex)
if err != nil {
t.Errorf("error from Read: %s", err)
return
}
expected, _ := hex.DecodeString(uncompressedHex)
if !bytes.Equal(out, expected) {
t.Errorf("incorrect result\ngot: %x\nwant: %x", out, expected)
}
}
func TestRandomData1(t *testing.T) {
testRandomData(t, randBZ2Hex, randHex)
}
func TestRandomData2(t *testing.T) {
// This test involves several repeated bytes in the output, but they
// should trigger RLE decoding.
testRandomData(t, rand2BZ2Hex, rand2Hex)
}
func TestRandomData3(t *testing.T) {
// This test uses the full range of symbols.
testRandomData(t, rand3BZ2Hex, rand3Hex)
}
func Test1MBSawtooth(t *testing.T) {
out, err := decompressHex(oneMBSawtoothBZ2Hex)
if err != nil {
t.Errorf("error from Read: %s", err)
return
}
expected := make([]byte, 1024*1024)
for i := range expected {
expected[i] = byte(i)
}
if !bytes.Equal(out, expected) {
t.Error("incorrect result")
}
}
const helloWorldBZ2Hex = "425a68393141592653594eece83600000251800010400006449080200031064c4101a7a9a580bb9431f8bb9229c28482776741b0"
var helloWorld = []byte("hello world\n")
const thirtyTwoZerosBZ2Hex = "425a6839314159265359b5aa5098000000600040000004200021008283177245385090b5aa5098"
const oneMBZerosBZ2Hex = "425a683931415926535938571ce50008084000c0040008200030cc0529a60806c4201e2ee48a70a12070ae39ca"
const randBZ2Hex = "425a6839314159265359905d990d0001957fffffffffffafffffffffffffffffbfff6fffdfffffffffffffffffffffffffffffc002b6dd75676ed5b77720098320d11a64626981323d4da47a83131a13d09e8040f534cd4f4d27a464d193008cd09804601347a980026350c9886234d36864193d1351b44c136919e90340d26127a4cd264c32023009898981310c0344c340027a8303427a99a04c00003534c230d034f5006468d268cf54d36a3009a69a62626261311b40026013d34201a6934c9a604c98ca6c8460989fa9346234d30d3469a2604fd4131a7aa6d0046043d4c62098479269e89e835190d018d4c046001a11e801a0264792321932308c43a130688c260d46686804cd01a9e80981193684c6a68c00000004c4c20c04627a4c0000260003400d04c0681a01334026009a6f48041466132581ec5212b081d96b0effc16543e2228b052fcd30f2567ee8d970e0f10aabca68dd8270591c376cfc1baae0dba00aaff2d6caf6b211322c997cc18eaee5927f75185336bf907021324c71626c1dd20e22b9b0977f05d0f901eaa51db9fbaf7c603b4c87bc82890e6dd7e61d0079e27ec050dd788fd958152061cd01e222f9547cb9efc465d775b6fc98bac7d387bffd151ae09dadf19494f7a638e2eae58e550faba5fe6820ea520eb986096de4e527d80def3ba625e71fbefdcf7e7844e0a25d29b52dcd1344fca083737d42692aab38d230485f3c8ed54c2ed31f15cf0270c8143765b10b92157233fa1dfe0d7ce8ffe70b8b8f7250071701dfe9f1c94de362c9031455951c93eb098a6b50ee45c6131fefc3b6f9643e21f4adc59497138e246f5c57d834aa67c4f10d8bd8b3908d8130dd7388409c299a268eab3664fa4907c5c31574874bd8d388a4ab22b339660804e53e1b8d05867d40e3082560608d35d5d2c6054e8bab23da28f61f83efd41d25529ad6ea15fb50505cacfabb0902166427354ca3830a2c8415f21b19e592690fbe447020d685a4bcd16ecc4ff1a1c0e572627d0ef6265c008a43fc243240541061ed7840606be466d1c0dac2c53250ed567507d926c844154560d631960c65e15157829b2c7f16859f111a3a8cb72bf24ffa57a680c3be67b1be67c8dd8aea73ac2437a78df5b686d427080ebc01bd30b71a49f6ea31dc0f08e4849e38face96717690239538bc08b6cc5aa8d467cb9c36aa83d40ac7e58bddbfa185b22065e89a86c0145569d9e23726651aec49e31588d70f40fe9a4449dcf4f89eac220171e9c938e803dc195679651004b79ad33cc0c13aeeba5941b33ffeeb8fbe16e76c7811445c67b4269c90479433ddf9e8ed1d00c166b6c17217fb22c3ef1b0c1c7e28e185446a111c37f1ea6c07a59fbcc6546ecc6968d36ba58bc5489a5640647e426b0c39350cb6f07d5dc7a717648c4ec7f841467597ae1f65f408fd2d9940a4b1b860b3c9ae351dcae0b4425f7e8538710f2e40b7f70d13b51ac05ccc6ecda8264a88cad2d721d18132a9b9110a9e759c2483c77dcefc7e464ec88588174cb0c9abff93230ea0bed8decdd8ed8bfe2b5df0a253803678df04fab44c03b9ab7cc97d6e6d6fd0c4c840ce0efc498436f453bbb181603459471f2b588724592b222ec990614db530e10cadd84705621cfdd9261fa44a5f5806a2d74b575056b3c915255c65678f9c16e6dc00a99180fef1a840aff0e842ac02731080cc92782538360a60a727991013984da4fad95f79d5030677b7528d076b2483685fca4429edf804682fdc110dfc2f7c30e23e20a72e039108a0ad6fdee2f76985a4b4be4f5afc6101bf9d5042b657a05dc914e1424241766434"
const randHex = "c95138082bdf2b9bfa5b1072b23f729735d42c785eeb94320fb14c265b9c2ca421d01a3db986df1ac2acde5a0e6bf955d6f95e61261540905928e195f1a66644cc7f37281744fff4dc6df35566a494c41a8167151950eb74f5fc45f85ad0e5ed28b49adfe218aa7ec1707e8e1d55825f61f72beda3b4c006b8c9188d7336a5d875329b1b58c27cc4e89ecbae02c7712400c39dd131d2c6de82e2863da51d472bdfb21ecce62cc9cf769ed28aedc7583d755da45a0d90874bda269dd53283a9bdfd05f95fc8e9a304bb338ea1a2111894678c18134f17d31a15d9bfc1237894650f3e715e2548639ecbddb845cfe4a46a7b3a3c540f48629488e8c869f1e9f3f4c552243a8105b20eb8e264994214349dae83b165fd6c2a5b8e83fce09fc0a80d3281c8d53a9a08095bd19cbc1388df23975646ed259e003d39261ee68cbece8bcf32971f7fe7e588e8ba8f5e8597909abaea693836a79a1964050ed910a45a0f13a58cd2d3ae18992c5b23082407fd920d0bf01e33118a017bb5e39f44931346845af52128f7965206759433a346034ea481671f501280067567619f5ecef6cded077f92ed7f3b3ce8e308c80f34ba06939e9303f91b4318c8c1dd4cc223c1f057ac0c91211c629cd30e46ee9ec1d9fd493086b7bc2bc83e33f08749a5d430b0ed4f79d70f481940c9b0930b16321886a0df4fa5a1465d5208c7d3494a7987d9a5e42aa256f0c9523947f8318d0ef0af3d59a45cfc2418d0785c9a548b32b81e7de18be7d55a69a4c156bbb3d7579c0ac8e9c72b24646e54b0d0e8725f8f49fb44ae3c6b9d0287be118586255a90a4a83483ed0328518037e52aa959c5748ed83e13023e532306be98b8288da306bbb040bcf5d92176f84a9306dc6b274b040370b61d71fde58dd6d20e6fee348eae0c54bd0a5a487b2d005f329794f2a902c296af0a4c1f638f63292a1fa18e006c1b1838636f4de71c73635b25660d32e88a0917e1a5677f6a02ca65585b82cbd99fb4badbfa97a585da1e6cadf6737b4ec6ca33f245d66ee6a9fae6785d69b003c17b9fc6ec34fe5824ab8caae5e8e14dc6f9e116e7bf4a60c04388783c8ae929e1b46b3ef3bbe81b38f2fa6da771bf39dfba2374d3d2ed356b8e2c42081d885a91a3afb2f31986d2f9873354c48cf5448492c32e62385af423aa4f83db6d1b2669650379a1134b0a04cbca0862d6f9743c791cbb527d36cd5d1f0fc7f503831c8bd1b7a0ef8ae1a5ed1155dfdd9e32b6bb33138112d3d476b802179cb85a2a6c354ccfed2f31604fbd8d6ec4baf9f1c8454f72c6588c06a7df3178c43a6970bfa02dd6f74cb5ec3b63f9eddaa17db5cbf27fac6de8e57c384afd0954179f7b5690c3bee42abc4fa79b4b12101a9cf5f0b9aecdda945def0bd04163237247d3539850e123fe18139f316fa0256d5bd2faa8"
const oneMBSawtoothBZ2Hex = "425a683931415926535971931ea00006ddffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe007de00000000000000024c00130001300000000000000000000000000000000000000000000000000000000126000980009800000000000000000000000000000000000000000000000000000000930004c0004c000000000000000000000000000000000000000000000000000000004980026000260000000000000000000000000000000000000000000000000000000009aaaaa0000000000000000000000000000000000000000000000000000000000000000498002600026000000000000000000000000000000000000000000000000000000007fc42271980d044c0a822607411304a08982d044c1a82260f411308a08984d044c2a82261741130ca08986d044c3a82261f411310a08988d044c4a822627411314a0898ad044c5a82262f411318a0898cd044c6a82263741131ca0898ed044c7a82263f411320a08990d044c8a822647411324a08992d044c9a82264f411328a08994d044caa82265741132ca08996d044cba82265f411330a08998d044cca822667411334a0899ad044cda82266f411338a0899cd044cea82267741133ca0899ed044cfa82267f411340a089a0d044d0a822687411344a089a2d044d1a82268f411348a089a4d044d2a82269741134ca089a6d044d3a82269f411350a089a8d044d4a8226a7411354a089aad044d5a8226af411358a089acd044d6a8226b741135ca089aed044d7a8226bf411360a089b0d044d8a8226c7411364a089b2d044d9a8226cf411368a089b4d044daa8226d741136ca089b6d044dba8226df411370a089b8d044dca8226e7411374a089bad044dda8226ef411378a089bcd044dea8226f741137ca089bed044dfa8226ff411380a089c0d044e0a822707411384a089c2d044e1a82270f411388a089c4d044e2a82271741138ca089c59089c69089c71089c79089c81089c89089c91089c99089ca1089ca9089cb1089cb9089cc1089cc9089cd1089cd9089ce1089ce9089cf1089cf9089d01089d09089d11089d19089d21089d29089d31089d39089d41089d49089d51089d59089d61089d69089d71089d79089d81089d89089d91089d99089da1089da9089db1089db9089dc1089dc9089dd1089dd9089de1089de9089df1089df9089e01089e09089e11089e19089e21089e29089e31089e39089e41089e49089e51089e59089e61089e69089e71089e79089e81089e89089e91089e99089ea1089ea9089eb1089eb9089ec1089ec9089ed1089ed9089ee1089ee9089ef1089ef9089f01089f09089f11089f19089f21089f29089f31089f39089f41089f49089f51089f59089f61089f69089f71089f79089f81089f89089f91089f99089fa1089fa9089fb1089fb9089fc1089fc9089fd1089fd9089fe1089fe9089ff1089ff98a0ac9329acf23ba884804fdd3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0034f800000000000024c00130001300000000000000000000000000000000000000000000000000000000126000980009800000000000000000000000000000000000000000000000000000000930004c0004c000000000000000000000000000000000000000000000000000000004980026000260000000000000000000000000000000000000000000000000000000024c0013000130000000000000000000000000000000000000000000000000000000002955540000000000000000000000000000000000000000000000000000000000000001ff108c00846024230221181908c108460a4230621183908c20846124230a21185908c308461a4230e21187908c40846224231221189908c508462a423162118b908c60846324231a2118d908c708463a4231e2118f908c80846424232221191908c908464a4232621193908ca0846524232a21195908cb08465a4232e21197908cc0846624233221199908cd08466a423362119b908ce0846724233a2119d908cf08467a4233e2119f908d008468242342211a1908d108468a42346211a3908d20846924234a211a5908d308469a4234e211a7908d40846a242352211a9908d50846aa42356211ab908d60846b24235a211ad908d70846ba4235e211af908d80846c242362211b1908d90846ca42366211b3908da0846d24236a211b5908db0846da4236e211b7908dc0846e242372211b9908dd0846ea42376211bb908de0846f24237a211bd908df0846fa4237e211bf908e008470242382211c1908e108470a42386211c3908e20847124238a211c5908e2f8c211c6c8471d211c7c84721211c8c84725211c9c84729211cac8472d211cbc84731211ccc84735211cdc84739211cec8473d211cfc84741211d0c84745211d1c84749211d2c8474d211d3c84751211d4c84755211d5c84759211d6c8475d211d7c84761211d8c84765211d9c84769211dac8476d211dbc84771211dcc84775211ddc84779211dec8477d211dfc84781211e0c84785211e1c84789211e2c8478d211e3c84791211e4c84795211e5c84799211e6c8479d211e7c847a1211e8c847a5211e9c847a9211eac847ad211ebc847b1211ecc847b5211edc847b9211eec847bd211efc847c1211f0c847c5211f1c847c9211f2c847cd211f3c847d1211f4c847d5211f5c847d9211f6c847dd211f7c847e1211f8c847e5211f9c847e9211fac847ed211fbc847f1211fcc847f5211fdc847f9211fec847fd211ff8bb9229c284803a8b6248"
const rand2BZ2Hex = "425a6839314159265359d992d0f60000137dfe84020310091c1e280e100e042801099210094806c0110002e70806402000546034000034000000f2830000032000d3403264049270eb7a9280d308ca06ad28f6981bee1bf8160727c7364510d73a1e123083421b63f031f63993a0f40051fbf177245385090d992d0f60"
const rand2Hex = "92d5652616ac444a4a04af1a8a3964aca0450d43d6cf233bd03233f4ba92f8719e6c2a2bd4f5f88db07ecd0da3a33b263483db9b2c158786ad6363be35d17335ba"
const rand3BZ2Hex = "425a68393141592653593be669d00000327ffffffffffffffffffffffffffffffffffff7ffffffffffffffffffffffffffffffc002b3b2b1b6e2bae400004c00132300004c0d268c004c08c0130026001a008683234c0684c34008c230261a04c0260064d07a8d00034000d27a1268c9931a8d327a3427a41faa69ea0da264c1a34219326869b51b49a6469a3268c689fa53269a62794687a9a68f5189994c9e487a8f534fd49a3d34043629e8c93d04da4f4648d30d4f44d3234c4d3023d0840680984d309934c234d3131a000640984f536a6132601300130130c8d00d04d1841ea7a8d31a02609b40023460010c01a34d4c1a0d04d3069306810034d0d0d4c0046130d034d0131a9a64d321804c68003400098344c13000991808c0001a00000000098004d3d4da4604c47a13012140aadf8d673c922c607ef6212a8c0403adea4b28aee578900e653b9cdeb8d11e6b838815f3ebaad5a01c5408d84a332170aff8734d4e06612d3c2889f31925fb89e33561f5100ae89b1f7047102e729373d3667e58d73aaa80fa7be368a1cc2dadd81d81ec8e1b504bd772ca31d03649269b01ceddaca07bf3d4eba24de141be3f86f93601e03714c0f64654671684f9f9528626fd4e1b76753dc0c54b842486b8d59d8ab314e86ca818e7a1f079463cbbd70d9b79b283c7edc419406311022e4be98c2c1374df9cdde2d008ce1d00e5f06ad1024baf555631f70831fc1023034e62be7c4bcb648caf276963ffa20e96bb50377fe1c113da0db4625b50741c35a058edb009c6ee5dbf93b8a6b060eec568180e8db791b82aab96cbf4326ca98361461379425ba8dcc347be670bdba7641883e5526ae3d833f6e9cb9bac9557747c79e206151072f7f0071dff3880411846f66bf4075c7462f302b53cb3400a74cf35652ad5641ed33572fd54e7ed7f85f58a0acba89327e7c6be5c58cb71528b99df2431f1d0358f8d28d81d95292da631fb06701decabb205fac59ff0fb1df536afc681eece6ea658c4d9eaa45f1342aa1ff70bdaff2ddaf25ec88c22f12829a0553db1ec2505554cb17d7b282e213a5a2aa30431ded2bce665bb199d023840832fedb2c0c350a27291407ff77440792872137df281592e82076a05c64c345ffb058c64f7f7c207ef78420b7010520610f17e302cc4dfcfaef72a0ed091aab4b541eb0531bbe941ca2f792bf7b31ca6162882b68054a8470115bc2c19f2df2023f7800432b39b04d3a304e8085ba3f1f0ca5b1ba4d38d339e6084de979cdea6d0e244c6c9fa0366bd890621e3d30846f5e8497e21597b8f29bbf52c961a485dfbea647600da0fc1f25ce4d203a8352ece310c39073525044e7ac46acf2ed9120bae1b4f6f02364abfe343f80b290983160c103557af1c68416480d024cc31b6c06cfec011456f1e95c420a12b48b1c3fe220c2879a982fb099948ac440db844b9a112a5188c7783fd3b19593290785f908d95c9db4b280bafe89c1313aeec24772046d9bc089645f0d182a21184e143823c5f52de50e5d7e98d3d7ab56f5413bbccd1415c9bcff707def475b643fb7f29842582104d4cc1dbaaca8f10a2f44273c339e0984f2b1e06ab2f0771db01fafa8142298345f3196f23e5847bda024034b6f59b11c29e981c881456e40d211929fd4f766200258aad8212016322bd5c605790dcfdf1bd2a93d99c9b8f498722d311d7eae7ff420496a31804c55f4759a7b13aaaf5f7ce006c3a8a998897d5e0a504398c2b627852545baf440798bcc5cc049357cf3f17d9771e4528a1af3d77dc794a11346e1bdf5efe37a405b127b4c43b616d61fbc5dc914e14240ef99a7400"
const rand3Hex = "1744b384d68c042371244e13500d4bfb98c6244e3d71a5b700224420b59c593553f33bd786e3d0ce31626f511bc985f59d1a88aa38ba8ad6218d306abee60dd9172540232b95be1af146c69e72e5fde667a090dc3f93bdc5c5af0ab80acdbaa7a505f628c59dc0247b31a439cacf5010a94376d71521df08c178b02fb96fdb1809144ea38c68536187c53201fea8631fb0a880b4451ccdca7cc61f6aafca21cc7449d920599db61789ac3b1e164b3390124f95022aeea39ccca3ec1053f4fa10de2978e2861ea58e477085c2220021a0927aa94c5d0006b5055abba340e4f9eba22e969978dfd18e278a8b89d877328ae34268bc0174cfe211954c0036f078025217d1269fac1932a03b05a0b616012271bbe1fb554171c7a59b196d8a4479f45a77931b5d97aaf6c0c673cbe597b79b96e2a0c1eae2e66e46ccc8c85798e23ffe972ebdaa3f6caea243c004e60321eb47cd79137d78fd0613be606feacc5b3637bdc96a89c13746db8cad886f3ccf912b2178c823bcac395f06d28080269bdca2debf3419c66c690fd1adcfbd53e32e79443d7a42511a84cb22ca94fffad9149275a075b2f8ae0b021dcde9bf62b102db920733b897560518b06e1ad7f4b03458493ddaa7f4fa2c1609f7a1735aeeb1b3e2cea3ab45fc376323cc91873b7e9c90d07c192e38d3f5dfc9bfab1fd821c854da9e607ea596c391c7ec4161c6c4493929a8176badaa5a5af7211c623f29643a937677d3df0da9266181b7c4da5dd40376db677fe8f4a1dc456adf6f33c1e37cec471dd318c2647644fe52f93707a77da7d1702380a80e14cc0fdce7bf2eed48a529090bae0388ee277ce6c7018c5fb00b88362554362205c641f0d0fab94fd5b8357b5ff08b207fee023709bc126ec90cfb17c006754638f8186aaeb1265e80be0c1189ec07d01d5f6f96cb9ce82744147d18490de7dc72862f42f024a16968891a356f5e7e0e695d8c933ba5b5e43ad4c4ade5399bc2cae9bb6189b7870d7f22956194d277f28b10e01c10c6ffe3e065f7e2d6d056aa790db5649ca84dc64c35566c0af1b68c32b5b7874aaa66467afa44f40e9a0846a07ae75360a641dd2acc69d93219b2891f190621511e62a27f5e4fbe641ece1fa234fc7e9a74f48d2a760d82160d9540f649256b169d1fed6fbefdc491126530f3cbad7913e19fbd7aa53b1e243fbf28d5f38c10ebd77c8b986775975cc1d619efb27cdcd733fa1ca36cffe9c0a33cc9f02463c91a886601fd349efee85ef1462065ef9bd2c8f533220ad93138b8382d5938103ab25b2d9af8ae106e1211eb9b18793fba033900c809c02cd6d17e2f3e6fc84dae873411f8e87c3f0a8f1765b7825d185ce3730f299c3028d4a62da9ee95c2b870fb70c79370d485f9d5d9acb78926d20444033d960524d2776dc31988ec7c0dbf23b9905d"

View File

@ -0,0 +1,223 @@
// 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 bzip2
import (
"os"
"sort"
)
// A huffmanTree is a binary tree which is navigated, bit-by-bit to reach a
// symbol.
type huffmanTree struct {
// nodes contains all the non-leaf nodes in the tree. nodes[0] is the
// root of the tree and nextNode contains the index of the next element
// of nodes to use when the tree is being constructed.
nodes []huffmanNode
nextNode int
}
// A huffmanNode is a node in the tree. left and right contain indexes into the
// nodes slice of the tree. If left or right is invalidNodeValue then the child
// is a left node and its value is in leftValue/rightValue.
//
// The symbols are uint16s because bzip2 encodes not only MTF indexes in the
// tree, but also two magic values for run-length encoding and an EOF symbol.
// Thus there are more than 256 possible symbols.
type huffmanNode struct {
left, right uint16
leftValue, rightValue uint16
}
// invalidNodeValue is an invalid index which marks a leaf node in the tree.
const invalidNodeValue = 0xffff
// Decode reads bits from the given bitReader and navigates the tree until a
// symbol is found.
func (t huffmanTree) Decode(br *bitReader) (v uint16) {
nodeIndex := uint16(0) // node 0 is the root of the tree.
for {
node := &t.nodes[nodeIndex]
bit := br.ReadBit()
// bzip2 encodes left as a true bit.
if bit {
// left
if node.left == invalidNodeValue {
return node.leftValue
}
nodeIndex = node.left
} else {
// right
if node.right == invalidNodeValue {
return node.rightValue
}
nodeIndex = node.right
}
}
panic("unreachable")
}
// newHuffmanTree builds a Huffman tree from a slice containing the code
// lengths of each symbol. The maximum code length is 32 bits.
func newHuffmanTree(lengths []uint8) (huffmanTree, os.Error) {
// There are many possible trees that assign the same code length to
// each symbol (consider reflecting a tree down the middle, for
// example). Since the code length assignments determine the
// efficiency of the tree, each of these trees is equally good. In
// order to minimise the amount of information needed to build a tree
// bzip2 uses a canonical tree so that it can be reconstructed given
// only the code length assignments.
if len(lengths) < 2 {
panic("newHuffmanTree: too few symbols")
}
var t huffmanTree
// First we sort the code length assignments by ascending code length,
// using the symbol value to break ties.
pairs := huffmanSymbolLengthPairs(make([]huffmanSymbolLengthPair, len(lengths)))
for i, length := range lengths {
pairs[i].value = uint16(i)
pairs[i].length = length
}
sort.Sort(pairs)
// Now we assign codes to the symbols, starting with the longest code.
// We keep the codes packed into a uint32, at the most-significant end.
// So branches are taken from the MSB downwards. This makes it easy to
// sort them later.
code := uint32(0)
length := uint8(32)
codes := huffmanCodes(make([]huffmanCode, len(lengths)))
for i := len(pairs) - 1; i >= 0; i-- {
if length > pairs[i].length {
// If the code length decreases we shift in order to
// zero any bits beyond the end of the code.
length >>= 32 - pairs[i].length
length <<= 32 - pairs[i].length
length = pairs[i].length
}
codes[i].code = code
codes[i].codeLen = length
codes[i].value = pairs[i].value
// We need to 'increment' the code, which means treating |code|
// like a |length| bit number.
code += 1 << (32 - length)
}
// Now we can sort by the code so that the left half of each branch are
// grouped together, recursively.
sort.Sort(codes)
t.nodes = make([]huffmanNode, len(codes))
_, err := buildHuffmanNode(&t, codes, 0)
return t, err
}
// huffmanSymbolLengthPair contains a symbol and its code length.
type huffmanSymbolLengthPair struct {
value uint16
length uint8
}
// huffmanSymbolLengthPair is used to provide an interface for sorting.
type huffmanSymbolLengthPairs []huffmanSymbolLengthPair
func (h huffmanSymbolLengthPairs) Len() int {
return len(h)
}
func (h huffmanSymbolLengthPairs) Less(i, j int) bool {
if h[i].length < h[j].length {
return true
}
if h[i].length > h[j].length {
return false
}
if h[i].value < h[j].value {
return true
}
return false
}
func (h huffmanSymbolLengthPairs) Swap(i, j int) {
h[i], h[j] = h[j], h[i]
}
// huffmanCode contains a symbol, its code and code length.
type huffmanCode struct {
code uint32
codeLen uint8
value uint16
}
// huffmanCodes is used to provide an interface for sorting.
type huffmanCodes []huffmanCode
func (n huffmanCodes) Len() int {
return len(n)
}
func (n huffmanCodes) Less(i, j int) bool {
return n[i].code < n[j].code
}
func (n huffmanCodes) Swap(i, j int) {
n[i], n[j] = n[j], n[i]
}
// buildHuffmanNode takes a slice of sorted huffmanCodes and builds a node in
// the Huffman tree at the given level. It returns the index of the newly
// constructed node.
func buildHuffmanNode(t *huffmanTree, codes []huffmanCode, level uint32) (nodeIndex uint16, err os.Error) {
test := uint32(1) << (31 - level)
// We have to search the list of codes to find the divide between the left and right sides.
firstRightIndex := len(codes)
for i, code := range codes {
if code.code&test != 0 {
firstRightIndex = i
break
}
}
left := codes[:firstRightIndex]
right := codes[firstRightIndex:]
if len(left) == 0 || len(right) == 0 {
return 0, StructuralError("superfluous level in Huffman tree")
}
nodeIndex = uint16(t.nextNode)
node := &t.nodes[t.nextNode]
t.nextNode++
if len(left) == 1 {
// leaf node
node.left = invalidNodeValue
node.leftValue = left[0].value
} else {
node.left, err = buildHuffmanNode(t, left, level+1)
}
if err != nil {
return
}
if len(right) == 1 {
// leaf node
node.right = invalidNodeValue
node.rightValue = right[0].value
} else {
node.right, err = buildHuffmanNode(t, right, level+1)
}
return
}

View File

@ -0,0 +1,105 @@
// 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 bzip2
// moveToFrontDecoder implements a move-to-front list. Such a list is an
// efficient way to transform a string with repeating elements into one with
// many small valued numbers, which is suitable for entropy encoding. It works
// by starting with an initial list of symbols and references symbols by their
// index into that list. When a symbol is referenced, it's moved to the front
// of the list. Thus, a repeated symbol ends up being encoded with many zeros,
// as the symbol will be at the front of the list after the first access.
type moveToFrontDecoder struct {
// Rather than actually keep the list in memory, the symbols are stored
// as a circular, double linked list with the symbol indexed by head
// at the front of the list.
symbols []byte
next []uint8
prev []uint8
head uint8
}
// newMTFDecoder creates a move-to-front decoder with an explicit initial list
// of symbols.
func newMTFDecoder(symbols []byte) *moveToFrontDecoder {
if len(symbols) > 256 {
panic("too many symbols")
}
m := &moveToFrontDecoder{
symbols: symbols,
next: make([]uint8, len(symbols)),
prev: make([]uint8, len(symbols)),
}
m.threadLinkedList()
return m
}
// newMTFDecoderWithRange creates a move-to-front decoder with an initial
// symbol list of 0...n-1.
func newMTFDecoderWithRange(n int) *moveToFrontDecoder {
if n > 256 {
panic("newMTFDecoderWithRange: cannot have > 256 symbols")
}
m := &moveToFrontDecoder{
symbols: make([]uint8, n),
next: make([]uint8, n),
prev: make([]uint8, n),
}
for i := 0; i < n; i++ {
m.symbols[i] = byte(i)
}
m.threadLinkedList()
return m
}
// threadLinkedList creates the initial linked-list pointers.
func (m *moveToFrontDecoder) threadLinkedList() {
if len(m.symbols) == 0 {
return
}
m.prev[0] = uint8(len(m.symbols) - 1)
for i := 0; i < len(m.symbols)-1; i++ {
m.next[i] = uint8(i + 1)
m.prev[i+1] = uint8(i)
}
m.next[len(m.symbols)-1] = 0
}
func (m *moveToFrontDecoder) Decode(n int) (b byte) {
// Most of the time, n will be zero so it's worth dealing with this
// simple case.
if n == 0 {
return m.symbols[m.head]
}
i := m.head
for j := 0; j < n; j++ {
i = m.next[i]
}
b = m.symbols[i]
m.next[m.prev[i]] = m.next[i]
m.prev[m.next[i]] = m.prev[i]
m.next[i] = m.head
m.prev[i] = m.prev[m.head]
m.next[m.prev[m.head]] = i
m.prev[m.head] = i
m.head = i
return
}
// First returns the symbol at the front of the list.
func (m *moveToFrontDecoder) First() byte {
return m.symbols[m.head]
}

View File

@ -116,9 +116,16 @@ func (b *syncBuffer) Read(p []byte) (n int, err os.Error) {
panic("unreachable")
}
func (b *syncBuffer) signal() {
select {
case b.ready <- true:
default:
}
}
func (b *syncBuffer) Write(p []byte) (n int, err os.Error) {
n, err = b.buf.Write(p)
_ = b.ready <- true
b.signal()
return
}
@ -128,12 +135,12 @@ func (b *syncBuffer) WriteMode() {
func (b *syncBuffer) ReadMode() {
b.mu.Unlock()
_ = b.ready <- true
b.signal()
}
func (b *syncBuffer) Close() os.Error {
b.closed = true
_ = b.ready <- true
b.signal()
return nil
}
@ -255,135 +262,9 @@ func TestReverseBits(t *testing.T) {
}
func TestDeflateInflateString(t *testing.T) {
gold := bytes.NewBufferString(getEdata()).Bytes()
gold, err := ioutil.ReadFile("../testdata/e.txt")
if err != nil {
t.Error(err)
}
testToFromWithLevel(t, 1, gold, "2.718281828...")
}
func getEdata() string {
return "2.718281828459045235360287471352662497757247093699959574966967627724076630353547" +
"59457138217852516642742746639193200305992181741359662904357290033429526059563073" +
"81323286279434907632338298807531952510190115738341879307021540891499348841675092" +
"44761460668082264800168477411853742345442437107539077744992069551702761838606261" +
"33138458300075204493382656029760673711320070932870912744374704723069697720931014" +
"16928368190255151086574637721112523897844250569536967707854499699679468644549059" +
"87931636889230098793127736178215424999229576351482208269895193668033182528869398" +
"49646510582093923982948879332036250944311730123819706841614039701983767932068328" +
"23764648042953118023287825098194558153017567173613320698112509961818815930416903" +
"51598888519345807273866738589422879228499892086805825749279610484198444363463244" +
"96848756023362482704197862320900216099023530436994184914631409343173814364054625" +
"31520961836908887070167683964243781405927145635490613031072085103837505101157477" +
"04171898610687396965521267154688957035035402123407849819334321068170121005627880" +
"23519303322474501585390473041995777709350366041699732972508868769664035557071622" +
"68447162560798826517871341951246652010305921236677194325278675398558944896970964" +
"09754591856956380236370162112047742722836489613422516445078182442352948636372141" +
"74023889344124796357437026375529444833799801612549227850925778256209262264832627" +
"79333865664816277251640191059004916449982893150566047258027786318641551956532442" +
"58698294695930801915298721172556347546396447910145904090586298496791287406870504" +
"89585867174798546677575732056812884592054133405392200011378630094556068816674001" +
"69842055804033637953764520304024322566135278369511778838638744396625322498506549" +
"95886234281899707733276171783928034946501434558897071942586398772754710962953741" +
"52111513683506275260232648472870392076431005958411661205452970302364725492966693" +
"81151373227536450988890313602057248176585118063036442812314965507047510254465011" +
"72721155519486685080036853228183152196003735625279449515828418829478761085263981" +
"39559900673764829224437528718462457803619298197139914756448826260390338144182326" +
"25150974827987779964373089970388867782271383605772978824125611907176639465070633" +
"04527954661855096666185664709711344474016070462621568071748187784437143698821855" +
"96709591025968620023537185887485696522000503117343920732113908032936344797273559" +
"55277349071783793421637012050054513263835440001863239914907054797780566978533580" +
"48966906295119432473099587655236812859041383241160722602998330535370876138939639" +
"17795745401613722361878936526053815584158718692553860616477983402543512843961294" +
"60352913325942794904337299085731580290958631382683291477116396337092400316894586" +
"36060645845925126994655724839186564209752685082307544254599376917041977780085362" +
"73094171016343490769642372229435236612557250881477922315197477806056967253801718" +
"07763603462459278778465850656050780844211529697521890874019660906651803516501792" +
"50461950136658543663271254963990854914420001457476081930221206602433009641270489" +
"43903971771951806990869986066365832322787093765022601492910115171776359446020232" +
"49300280401867723910288097866605651183260043688508817157238669842242201024950551" +
"88169480322100251542649463981287367765892768816359831247788652014117411091360116" +
"49950766290779436460058519419985601626479076153210387275571269925182756879893027" +
"61761146162549356495903798045838182323368612016243736569846703785853305275833337" +
"93990752166069238053369887956513728559388349989470741618155012539706464817194670" +
"83481972144888987906765037959036696724949925452790337296361626589760394985767413" +
"97359441023744329709355477982629614591442936451428617158587339746791897571211956" +
"18738578364475844842355558105002561149239151889309946342841393608038309166281881" +
"15037152849670597416256282360921680751501777253874025642534708790891372917228286" +
"11515915683725241630772254406337875931059826760944203261924285317018781772960235" +
"41306067213604600038966109364709514141718577701418060644363681546444005331608778" +
"31431744408119494229755993140118886833148328027065538330046932901157441475631399" +
"97221703804617092894579096271662260740718749975359212756084414737823303270330168" +
"23719364800217328573493594756433412994302485023573221459784328264142168487872167" +
"33670106150942434569844018733128101079451272237378861260581656680537143961278887" +
"32527373890392890506865324138062796025930387727697783792868409325365880733988457" +
"21874602100531148335132385004782716937621800490479559795929059165547050577751430" +
"81751126989851884087185640260353055837378324229241856256442550226721559802740126" +
"17971928047139600689163828665277009752767069777036439260224372841840883251848770" +
"47263844037953016690546593746161932384036389313136432713768884102681121989127522" +
"30562567562547017250863497653672886059667527408686274079128565769963137897530346" +
"60616669804218267724560530660773899624218340859882071864682623215080288286359746" +
"83965435885668550377313129658797581050121491620765676995065971534476347032085321" +
"56036748286083786568030730626576334697742956346437167093971930608769634953288468" +
"33613038829431040800296873869117066666146800015121143442256023874474325250769387" +
"07777519329994213727721125884360871583483562696166198057252661220679754062106208" +
"06498829184543953015299820925030054982570433905535701686531205264956148572492573" +
"86206917403695213533732531666345466588597286659451136441370331393672118569553952" +
"10845840724432383558606310680696492485123263269951460359603729725319836842336390" +
"46321367101161928217111502828016044880588023820319814930963695967358327420249882" +
"45684941273860566491352526706046234450549227581151709314921879592718001940968866" +
"98683703730220047531433818109270803001720593553052070070607223399946399057131158" +
"70996357773590271962850611465148375262095653467132900259943976631145459026858989" +
"79115837093419370441155121920117164880566945938131183843765620627846310490346293" +
"95002945834116482411496975832601180073169943739350696629571241027323913874175492" +
"30718624545432220395527352952402459038057445028922468862853365422138157221311632" +
"88112052146489805180092024719391710555390113943316681515828843687606961102505171" +
"00739276238555338627255353883096067164466237092264680967125406186950214317621166" +
"81400975952814939072226011126811531083873176173232352636058381731510345957365382" +
"23534992935822836851007810884634349983518404451704270189381994243410090575376257" +
"76757111809008816418331920196262341628816652137471732547772778348877436651882875" +
"21566857195063719365653903894493664217640031215278702223664636357555035655769488" +
"86549500270853923617105502131147413744106134445544192101336172996285694899193369" +
"18472947858072915608851039678195942983318648075608367955149663644896559294818785" +
"17840387733262470519450504198477420141839477312028158868457072905440575106012852" +
"58056594703046836344592652552137008068752009593453607316226118728173928074623094" +
"68536782310609792159936001994623799343421068781349734695924646975250624695861690" +
"91785739765951993929939955675427146549104568607020990126068187049841780791739240" +
"71945996323060254707901774527513186809982284730860766536866855516467702911336827" +
"56310722334672611370549079536583453863719623585631261838715677411873852772292259" +
"47433737856955384562468010139057278710165129666367644518724656537304024436841408" +
"14488732957847348490003019477888020460324660842875351848364959195082888323206522" +
"12810419044804724794929134228495197002260131043006241071797150279343326340799596" +
"05314460532304885289729176598760166678119379323724538572096075822771784833616135" +
"82612896226118129455927462767137794487586753657544861407611931125958512655759734" +
"57301533364263076798544338576171533346232527057200530398828949903425956623297578" +
"24887350292591668258944568946559926584547626945287805165017206747854178879822768" +
"06536650641910973434528878338621726156269582654478205672987756426325321594294418" +
"03994321700009054265076309558846589517170914760743713689331946909098190450129030" +
"70995662266203031826493657336984195557769637876249188528656866076005660256054457" +
"11337286840205574416030837052312242587223438854123179481388550075689381124935386" +
"31863528708379984569261998179452336408742959118074745341955142035172618420084550" +
"91708456823682008977394558426792142734775608796442792027083121501564063413416171" +
"66448069815483764491573900121217041547872591998943825364950514771379399147205219" +
"52907939613762110723849429061635760459623125350606853765142311534966568371511660" +
"42207963944666211632551577290709784731562782775987881364919512574833287937715714" +
"59091064841642678309949723674420175862269402159407924480541255360431317992696739" +
"15754241929660731239376354213923061787675395871143610408940996608947141834069836" +
"29936753626215452472984642137528910798843813060955526227208375186298370667872244" +
"30195793793786072107254277289071732854874374355781966511716618330881129120245204" +
"04868220007234403502544820283425418788465360259150644527165770004452109773558589" +
"76226554849416217149895323834216001140629507184904277892585527430352213968356790" +
"18076406042138307308774460170842688272261177180842664333651780002171903449234264" +
"26629226145600433738386833555534345300426481847398921562708609565062934040526494" +
"32442614456659212912256488935696550091543064261342526684725949143142393988454324" +
"86327461842846655985332312210466259890141712103446084271616619001257195870793217" +
"56969854401339762209674945418540711844643394699016269835160784892451405894094639" +
"52678073545797003070511636825194877011897640028276484141605872061841852971891540" +
"19688253289309149665345753571427318482016384644832499037886069008072709327673127" +
"58196656394114896171683298045513972950668760474091542042842999354102582911350224" +
"16907694316685742425225090269390348148564513030699251995904363840284292674125734" +
"22447765584177886171737265462085498294498946787350929581652632072258992368768457" +
"01782303809656788311228930580914057261086588484587310165815116753332767488701482" +
"91674197015125597825727074064318086014281490241467804723275976842696339357735429" +
"30186739439716388611764209004068663398856841681003872389214483176070116684503887" +
"21236436704331409115573328018297798873659091665961240202177855885487617616198937" +
"07943800566633648843650891448055710397652146960276625835990519870423001794655367" +
"9"
}

View File

@ -0,0 +1,210 @@
// 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.
// The lzw package implements the Lempel-Ziv-Welch compressed data format,
// described in T. A. Welch, ``A Technique for High-Performance Data
// Compression'', Computer, 17(6) (June 1984), pp 8-19.
//
// In particular, it implements LZW as used by the GIF, TIFF and PDF file
// formats, which means variable-width codes up to 12 bits and the first
// two non-literal codes are a clear code and an EOF code.
package lzw
// TODO(nigeltao): check that TIFF and PDF use LZW in the same way as GIF,
// modulo LSB/MSB packing order.
import (
"bufio"
"fmt"
"io"
"os"
)
// Order specifies the bit ordering in an LZW data stream.
type Order int
const (
// LSB means Least Significant Bits first, as used in the GIF file format.
LSB Order = iota
// MSB means Most Significant Bits first, as used in the TIFF and PDF
// file formats.
MSB
)
// decoder is the state from which the readXxx method converts a byte
// stream into a code stream.
type decoder struct {
r io.ByteReader
bits uint32
nBits uint
width uint
}
// readLSB returns the next code for "Least Significant Bits first" data.
func (d *decoder) readLSB() (uint16, os.Error) {
for d.nBits < d.width {
x, err := d.r.ReadByte()
if err != nil {
return 0, err
}
d.bits |= uint32(x) << d.nBits
d.nBits += 8
}
code := uint16(d.bits & (1<<d.width - 1))
d.bits >>= d.width
d.nBits -= d.width
return code, nil
}
// readMSB returns the next code for "Most Significant Bits first" data.
func (d *decoder) readMSB() (uint16, os.Error) {
for d.nBits < d.width {
x, err := d.r.ReadByte()
if err != nil {
return 0, err
}
d.bits |= uint32(x) << (24 - d.nBits)
d.nBits += 8
}
code := uint16(d.bits >> (32 - d.width))
d.bits <<= d.width
d.nBits -= d.width
return code, nil
}
// decode decompresses bytes from r and writes them to pw.
// read specifies how to decode bytes into codes.
// litWidth is the width in bits of literal codes.
func decode(r io.Reader, read func(*decoder) (uint16, os.Error), litWidth int, pw *io.PipeWriter) {
br, ok := r.(io.ByteReader)
if !ok {
br = bufio.NewReader(r)
}
pw.CloseWithError(decode1(pw, br, read, uint(litWidth)))
}
func decode1(pw *io.PipeWriter, r io.ByteReader, read func(*decoder) (uint16, os.Error), litWidth uint) os.Error {
const (
maxWidth = 12
invalidCode = 0xffff
)
d := decoder{r, 0, 0, 1 + litWidth}
w := bufio.NewWriter(pw)
// The first 1<<litWidth codes are literal codes.
// The next two codes mean clear and EOF.
// Other valid codes are in the range [lo, hi] where lo := clear + 2,
// with the upper bound incrementing on each code seen.
clear := uint16(1) << litWidth
eof, hi := clear+1, clear+1
// overflow is the code at which hi overflows the code width.
overflow := uint16(1) << d.width
var (
// Each code c in [lo, hi] expands to two or more bytes. For c != hi:
// suffix[c] is the last of these bytes.
// prefix[c] is the code for all but the last byte.
// This code can either be a literal code or another code in [lo, c).
// The c == hi case is a special case.
suffix [1 << maxWidth]uint8
prefix [1 << maxWidth]uint16
// buf is a scratch buffer for reconstituting the bytes that a code expands to.
// Code suffixes are written right-to-left from the end of the buffer.
buf [1 << maxWidth]byte
)
// Loop over the code stream, converting codes into decompressed bytes.
last := uint16(invalidCode)
for {
code, err := read(&d)
if err != nil {
if err == os.EOF {
err = io.ErrUnexpectedEOF
}
return err
}
switch {
case code < clear:
// We have a literal code.
if err := w.WriteByte(uint8(code)); err != nil {
return err
}
if last != invalidCode {
// Save what the hi code expands to.
suffix[hi] = uint8(code)
prefix[hi] = last
}
case code == clear:
d.width = 1 + litWidth
hi = eof
overflow = 1 << d.width
last = invalidCode
continue
case code == eof:
return w.Flush()
case code <= hi:
c, i := code, len(buf)-1
if code == hi {
// code == hi is a special case which expands to the last expansion
// followed by the head of the last expansion. To find the head, we walk
// the prefix chain until we find a literal code.
c = last
for c >= clear {
c = prefix[c]
}
buf[i] = uint8(c)
i--
c = last
}
// Copy the suffix chain into buf and then write that to w.
for c >= clear {
buf[i] = suffix[c]
i--
c = prefix[c]
}
buf[i] = uint8(c)
if _, err := w.Write(buf[i:]); err != nil {
return err
}
// Save what the hi code expands to.
suffix[hi] = uint8(c)
prefix[hi] = last
default:
return os.NewError("lzw: invalid code")
}
last, hi = code, hi+1
if hi == overflow {
if d.width == maxWidth {
return os.NewError("lzw: missing clear code")
}
d.width++
overflow <<= 1
}
}
panic("unreachable")
}
// NewReader creates a new io.ReadCloser that satisfies reads by decompressing
// the data read from r.
// It is the caller's responsibility to call Close on the ReadCloser when
// finished reading.
// The number of bits to use for literal codes, litWidth, must be in the
// range [2,8] and is typically 8.
func NewReader(r io.Reader, order Order, litWidth int) io.ReadCloser {
pr, pw := io.Pipe()
var read func(*decoder) (uint16, os.Error)
switch order {
case LSB:
read = (*decoder).readLSB
case MSB:
read = (*decoder).readMSB
default:
pw.CloseWithError(os.NewError("lzw: unknown order"))
return pr
}
if litWidth < 2 || 8 < litWidth {
pw.CloseWithError(fmt.Errorf("lzw: litWidth %d out of range", litWidth))
return pr
}
go decode(r, read, litWidth, pw)
return pr
}

View File

@ -0,0 +1,132 @@
// 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 lzw
import (
"bytes"
"io"
"io/ioutil"
"os"
"strconv"
"strings"
"testing"
)
type lzwTest struct {
desc string
raw string
compressed string
err os.Error
}
var lzwTests = []lzwTest{
{
"empty;LSB;8",
"",
"\x01\x01",
nil,
},
{
"empty;MSB;8",
"",
"\x80\x80",
nil,
},
{
"tobe;LSB;7",
"TOBEORNOTTOBEORTOBEORNOT",
"\x54\x4f\x42\x45\x4f\x52\x4e\x4f\x54\x82\x84\x86\x8b\x85\x87\x89\x81",
nil,
},
{
"tobe;LSB;8",
"TOBEORNOTTOBEORTOBEORNOT",
"\x54\x9e\x08\x29\xf2\x44\x8a\x93\x27\x54\x04\x12\x34\xb8\xb0\xe0\xc1\x84\x01\x01",
nil,
},
{
"tobe;MSB;7",
"TOBEORNOTTOBEORTOBEORNOT",
"\x54\x4f\x42\x45\x4f\x52\x4e\x4f\x54\x82\x84\x86\x8b\x85\x87\x89\x81",
nil,
},
{
"tobe;MSB;8",
"TOBEORNOTTOBEORTOBEORNOT",
"\x2a\x13\xc8\x44\x52\x79\x48\x9c\x4f\x2a\x40\xa0\x90\x68\x5c\x16\x0f\x09\x80\x80",
nil,
},
{
"tobe-truncated;LSB;8",
"TOBEORNOTTOBEORTOBEORNOT",
"\x54\x9e\x08\x29\xf2\x44\x8a\x93\x27\x54\x04",
io.ErrUnexpectedEOF,
},
// This example comes from http://en.wikipedia.org/wiki/Graphics_Interchange_Format.
{
"gif;LSB;8",
"\x28\xff\xff\xff\x28\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff",
"\x00\x51\xfc\x1b\x28\x70\xa0\xc1\x83\x01\x01",
nil,
},
// This example comes from http://compgroups.net/comp.lang.ruby/Decompressing-LZW-compression-from-PDF-file
{
"pdf;MSB;8",
"-----A---B",
"\x80\x0b\x60\x50\x22\x0c\x0c\x85\x01",
nil,
},
}
func TestReader(t *testing.T) {
b := bytes.NewBuffer(nil)
for _, tt := range lzwTests {
d := strings.Split(tt.desc, ";", -1)
var order Order
switch d[1] {
case "LSB":
order = LSB
case "MSB":
order = MSB
default:
t.Errorf("%s: bad order %q", tt.desc, d[1])
}
litWidth, _ := strconv.Atoi(d[2])
rc := NewReader(strings.NewReader(tt.compressed), order, litWidth)
defer rc.Close()
b.Reset()
n, err := io.Copy(b, rc)
if err != nil {
if err != tt.err {
t.Errorf("%s: io.Copy: %v want %v", tt.desc, err, tt.err)
}
continue
}
s := b.String()
if s != tt.raw {
t.Errorf("%s: got %d-byte %q want %d-byte %q", tt.desc, n, s, len(tt.raw), tt.raw)
}
}
}
type devNull struct{}
func (devNull) Write(p []byte) (int, os.Error) {
return len(p), nil
}
func BenchmarkDecoder(b *testing.B) {
b.StopTimer()
buf0, _ := ioutil.ReadFile("../testdata/e.txt")
compressed := bytes.NewBuffer(nil)
w := NewWriter(compressed, LSB, 8)
io.Copy(w, bytes.NewBuffer(buf0))
w.Close()
buf1 := compressed.Bytes()
b.StartTimer()
for i := 0; i < b.N; i++ {
io.Copy(devNull{}, NewReader(bytes.NewBuffer(buf1), LSB, 8))
}
}

View File

@ -0,0 +1,259 @@
// 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 lzw
import (
"bufio"
"fmt"
"io"
"os"
)
// A writer is a buffered, flushable writer.
type writer interface {
WriteByte(byte) os.Error
Flush() os.Error
}
// An errWriteCloser is an io.WriteCloser that always returns a given error.
type errWriteCloser struct {
err os.Error
}
func (e *errWriteCloser) Write([]byte) (int, os.Error) {
return 0, e.err
}
func (e *errWriteCloser) Close() os.Error {
return e.err
}
const (
// A code is a 12 bit value, stored as a uint32 when encoding to avoid
// type conversions when shifting bits.
maxCode = 1<<12 - 1
invalidCode = 1<<32 - 1
// There are 1<<12 possible codes, which is an upper bound on the number of
// valid hash table entries at any given point in time. tableSize is 4x that.
tableSize = 4 * 1 << 12
tableMask = tableSize - 1
// A hash table entry is a uint32. Zero is an invalid entry since the
// lower 12 bits of a valid entry must be a non-literal code.
invalidEntry = 0
)
// encoder is LZW compressor.
type encoder struct {
// w is the writer that compressed bytes are written to.
w writer
// write, bits, nBits and width are the state for converting a code stream
// into a byte stream.
write func(*encoder, uint32) os.Error
bits uint32
nBits uint
width uint
// litWidth is the width in bits of literal codes.
litWidth uint
// hi is the code implied by the next code emission.
// overflow is the code at which hi overflows the code width.
hi, overflow uint32
// savedCode is the accumulated code at the end of the most recent Write
// call. It is equal to invalidCode if there was no such call.
savedCode uint32
// err is the first error encountered during writing. Closing the encoder
// will make any future Write calls return os.EINVAL.
err os.Error
// table is the hash table from 20-bit keys to 12-bit values. Each table
// entry contains key<<12|val and collisions resolve by linear probing.
// The keys consist of a 12-bit code prefix and an 8-bit byte suffix.
// The values are a 12-bit code.
table [tableSize]uint32
}
// writeLSB writes the code c for "Least Significant Bits first" data.
func (e *encoder) writeLSB(c uint32) os.Error {
e.bits |= c << e.nBits
e.nBits += e.width
for e.nBits >= 8 {
if err := e.w.WriteByte(uint8(e.bits)); err != nil {
return err
}
e.bits >>= 8
e.nBits -= 8
}
return nil
}
// writeMSB writes the code c for "Most Significant Bits first" data.
func (e *encoder) writeMSB(c uint32) os.Error {
e.bits |= c << (32 - e.width - e.nBits)
e.nBits += e.width
for e.nBits >= 8 {
if err := e.w.WriteByte(uint8(e.bits >> 24)); err != nil {
return err
}
e.bits <<= 8
e.nBits -= 8
}
return nil
}
// errOutOfCodes is an internal error that means that the encoder has run out
// of unused codes and a clear code needs to be sent next.
var errOutOfCodes = os.NewError("lzw: out of codes")
// incHi increments e.hi and checks for both overflow and running out of
// unused codes. In the latter case, incHi sends a clear code, resets the
// encoder state and returns errOutOfCodes.
func (e *encoder) incHi() os.Error {
e.hi++
if e.hi == e.overflow {
e.width++
e.overflow <<= 1
}
if e.hi == maxCode {
clear := uint32(1) << e.litWidth
if err := e.write(e, clear); err != nil {
return err
}
e.width = uint(e.litWidth) + 1
e.hi = clear + 1
e.overflow = clear << 1
for i := range e.table {
e.table[i] = invalidEntry
}
return errOutOfCodes
}
return nil
}
// Write writes a compressed representation of p to e's underlying writer.
func (e *encoder) Write(p []byte) (int, os.Error) {
if e.err != nil {
return 0, e.err
}
if len(p) == 0 {
return 0, nil
}
litMask := uint32(1<<e.litWidth - 1)
code := e.savedCode
if code == invalidCode {
// The first code sent is always a literal code.
code, p = uint32(p[0])&litMask, p[1:]
}
loop:
for _, x := range p {
literal := uint32(x) & litMask
key := code<<8 | literal
// If there is a hash table hit for this key then we continue the loop
// and do not emit a code yet.
hash := (key>>12 ^ key) & tableMask
for h, t := hash, e.table[hash]; t != invalidEntry; {
if key == t>>12 {
code = t & maxCode
continue loop
}
h = (h + 1) & tableMask
t = e.table[h]
}
// Otherwise, write the current code, and literal becomes the start of
// the next emitted code.
if e.err = e.write(e, code); e.err != nil {
return 0, e.err
}
code = literal
// Increment e.hi, the next implied code. If we run out of codes, reset
// the encoder state (including clearing the hash table) and continue.
if err := e.incHi(); err != nil {
if err == errOutOfCodes {
continue
}
e.err = err
return 0, e.err
}
// Otherwise, insert key -> e.hi into the map that e.table represents.
for {
if e.table[hash] == invalidEntry {
e.table[hash] = (key << 12) | e.hi
break
}
hash = (hash + 1) & tableMask
}
}
e.savedCode = code
return len(p), nil
}
// Close closes the encoder, flushing any pending output. It does not close or
// flush e's underlying writer.
func (e *encoder) Close() os.Error {
if e.err != nil {
if e.err == os.EINVAL {
return nil
}
return e.err
}
// Make any future calls to Write return os.EINVAL.
e.err = os.EINVAL
// Write the savedCode if valid.
if e.savedCode != invalidCode {
if err := e.write(e, e.savedCode); err != nil {
return err
}
if err := e.incHi(); err != nil && err != errOutOfCodes {
return err
}
}
// Write the eof code.
eof := uint32(1)<<e.litWidth + 1
if err := e.write(e, eof); err != nil {
return err
}
// Write the final bits.
if e.nBits > 0 {
if e.write == (*encoder).writeMSB {
e.bits >>= 24
}
if err := e.w.WriteByte(uint8(e.bits)); err != nil {
return err
}
}
return e.w.Flush()
}
// NewWriter creates a new io.WriteCloser that satisfies writes by compressing
// the data and writing it to w.
// It is the caller's responsibility to call Close on the WriteCloser when
// finished writing.
// The number of bits to use for literal codes, litWidth, must be in the
// range [2,8] and is typically 8.
func NewWriter(w io.Writer, order Order, litWidth int) io.WriteCloser {
var write func(*encoder, uint32) os.Error
switch order {
case LSB:
write = (*encoder).writeLSB
case MSB:
write = (*encoder).writeMSB
default:
return &errWriteCloser{os.NewError("lzw: unknown order")}
}
if litWidth < 2 || 8 < litWidth {
return &errWriteCloser{fmt.Errorf("lzw: litWidth %d out of range", litWidth)}
}
bw, ok := w.(writer)
if !ok {
bw = bufio.NewWriter(w)
}
lw := uint(litWidth)
return &encoder{
w: bw,
write: write,
width: 1 + lw,
litWidth: lw,
hi: 1<<lw + 1,
overflow: 1 << (lw + 1),
savedCode: invalidCode,
}
}

View File

@ -0,0 +1,111 @@
// 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 lzw
import (
"io"
"io/ioutil"
"os"
"testing"
)
var filenames = []string{
"../testdata/e.txt",
"../testdata/pi.txt",
}
// testFile tests that compressing and then decompressing the given file with
// 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)
if err != nil {
t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err)
return
}
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)
if err != nil {
t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err)
return
}
piper, pipew := io.Pipe()
defer piper.Close()
go func() {
defer raw.Close()
defer pipew.Close()
lzww := NewWriter(pipew, order, litWidth)
defer lzww.Close()
var b [4096]byte
for {
n, err0 := raw.Read(b[:])
if err0 != nil && err0 != os.EOF {
t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err0)
return
}
_, err1 := lzww.Write(b[:n])
if err1 == os.EPIPE {
// Fail, but do not report the error, as some other (presumably reportable) error broke the pipe.
return
}
if err1 != nil {
t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err1)
return
}
if err0 == os.EOF {
break
}
}
}()
lzwr := NewReader(piper, order, litWidth)
defer lzwr.Close()
// Compare the two.
b0, err0 := ioutil.ReadAll(golden)
b1, err1 := ioutil.ReadAll(lzwr)
if err0 != nil {
t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err0)
return
}
if err1 != nil {
t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err1)
return
}
if len(b0) != len(b1) {
t.Errorf("%s (order=%d litWidth=%d): length mismatch %d versus %d", fn, order, litWidth, len(b0), len(b1))
return
}
for i := 0; i < len(b0); i++ {
if b0[i] != b1[i] {
t.Errorf("%s (order=%d litWidth=%d): mismatch at %d, 0x%02x versus 0x%02x\n", fn, order, litWidth, i, b0[i], b1[i])
return
}
}
}
func TestWriter(t *testing.T) {
for _, filename := range filenames {
for _, order := range [...]Order{LSB, MSB} {
// The test data "2.71828 etcetera" is ASCII text requiring at least 6 bits.
for _, litWidth := range [...]int{6, 7, 8} {
testFile(t, filename, order, litWidth)
}
}
}
}
func BenchmarkEncoder(b *testing.B) {
b.StopTimer()
buf, _ := ioutil.ReadFile("../testdata/e.txt")
b.StartTimer()
for i := 0; i < b.N; i++ {
w := NewWriter(devNull{}, LSB, 8)
w.Write(buf)
w.Close()
}
}

1
libgo/go/compress/testdata/e.txt vendored Normal file

File diff suppressed because one or more lines are too long

1
libgo/go/compress/testdata/pi.txt vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -12,8 +12,8 @@ import (
)
var filenames = []string{
"testdata/e.txt",
"testdata/pi.txt",
"../testdata/e.txt",
"../testdata/pi.txt",
}
// Tests that compressing and then decompressing the given file at the given compression level

View File

@ -138,16 +138,13 @@ func (r *Ring) Len() int {
}
func (r *Ring) Iter() <-chan interface{} {
c := make(chan interface{})
go func() {
if r != nil {
c <- r.Value
for p := r.Next(); p != r; p = p.next {
c <- p.Value
}
// Do calls function f on each element of the ring, in forward order.
// The behavior of Do is undefined if f changes *r.
func (r *Ring) Do(f func(interface{})) {
if r != nil {
f(r.Value)
for p := r.Next(); p != r; p = p.next {
f(p.Value)
}
close(c)
}()
return c
}
}

View File

@ -35,12 +35,12 @@ func verify(t *testing.T, r *Ring, N int, sum int) {
// iteration
n = 0
s := 0
for p := range r.Iter() {
r.Do(func(p interface{}) {
n++
if p != nil {
s += p.(int)
}
}
})
if n != N {
t.Errorf("number of forward iterations == %d; expected %d", n, N)
}
@ -128,16 +128,6 @@ func makeN(n int) *Ring {
return r
}
func sum(r *Ring) int {
s := 0
for p := range r.Iter() {
s += p.(int)
}
return s
}
func sumN(n int) int { return (n*n + n) / 2 }

View File

@ -12,11 +12,21 @@ type ocfbEncrypter struct {
outUsed int
}
// An OCFBResyncOption determines if the "resynchronization step" of OCFB is
// performed.
type OCFBResyncOption bool
const (
OCFBResync OCFBResyncOption = true
OCFBNoResync OCFBResyncOption = false
)
// NewOCFBEncrypter returns a Stream which encrypts data with OpenPGP's cipher
// feedback mode using the given Block, and an initial amount of ciphertext.
// randData must be random bytes and be the same length as the Block's block
// size.
func NewOCFBEncrypter(block Block, randData []byte) (Stream, []byte) {
// size. Resync determines if the "resynchronization step" from RFC 4880, 13.9
// step 7 is performed. Different parts of OpenPGP vary on this point.
func NewOCFBEncrypter(block Block, randData []byte, resync OCFBResyncOption) (Stream, []byte) {
blockSize := block.BlockSize()
if len(randData) != blockSize {
return nil, nil
@ -38,7 +48,13 @@ func NewOCFBEncrypter(block Block, randData []byte) (Stream, []byte) {
prefix[blockSize] = x.fre[0] ^ randData[blockSize-2]
prefix[blockSize+1] = x.fre[1] ^ randData[blockSize-1]
block.Encrypt(x.fre, prefix[2:])
if resync {
block.Encrypt(x.fre, prefix[2:])
} else {
x.fre[0] = prefix[blockSize]
x.fre[1] = prefix[blockSize+1]
x.outUsed = 2
}
return x, prefix
}
@ -64,8 +80,10 @@ type ocfbDecrypter struct {
// NewOCFBDecrypter returns a Stream which decrypts data with OpenPGP's cipher
// feedback mode using the given Block. Prefix must be the first blockSize + 2
// bytes of the ciphertext, where blockSize is the Block's block size. If an
// incorrect key is detected then nil is returned.
func NewOCFBDecrypter(block Block, prefix []byte) Stream {
// incorrect key is detected then nil is returned. Resync determines if the
// "resynchronization step" from RFC 4880, 13.9 step 7 is performed. Different
// parts of OpenPGP vary on this point.
func NewOCFBDecrypter(block Block, prefix []byte, resync OCFBResyncOption) Stream {
blockSize := block.BlockSize()
if len(prefix) != blockSize+2 {
return nil
@ -93,7 +111,13 @@ func NewOCFBDecrypter(block Block, prefix []byte) Stream {
return nil
}
block.Encrypt(x.fre, prefix[2:])
if resync {
block.Encrypt(x.fre, prefix[2:])
} else {
x.fre[0] = prefix[blockSize]
x.fre[1] = prefix[blockSize+1]
x.outUsed = 2
}
return x
}

View File

@ -11,29 +11,34 @@ import (
"testing"
)
func TestOCFB(t *testing.T) {
func testOCFB(t *testing.T, resync OCFBResyncOption) {
block, err := aes.NewCipher(commonKey128)
if err != nil {
t.Error(err)
return
}
plaintext := []byte("this is the plaintext")
plaintext := []byte("this is the plaintext, which is long enough to span several blocks.")
randData := make([]byte, block.BlockSize())
rand.Reader.Read(randData)
ocfb, prefix := NewOCFBEncrypter(block, randData)
ocfb, prefix := NewOCFBEncrypter(block, randData, resync)
ciphertext := make([]byte, len(plaintext))
ocfb.XORKeyStream(ciphertext, plaintext)
ocfbdec := NewOCFBDecrypter(block, prefix)
ocfbdec := NewOCFBDecrypter(block, prefix, resync)
if ocfbdec == nil {
t.Error("NewOCFBDecrypter failed")
t.Errorf("NewOCFBDecrypter failed (resync: %t)", resync)
return
}
plaintextCopy := make([]byte, len(plaintext))
ocfbdec.XORKeyStream(plaintextCopy, ciphertext)
if !bytes.Equal(plaintextCopy, plaintext) {
t.Errorf("got: %x, want: %x", plaintextCopy, plaintext)
t.Errorf("got: %x, want: %x (resync: %t)", plaintextCopy, plaintext, resync)
}
}
func TestOCFB(t *testing.T) {
testOCFB(t, OCFBNoResync)
testOCFB(t, OCFBResync)
}

73
libgo/go/crypto/crypto.go Normal file
View File

@ -0,0 +1,73 @@
// 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.
// The crypto package collects common cryptographic constants.
package crypto
import (
"hash"
)
// Hash identifies a cryptographic hash function that is implemented in another
// package.
type Hash uint
const (
MD4 Hash = 1 + iota // in package crypto/md4
MD5 // in package crypto/md5
SHA1 // in package crypto/sha1
SHA224 // in package crypto/sha256
SHA256 // in package crypto/sha256
SHA384 // in package crypto/sha512
SHA512 // in package crypto/sha512
MD5SHA1 // no implementation; MD5+SHA1 used for TLS RSA
RIPEMD160 // in package crypto/ripemd160
maxHash
)
var digestSizes = []uint8{
MD4: 16,
MD5: 16,
SHA1: 20,
SHA224: 28,
SHA256: 32,
SHA384: 48,
SHA512: 64,
MD5SHA1: 36,
RIPEMD160: 20,
}
// Size returns the length, in bytes, of a digest resulting from the given hash
// function. It doesn't require that the hash function in question be linked
// into the program.
func (h Hash) Size() int {
if h > 0 && h < maxHash {
return int(digestSizes[h])
}
panic("crypto: Size of unknown hash function")
}
var hashes = make([]func() hash.Hash, maxHash)
// New returns a new hash.Hash calculating the given hash function. If the
// hash function is not linked into the binary, New returns nil.
func (h Hash) New() hash.Hash {
if h > 0 && h < maxHash {
f := hashes[h]
if f != nil {
return f()
}
}
return nil
}
// RegisterHash registers a function that returns a new instance of the given
// hash function. This is intended to be called from the init function in
// packages that implement hash functions.
func RegisterHash(h Hash, f func() hash.Hash) {
if h >= maxHash {
panic("crypto: RegisterHash of unknown hash function")
}
hashes[h] = f
}

276
libgo/go/crypto/dsa/dsa.go Normal file
View File

@ -0,0 +1,276 @@
// 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 dsa implements the Digital Signature Algorithm, as defined in FIPS 186-3
package dsa
import (
"big"
"io"
"os"
)
// Parameters represents the domain parameters for a key. These parameters can
// be shared across many keys. The bit length of Q must be a multiple of 8.
type Parameters struct {
P, Q, G *big.Int
}
// PublicKey represents a DSA public key.
type PublicKey struct {
Parameters
Y *big.Int
}
// PrivateKey represents a DSA private key.
type PrivateKey struct {
PublicKey
X *big.Int
}
type invalidPublicKeyError int
func (invalidPublicKeyError) String() string {
return "crypto/dsa: invalid public key"
}
// InvalidPublicKeyError results when a public key is not usable by this code.
// FIPS is quite strict about the format of DSA keys, but other code may be
// less so. Thus, when using keys which may have been generated by other code,
// this error must be handled.
var InvalidPublicKeyError = invalidPublicKeyError(0)
// ParameterSizes is a enumeration of the acceptable bit lengths of the primes
// in a set of DSA parameters. See FIPS 186-3, section 4.2.
type ParameterSizes int
const (
L1024N160 ParameterSizes = iota
L2048N224
L2048N256
L3072N256
)
// numMRTests is the number of Miller-Rabin primality tests that we perform. We
// pick the largest recommended number from table C.1 of FIPS 186-3.
const numMRTests = 64
// GenerateParameters puts a random, valid set of DSA parameters into params.
// This function takes many seconds, even on fast machines.
func GenerateParameters(params *Parameters, rand io.Reader, sizes ParameterSizes) (err os.Error) {
// This function doesn't follow FIPS 186-3 exactly in that it doesn't
// use a verification seed to generate the primes. The verification
// seed doesn't appear to be exported or used by other code and
// omitting it makes the code cleaner.
var L, N int
switch sizes {
case L1024N160:
L = 1024
N = 160
case L2048N224:
L = 2048
N = 224
case L2048N256:
L = 2048
N = 256
case L3072N256:
L = 3072
N = 256
default:
return os.ErrorString("crypto/dsa: invalid ParameterSizes")
}
qBytes := make([]byte, N/8)
pBytes := make([]byte, L/8)
q := new(big.Int)
p := new(big.Int)
rem := new(big.Int)
one := new(big.Int)
one.SetInt64(1)
GeneratePrimes:
for {
_, err = io.ReadFull(rand, qBytes)
if err != nil {
return
}
qBytes[len(qBytes)-1] |= 1
qBytes[0] |= 0x80
q.SetBytes(qBytes)
if !big.ProbablyPrime(q, numMRTests) {
continue
}
for i := 0; i < 4*L; i++ {
_, err = io.ReadFull(rand, pBytes)
if err != nil {
return
}
pBytes[len(pBytes)-1] |= 1
pBytes[0] |= 0x80
p.SetBytes(pBytes)
rem.Mod(p, q)
rem.Sub(rem, one)
p.Sub(p, rem)
if p.BitLen() < L {
continue
}
if !big.ProbablyPrime(p, numMRTests) {
continue
}
params.P = p
params.Q = q
break GeneratePrimes
}
}
h := new(big.Int)
h.SetInt64(2)
g := new(big.Int)
pm1 := new(big.Int).Sub(p, one)
e := new(big.Int).Div(pm1, q)
for {
g.Exp(h, e, p)
if g.Cmp(one) == 0 {
h.Add(h, one)
continue
}
params.G = g
return
}
panic("unreachable")
}
// GenerateKey generates a public&private key pair. The Parameters of the
// PrivateKey must already be valid (see GenerateParameters).
func GenerateKey(priv *PrivateKey, rand io.Reader) os.Error {
if priv.P == nil || priv.Q == nil || priv.G == nil {
return os.ErrorString("crypto/dsa: parameters not set up before generating key")
}
x := new(big.Int)
xBytes := make([]byte, priv.Q.BitLen()/8)
for {
_, err := io.ReadFull(rand, xBytes)
if err != nil {
return err
}
x.SetBytes(xBytes)
if x.Sign() != 0 && x.Cmp(priv.Q) < 0 {
break
}
}
priv.X = x
priv.Y = new(big.Int)
priv.Y.Exp(priv.G, x, priv.P)
return nil
}
// Sign signs an arbitrary length hash (which should be the result of hashing a
// larger message) using the private key, priv. It returns the signature as a
// pair of integers. The security of the private key depends on the entropy of
// rand.
func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err os.Error) {
// FIPS 186-3, section 4.6
n := priv.Q.BitLen()
if n&7 != 0 {
err = InvalidPublicKeyError
return
}
n >>= 3
for {
k := new(big.Int)
buf := make([]byte, n)
for {
_, err = io.ReadFull(rand, buf)
if err != nil {
return
}
k.SetBytes(buf)
if k.Sign() > 0 && k.Cmp(priv.Q) < 0 {
break
}
}
kInv := new(big.Int).ModInverse(k, priv.Q)
r = new(big.Int).Exp(priv.G, k, priv.P)
r.Mod(r, priv.Q)
if r.Sign() == 0 {
continue
}
if n > len(hash) {
n = len(hash)
}
z := k.SetBytes(hash[:n])
s = new(big.Int).Mul(priv.X, r)
s.Add(s, z)
s.Mod(s, priv.Q)
s.Mul(s, kInv)
s.Mod(s, priv.Q)
if s.Sign() != 0 {
break
}
}
return
}
// Verify verifies the signature in r, s of hash using the public key, pub. It
// returns true iff the signature is valid.
func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
// FIPS 186-3, section 4.7
if r.Sign() < 1 || r.Cmp(pub.Q) >= 0 {
return false
}
if s.Sign() < 1 || s.Cmp(pub.Q) >= 0 {
return false
}
w := new(big.Int).ModInverse(s, pub.Q)
n := pub.Q.BitLen()
if n&7 != 0 {
return false
}
n >>= 3
if n > len(hash) {
n = len(hash)
}
z := new(big.Int).SetBytes(hash[:n])
u1 := new(big.Int).Mul(z, w)
u1.Mod(u1, pub.Q)
u2 := w.Mul(r, w)
u2.Mod(u2, pub.Q)
v := u1.Exp(pub.G, u1, pub.P)
u2.Exp(pub.Y, u2, pub.P)
v.Mul(v, u2)
v.Mod(v, pub.P)
v.Mod(v, pub.Q)
return v.Cmp(r) == 0
}

View File

@ -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 dsa
import (
"big"
"crypto/rand"
"testing"
)
func testSignAndVerify(t *testing.T, i int, priv *PrivateKey) {
hashed := []byte("testing")
r, s, err := Sign(rand.Reader, priv, hashed)
if err != nil {
t.Errorf("%d: error signing: %s", i, err)
return
}
if !Verify(&priv.PublicKey, hashed, r, s) {
t.Errorf("%d: Verify failed", i)
}
}
func testParameterGeneration(t *testing.T, sizes ParameterSizes, L, N int) {
var priv PrivateKey
params := &priv.Parameters
err := GenerateParameters(params, rand.Reader, sizes)
if err != nil {
t.Errorf("%d: %s", int(sizes), err)
return
}
if params.P.BitLen() != L {
t.Errorf("%d: params.BitLen got:%d want:%d", int(sizes), params.P.BitLen(), L)
}
if params.Q.BitLen() != N {
t.Errorf("%d: q.BitLen got:%d want:%d", int(sizes), params.Q.BitLen(), L)
}
one := new(big.Int)
one.SetInt64(1)
pm1 := new(big.Int).Sub(params.P, one)
quo, rem := new(big.Int).DivMod(pm1, params.Q, new(big.Int))
if rem.Sign() != 0 {
t.Errorf("%d: p-1 mod q != 0", int(sizes))
}
x := new(big.Int).Exp(params.G, quo, params.P)
if x.Cmp(one) == 0 {
t.Errorf("%d: invalid generator", int(sizes))
}
err = GenerateKey(&priv, rand.Reader)
if err != nil {
t.Errorf("error generating key: %s", err)
return
}
testSignAndVerify(t, int(sizes), &priv)
}
func TestParameterGeneration(t *testing.T) {
// This test is too slow to run all the time.
return
testParameterGeneration(t, L1024N160, 1024, 160)
testParameterGeneration(t, L2048N224, 2048, 224)
testParameterGeneration(t, L2048N256, 2048, 256)
testParameterGeneration(t, L3072N256, 3072, 256)
}
func TestSignAndVerify(t *testing.T) {
var priv PrivateKey
priv.P, _ = new(big.Int).SetString("A9B5B793FB4785793D246BAE77E8FF63CA52F442DA763C440259919FE1BC1D6065A9350637A04F75A2F039401D49F08E066C4D275A5A65DA5684BC563C14289D7AB8A67163BFBF79D85972619AD2CFF55AB0EE77A9002B0EF96293BDD0F42685EBB2C66C327079F6C98000FBCB79AACDE1BC6F9D5C7B1A97E3D9D54ED7951FEF", 16)
priv.Q, _ = new(big.Int).SetString("E1D3391245933D68A0714ED34BBCB7A1F422B9C1", 16)
priv.G, _ = new(big.Int).SetString("634364FC25248933D01D1993ECABD0657CC0CB2CEED7ED2E3E8AECDFCDC4A25C3B15E9E3B163ACA2984B5539181F3EFF1A5E8903D71D5B95DA4F27202B77D2C44B430BB53741A8D59A8F86887525C9F2A6A5980A195EAA7F2FF910064301DEF89D3AA213E1FAC7768D89365318E370AF54A112EFBA9246D9158386BA1B4EEFDA", 16)
priv.Y, _ = new(big.Int).SetString("32969E5780CFE1C849A1C276D7AEB4F38A23B591739AA2FE197349AEEBD31366AEE5EB7E6C6DDB7C57D02432B30DB5AA66D9884299FAA72568944E4EEDC92EA3FBC6F39F53412FBCC563208F7C15B737AC8910DBC2D9C9B8C001E72FDC40EB694AB1F06A5A2DBD18D9E36C66F31F566742F11EC0A52E9F7B89355C02FB5D32D2", 16)
priv.X, _ = new(big.Int).SetString("5078D4D29795CBE76D3AACFE48C9AF0BCDBEE91A", 16)
testSignAndVerify(t, 0, &priv)
}

View File

@ -6,10 +6,15 @@
package md4
import (
"crypto"
"hash"
"os"
)
func init() {
crypto.RegisterHash(crypto.MD4, New)
}
// The size of an MD4 checksum in bytes.
const Size = 16

View File

@ -6,10 +6,15 @@
package md5
import (
"crypto"
"hash"
"os"
)
func init() {
crypto.RegisterHash(crypto.MD5, New)
}
// The size of an MD5 checksum in bytes.
const Size = 16

View File

@ -9,8 +9,9 @@ package ocsp
import (
"asn1"
"crypto"
"crypto/rsa"
"crypto/sha1"
_ "crypto/sha1"
"crypto/x509"
"os"
"time"
@ -168,8 +169,8 @@ func ParseResponse(bytes []byte) (*Response, os.Error) {
return nil, x509.UnsupportedAlgorithmError{}
}
h := sha1.New()
hashType := rsa.HashSHA1
hashType := crypto.SHA1
h := hashType.New()
pub := ret.Certificate.PublicKey.(*rsa.PublicKey)
h.Write(basicResp.TBSResponseData.Raw)

View File

@ -112,7 +112,7 @@ func (l *lineReader) Read(p []byte) (n int, err os.Error) {
return 0, os.EOF
}
if len(line) != 64 {
if len(line) > 64 {
return 0, ArmorCorrupt
}

View File

@ -34,7 +34,7 @@ func TestDecodeEncode(t *testing.T) {
t.Error(err)
}
if adler32.Checksum(contents) != 0x789d7f00 {
if adler32.Checksum(contents) != 0x27b144be {
t.Errorf("contents: got: %x", contents)
}
@ -73,13 +73,11 @@ func TestLongHeader(t *testing.T) {
const armorExample1 = `-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
iQEcBAABAgAGBQJMtFESAAoJEKsQXJGvOPsVj40H/1WW6jaMXv4BW+1ueDSMDwM8
kx1fLOXbVM5/Kn5LStZNt1jWWnpxdz7eq3uiqeCQjmqUoRde3YbB2EMnnwRbAhpp
cacnAvy9ZQ78OTxUdNW1mhX5bS6q1MTEJnl+DcyigD70HG/yNNQD7sOPMdYQw0TA
byQBwmLwmTsuZsrYqB68QyLHI+DUugn+kX6Hd2WDB62DKa2suoIUIHQQCd/ofwB3
WfCYInXQKKOSxu2YOg2Eb4kLNhSMc1i9uKUWAH+sdgJh7NBgdoE4MaNtBFkHXRvv
okWuf3+xA9ksp1npSY/mDvgHijmjvtpRDe6iUeqfCn8N9u9CBg8geANgaG8+QA4=
=wfQG
iJwEAAECAAYFAk1Fv/0ACgkQo01+GMIMMbsYTwQAiAw+QAaNfY6WBdplZ/uMAccm
4g+81QPmTSGHnetSb6WBiY13kVzK4HQiZH8JSkmmroMLuGeJwsRTEL4wbjRyUKEt
p1xwUZDECs234F1xiG5enc5SGlRtP7foLBz9lOsjx+LEcA4sTl5/2eZR9zyFZqWW
TxRjs+fJCIFuo71xb1g=
=/teI
-----END PGP SIGNATURE-----`
const armorLongLine = `-----BEGIN PGP SIGNATURE-----

View File

@ -116,6 +116,7 @@ func (e *encoding) Close() (err os.Error) {
if err != nil {
return
}
e.breaker.Close()
var checksumBytes [3]byte
checksumBytes[0] = byte(e.crc >> 16)
@ -144,11 +145,9 @@ func Encode(out io.Writer, blockType string, headers map[string]string) (w io.Wr
}
}
if len(headers) > 0 {
_, err := out.Write(newline)
if err != nil {
return
}
_, err = out.Write(newline)
if err != nil {
return
}
e := &encoding{

View File

@ -0,0 +1,58 @@
// 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 openpgp
import (
"hash"
"os"
)
// NewCanonicalTextHash reformats text written to it into the canonical
// form and then applies the hash h. See RFC 4880, section 5.2.1.
func NewCanonicalTextHash(h hash.Hash) hash.Hash {
return &canonicalTextHash{h, 0}
}
type canonicalTextHash struct {
h hash.Hash
s int
}
var newline = []byte{'\r', '\n'}
func (cth *canonicalTextHash) Write(buf []byte) (int, os.Error) {
start := 0
for i, c := range buf {
switch cth.s {
case 0:
if c == '\r' {
cth.s = 1
} else if c == '\n' {
cth.h.Write(buf[start:i])
cth.h.Write(newline)
start = i + 1
}
case 1:
cth.s = 0
}
}
cth.h.Write(buf[start:])
return len(buf), nil
}
func (cth *canonicalTextHash) Sum() []byte {
return cth.h.Sum()
}
func (cth *canonicalTextHash) Reset() {
cth.h.Reset()
cth.s = 0
}
func (cth *canonicalTextHash) Size() int {
return cth.h.Size()
}

View File

@ -0,0 +1,50 @@
// 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 openpgp
import (
"bytes"
"os"
"testing"
)
type recordingHash struct {
buf *bytes.Buffer
}
func (r recordingHash) Write(b []byte) (n int, err os.Error) {
return r.buf.Write(b)
}
func (r recordingHash) Sum() []byte {
return r.buf.Bytes()
}
func (r recordingHash) Reset() {
panic("shouldn't be called")
}
func (r recordingHash) Size() int {
panic("shouldn't be called")
}
func testCanonicalText(t *testing.T, input, expected string) {
r := recordingHash{bytes.NewBuffer(nil)}
c := NewCanonicalTextHash(r)
c.Write([]byte(input))
result := c.Sum()
if expected != string(result) {
t.Errorf("input: %x got: %x want: %x", input, result, expected)
}
}
func TestCanonicalText(t *testing.T) {
testCanonicalText(t, "foo\n", "foo\r\n")
testCanonicalText(t, "foo", "foo")
testCanonicalText(t, "foo\r\n", "foo\r\n")
testCanonicalText(t, "foo\r\nbar", "foo\r\nbar")
testCanonicalText(t, "foo\r\nbar\n\n", "foo\r\nbar\r\n\r\n")
}

View File

@ -5,6 +5,10 @@
// This package contains common error types for the OpenPGP packages.
package error
import (
"strconv"
)
// A StructuralError is returned when OpenPGP data is found to be syntactically
// invalid.
type StructuralError string
@ -44,3 +48,17 @@ func (ki keyIncorrect) String() string {
}
var KeyIncorrectError = keyIncorrect(0)
type unknownIssuer int
func (unknownIssuer) String() string {
return "signature make by unknown entity"
}
var UnknownIssuerError = unknownIssuer(0)
type UnknownPacketTypeError uint8
func (upte UnknownPacketTypeError) String() string {
return "unknown OpenPGP packet type: " + strconv.Itoa(int(upte))
}

View File

@ -0,0 +1,280 @@
// 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 openpgp
import (
"crypto/openpgp/error"
"crypto/openpgp/packet"
"io"
"os"
)
// PublicKeyType is the armor type for a PGP public key.
var PublicKeyType = "PGP PUBLIC KEY BLOCK"
// An Entity represents the components of an OpenPGP key: a primary public key
// (which must be a signing key), one or more identities claimed by that key,
// and zero or more subkeys, which may be encryption keys.
type Entity struct {
PrimaryKey *packet.PublicKey
PrivateKey *packet.PrivateKey
Identities map[string]*Identity // indexed by Identity.Name
Subkeys []Subkey
}
// An Identity represents an identity claimed by an Entity and zero or more
// assertions by other entities about that claim.
type Identity struct {
Name string // by convention, has the form "Full Name (comment) <email@example.com>"
UserId *packet.UserId
SelfSignature *packet.Signature
Signatures []*packet.Signature
}
// A Subkey is an additional public key in an Entity. Subkeys can be used for
// encryption.
type Subkey struct {
PublicKey *packet.PublicKey
PrivateKey *packet.PrivateKey
Sig *packet.Signature
}
// A Key identifies a specific public key in an Entity. This is either the
// Entity's primary key or a subkey.
type Key struct {
Entity *Entity
PublicKey *packet.PublicKey
PrivateKey *packet.PrivateKey
SelfSignature *packet.Signature
}
// A KeyRing provides access to public and private keys.
type KeyRing interface {
// KeysById returns the set of keys that have the given key id.
KeysById(id uint64) []Key
// DecryptionKeys returns all private keys that are valid for
// decryption.
DecryptionKeys() []Key
}
// An EntityList contains one or more Entities.
type EntityList []*Entity
// KeysById returns the set of keys that have the given key id.
func (el EntityList) KeysById(id uint64) (keys []Key) {
for _, e := range el {
if e.PrimaryKey.KeyId == id {
var selfSig *packet.Signature
for _, ident := range e.Identities {
if selfSig == nil {
selfSig = ident.SelfSignature
} else if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId {
selfSig = ident.SelfSignature
break
}
}
keys = append(keys, Key{e, e.PrimaryKey, e.PrivateKey, selfSig})
}
for _, subKey := range e.Subkeys {
if subKey.PublicKey.KeyId == id {
keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig})
}
}
}
return
}
// DecryptionKeys returns all private keys that are valid for decryption.
func (el EntityList) DecryptionKeys() (keys []Key) {
for _, e := range el {
for _, subKey := range e.Subkeys {
if subKey.PrivateKey != nil && (!subKey.Sig.FlagsValid || subKey.Sig.FlagEncryptStorage || subKey.Sig.FlagEncryptCommunications) {
keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig})
}
}
}
return
}
// ReadArmoredKeyRing reads one or more public/private keys from an armor keyring file.
func ReadArmoredKeyRing(r io.Reader) (EntityList, os.Error) {
body, err := readArmored(r, PublicKeyType)
if err != nil {
return nil, err
}
return ReadKeyRing(body)
}
// ReadKeyRing reads one or more public/private keys, ignoring unsupported keys.
func ReadKeyRing(r io.Reader) (el EntityList, err os.Error) {
packets := packet.NewReader(r)
for {
var e *Entity
e, err = readEntity(packets)
if err != nil {
if _, ok := err.(error.UnsupportedError); ok {
err = readToNextPublicKey(packets)
}
if err == os.EOF {
err = nil
return
}
if err != nil {
el = nil
return
}
} else {
el = append(el, e)
}
}
return
}
// readToNextPublicKey reads packets until the start of the entity and leaves
// the first packet of the new entity in the Reader.
func readToNextPublicKey(packets *packet.Reader) (err os.Error) {
var p packet.Packet
for {
p, err = packets.Next()
if err == os.EOF {
return
} else if err != nil {
if _, ok := err.(error.UnsupportedError); ok {
err = nil
continue
}
return
}
if pk, ok := p.(*packet.PublicKey); ok && !pk.IsSubkey {
packets.Unread(p)
return
}
}
panic("unreachable")
}
// readEntity reads an entity (public key, identities, subkeys etc) from the
// given Reader.
func readEntity(packets *packet.Reader) (*Entity, os.Error) {
e := new(Entity)
e.Identities = make(map[string]*Identity)
p, err := packets.Next()
if err != nil {
return nil, err
}
var ok bool
if e.PrimaryKey, ok = p.(*packet.PublicKey); !ok {
if e.PrivateKey, ok = p.(*packet.PrivateKey); !ok {
packets.Unread(p)
return nil, error.StructuralError("first packet was not a public/private key")
} else {
e.PrimaryKey = &e.PrivateKey.PublicKey
}
}
var current *Identity
EachPacket:
for {
p, err := packets.Next()
if err == os.EOF {
break
} else if err != nil {
return nil, err
}
switch pkt := p.(type) {
case *packet.UserId:
current = new(Identity)
current.Name = pkt.Id
current.UserId = pkt
e.Identities[pkt.Id] = current
p, err = packets.Next()
if err == os.EOF {
err = io.ErrUnexpectedEOF
}
if err != nil {
if _, ok := err.(error.UnsupportedError); ok {
return nil, err
}
return nil, error.StructuralError("identity self-signature invalid: " + err.String())
}
current.SelfSignature, ok = p.(*packet.Signature)
if !ok {
return nil, error.StructuralError("user ID packet not followed by self signature")
}
if current.SelfSignature.SigType != packet.SigTypePositiveCert {
return nil, error.StructuralError("user ID self-signature with wrong type")
}
if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, current.SelfSignature); err != nil {
return nil, error.StructuralError("user ID self-signature invalid: " + err.String())
}
case *packet.Signature:
if current == nil {
return nil, error.StructuralError("signature packet found before user id packet")
}
current.Signatures = append(current.Signatures, pkt)
case *packet.PrivateKey:
if pkt.IsSubkey == false {
packets.Unread(p)
break EachPacket
}
err = addSubkey(e, packets, &pkt.PublicKey, pkt)
if err != nil {
return nil, err
}
case *packet.PublicKey:
if pkt.IsSubkey == false {
packets.Unread(p)
break EachPacket
}
err = addSubkey(e, packets, pkt, nil)
if err != nil {
return nil, err
}
default:
// we ignore unknown packets
}
}
if len(e.Identities) == 0 {
return nil, error.StructuralError("entity without any identities")
}
return e, nil
}
func addSubkey(e *Entity, packets *packet.Reader, pub *packet.PublicKey, priv *packet.PrivateKey) os.Error {
var subKey Subkey
subKey.PublicKey = pub
subKey.PrivateKey = priv
p, err := packets.Next()
if err == os.EOF {
return io.ErrUnexpectedEOF
}
if err != nil {
return error.StructuralError("subkey signature invalid: " + err.String())
}
var ok bool
subKey.Sig, ok = p.(*packet.Signature)
if !ok {
return error.StructuralError("subkey packet not followed by signature")
}
if subKey.Sig.SigType != packet.SigTypeSubkeyBinding {
return error.StructuralError("subkey signature with wrong type")
}
err = e.PrimaryKey.VerifyKeySignature(subKey.PublicKey, subKey.Sig)
if err != nil {
return error.StructuralError("subkey signature invalid: " + err.String())
}
e.Subkeys = append(e.Subkeys, subKey)
return nil
}

View File

@ -0,0 +1,39 @@
// 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 packet
import (
"compress/flate"
"compress/zlib"
"crypto/openpgp/error"
"io"
"os"
"strconv"
)
// Compressed represents a compressed OpenPGP packet. The decompressed contents
// will contain more OpenPGP packets. See RFC 4880, section 5.6.
type Compressed struct {
Body io.Reader
}
func (c *Compressed) parse(r io.Reader) os.Error {
var buf [1]byte
_, err := readFull(r, buf[:])
if err != nil {
return err
}
switch buf[0] {
case 1:
c.Body = flate.NewReader(r)
case 2:
c.Body, err = zlib.NewReader(r)
default:
err = error.UnsupportedError("unknown compression algorithm: " + strconv.Itoa(int(buf[0])))
}
return err
}

View File

@ -0,0 +1,41 @@
// 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 packet
import (
"bytes"
"encoding/hex"
"os"
"io/ioutil"
"testing"
)
func TestCompressed(t *testing.T) {
packet, err := Read(readerFromHex(compressedHex))
if err != nil {
t.Errorf("failed to read Compressed: %s", err)
return
}
c, ok := packet.(*Compressed)
if !ok {
t.Error("didn't find Compressed packet")
return
}
contents, err := ioutil.ReadAll(c.Body)
if err != nil && err != os.EOF {
t.Error(err)
return
}
expected, _ := hex.DecodeString(compressedExpectedHex)
if !bytes.Equal(expected, contents) {
t.Errorf("got:%x want:%x", contents, expected)
}
}
const compressedHex = "a3013b2d90c4e02b72e25f727e5e496a5e49b11e1700"
const compressedExpectedHex = "cb1062004d14c8fe636f6e74656e74732e0a"

View File

@ -0,0 +1,66 @@
// 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 packet
import (
"crypto/openpgp/error"
"crypto/rand"
"crypto/rsa"
"encoding/binary"
"io"
"os"
"strconv"
)
// EncryptedKey represents a public-key encrypted session key. See RFC 4880,
// section 5.1.
type EncryptedKey struct {
KeyId uint64
Algo PublicKeyAlgorithm
Encrypted []byte
CipherFunc CipherFunction // only valid after a successful Decrypt
Key []byte // only valid after a successful Decrypt
}
func (e *EncryptedKey) parse(r io.Reader) (err os.Error) {
var buf [10]byte
_, err = readFull(r, buf[:])
if err != nil {
return
}
if buf[0] != 3 {
return error.UnsupportedError("unknown EncryptedKey version " + strconv.Itoa(int(buf[0])))
}
e.KeyId = binary.BigEndian.Uint64(buf[1:9])
e.Algo = PublicKeyAlgorithm(buf[9])
if e.Algo == PubKeyAlgoRSA || e.Algo == PubKeyAlgoRSAEncryptOnly {
e.Encrypted, _, err = readMPI(r)
}
_, err = consumeAll(r)
return
}
// DecryptRSA decrypts an RSA encrypted session key with the given private key.
func (e *EncryptedKey) DecryptRSA(priv *rsa.PrivateKey) (err os.Error) {
if e.Algo != PubKeyAlgoRSA && e.Algo != PubKeyAlgoRSAEncryptOnly {
return error.InvalidArgumentError("EncryptedKey not RSA encrypted")
}
b, err := rsa.DecryptPKCS1v15(rand.Reader, priv, e.Encrypted)
if err != nil {
return
}
e.CipherFunc = CipherFunction(b[0])
e.Key = b[1 : len(b)-2]
expectedChecksum := uint16(b[len(b)-2])<<8 | uint16(b[len(b)-1])
var checksum uint16
for _, v := range e.Key {
checksum += uint16(v)
}
if checksum != expectedChecksum {
return error.StructuralError("EncryptedKey checksum incorrect")
}
return
}

View File

@ -0,0 +1,67 @@
// 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 packet
import (
"big"
"crypto/rsa"
"fmt"
"testing"
)
func bigFromBase10(s string) *big.Int {
b, ok := new(big.Int).SetString(s, 10)
if !ok {
panic("bigFromBase10 failed")
}
return b
}
func TestEncryptedKey(t *testing.T) {
p, err := Read(readerFromHex(encryptedKeyHex))
if err != nil {
t.Errorf("error from Read: %s", err)
return
}
ek, ok := p.(*EncryptedKey)
if !ok {
t.Errorf("didn't parse an EncryptedKey, got %#v", p)
return
}
if ek.KeyId != 0x2a67d68660df41c7 || ek.Algo != PubKeyAlgoRSA {
t.Errorf("unexpected EncryptedKey contents: %#v", ek)
return
}
pub := rsa.PublicKey{
E: 65537,
N: bigFromBase10("115804063926007623305902631768113868327816898845124614648849934718568541074358183759250136204762053879858102352159854352727097033322663029387610959884180306668628526686121021235757016368038585212410610742029286439607686208110250133174279811431933746643015923132833417396844716207301518956640020862630546868823"),
}
priv := &rsa.PrivateKey{
PublicKey: pub,
D: bigFromBase10("32355588668219869544751561565313228297765464314098552250409557267371233892496951383426602439009993875125222579159850054973310859166139474359774543943714622292329487391199285040721944491839695981199720170366763547754915493640685849961780092241140181198779299712578774460837139360803883139311171713302987058393"),
}
err = ek.DecryptRSA(priv)
if err != nil {
t.Errorf("error from DecryptRSA: %s", err)
return
}
if ek.CipherFunc != CipherAES256 {
t.Errorf("unexpected EncryptedKey contents: %#v", ek)
return
}
keyHex := fmt.Sprintf("%x", ek.Key)
if keyHex != expectedKeyHex {
t.Errorf("bad key, got %s want %x", keyHex, expectedKeyHex)
}
}
const encryptedKeyHex = "c18c032a67d68660df41c70104005789d0de26b6a50c985a02a13131ca829c413a35d0e6fa8d6842599252162808ac7439c72151c8c6183e76923fe3299301414d0c25a2f06a2257db3839e7df0ec964773f6e4c4ac7ff3b48c444237166dd46ba8ff443a5410dc670cb486672fdbe7c9dfafb75b4fea83af3a204fe2a7dfa86bd20122b4f3d2646cbeecb8f7be8"
const expectedKeyHex = "d930363f7e0308c333b9618617ea728963d8df993665ae7be1092d4926fd864b"

View File

@ -0,0 +1,53 @@
// 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 packet
import (
"encoding/binary"
"io"
"os"
)
// LiteralData represents an encrypted file. See RFC 4880, section 5.9.
type LiteralData struct {
IsBinary bool
FileName string
Time uint32 // Unix epoch time. Either creation time or modification time. 0 means undefined.
Body io.Reader
}
// ForEyesOnly returns whether the contents of the LiteralData have been marked
// as especially sensitive.
func (l *LiteralData) ForEyesOnly() bool {
return l.FileName == "_CONSOLE"
}
func (l *LiteralData) parse(r io.Reader) (err os.Error) {
var buf [256]byte
_, err = readFull(r, buf[:2])
if err != nil {
return
}
l.IsBinary = buf[0] == 'b'
fileNameLen := int(buf[1])
_, err = readFull(r, buf[:fileNameLen])
if err != nil {
return
}
l.FileName = string(buf[:fileNameLen])
_, err = readFull(r, buf[:4])
if err != nil {
return
}
l.Time = binary.BigEndian.Uint32(buf[:4])
l.Body = r
return
}

View File

@ -0,0 +1,49 @@
// 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 packet
import (
"crypto"
"crypto/openpgp/error"
"crypto/openpgp/s2k"
"encoding/binary"
"io"
"os"
"strconv"
)
// OnePassSignature represents a one-pass signature packet. See RFC 4880,
// section 5.4.
type OnePassSignature struct {
SigType SignatureType
Hash crypto.Hash
PubKeyAlgo PublicKeyAlgorithm
KeyId uint64
IsLast bool
}
func (ops *OnePassSignature) parse(r io.Reader) (err os.Error) {
var buf [13]byte
_, err = readFull(r, buf[:])
if err != nil {
return
}
if buf[0] != 3 {
err = error.UnsupportedError("one-pass-signature packet version " + strconv.Itoa(int(buf[0])))
}
var ok bool
ops.Hash, ok = s2k.HashIdToHash(buf[2])
if !ok {
return error.UnsupportedError("hash function: " + strconv.Itoa(int(buf[2])))
}
ops.SigType = SignatureType(buf[1])
ops.PubKeyAlgo = PublicKeyAlgorithm(buf[3])
ops.KeyId = binary.BigEndian.Uint64(buf[4:12])
ops.IsLast = buf[12] != 0
return
}

View File

@ -0,0 +1,395 @@
// 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.
// This package implements parsing and serialisation of OpenPGP packets, as
// specified in RFC 4880.
package packet
import (
"crypto/aes"
"crypto/cast5"
"crypto/cipher"
"crypto/openpgp/error"
"io"
"os"
)
// readFull is the same as io.ReadFull except that reading zero bytes returns
// ErrUnexpectedEOF rather than EOF.
func readFull(r io.Reader, buf []byte) (n int, err os.Error) {
n, err = io.ReadFull(r, buf)
if err == os.EOF {
err = io.ErrUnexpectedEOF
}
return
}
// readLength reads an OpenPGP length from r. See RFC 4880, section 4.2.2.
func readLength(r io.Reader) (length int64, isPartial bool, err os.Error) {
var buf [4]byte
_, err = readFull(r, buf[:1])
if err != nil {
return
}
switch {
case buf[0] < 192:
length = int64(buf[0])
case buf[0] < 224:
length = int64(buf[0]-192) << 8
_, err = readFull(r, buf[0:1])
if err != nil {
return
}
length += int64(buf[0]) + 192
case buf[0] < 255:
length = int64(1) << (buf[0] & 0x1f)
isPartial = true
default:
_, err = readFull(r, buf[0:4])
if err != nil {
return
}
length = int64(buf[0])<<24 |
int64(buf[1])<<16 |
int64(buf[2])<<8 |
int64(buf[3])
}
return
}
// partialLengthReader wraps an io.Reader and handles OpenPGP partial lengths.
// The continuation lengths are parsed and removed from the stream and EOF is
// returned at the end of the packet. See RFC 4880, section 4.2.2.4.
type partialLengthReader struct {
r io.Reader
remaining int64
isPartial bool
}
func (r *partialLengthReader) Read(p []byte) (n int, err os.Error) {
for r.remaining == 0 {
if !r.isPartial {
return 0, os.EOF
}
r.remaining, r.isPartial, err = readLength(r.r)
if err != nil {
return 0, err
}
}
toRead := int64(len(p))
if toRead > r.remaining {
toRead = r.remaining
}
n, err = r.r.Read(p[:int(toRead)])
r.remaining -= int64(n)
if n < int(toRead) && err == os.EOF {
err = io.ErrUnexpectedEOF
}
return
}
// A spanReader is an io.LimitReader, but it returns ErrUnexpectedEOF if the
// underlying Reader returns EOF before the limit has been reached.
type spanReader struct {
r io.Reader
n int64
}
func (l *spanReader) Read(p []byte) (n int, err os.Error) {
if l.n <= 0 {
return 0, os.EOF
}
if int64(len(p)) > l.n {
p = p[0:l.n]
}
n, err = l.r.Read(p)
l.n -= int64(n)
if l.n > 0 && err == os.EOF {
err = io.ErrUnexpectedEOF
}
return
}
// readHeader parses a packet header and returns an io.Reader which will return
// the contents of the packet. See RFC 4880, section 4.2.
func readHeader(r io.Reader) (tag packetType, length int64, contents io.Reader, err os.Error) {
var buf [4]byte
_, err = io.ReadFull(r, buf[:1])
if err != nil {
return
}
if buf[0]&0x80 == 0 {
err = error.StructuralError("tag byte does not have MSB set")
return
}
if buf[0]&0x40 == 0 {
// Old format packet
tag = packetType((buf[0] & 0x3f) >> 2)
lengthType := buf[0] & 3
if lengthType == 3 {
length = -1
contents = r
return
}
lengthBytes := 1 << lengthType
_, err = readFull(r, buf[0:lengthBytes])
if err != nil {
return
}
for i := 0; i < lengthBytes; i++ {
length <<= 8
length |= int64(buf[i])
}
contents = &spanReader{r, length}
return
}
// New format packet
tag = packetType(buf[0] & 0x3f)
length, isPartial, err := readLength(r)
if err != nil {
return
}
if isPartial {
contents = &partialLengthReader{
remaining: length,
isPartial: true,
r: r,
}
length = -1
} else {
contents = &spanReader{r, length}
}
return
}
// serialiseHeader writes an OpenPGP packet header to w. See RFC 4880, section
// 4.2.
func serialiseHeader(w io.Writer, ptype packetType, length int) (err os.Error) {
var buf [5]byte
var n int
buf[0] = 0x80 | 0x40 | byte(ptype)
if length < 192 {
buf[1] = byte(length)
n = 2
} else if length < 8384 {
length -= 192
buf[1] = byte(length >> 8)
buf[2] = byte(length)
n = 3
} else {
buf[0] = 255
buf[1] = byte(length >> 24)
buf[2] = byte(length >> 16)
buf[3] = byte(length >> 8)
buf[4] = byte(length)
n = 5
}
_, err = w.Write(buf[:n])
return
}
// Packet represents an OpenPGP packet. Users are expected to try casting
// instances of this interface to specific packet types.
type Packet interface {
parse(io.Reader) os.Error
}
// consumeAll reads from the given Reader until error, returning the number of
// bytes read.
func consumeAll(r io.Reader) (n int64, err os.Error) {
var m int
var buf [1024]byte
for {
m, err = r.Read(buf[:])
n += int64(m)
if err == os.EOF {
err = nil
return
}
if err != nil {
return
}
}
panic("unreachable")
}
// packetType represents the numeric ids of the different OpenPGP packet types. See
// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-2
type packetType uint8
const (
packetTypeEncryptedKey packetType = 1
packetTypeSignature packetType = 2
packetTypeSymmetricKeyEncrypted packetType = 3
packetTypeOnePassSignature packetType = 4
packetTypePrivateKey packetType = 5
packetTypePublicKey packetType = 6
packetTypePrivateSubkey packetType = 7
packetTypeCompressed packetType = 8
packetTypeSymmetricallyEncrypted packetType = 9
packetTypeLiteralData packetType = 11
packetTypeUserId packetType = 13
packetTypePublicSubkey packetType = 14
packetTypeSymmetricallyEncryptedMDC packetType = 18
)
// Read reads a single OpenPGP packet from the given io.Reader. If there is an
// error parsing a packet, the whole packet is consumed from the input.
func Read(r io.Reader) (p Packet, err os.Error) {
tag, _, contents, err := readHeader(r)
if err != nil {
return
}
switch tag {
case packetTypeEncryptedKey:
p = new(EncryptedKey)
case packetTypeSignature:
p = new(Signature)
case packetTypeSymmetricKeyEncrypted:
p = new(SymmetricKeyEncrypted)
case packetTypeOnePassSignature:
p = new(OnePassSignature)
case packetTypePrivateKey, packetTypePrivateSubkey:
pk := new(PrivateKey)
if tag == packetTypePrivateSubkey {
pk.IsSubkey = true
}
p = pk
case packetTypePublicKey, packetTypePublicSubkey:
pk := new(PublicKey)
if tag == packetTypePublicSubkey {
pk.IsSubkey = true
}
p = pk
case packetTypeCompressed:
p = new(Compressed)
case packetTypeSymmetricallyEncrypted:
p = new(SymmetricallyEncrypted)
case packetTypeLiteralData:
p = new(LiteralData)
case packetTypeUserId:
p = new(UserId)
case packetTypeSymmetricallyEncryptedMDC:
se := new(SymmetricallyEncrypted)
se.MDC = true
p = se
default:
err = error.UnknownPacketTypeError(tag)
}
if p != nil {
err = p.parse(contents)
}
if err != nil {
consumeAll(contents)
}
return
}
// SignatureType represents the different semantic meanings of an OpenPGP
// signature. See RFC 4880, section 5.2.1.
type SignatureType uint8
const (
SigTypeBinary SignatureType = 0
SigTypeText = 1
SigTypeGenericCert = 0x10
SigTypePersonaCert = 0x11
SigTypeCasualCert = 0x12
SigTypePositiveCert = 0x13
SigTypeSubkeyBinding = 0x18
)
// PublicKeyAlgorithm represents the different public key system specified for
// OpenPGP. See
// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-12
type PublicKeyAlgorithm uint8
const (
PubKeyAlgoRSA PublicKeyAlgorithm = 1
PubKeyAlgoRSAEncryptOnly PublicKeyAlgorithm = 2
PubKeyAlgoRSASignOnly PublicKeyAlgorithm = 3
PubKeyAlgoElgamal PublicKeyAlgorithm = 16
PubKeyAlgoDSA PublicKeyAlgorithm = 17
)
// CipherFunction represents the different block ciphers specified for OpenPGP. See
// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-13
type CipherFunction uint8
const (
CipherCAST5 = 3
CipherAES128 = 7
CipherAES192 = 8
CipherAES256 = 9
)
// keySize returns the key size, in bytes, of cipher.
func (cipher CipherFunction) keySize() int {
switch cipher {
case CipherCAST5:
return cast5.KeySize
case CipherAES128:
return 16
case CipherAES192:
return 24
case CipherAES256:
return 32
}
return 0
}
// blockSize returns the block size, in bytes, of cipher.
func (cipher CipherFunction) blockSize() int {
switch cipher {
case CipherCAST5:
return 8
case CipherAES128, CipherAES192, CipherAES256:
return 16
}
return 0
}
// new returns a fresh instance of the given cipher.
func (cipher CipherFunction) new(key []byte) (block cipher.Block) {
switch cipher {
case CipherCAST5:
block, _ = cast5.NewCipher(key)
case CipherAES128, CipherAES192, CipherAES256:
block, _ = aes.NewCipher(key)
}
return
}
// readMPI reads a big integer from r. The bit length returned is the bit
// length that was specified in r. This is preserved so that the integer can be
// reserialised exactly.
func readMPI(r io.Reader) (mpi []byte, bitLength uint16, err os.Error) {
var buf [2]byte
_, err = readFull(r, buf[0:])
if err != nil {
return
}
bitLength = uint16(buf[0])<<8 | uint16(buf[1])
numBytes := (int(bitLength) + 7) / 8
mpi = make([]byte, numBytes)
_, err = readFull(r, mpi)
return
}
// writeMPI serialises a big integer to r.
func writeMPI(w io.Writer, bitLength uint16, mpiBytes []byte) (err os.Error) {
_, err = w.Write([]byte{byte(bitLength >> 8), byte(bitLength)})
if err == nil {
_, err = w.Write(mpiBytes)
}
return
}

View File

@ -0,0 +1,192 @@
// 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 packet
import (
"bytes"
"crypto/openpgp/error"
"encoding/hex"
"fmt"
"io"
"io/ioutil"
"os"
"testing"
)
func TestReadFull(t *testing.T) {
var out [4]byte
b := bytes.NewBufferString("foo")
n, err := readFull(b, out[:3])
if n != 3 || err != nil {
t.Errorf("full read failed n:%d err:%s", n, err)
}
b = bytes.NewBufferString("foo")
n, err = readFull(b, out[:4])
if n != 3 || err != io.ErrUnexpectedEOF {
t.Errorf("partial read failed n:%d err:%s", n, err)
}
b = bytes.NewBuffer(nil)
n, err = readFull(b, out[:3])
if n != 0 || err != io.ErrUnexpectedEOF {
t.Errorf("empty read failed n:%d err:%s", n, err)
}
}
func readerFromHex(s string) io.Reader {
data, err := hex.DecodeString(s)
if err != nil {
panic("readerFromHex: bad input")
}
return bytes.NewBuffer(data)
}
var readLengthTests = []struct {
hexInput string
length int64
isPartial bool
err os.Error
}{
{"", 0, false, io.ErrUnexpectedEOF},
{"1f", 31, false, nil},
{"c0", 0, false, io.ErrUnexpectedEOF},
{"c101", 256 + 1 + 192, false, nil},
{"e0", 1, true, nil},
{"e1", 2, true, nil},
{"e2", 4, true, nil},
{"ff", 0, false, io.ErrUnexpectedEOF},
{"ff00", 0, false, io.ErrUnexpectedEOF},
{"ff0000", 0, false, io.ErrUnexpectedEOF},
{"ff000000", 0, false, io.ErrUnexpectedEOF},
{"ff00000000", 0, false, nil},
{"ff01020304", 16909060, false, nil},
}
func TestReadLength(t *testing.T) {
for i, test := range readLengthTests {
length, isPartial, err := readLength(readerFromHex(test.hexInput))
if test.err != nil {
if err != test.err {
t.Errorf("%d: expected different error got:%s want:%s", i, err, test.err)
}
continue
}
if err != nil {
t.Errorf("%d: unexpected error: %s", i, err)
continue
}
if length != test.length || isPartial != test.isPartial {
t.Errorf("%d: bad result got:(%d,%t) want:(%d,%t)", i, length, isPartial, test.length, test.isPartial)
}
}
}
var partialLengthReaderTests = []struct {
hexInput string
err os.Error
hexOutput string
}{
{"e0", io.ErrUnexpectedEOF, ""},
{"e001", io.ErrUnexpectedEOF, ""},
{"e0010102", nil, "0102"},
{"ff00000000", nil, ""},
{"e10102e1030400", nil, "01020304"},
{"e101", io.ErrUnexpectedEOF, ""},
}
func TestPartialLengthReader(t *testing.T) {
for i, test := range partialLengthReaderTests {
r := &partialLengthReader{readerFromHex(test.hexInput), 0, true}
out, err := ioutil.ReadAll(r)
if test.err != nil {
if err != test.err {
t.Errorf("%d: expected different error got:%s want:%s", i, err, test.err)
}
continue
}
if err != nil {
t.Errorf("%d: unexpected error: %s", i, err)
continue
}
got := fmt.Sprintf("%x", out)
if got != test.hexOutput {
t.Errorf("%d: got:%s want:%s", i, test.hexOutput, got)
}
}
}
var readHeaderTests = []struct {
hexInput string
structuralError bool
unexpectedEOF bool
tag int
length int64
hexOutput string
}{
{"", false, false, 0, 0, ""},
{"7f", true, false, 0, 0, ""},
// Old format headers
{"80", false, true, 0, 0, ""},
{"8001", false, true, 0, 1, ""},
{"800102", false, false, 0, 1, "02"},
{"81000102", false, false, 0, 1, "02"},
{"820000000102", false, false, 0, 1, "02"},
{"860000000102", false, false, 1, 1, "02"},
{"83010203", false, false, 0, -1, "010203"},
// New format headers
{"c0", false, true, 0, 0, ""},
{"c000", false, false, 0, 0, ""},
{"c00102", false, false, 0, 1, "02"},
{"c0020203", false, false, 0, 2, "0203"},
{"c00202", false, true, 0, 2, ""},
{"c3020203", false, false, 3, 2, "0203"},
}
func TestReadHeader(t *testing.T) {
for i, test := range readHeaderTests {
tag, length, contents, err := readHeader(readerFromHex(test.hexInput))
if test.structuralError {
if _, ok := err.(error.StructuralError); ok {
continue
}
t.Errorf("%d: expected StructuralError, got:%s", i, err)
continue
}
if err != nil {
if len(test.hexInput) == 0 && err == os.EOF {
continue
}
if !test.unexpectedEOF || err != io.ErrUnexpectedEOF {
t.Errorf("%d: unexpected error from readHeader: %s", i, err)
}
continue
}
if int(tag) != test.tag || length != test.length {
t.Errorf("%d: got:(%d,%d) want:(%d,%d)", i, int(tag), length, test.tag, test.length)
continue
}
body, err := ioutil.ReadAll(contents)
if err != nil {
if !test.unexpectedEOF || err != io.ErrUnexpectedEOF {
t.Errorf("%d: unexpected error from contents: %s", i, err)
}
continue
}
if test.unexpectedEOF {
t.Errorf("%d: expected ErrUnexpectedEOF from contents but got no error", i)
continue
}
got := fmt.Sprintf("%x", body)
if got != test.hexOutput {
t.Errorf("%d: got:%s want:%s", i, got, test.hexOutput)
}
}
}

View File

@ -0,0 +1,164 @@
// 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 packet
import (
"big"
"bytes"
"crypto/cipher"
"crypto/openpgp/error"
"crypto/openpgp/s2k"
"crypto/rsa"
"crypto/sha1"
"io"
"io/ioutil"
"os"
"strconv"
)
// PrivateKey represents a possibly encrypted private key. See RFC 4880,
// section 5.5.3.
type PrivateKey struct {
PublicKey
Encrypted bool // if true then the private key is unavailable until Decrypt has been called.
encryptedData []byte
cipher CipherFunction
s2k func(out, in []byte)
PrivateKey interface{} // An *rsa.PrivateKey.
sha1Checksum bool
iv []byte
}
func (pk *PrivateKey) parse(r io.Reader) (err os.Error) {
err = (&pk.PublicKey).parse(r)
if err != nil {
return
}
var buf [1]byte
_, err = readFull(r, buf[:])
if err != nil {
return
}
s2kType := buf[0]
switch s2kType {
case 0:
pk.s2k = nil
pk.Encrypted = false
case 254, 255:
_, err = readFull(r, buf[:])
if err != nil {
return
}
pk.cipher = CipherFunction(buf[0])
pk.Encrypted = true
pk.s2k, err = s2k.Parse(r)
if err != nil {
return
}
if s2kType == 254 {
pk.sha1Checksum = true
}
default:
return error.UnsupportedError("deprecated s2k function in private key")
}
if pk.Encrypted {
blockSize := pk.cipher.blockSize()
if blockSize == 0 {
return error.UnsupportedError("unsupported cipher in private key: " + strconv.Itoa(int(pk.cipher)))
}
pk.iv = make([]byte, blockSize)
_, err = readFull(r, pk.iv)
if err != nil {
return
}
}
pk.encryptedData, err = ioutil.ReadAll(r)
if err != nil {
return
}
if !pk.Encrypted {
return pk.parsePrivateKey(pk.encryptedData)
}
return
}
// Decrypt decrypts an encrypted private key using a passphrase.
func (pk *PrivateKey) Decrypt(passphrase []byte) os.Error {
if !pk.Encrypted {
return nil
}
key := make([]byte, pk.cipher.keySize())
pk.s2k(key, passphrase)
block := pk.cipher.new(key)
cfb := cipher.NewCFBDecrypter(block, pk.iv)
data := pk.encryptedData
cfb.XORKeyStream(data, data)
if pk.sha1Checksum {
if len(data) < sha1.Size {
return error.StructuralError("truncated private key data")
}
h := sha1.New()
h.Write(data[:len(data)-sha1.Size])
sum := h.Sum()
if !bytes.Equal(sum, data[len(data)-sha1.Size:]) {
return error.StructuralError("private key checksum failure")
}
data = data[:len(data)-sha1.Size]
} else {
if len(data) < 2 {
return error.StructuralError("truncated private key data")
}
var sum uint16
for i := 0; i < len(data)-2; i++ {
sum += uint16(data[i])
}
if data[len(data)-2] != uint8(sum>>8) ||
data[len(data)-1] != uint8(sum) {
return error.StructuralError("private key checksum failure")
}
data = data[:len(data)-2]
}
return pk.parsePrivateKey(data)
}
func (pk *PrivateKey) parsePrivateKey(data []byte) (err os.Error) {
// TODO(agl): support DSA and ECDSA private keys.
rsaPub := pk.PublicKey.PublicKey.(*rsa.PublicKey)
rsaPriv := new(rsa.PrivateKey)
rsaPriv.PublicKey = *rsaPub
buf := bytes.NewBuffer(data)
d, _, err := readMPI(buf)
if err != nil {
return
}
p, _, err := readMPI(buf)
if err != nil {
return
}
q, _, err := readMPI(buf)
if err != nil {
return
}
rsaPriv.D = new(big.Int).SetBytes(d)
rsaPriv.P = new(big.Int).SetBytes(p)
rsaPriv.Q = new(big.Int).SetBytes(q)
pk.PrivateKey = rsaPriv
pk.Encrypted = false
pk.encryptedData = nil
return nil
}

View File

@ -0,0 +1,37 @@
// 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 packet
import (
"testing"
)
func TestPrivateKeyRead(t *testing.T) {
packet, err := Read(readerFromHex(privKeyHex))
if err != nil {
t.Error(err)
return
}
privKey := packet.(*PrivateKey)
if !privKey.Encrypted {
t.Error("private key isn't encrypted")
return
}
err = privKey.Decrypt([]byte("testing"))
if err != nil {
t.Error(err)
return
}
if privKey.CreationTime != 0x4cc349a8 || privKey.Encrypted {
t.Errorf("failed to parse, got: %#v", privKey)
}
}
// Generated with `gpg --export-secret-keys "Test Key 2"`
const privKeyHex = "9501fe044cc349a8010400b70ca0010e98c090008d45d1ee8f9113bd5861fd57b88bacb7c68658747663f1e1a3b5a98f32fda6472373c024b97359cd2efc88ff60f77751adfbf6af5e615e6a1408cfad8bf0cea30b0d5f53aa27ad59089ba9b15b7ebc2777a25d7b436144027e3bcd203909f147d0e332b240cf63d3395f5dfe0df0a6c04e8655af7eacdf0011010001fe0303024a252e7d475fd445607de39a265472aa74a9320ba2dac395faa687e9e0336aeb7e9a7397e511b5afd9dc84557c80ac0f3d4d7bfec5ae16f20d41c8c84a04552a33870b930420e230e179564f6d19bb153145e76c33ae993886c388832b0fa042ddda7f133924f3854481533e0ede31d51278c0519b29abc3bf53da673e13e3e1214b52413d179d7f66deee35cac8eacb060f78379d70ef4af8607e68131ff529439668fc39c9ce6dfef8a5ac234d234802cbfb749a26107db26406213ae5c06d4673253a3cbee1fcbae58d6ab77e38d6e2c0e7c6317c48e054edadb5a40d0d48acb44643d998139a8a66bb820be1f3f80185bc777d14b5954b60effe2448a036d565c6bc0b915fcea518acdd20ab07bc1529f561c58cd044f723109b93f6fd99f876ff891d64306b5d08f48bab59f38695e9109c4dec34013ba3153488ce070268381ba923ee1eb77125b36afcb4347ec3478c8f2735b06ef17351d872e577fa95d0c397c88c71b59629a36aec"

View File

@ -0,0 +1,260 @@
// 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 packet
import (
"big"
"crypto/dsa"
"crypto/openpgp/error"
"crypto/rsa"
"crypto/sha1"
"encoding/binary"
"hash"
"io"
"os"
)
// PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2.
type PublicKey struct {
CreationTime uint32 // seconds since the epoch
PubKeyAlgo PublicKeyAlgorithm
PublicKey interface{} // Either a *rsa.PublicKey or *dsa.PublicKey
Fingerprint [20]byte
KeyId uint64
IsSubkey bool
n, e, p, q, g, y parsedMPI
}
func (pk *PublicKey) parse(r io.Reader) (err os.Error) {
// RFC 4880, section 5.5.2
var buf [6]byte
_, err = readFull(r, buf[:])
if err != nil {
return
}
if buf[0] != 4 {
return error.UnsupportedError("public key version")
}
pk.CreationTime = uint32(buf[1])<<24 | uint32(buf[2])<<16 | uint32(buf[3])<<8 | uint32(buf[4])
pk.PubKeyAlgo = PublicKeyAlgorithm(buf[5])
switch pk.PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
err = pk.parseRSA(r)
case PubKeyAlgoDSA:
err = pk.parseDSA(r)
default:
err = error.UnsupportedError("public key type")
}
if err != nil {
return
}
// RFC 4880, section 12.2
fingerPrint := sha1.New()
pk.SerializeSignaturePrefix(fingerPrint)
pk.Serialize(fingerPrint)
copy(pk.Fingerprint[:], fingerPrint.Sum())
pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[12:20])
return
}
// parseRSA parses RSA public key material from the given Reader. See RFC 4880,
// section 5.5.2.
func (pk *PublicKey) parseRSA(r io.Reader) (err os.Error) {
pk.n.bytes, pk.n.bitLength, err = readMPI(r)
if err != nil {
return
}
pk.e.bytes, pk.e.bitLength, err = readMPI(r)
if err != nil {
return
}
if len(pk.e.bytes) > 3 {
err = error.UnsupportedError("large public exponent")
return
}
rsa := &rsa.PublicKey{
N: new(big.Int).SetBytes(pk.n.bytes),
E: 0,
}
for i := 0; i < len(pk.e.bytes); i++ {
rsa.E <<= 8
rsa.E |= int(pk.e.bytes[i])
}
pk.PublicKey = rsa
return
}
// parseRSA parses DSA public key material from the given Reader. See RFC 4880,
// section 5.5.2.
func (pk *PublicKey) parseDSA(r io.Reader) (err os.Error) {
pk.p.bytes, pk.p.bitLength, err = readMPI(r)
if err != nil {
return
}
pk.q.bytes, pk.q.bitLength, err = readMPI(r)
if err != nil {
return
}
pk.g.bytes, pk.g.bitLength, err = readMPI(r)
if err != nil {
return
}
pk.y.bytes, pk.y.bitLength, err = readMPI(r)
if err != nil {
return
}
dsa := new(dsa.PublicKey)
dsa.P = new(big.Int).SetBytes(pk.p.bytes)
dsa.Q = new(big.Int).SetBytes(pk.q.bytes)
dsa.G = new(big.Int).SetBytes(pk.g.bytes)
dsa.Y = new(big.Int).SetBytes(pk.y.bytes)
pk.PublicKey = dsa
return
}
// SerializeSignaturePrefix writes the prefix for this public key to the given Writer.
// The prefix is used when calculating a signature over this public key. See
// RFC 4880, section 5.2.4.
func (pk *PublicKey) SerializeSignaturePrefix(h hash.Hash) {
var pLength uint16
switch pk.PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
pLength += 2 + uint16(len(pk.n.bytes))
pLength += 2 + uint16(len(pk.e.bytes))
case PubKeyAlgoDSA:
pLength += 2 + uint16(len(pk.p.bytes))
pLength += 2 + uint16(len(pk.q.bytes))
pLength += 2 + uint16(len(pk.g.bytes))
pLength += 2 + uint16(len(pk.y.bytes))
default:
panic("unknown public key algorithm")
}
pLength += 6
h.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)})
return
}
// Serialize marshals the PublicKey to w in the form of an OpenPGP public key
// packet, not including the packet header.
func (pk *PublicKey) Serialize(w io.Writer) (err os.Error) {
var buf [6]byte
buf[0] = 4
buf[1] = byte(pk.CreationTime >> 24)
buf[2] = byte(pk.CreationTime >> 16)
buf[3] = byte(pk.CreationTime >> 8)
buf[4] = byte(pk.CreationTime)
buf[5] = byte(pk.PubKeyAlgo)
_, err = w.Write(buf[:])
if err != nil {
return
}
switch pk.PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
return writeMPIs(w, pk.n, pk.e)
case PubKeyAlgoDSA:
return writeMPIs(w, pk.p, pk.q, pk.g, pk.y)
}
return error.InvalidArgumentError("bad public-key algorithm")
}
// CanSign returns true iff this public key can generate signatures
func (pk *PublicKey) CanSign() bool {
return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly && pk.PubKeyAlgo != PubKeyAlgoElgamal
}
// VerifySignature returns nil iff sig is a valid signature, made by this
// public key, of the data hashed into signed. signed is mutated by this call.
func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err os.Error) {
if !pk.CanSign() {
return error.InvalidArgumentError("public key cannot generate signatures")
}
rsaPublicKey, ok := pk.PublicKey.(*rsa.PublicKey)
if !ok {
// TODO(agl): support DSA and ECDSA keys.
return error.UnsupportedError("non-RSA public key")
}
signed.Write(sig.HashSuffix)
hashBytes := signed.Sum()
if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
return error.SignatureError("hash tag doesn't match")
}
err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, sig.Signature)
if err != nil {
return error.SignatureError("RSA verification failure")
}
return nil
}
// VerifyKeySignature returns nil iff sig is a valid signature, make by this
// public key, of the public key in signed.
func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) (err os.Error) {
h := sig.Hash.New()
if h == nil {
return error.UnsupportedError("hash function")
}
// RFC 4880, section 5.2.4
pk.SerializeSignaturePrefix(h)
pk.Serialize(h)
signed.SerializeSignaturePrefix(h)
signed.Serialize(h)
return pk.VerifySignature(h, sig)
}
// VerifyUserIdSignature returns nil iff sig is a valid signature, make by this
// public key, of the given user id.
func (pk *PublicKey) VerifyUserIdSignature(id string, sig *Signature) (err os.Error) {
h := sig.Hash.New()
if h == nil {
return error.UnsupportedError("hash function")
}
// RFC 4880, section 5.2.4
pk.SerializeSignaturePrefix(h)
pk.Serialize(h)
var buf [5]byte
buf[0] = 0xb4
buf[1] = byte(len(id) >> 24)
buf[2] = byte(len(id) >> 16)
buf[3] = byte(len(id) >> 8)
buf[4] = byte(len(id))
h.Write(buf[:])
h.Write([]byte(id))
return pk.VerifySignature(h, sig)
}
// A parsedMPI is used to store the contents of a big integer, along with the
// bit length that was specified in the original input. This allows the MPI to
// be reserialised exactly.
type parsedMPI struct {
bytes []byte
bitLength uint16
}
// writeMPIs is a utility function for serialising several big integers to the
// given Writer.
func writeMPIs(w io.Writer, mpis ...parsedMPI) (err os.Error) {
for _, mpi := range mpis {
err = writeMPI(w, mpi.bitLength, mpi.bytes)
if err != nil {
return
}
}
return
}

View File

@ -0,0 +1,58 @@
// 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 packet
import (
"bytes"
"encoding/hex"
"testing"
)
var pubKeyTests = []struct {
hexData string
hexFingerprint string
creationTime uint32
pubKeyAlgo PublicKeyAlgorithm
keyId uint64
}{
{rsaPkDataHex, rsaFingerprintHex, 0x4d3c5c10, PubKeyAlgoRSA, 0xa34d7e18c20c31bb},
{dsaPkDataHex, dsaFingerprintHex, 0x4d432f89, PubKeyAlgoDSA, 0x8e8fbe54062f19ed},
}
func TestPublicKeyRead(t *testing.T) {
for i, test := range pubKeyTests {
packet, err := Read(readerFromHex(test.hexData))
if err != nil {
t.Errorf("#%d: Read error: %s", i, err)
return
}
pk, ok := packet.(*PublicKey)
if !ok {
t.Errorf("#%d: failed to parse, got: %#v", i, packet)
return
}
if pk.PubKeyAlgo != test.pubKeyAlgo {
t.Errorf("#%d: bad public key algorithm got:%x want:%x", i, pk.PubKeyAlgo, test.pubKeyAlgo)
}
if pk.CreationTime != test.creationTime {
t.Errorf("#%d: bad creation time got:%x want:%x", i, pk.CreationTime, test.creationTime)
}
expectedFingerprint, _ := hex.DecodeString(test.hexFingerprint)
if !bytes.Equal(expectedFingerprint, pk.Fingerprint[:]) {
t.Errorf("#%d: bad fingerprint got:%x want:%x", i, pk.Fingerprint[:], expectedFingerprint)
}
if pk.KeyId != test.keyId {
t.Errorf("#%d: bad keyid got:%x want:%x", i, pk.KeyId, test.keyId)
}
}
}
const rsaFingerprintHex = "5fb74b1d03b1e3cb31bc2f8aa34d7e18c20c31bb"
const rsaPkDataHex = "988d044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd0011010001"
const dsaFingerprintHex = "eece4c094db002103714c63c8e8fbe54062f19ed"
const dsaPkDataHex = "9901a2044d432f89110400cd581334f0d7a1e1bdc8b9d6d8c0baf68793632735d2bb0903224cbaa1dfbf35a60ee7a13b92643421e1eb41aa8d79bea19a115a677f6b8ba3c7818ce53a6c2a24a1608bd8b8d6e55c5090cbde09dd26e356267465ae25e69ec8bdd57c7bbb2623e4d73336f73a0a9098f7f16da2e25252130fd694c0e8070c55a812a423ae7f00a0ebf50e70c2f19c3520a551bd4b08d30f23530d3d03ff7d0bf4a53a64a09dc5e6e6e35854b7d70c882b0c60293401958b1bd9e40abec3ea05ba87cf64899299d4bd6aa7f459c201d3fbbd6c82004bdc5e8a9eb8082d12054cc90fa9d4ec251a843236a588bf49552441817436c4f43326966fe85447d4e6d0acf8fa1ef0f014730770603ad7634c3088dc52501c237328417c31c89ed70400b2f1a98b0bf42f11fefc430704bebbaa41d9f355600c3facee1e490f64208e0e094ea55e3a598a219a58500bf78ac677b670a14f4e47e9cf8eab4f368cc1ddcaa18cc59309d4cc62dd4f680e73e6cc3e1ce87a84d0925efbcb26c575c093fc42eecf45135fabf6403a25c2016e1774c0484e440a18319072c617cc97ac0a3bb0"

View File

@ -0,0 +1,63 @@
// 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 packet
import (
"crypto/openpgp/error"
"io"
"os"
)
// Reader reads packets from an io.Reader and allows packets to be 'unread' so
// that they result from the next call to Next.
type Reader struct {
q []Packet
readers []io.Reader
}
// Next returns the most recently unread Packet, or reads another packet from
// the top-most io.Reader. Unknown packet types are skipped.
func (r *Reader) Next() (p Packet, err os.Error) {
if len(r.q) > 0 {
p = r.q[len(r.q)-1]
r.q = r.q[:len(r.q)-1]
return
}
for len(r.readers) > 0 {
p, err = Read(r.readers[len(r.readers)-1])
if err == nil {
return
}
if err == os.EOF {
r.readers = r.readers[:len(r.readers)-1]
continue
}
if _, ok := err.(error.UnknownPacketTypeError); !ok {
return nil, err
}
}
return nil, os.EOF
}
// Push causes the Reader to start reading from a new io.Reader. When an EOF
// error is seen from the new io.Reader, it is popped and the Reader continues
// to read from the next most recent io.Reader.
func (r *Reader) Push(reader io.Reader) {
r.readers = append(r.readers, reader)
}
// Unread causes the given Packet to be returned from the next call to Next.
func (r *Reader) Unread(p Packet) {
r.q = append(r.q, p)
}
func NewReader(r io.Reader) *Reader {
return &Reader{
q: nil,
readers: []io.Reader{r},
}
}

View File

@ -0,0 +1,468 @@
// 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 packet
import (
"crypto"
"crypto/openpgp/error"
"crypto/openpgp/s2k"
"crypto/rand"
"crypto/rsa"
"encoding/binary"
"hash"
"io"
"os"
"strconv"
)
// Signature represents a signature. See RFC 4880, section 5.2.
type Signature struct {
SigType SignatureType
PubKeyAlgo PublicKeyAlgorithm
Hash crypto.Hash
// HashSuffix is extra data that is hashed in after the signed data.
HashSuffix []byte
// HashTag contains the first two bytes of the hash for fast rejection
// of bad signed data.
HashTag [2]byte
CreationTime uint32 // Unix epoch time
Signature []byte
// The following are optional so are nil when not included in the
// signature.
SigLifetimeSecs, KeyLifetimeSecs *uint32
PreferredSymmetric, PreferredHash, PreferredCompression []uint8
IssuerKeyId *uint64
IsPrimaryId *bool
// FlagsValid is set if any flags were given. See RFC 4880, section
// 5.2.3.21 for details.
FlagsValid bool
FlagCertify, FlagSign, FlagEncryptCommunications, FlagEncryptStorage bool
outSubpackets []outputSubpacket
}
func (sig *Signature) parse(r io.Reader) (err os.Error) {
// RFC 4880, section 5.2.3
var buf [5]byte
_, err = readFull(r, buf[:1])
if err != nil {
return
}
if buf[0] != 4 {
err = error.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0])))
return
}
_, err = readFull(r, buf[:5])
if err != nil {
return
}
sig.SigType = SignatureType(buf[0])
sig.PubKeyAlgo = PublicKeyAlgorithm(buf[1])
switch sig.PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
default:
err = error.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo)))
return
}
var ok bool
sig.Hash, ok = s2k.HashIdToHash(buf[2])
if !ok {
return error.UnsupportedError("hash function " + strconv.Itoa(int(buf[2])))
}
hashedSubpacketsLength := int(buf[3])<<8 | int(buf[4])
l := 6 + hashedSubpacketsLength
sig.HashSuffix = make([]byte, l+6)
sig.HashSuffix[0] = 4
copy(sig.HashSuffix[1:], buf[:5])
hashedSubpackets := sig.HashSuffix[6:l]
_, err = readFull(r, hashedSubpackets)
if err != nil {
return
}
// See RFC 4880, section 5.2.4
trailer := sig.HashSuffix[l:]
trailer[0] = 4
trailer[1] = 0xff
trailer[2] = uint8(l >> 24)
trailer[3] = uint8(l >> 16)
trailer[4] = uint8(l >> 8)
trailer[5] = uint8(l)
err = parseSignatureSubpackets(sig, hashedSubpackets, true)
if err != nil {
return
}
_, err = readFull(r, buf[:2])
if err != nil {
return
}
unhashedSubpacketsLength := int(buf[0])<<8 | int(buf[1])
unhashedSubpackets := make([]byte, unhashedSubpacketsLength)
_, err = readFull(r, unhashedSubpackets)
if err != nil {
return
}
err = parseSignatureSubpackets(sig, unhashedSubpackets, false)
if err != nil {
return
}
_, err = readFull(r, sig.HashTag[:2])
if err != nil {
return
}
// We have already checked that the public key algorithm is RSA.
sig.Signature, _, err = readMPI(r)
return
}
// parseSignatureSubpackets parses subpackets of the main signature packet. See
// RFC 4880, section 5.2.3.1.
func parseSignatureSubpackets(sig *Signature, subpackets []byte, isHashed bool) (err os.Error) {
for len(subpackets) > 0 {
subpackets, err = parseSignatureSubpacket(sig, subpackets, isHashed)
if err != nil {
return
}
}
if sig.CreationTime == 0 {
err = error.StructuralError("no creation time in signature")
}
return
}
type signatureSubpacketType uint8
const (
creationTimeSubpacket signatureSubpacketType = 2
signatureExpirationSubpacket signatureSubpacketType = 3
keyExpirySubpacket signatureSubpacketType = 9
prefSymmetricAlgosSubpacket signatureSubpacketType = 11
issuerSubpacket signatureSubpacketType = 16
prefHashAlgosSubpacket signatureSubpacketType = 21
prefCompressionSubpacket signatureSubpacketType = 22
primaryUserIdSubpacket signatureSubpacketType = 25
keyFlagsSubpacket signatureSubpacketType = 27
)
// parseSignatureSubpacket parses a single subpacket. len(subpacket) is >= 1.
func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (rest []byte, err os.Error) {
// RFC 4880, section 5.2.3.1
var length uint32
switch {
case subpacket[0] < 192:
length = uint32(subpacket[0])
subpacket = subpacket[1:]
case subpacket[0] < 255:
if len(subpacket) < 2 {
goto Truncated
}
length = uint32(subpacket[0]-192)<<8 + uint32(subpacket[1]) + 192
subpacket = subpacket[2:]
default:
if len(subpacket) < 5 {
goto Truncated
}
length = uint32(subpacket[1])<<24 |
uint32(subpacket[2])<<16 |
uint32(subpacket[3])<<8 |
uint32(subpacket[4])
subpacket = subpacket[5:]
}
if length > uint32(len(subpacket)) {
goto Truncated
}
rest = subpacket[length:]
subpacket = subpacket[:length]
if len(subpacket) == 0 {
err = error.StructuralError("zero length signature subpacket")
return
}
packetType := subpacket[0] & 0x7f
isCritial := subpacket[0]&0x80 == 0x80
subpacket = subpacket[1:]
switch signatureSubpacketType(packetType) {
case creationTimeSubpacket:
if !isHashed {
err = error.StructuralError("signature creation time in non-hashed area")
return
}
if len(subpacket) != 4 {
err = error.StructuralError("signature creation time not four bytes")
return
}
sig.CreationTime = binary.BigEndian.Uint32(subpacket)
case signatureExpirationSubpacket:
// Signature expiration time, section 5.2.3.10
if !isHashed {
return
}
if len(subpacket) != 4 {
err = error.StructuralError("expiration subpacket with bad length")
return
}
sig.SigLifetimeSecs = new(uint32)
*sig.SigLifetimeSecs = binary.BigEndian.Uint32(subpacket)
case keyExpirySubpacket:
// Key expiration time, section 5.2.3.6
if !isHashed {
return
}
if len(subpacket) != 4 {
err = error.StructuralError("key expiration subpacket with bad length")
return
}
sig.KeyLifetimeSecs = new(uint32)
*sig.KeyLifetimeSecs = binary.BigEndian.Uint32(subpacket)
case prefSymmetricAlgosSubpacket:
// Preferred symmetric algorithms, section 5.2.3.7
if !isHashed {
return
}
sig.PreferredSymmetric = make([]byte, len(subpacket))
copy(sig.PreferredSymmetric, subpacket)
case issuerSubpacket:
// Issuer, section 5.2.3.5
if len(subpacket) != 8 {
err = error.StructuralError("issuer subpacket with bad length")
return
}
sig.IssuerKeyId = new(uint64)
*sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket)
case prefHashAlgosSubpacket:
// Preferred hash algorithms, section 5.2.3.8
if !isHashed {
return
}
sig.PreferredHash = make([]byte, len(subpacket))
copy(sig.PreferredHash, subpacket)
case prefCompressionSubpacket:
// Preferred compression algorithms, section 5.2.3.9
if !isHashed {
return
}
sig.PreferredCompression = make([]byte, len(subpacket))
copy(sig.PreferredCompression, subpacket)
case primaryUserIdSubpacket:
// Primary User ID, section 5.2.3.19
if !isHashed {
return
}
if len(subpacket) != 1 {
err = error.StructuralError("primary user id subpacket with bad length")
return
}
sig.IsPrimaryId = new(bool)
if subpacket[0] > 0 {
*sig.IsPrimaryId = true
}
case keyFlagsSubpacket:
// Key flags, section 5.2.3.21
if !isHashed {
return
}
if len(subpacket) == 0 {
err = error.StructuralError("empty key flags subpacket")
return
}
sig.FlagsValid = true
if subpacket[0]&1 != 0 {
sig.FlagCertify = true
}
if subpacket[0]&2 != 0 {
sig.FlagSign = true
}
if subpacket[0]&4 != 0 {
sig.FlagEncryptCommunications = true
}
if subpacket[0]&8 != 0 {
sig.FlagEncryptStorage = true
}
default:
if isCritial {
err = error.UnsupportedError("unknown critical signature subpacket type " + strconv.Itoa(int(packetType)))
return
}
}
return
Truncated:
err = error.StructuralError("signature subpacket truncated")
return
}
// subpacketLengthLength returns the length, in bytes, of an encoded length value.
func subpacketLengthLength(length int) int {
if length < 192 {
return 1
}
if length < 16320 {
return 2
}
return 5
}
// serialiseSubpacketLength marshals the given length into to.
func serialiseSubpacketLength(to []byte, length int) int {
if length < 192 {
to[0] = byte(length)
return 1
}
if length < 16320 {
length -= 192
to[0] = byte(length >> 8)
to[1] = byte(length)
return 2
}
to[0] = 255
to[1] = byte(length >> 24)
to[2] = byte(length >> 16)
to[3] = byte(length >> 8)
to[4] = byte(length)
return 5
}
// subpacketsLength returns the serialised length, in bytes, of the given
// subpackets.
func subpacketsLength(subpackets []outputSubpacket, hashed bool) (length int) {
for _, subpacket := range subpackets {
if subpacket.hashed == hashed {
length += subpacketLengthLength(len(subpacket.contents) + 1)
length += 1 // type byte
length += len(subpacket.contents)
}
}
return
}
// serialiseSubpackets marshals the given subpackets into to.
func serialiseSubpackets(to []byte, subpackets []outputSubpacket, hashed bool) {
for _, subpacket := range subpackets {
if subpacket.hashed == hashed {
n := serialiseSubpacketLength(to, len(subpacket.contents)+1)
to[n] = byte(subpacket.subpacketType)
to = to[1+n:]
n = copy(to, subpacket.contents)
to = to[n:]
}
}
return
}
// buildHashSuffix constructs the HashSuffix member of sig in preparation for signing.
func (sig *Signature) buildHashSuffix() (err os.Error) {
sig.outSubpackets = sig.buildSubpackets()
hashedSubpacketsLen := subpacketsLength(sig.outSubpackets, true)
var ok bool
l := 6 + hashedSubpacketsLen
sig.HashSuffix = make([]byte, l+6)
sig.HashSuffix[0] = 4
sig.HashSuffix[1] = uint8(sig.SigType)
sig.HashSuffix[2] = uint8(sig.PubKeyAlgo)
sig.HashSuffix[3], ok = s2k.HashToHashId(sig.Hash)
if !ok {
sig.HashSuffix = nil
return error.InvalidArgumentError("hash cannot be repesented in OpenPGP: " + strconv.Itoa(int(sig.Hash)))
}
sig.HashSuffix[4] = byte(hashedSubpacketsLen >> 8)
sig.HashSuffix[5] = byte(hashedSubpacketsLen)
serialiseSubpackets(sig.HashSuffix[6:l], sig.outSubpackets, true)
trailer := sig.HashSuffix[l:]
trailer[0] = 4
trailer[1] = 0xff
trailer[2] = byte(l >> 24)
trailer[3] = byte(l >> 16)
trailer[4] = byte(l >> 8)
trailer[5] = byte(l)
return
}
// SignRSA signs a message with an RSA private key. The hash, h, must contain
// the hash of message to be signed and will be mutated by this function.
func (sig *Signature) SignRSA(h hash.Hash, priv *rsa.PrivateKey) (err os.Error) {
err = sig.buildHashSuffix()
if err != nil {
return
}
h.Write(sig.HashSuffix)
digest := h.Sum()
copy(sig.HashTag[:], digest)
sig.Signature, err = rsa.SignPKCS1v15(rand.Reader, priv, sig.Hash, digest)
return
}
// Serialize marshals sig to w. SignRSA must have been called first.
func (sig *Signature) Serialize(w io.Writer) (err os.Error) {
if sig.Signature == nil {
return error.InvalidArgumentError("Signature: need to call SignRSA before Serialize")
}
unhashedSubpacketsLen := subpacketsLength(sig.outSubpackets, false)
length := len(sig.HashSuffix) - 6 /* trailer not included */ +
2 /* length of unhashed subpackets */ + unhashedSubpacketsLen +
2 /* hash tag */ + 2 /* length of signature MPI */ + len(sig.Signature)
err = serialiseHeader(w, packetTypeSignature, length)
if err != nil {
return
}
_, err = w.Write(sig.HashSuffix[:len(sig.HashSuffix)-6])
if err != nil {
return
}
unhashedSubpackets := make([]byte, 2+unhashedSubpacketsLen)
unhashedSubpackets[0] = byte(unhashedSubpacketsLen >> 8)
unhashedSubpackets[1] = byte(unhashedSubpacketsLen)
serialiseSubpackets(unhashedSubpackets[2:], sig.outSubpackets, false)
_, err = w.Write(unhashedSubpackets)
if err != nil {
return
}
_, err = w.Write(sig.HashTag[:])
if err != nil {
return
}
return writeMPI(w, 8*uint16(len(sig.Signature)), sig.Signature)
}
// outputSubpacket represents a subpacket to be marshaled.
type outputSubpacket struct {
hashed bool // true if this subpacket is in the hashed area.
subpacketType signatureSubpacketType
contents []byte
}
func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) {
creationTime := make([]byte, 4)
creationTime[0] = byte(sig.CreationTime >> 24)
creationTime[1] = byte(sig.CreationTime >> 16)
creationTime[2] = byte(sig.CreationTime >> 8)
creationTime[3] = byte(sig.CreationTime)
subpackets = append(subpackets, outputSubpacket{true, creationTimeSubpacket, creationTime})
if sig.IssuerKeyId != nil {
keyId := make([]byte, 8)
binary.BigEndian.PutUint64(keyId, *sig.IssuerKeyId)
subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, keyId})
}
return
}

View File

@ -0,0 +1,28 @@
// 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 packet
import (
"bytes"
"crypto"
"encoding/hex"
"testing"
)
func TestSignatureRead(t *testing.T) {
signatureData, _ := hex.DecodeString(signatureDataHex)
buf := bytes.NewBuffer(signatureData)
packet, err := Read(buf)
if err != nil {
t.Error(err)
return
}
sig, ok := packet.(*Signature)
if !ok || sig.SigType != SigTypeBinary || sig.PubKeyAlgo != PubKeyAlgoRSA || sig.Hash != crypto.SHA1 {
t.Errorf("failed to parse, got: %#v", packet)
}
}
const signatureDataHex = "89011c04000102000605024cb45112000a0910ab105c91af38fb158f8d07ff5596ea368c5efe015bed6e78348c0f033c931d5f2ce5db54ce7f2a7e4b4ad64db758d65a7a71773edeab7ba2a9e0908e6a94a1175edd86c1d843279f045b021a6971a72702fcbd650efc393c5474d5b59a15f96d2eaad4c4c426797e0dcca2803ef41c6ff234d403eec38f31d610c344c06f2401c262f0993b2e66cad8a81ebc4322c723e0d4ba09fe917e8777658307ad8329adacba821420741009dfe87f007759f0982275d028a392c6ed983a0d846f890b36148c7358bdb8a516007fac760261ecd06076813831a36d0459075d1befa245ae7f7fb103d92ca759e9498fe60ef8078a39a3beda510deea251ea9f0a7f0df6ef42060f20780360686f3e400e"

View File

@ -0,0 +1,102 @@
// 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 packet
import (
"crypto/cipher"
"crypto/openpgp/error"
"crypto/openpgp/s2k"
"io"
"os"
"strconv"
)
// This is the largest session key that we'll support. Since no 512-bit cipher
// has even been seriously used, this is comfortably large.
const maxSessionKeySizeInBytes = 64
// SymmetricKeyEncrypted represents a passphrase protected session key. See RFC
// 4880, section 5.3.
type SymmetricKeyEncrypted struct {
CipherFunc CipherFunction
Encrypted bool
Key []byte // Empty unless Encrypted is false.
s2k func(out, in []byte)
encryptedKey []byte
}
func (ske *SymmetricKeyEncrypted) parse(r io.Reader) (err os.Error) {
// RFC 4880, section 5.3.
var buf [2]byte
_, err = readFull(r, buf[:])
if err != nil {
return
}
if buf[0] != 4 {
return error.UnsupportedError("SymmetricKeyEncrypted version")
}
ske.CipherFunc = CipherFunction(buf[1])
if ske.CipherFunc.keySize() == 0 {
return error.UnsupportedError("unknown cipher: " + strconv.Itoa(int(buf[1])))
}
ske.s2k, err = s2k.Parse(r)
if err != nil {
return
}
encryptedKey := make([]byte, maxSessionKeySizeInBytes)
// The session key may follow. We just have to try and read to find
// out. If it exists then we limit it to maxSessionKeySizeInBytes.
n, err := readFull(r, encryptedKey)
if err != nil && err != io.ErrUnexpectedEOF {
return
}
err = nil
if n != 0 {
if n == maxSessionKeySizeInBytes {
return error.UnsupportedError("oversized encrypted session key")
}
ske.encryptedKey = encryptedKey[:n]
}
ske.Encrypted = true
return
}
// Decrypt attempts to decrypt an encrypted session key. If it returns nil,
// ske.Key will contain the session key.
func (ske *SymmetricKeyEncrypted) Decrypt(passphrase []byte) os.Error {
if !ske.Encrypted {
return nil
}
key := make([]byte, ske.CipherFunc.keySize())
ske.s2k(key, passphrase)
if len(ske.encryptedKey) == 0 {
ske.Key = key
} else {
// the IV is all zeros
iv := make([]byte, ske.CipherFunc.blockSize())
c := cipher.NewCFBDecrypter(ske.CipherFunc.new(key), iv)
c.XORKeyStream(ske.encryptedKey, ske.encryptedKey)
ske.CipherFunc = CipherFunction(ske.encryptedKey[0])
if ske.CipherFunc.blockSize() == 0 {
return error.UnsupportedError("unknown cipher: " + strconv.Itoa(int(ske.CipherFunc)))
}
ske.CipherFunc = CipherFunction(ske.encryptedKey[0])
ske.Key = ske.encryptedKey[1:]
if len(ske.Key)%ske.CipherFunc.blockSize() != 0 {
ske.Key = nil
return error.StructuralError("length of decrypted key not a multiple of block size")
}
}
ske.Encrypted = false
return nil
}

View File

@ -0,0 +1,62 @@
// 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 packet
import (
"bytes"
"encoding/hex"
"io/ioutil"
"os"
"testing"
)
func TestSymmetricKeyEncrypted(t *testing.T) {
buf := readerFromHex(symmetricallyEncryptedHex)
packet, err := Read(buf)
if err != nil {
t.Errorf("failed to read SymmetricKeyEncrypted: %s", err)
return
}
ske, ok := packet.(*SymmetricKeyEncrypted)
if !ok {
t.Error("didn't find SymmetricKeyEncrypted packet")
return
}
err = ske.Decrypt([]byte("password"))
if err != nil {
t.Error(err)
return
}
packet, err = Read(buf)
if err != nil {
t.Errorf("failed to read SymmetricallyEncrypted: %s", err)
return
}
se, ok := packet.(*SymmetricallyEncrypted)
if !ok {
t.Error("didn't find SymmetricallyEncrypted packet")
return
}
r, err := se.Decrypt(ske.CipherFunc, ske.Key)
if err != nil {
t.Error(err)
return
}
contents, err := ioutil.ReadAll(r)
if err != nil && err != os.EOF {
t.Error(err)
return
}
expectedContents, _ := hex.DecodeString(symmetricallyEncryptedContentsHex)
if !bytes.Equal(expectedContents, contents) {
t.Errorf("bad contents got:%x want:%x", contents, expectedContents)
}
}
const symmetricallyEncryptedHex = "8c0d04030302371a0b38d884f02060c91cf97c9973b8e58e028e9501708ccfe618fb92afef7fa2d80ddadd93cf"
const symmetricallyEncryptedContentsHex = "cb1062004d14c4df636f6e74656e74732e0a"

View File

@ -0,0 +1,206 @@
// 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 packet
import (
"crypto/cipher"
"crypto/openpgp/error"
"crypto/sha1"
"crypto/subtle"
"hash"
"io"
"os"
"strconv"
)
// SymmetricallyEncrypted represents a symmetrically encrypted byte string. The
// encrypted contents will consist of more OpenPGP packets. See RFC 4880,
// sections 5.7 and 5.13.
type SymmetricallyEncrypted struct {
MDC bool // true iff this is a type 18 packet and thus has an embedded MAC.
contents io.Reader
prefix []byte
}
func (se *SymmetricallyEncrypted) parse(r io.Reader) os.Error {
if se.MDC {
// See RFC 4880, section 5.13.
var buf [1]byte
_, err := readFull(r, buf[:])
if err != nil {
return err
}
if buf[0] != 1 {
return error.UnsupportedError("unknown SymmetricallyEncrypted version")
}
}
se.contents = r
return nil
}
// Decrypt returns a ReadCloser, from which the decrypted contents of the
// packet can be read. An incorrect key can, with high probability, be detected
// immediately and this will result in a KeyIncorrect error being returned.
func (se *SymmetricallyEncrypted) Decrypt(c CipherFunction, key []byte) (io.ReadCloser, os.Error) {
keySize := c.keySize()
if keySize == 0 {
return nil, error.UnsupportedError("unknown cipher: " + strconv.Itoa(int(c)))
}
if len(key) != keySize {
return nil, error.InvalidArgumentError("SymmetricallyEncrypted: incorrect key length")
}
if se.prefix == nil {
se.prefix = make([]byte, c.blockSize()+2)
_, err := readFull(se.contents, se.prefix)
if err != nil {
return nil, err
}
} else if len(se.prefix) != c.blockSize()+2 {
return nil, error.InvalidArgumentError("can't try ciphers with different block lengths")
}
ocfbResync := cipher.OCFBResync
if se.MDC {
// MDC packets use a different form of OCFB mode.
ocfbResync = cipher.OCFBNoResync
}
s := cipher.NewOCFBDecrypter(c.new(key), se.prefix, ocfbResync)
if s == nil {
return nil, error.KeyIncorrectError
}
plaintext := cipher.StreamReader{S: s, R: se.contents}
if se.MDC {
// MDC packets have an embedded hash that we need to check.
h := sha1.New()
h.Write(se.prefix)
return &seMDCReader{in: plaintext, h: h}, nil
}
// Otherwise, we just need to wrap plaintext so that it's a valid ReadCloser.
return seReader{plaintext}, nil
}
// seReader wraps an io.Reader with a no-op Close method.
type seReader struct {
in io.Reader
}
func (ser seReader) Read(buf []byte) (int, os.Error) {
return ser.in.Read(buf)
}
func (ser seReader) Close() os.Error {
return nil
}
const mdcTrailerSize = 1 /* tag byte */ + 1 /* length byte */ + sha1.Size
// An seMDCReader wraps an io.Reader, maintains a running hash and keeps hold
// of the most recent 22 bytes (mdcTrailerSize). Upon EOF, those bytes form an
// MDC packet containing a hash of the previous contents which is checked
// against the running hash. See RFC 4880, section 5.13.
type seMDCReader struct {
in io.Reader
h hash.Hash
trailer [mdcTrailerSize]byte
scratch [mdcTrailerSize]byte
trailerUsed int
error bool
eof bool
}
func (ser *seMDCReader) Read(buf []byte) (n int, err os.Error) {
if ser.error {
err = io.ErrUnexpectedEOF
return
}
if ser.eof {
err = os.EOF
return
}
// If we haven't yet filled the trailer buffer then we must do that
// first.
for ser.trailerUsed < mdcTrailerSize {
n, err = ser.in.Read(ser.trailer[ser.trailerUsed:])
ser.trailerUsed += n
if err == os.EOF {
if ser.trailerUsed != mdcTrailerSize {
n = 0
err = io.ErrUnexpectedEOF
ser.error = true
return
}
ser.eof = true
n = 0
return
}
if err != nil {
n = 0
return
}
}
// If it's a short read then we read into a temporary buffer and shift
// the data into the caller's buffer.
if len(buf) <= mdcTrailerSize {
n, err = readFull(ser.in, ser.scratch[:len(buf)])
copy(buf, ser.trailer[:n])
ser.h.Write(buf[:n])
copy(ser.trailer[:], ser.trailer[n:])
copy(ser.trailer[mdcTrailerSize-n:], ser.scratch[:])
if n < len(buf) {
ser.eof = true
err = os.EOF
}
return
}
n, err = ser.in.Read(buf[mdcTrailerSize:])
copy(buf, ser.trailer[:])
ser.h.Write(buf[:n])
copy(ser.trailer[:], buf[n:])
if err == os.EOF {
ser.eof = true
}
return
}
func (ser *seMDCReader) Close() os.Error {
if ser.error {
return error.SignatureError("error during reading")
}
for !ser.eof {
// We haven't seen EOF so we need to read to the end
var buf [1024]byte
_, err := ser.Read(buf[:])
if err == os.EOF {
break
}
if err != nil {
return error.SignatureError("error during reading")
}
}
// This is a new-format packet tag byte for a type 19 (MDC) packet.
const mdcPacketTagByte = byte(0x80) | 0x40 | 19
if ser.trailer[0] != mdcPacketTagByte || ser.trailer[1] != sha1.Size {
return error.SignatureError("MDC packet not found")
}
ser.h.Write(ser.trailer[:2])
final := ser.h.Sum()
if subtle.ConstantTimeCompare(final, ser.trailer[2:]) == 1 {
return error.SignatureError("hash mismatch")
}
return nil
}

View File

@ -0,0 +1,78 @@
// 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 packet
import (
"bytes"
"crypto/openpgp/error"
"crypto/sha1"
"encoding/hex"
"io/ioutil"
"os"
"testing"
)
// TestReader wraps a []byte and returns reads of a specific length.
type testReader struct {
data []byte
stride int
}
func (t *testReader) Read(buf []byte) (n int, err os.Error) {
n = t.stride
if n > len(t.data) {
n = len(t.data)
}
if n > len(buf) {
n = len(buf)
}
copy(buf, t.data)
t.data = t.data[n:]
if len(t.data) == 0 {
err = os.EOF
}
return
}
func testMDCReader(t *testing.T) {
mdcPlaintext, _ := hex.DecodeString(mdcPlaintextHex)
for stride := 1; stride < len(mdcPlaintext)/2; stride++ {
r := &testReader{data: mdcPlaintext, stride: stride}
mdcReader := &seMDCReader{in: r, h: sha1.New()}
body, err := ioutil.ReadAll(mdcReader)
if err != nil {
t.Errorf("stride: %d, error: %s", stride, err)
continue
}
if !bytes.Equal(body, mdcPlaintext[:len(mdcPlaintext)-22]) {
t.Errorf("stride: %d: bad contents %x", stride, body)
continue
}
err = mdcReader.Close()
if err != nil {
t.Errorf("stride: %d, error on Close: %s", stride, err)
}
}
mdcPlaintext[15] ^= 80
r := &testReader{data: mdcPlaintext, stride: 2}
mdcReader := &seMDCReader{in: r, h: sha1.New()}
_, err := ioutil.ReadAll(mdcReader)
if err != nil {
t.Errorf("corruption test, error: %s", err)
return
}
err = mdcReader.Close()
if err == nil {
t.Error("corruption: no error")
} else if _, ok := err.(*error.SignatureError); !ok {
t.Errorf("corruption: expected SignatureError, got: %s", err)
}
}
const mdcPlaintextHex = "a302789c3b2d93c4e0eb9aba22283539b3203335af44a134afb800c849cb4c4de10200aff40b45d31432c80cb384299a0655966d6939dfdeed1dddf980"

View File

@ -0,0 +1,105 @@
// 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 packet
import (
"io"
"io/ioutil"
"os"
"strings"
)
// UserId contains text that is intended to represent the name and email
// address of the key holder. See RFC 4880, section 5.11. By convention, this
// takes the form "Full Name (Comment) <email@example.com>"
type UserId struct {
Id string // By convention, this takes the form "Full Name (Comment) <email@example.com>" which is split out in the fields below.
Name, Comment, Email string
}
func (uid *UserId) parse(r io.Reader) (err os.Error) {
// RFC 4880, section 5.11
b, err := ioutil.ReadAll(r)
if err != nil {
return
}
uid.Id = string(b)
uid.Name, uid.Comment, uid.Email = parseUserId(uid.Id)
return
}
// parseUserId extracts the name, comment and email from a user id string that
// is formatted as "Full Name (Comment) <email@example.com>".
func parseUserId(id string) (name, comment, email string) {
var n, c, e struct {
start, end int
}
var state int
for offset, rune := range id {
switch state {
case 0:
// Entering name
n.start = offset
state = 1
fallthrough
case 1:
// In name
if rune == '(' {
state = 2
n.end = offset
} else if rune == '<' {
state = 5
n.end = offset
}
case 2:
// Entering comment
c.start = offset
state = 3
fallthrough
case 3:
// In comment
if rune == ')' {
state = 4
c.end = offset
}
case 4:
// Between comment and email
if rune == '<' {
state = 5
}
case 5:
// Entering email
e.start = offset
state = 6
fallthrough
case 6:
// In email
if rune == '>' {
state = 7
e.end = offset
}
default:
// After email
}
}
switch state {
case 1:
// ended in the name
n.end = len(id)
case 3:
// ended in comment
c.end = len(id)
case 6:
// ended in email
e.end = len(id)
}
name = strings.TrimSpace(id[n.start:n.end])
comment = strings.TrimSpace(id[c.start:c.end])
email = strings.TrimSpace(id[e.start:e.end])
return
}

View File

@ -0,0 +1,42 @@
// 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 packet
import (
"testing"
)
var userIdTests = []struct {
id string
name, comment, email string
}{
{"", "", "", ""},
{"John Smith", "John Smith", "", ""},
{"John Smith ()", "John Smith", "", ""},
{"John Smith () <>", "John Smith", "", ""},
{"(comment", "", "comment", ""},
{"(comment)", "", "comment", ""},
{"<email", "", "", "email"},
{"<email> sdfk", "", "", "email"},
{" John Smith ( Comment ) asdkflj < email > lksdfj", "John Smith", "Comment", "email"},
{" John Smith < email > lksdfj", "John Smith", "", "email"},
{"(<foo", "", "<foo", ""},
{"René Descartes (العربي)", "René Descartes", "العربي", ""},
}
func TestParseUserId(t *testing.T) {
for i, test := range userIdTests {
name, comment, email := parseUserId(test.id)
if name != test.name {
t.Errorf("%d: name mismatch got:%s want:%s", i, name, test.name)
}
if comment != test.comment {
t.Errorf("%d: comment mismatch got:%s want:%s", i, comment, test.comment)
}
if email != test.email {
t.Errorf("%d: email mismatch got:%s want:%s", i, email, test.email)
}
}
}

View File

@ -0,0 +1,413 @@
// 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.
// This openpgp package implements high level operations on OpenPGP messages.
package openpgp
import (
"crypto"
"crypto/openpgp/armor"
"crypto/openpgp/error"
"crypto/openpgp/packet"
"crypto/rsa"
_ "crypto/sha256"
"hash"
"io"
"os"
"strconv"
)
// SignatureType is the armor type for a PGP signature.
var SignatureType = "PGP SIGNATURE"
// readArmored reads an armored block with the given type.
func readArmored(r io.Reader, expectedType string) (body io.Reader, err os.Error) {
block, err := armor.Decode(r)
if err != nil {
return
}
if block.Type != expectedType {
return nil, error.InvalidArgumentError("expected '" + expectedType + "', got: " + block.Type)
}
return block.Body, nil
}
// MessageDetails contains the result of parsing an OpenPGP encrypted and/or
// signed message.
type MessageDetails struct {
IsEncrypted bool // true if the message was encrypted.
EncryptedToKeyIds []uint64 // the list of recipient key ids.
IsSymmetricallyEncrypted bool // true if a passphrase could have decrypted the message.
DecryptedWith Key // the private key used to decrypt the message, if any.
IsSigned bool // true if the message is signed.
SignedByKeyId uint64 // the key id of the signer, if any.
SignedBy *Key // the key of the signer, if availible.
LiteralData *packet.LiteralData // the metadata of the contents
UnverifiedBody io.Reader // the contents of the message.
// If IsSigned is true and SignedBy is non-zero then the signature will
// be verified as UnverifiedBody is read. The signature cannot be
// checked until the whole of UnverifiedBody is read so UnverifiedBody
// must be consumed until EOF before the data can trusted. Even if a
// message isn't signed (or the signer is unknown) the data may contain
// an authentication code that is only checked once UnverifiedBody has
// been consumed. Once EOF has been seen, the following fields are
// valid. (An authentication code failure is reported as a
// SignatureError error when reading from UnverifiedBody.)
SignatureError os.Error // nil if the signature is good.
Signature *packet.Signature // the signature packet itself.
decrypted io.ReadCloser
}
// A PromptFunction is used as a callback by functions that may need to decrypt
// a private key, or prompt for a passphrase. It is called with a list of
// acceptable, encrypted private keys and a boolean that indicates whether a
// passphrase is usable. It should either decrypt a private key or return a
// passphrase to try. If the decrypted private key or given passphrase isn't
// correct, the function will be called again, forever. Any error returned will
// be passed up.
type PromptFunction func(keys []Key, symmetric bool) ([]byte, os.Error)
// A keyEnvelopePair is used to store a private key with the envelope that
// contains a symmetric key, encrypted with that key.
type keyEnvelopePair struct {
key Key
encryptedKey *packet.EncryptedKey
}
// ReadMessage parses an OpenPGP message that may be signed and/or encrypted.
// The given KeyRing should contain both public keys (for signature
// verification) and, possibly encrypted, private keys for decrypting.
func ReadMessage(r io.Reader, keyring KeyRing, prompt PromptFunction) (md *MessageDetails, err os.Error) {
var p packet.Packet
var symKeys []*packet.SymmetricKeyEncrypted
var pubKeys []keyEnvelopePair
var se *packet.SymmetricallyEncrypted
packets := packet.NewReader(r)
md = new(MessageDetails)
md.IsEncrypted = true
// The message, if encrypted, starts with a number of packets
// containing an encrypted decryption key. The decryption key is either
// encrypted to a public key, or with a passphrase. This loop
// collects these packets.
ParsePackets:
for {
p, err = packets.Next()
if err != nil {
return nil, err
}
switch p := p.(type) {
case *packet.SymmetricKeyEncrypted:
// This packet contains the decryption key encrypted with a passphrase.
md.IsSymmetricallyEncrypted = true
symKeys = append(symKeys, p)
case *packet.EncryptedKey:
// This packet contains the decryption key encrypted to a public key.
md.EncryptedToKeyIds = append(md.EncryptedToKeyIds, p.KeyId)
if p.Algo != packet.PubKeyAlgoRSA && p.Algo != packet.PubKeyAlgoRSAEncryptOnly {
continue
}
var keys []Key
if p.KeyId == 0 {
keys = keyring.DecryptionKeys()
} else {
keys = keyring.KeysById(p.KeyId)
}
for _, k := range keys {
pubKeys = append(pubKeys, keyEnvelopePair{k, p})
}
case *packet.SymmetricallyEncrypted:
se = p
break ParsePackets
case *packet.Compressed, *packet.LiteralData, *packet.OnePassSignature:
// This message isn't encrypted.
if len(symKeys) != 0 || len(pubKeys) != 0 {
return nil, error.StructuralError("key material not followed by encrypted message")
}
packets.Unread(p)
return readSignedMessage(packets, nil, keyring)
}
}
var candidates []Key
var decrypted io.ReadCloser
// Now that we have the list of encrypted keys we need to decrypt at
// least one of them or, if we cannot, we need to call the prompt
// function so that it can decrypt a key or give us a passphrase.
FindKey:
for {
// See if any of the keys already have a private key availible
candidates = candidates[:0]
candidateFingerprints := make(map[string]bool)
for _, pk := range pubKeys {
if pk.key.PrivateKey == nil {
continue
}
if !pk.key.PrivateKey.Encrypted {
if len(pk.encryptedKey.Key) == 0 {
pk.encryptedKey.DecryptRSA(pk.key.PrivateKey.PrivateKey.(*rsa.PrivateKey))
}
if len(pk.encryptedKey.Key) == 0 {
continue
}
decrypted, err = se.Decrypt(pk.encryptedKey.CipherFunc, pk.encryptedKey.Key)
if err != nil && err != error.KeyIncorrectError {
return nil, err
}
if decrypted != nil {
md.DecryptedWith = pk.key
break FindKey
}
} else {
fpr := string(pk.key.PublicKey.Fingerprint[:])
if v := candidateFingerprints[fpr]; v {
continue
}
candidates = append(candidates, pk.key)
candidateFingerprints[fpr] = true
}
}
if len(candidates) == 0 && len(symKeys) == 0 {
return nil, error.KeyIncorrectError
}
if prompt == nil {
return nil, error.KeyIncorrectError
}
passphrase, err := prompt(candidates, len(symKeys) != 0)
if err != nil {
return nil, err
}
// Try the symmetric passphrase first
if len(symKeys) != 0 && passphrase != nil {
for _, s := range symKeys {
err = s.Decrypt(passphrase)
if err == nil && !s.Encrypted {
decrypted, err = se.Decrypt(s.CipherFunc, s.Key)
if err != nil && err != error.KeyIncorrectError {
return nil, err
}
if decrypted != nil {
break FindKey
}
}
}
}
}
md.decrypted = decrypted
packets.Push(decrypted)
return readSignedMessage(packets, md, keyring)
}
// readSignedMessage reads a possibily signed message if mdin is non-zero then
// that structure is updated and returned. Otherwise a fresh MessageDetails is
// used.
func readSignedMessage(packets *packet.Reader, mdin *MessageDetails, keyring KeyRing) (md *MessageDetails, err os.Error) {
if mdin == nil {
mdin = new(MessageDetails)
}
md = mdin
var p packet.Packet
var h hash.Hash
var wrappedHash hash.Hash
FindLiteralData:
for {
p, err = packets.Next()
if err != nil {
return nil, err
}
switch p := p.(type) {
case *packet.Compressed:
packets.Push(p.Body)
case *packet.OnePassSignature:
if !p.IsLast {
return nil, error.UnsupportedError("nested signatures")
}
h, wrappedHash, err = hashForSignature(p.Hash, p.SigType)
if err != nil {
md = nil
return
}
md.IsSigned = true
md.SignedByKeyId = p.KeyId
keys := keyring.KeysById(p.KeyId)
for _, key := range keys {
if key.SelfSignature.FlagsValid && !key.SelfSignature.FlagSign {
continue
}
md.SignedBy = &key
}
case *packet.LiteralData:
md.LiteralData = p
break FindLiteralData
}
}
if md.SignedBy != nil {
md.UnverifiedBody = &signatureCheckReader{packets, h, wrappedHash, md}
} else if md.decrypted != nil {
md.UnverifiedBody = checkReader{md}
} else {
md.UnverifiedBody = md.LiteralData.Body
}
return md, nil
}
// hashForSignature returns a pair of hashes that can be used to verify a
// signature. The signature may specify that the contents of the signed message
// should be preprocessed (i.e. to normalise line endings). Thus this function
// returns two hashes. The second should be used to hash the message itself and
// performs any needed preprocessing.
func hashForSignature(hashId crypto.Hash, sigType packet.SignatureType) (hash.Hash, hash.Hash, os.Error) {
h := hashId.New()
if h == nil {
return nil, nil, error.UnsupportedError("hash not availible: " + strconv.Itoa(int(hashId)))
}
switch sigType {
case packet.SigTypeBinary:
return h, h, nil
case packet.SigTypeText:
return h, NewCanonicalTextHash(h), nil
}
return nil, nil, error.UnsupportedError("unsupported signature type: " + strconv.Itoa(int(sigType)))
}
// checkReader wraps an io.Reader from a LiteralData packet. When it sees EOF
// it closes the ReadCloser from any SymmetricallyEncrypted packet to trigger
// MDC checks.
type checkReader struct {
md *MessageDetails
}
func (cr checkReader) Read(buf []byte) (n int, err os.Error) {
n, err = cr.md.LiteralData.Body.Read(buf)
if err == os.EOF {
mdcErr := cr.md.decrypted.Close()
if mdcErr != nil {
err = mdcErr
}
}
return
}
// signatureCheckReader wraps an io.Reader from a LiteralData packet and hashes
// the data as it is read. When it sees an EOF from the underlying io.Reader
// it parses and checks a trailing Signature packet and triggers any MDC checks.
type signatureCheckReader struct {
packets *packet.Reader
h, wrappedHash hash.Hash
md *MessageDetails
}
func (scr *signatureCheckReader) Read(buf []byte) (n int, err os.Error) {
n, err = scr.md.LiteralData.Body.Read(buf)
scr.wrappedHash.Write(buf[:n])
if err == os.EOF {
var p packet.Packet
p, scr.md.SignatureError = scr.packets.Next()
if scr.md.SignatureError != nil {
return
}
var ok bool
if scr.md.Signature, ok = p.(*packet.Signature); !ok {
scr.md.SignatureError = error.StructuralError("LiteralData not followed by Signature")
return
}
scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignature(scr.h, scr.md.Signature)
// The SymmetricallyEncrypted packet, if any, might have an
// unsigned hash of its own. In order to check this we need to
// close that Reader.
if scr.md.decrypted != nil {
mdcErr := scr.md.decrypted.Close()
if mdcErr != nil {
err = mdcErr
}
}
}
return
}
// CheckDetachedSignature takes a signed file and a detached signature and
// returns the signer if the signature is valid. If the signer isn't know,
// UnknownIssuerError is returned.
func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err os.Error) {
p, err := packet.Read(signature)
if err != nil {
return
}
sig, ok := p.(*packet.Signature)
if !ok {
return nil, error.StructuralError("non signature packet found")
}
if sig.IssuerKeyId == nil {
return nil, error.StructuralError("signature doesn't have an issuer")
}
keys := keyring.KeysById(*sig.IssuerKeyId)
if len(keys) == 0 {
return nil, error.UnknownIssuerError
}
h, wrappedHash, err := hashForSignature(sig.Hash, sig.SigType)
if err != nil {
return
}
_, err = io.Copy(wrappedHash, signed)
if err != nil && err != os.EOF {
return
}
for _, key := range keys {
if key.SelfSignature.FlagsValid && !key.SelfSignature.FlagSign {
continue
}
err = key.PublicKey.VerifySignature(h, sig)
if err == nil {
return key.Entity, nil
}
}
if err != nil {
return
}
return nil, error.UnknownIssuerError
}
// CheckArmoredDetachedSignature performs the same actions as
// CheckDetachedSignature but expects the signature to be armored.
func CheckArmoredDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err os.Error) {
body, err := readArmored(signature, SignatureType)
if err != nil {
return
}
return CheckDetachedSignature(keyring, signed, body)
}

File diff suppressed because one or more lines are too long

View File

@ -7,15 +7,12 @@
package s2k
import (
"crypto/md5"
"crypto"
"crypto/openpgp/error"
"crypto/ripemd160"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"hash"
"io"
"os"
"strconv"
)
// Simple writes to out the result of computing the Simple S2K function (RFC
@ -87,9 +84,13 @@ func Parse(r io.Reader) (f func(out, in []byte), err os.Error) {
return
}
h := hashFuncFromType(buf[1])
hash, ok := HashIdToHash(buf[1])
if !ok {
return nil, error.UnsupportedError("hash for S2K function: " + strconv.Itoa(int(buf[1])))
}
h := hash.New()
if h == nil {
return nil, error.UnsupportedError("hash for S2K function")
return nil, error.UnsupportedError("hash not availible: " + strconv.Itoa(int(hash)))
}
switch buf[0] {
@ -122,25 +123,38 @@ func Parse(r io.Reader) (f func(out, in []byte), err os.Error) {
return nil, error.UnsupportedError("S2K function")
}
// hashFuncFromType returns a hash.Hash which corresponds to the given hash
// type byte. See RFC 4880, section 9.4.
func hashFuncFromType(hashType byte) hash.Hash {
switch hashType {
case 1:
return md5.New()
case 2:
return sha1.New()
case 3:
return ripemd160.New()
case 8:
return sha256.New()
case 9:
return sha512.New384()
case 10:
return sha512.New()
case 11:
return sha256.New224()
}
return nil
// hashToHashIdMapping contains pairs relating OpenPGP's hash identifier with
// Go's crypto.Hash type. See RFC 4880, section 9.4.
var hashToHashIdMapping = []struct {
id byte
hash crypto.Hash
}{
{1, crypto.MD5},
{2, crypto.SHA1},
{3, crypto.RIPEMD160},
{8, crypto.SHA256},
{9, crypto.SHA384},
{10, crypto.SHA512},
{11, crypto.SHA224},
}
// HashIdToHash returns a crypto.Hash which corresponds to the given OpenPGP
// hash id.
func HashIdToHash(id byte) (h crypto.Hash, ok bool) {
for _, m := range hashToHashIdMapping {
if m.id == id {
return m.hash, true
}
}
return 0, false
}
// HashIdToHash returns an OpenPGP hash id which corresponds the given Hash.
func HashToHashId(h crypto.Hash) (id byte, ok bool) {
for _, m := range hashToHashIdMapping {
if m.hash == h {
return m.id, true
}
}
return 0, false
}

View File

@ -0,0 +1,92 @@
// 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 openpgp
import (
"crypto"
"crypto/openpgp/armor"
"crypto/openpgp/error"
"crypto/openpgp/packet"
"crypto/rsa"
_ "crypto/sha256"
"io"
"os"
"strconv"
"time"
)
// DetachSign signs message with the private key from signer (which must
// already have been decrypted) and writes the signature to w.
func DetachSign(w io.Writer, signer *Entity, message io.Reader) os.Error {
return detachSign(w, signer, message, packet.SigTypeBinary)
}
// ArmoredDetachSign signs message with the private key from signer (which
// must already have been decrypted) and writes an armored signature to w.
func ArmoredDetachSign(w io.Writer, signer *Entity, message io.Reader) (err os.Error) {
return armoredDetachSign(w, signer, message, packet.SigTypeBinary)
}
// DetachSignText signs message (after canonicalising the line endings) with
// the private key from signer (which must already have been decrypted) and
// writes the signature to w.
func DetachSignText(w io.Writer, signer *Entity, message io.Reader) os.Error {
return detachSign(w, signer, message, packet.SigTypeText)
}
// ArmoredDetachSignText signs message (after canonicalising the line endings)
// with the private key from signer (which must already have been decrypted)
// and writes an armored signature to w.
func SignTextDetachedArmored(w io.Writer, signer *Entity, message io.Reader) os.Error {
return armoredDetachSign(w, signer, message, packet.SigTypeText)
}
func armoredDetachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType) (err os.Error) {
out, err := armor.Encode(w, SignatureType, nil)
if err != nil {
return
}
err = detachSign(out, signer, message, sigType)
if err != nil {
return
}
return out.Close()
}
func detachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType) (err os.Error) {
if signer.PrivateKey == nil {
return error.InvalidArgumentError("signing key doesn't have a private key")
}
if signer.PrivateKey.Encrypted {
return error.InvalidArgumentError("signing key is encrypted")
}
sig := new(packet.Signature)
sig.SigType = sigType
sig.PubKeyAlgo = signer.PrivateKey.PubKeyAlgo
sig.Hash = crypto.SHA256
sig.CreationTime = uint32(time.Seconds())
sig.IssuerKeyId = &signer.PrivateKey.KeyId
h, wrappedHash, err := hashForSignature(sig.Hash, sig.SigType)
if err != nil {
return
}
io.Copy(wrappedHash, message)
switch signer.PrivateKey.PubKeyAlgo {
case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSASignOnly:
priv := signer.PrivateKey.PrivateKey.(*rsa.PrivateKey)
err = sig.SignRSA(h, priv)
default:
err = error.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo)))
}
if err != nil {
return
}
return sig.Serialize(w)
}

View File

@ -0,0 +1,34 @@
// 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 openpgp
import (
"bytes"
"testing"
)
func TestSignDetached(t *testing.T) {
kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex))
out := bytes.NewBuffer(nil)
message := bytes.NewBufferString(signedInput)
err := DetachSign(out, kring[0], message)
if err != nil {
t.Error(err)
}
testDetachedSignature(t, kring, out, signedInput, "check")
}
func TestSignTextDetached(t *testing.T) {
kring, _ := ReadKeyRing(readerFromHex(testKeys1And2PrivateHex))
out := bytes.NewBuffer(nil)
message := bytes.NewBufferString(signedInput)
err := DetachSignText(out, kring[0], message)
if err != nil {
t.Error(err)
}
testDetachedSignature(t, kring, out, signedInput, "check")
}

View File

@ -8,6 +8,7 @@
package rand
import (
"bufio"
"crypto/aes"
"io"
"os"
@ -23,21 +24,20 @@ func init() { Reader = &devReader{name: "/dev/urandom"} }
// A devReader satisfies reads by reading the file named name.
type devReader struct {
name string
f *os.File
f io.Reader
mu sync.Mutex
}
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)
if f == nil {
r.mu.Unlock()
return 0, err
}
r.f = f
r.f = bufio.NewReader(f)
}
r.mu.Unlock()
return r.f.Read(b)
}

View File

@ -28,15 +28,15 @@ func (r *rngReader) Read(b []byte) (n int, err os.Error) {
if r.prov == 0 {
const provType = syscall.PROV_RSA_FULL
const flags = syscall.CRYPT_VERIFYCONTEXT | syscall.CRYPT_SILENT
ok, errno := syscall.CryptAcquireContext(&r.prov, nil, nil, provType, flags)
if !ok {
errno := syscall.CryptAcquireContext(&r.prov, nil, nil, provType, flags)
if errno != 0 {
r.mu.Unlock()
return 0, os.NewSyscallError("CryptAcquireContext", errno)
}
}
r.mu.Unlock()
ok, errno := syscall.CryptGenRandom(r.prov, uint32(len(b)), &b[0])
if !ok {
errno := syscall.CryptGenRandom(r.prov, uint32(len(b)), &b[0])
if errno != 0 {
return 0, os.NewSyscallError("CryptGenRandom", errno)
}
return len(b), nil

View File

@ -10,10 +10,15 @@ package ripemd160
// http://homes.esat.kuleuven.be/~cosicart/pdf/AB-9601/AB-9601.pdf.
import (
"crypto"
"hash"
"os"
)
func init() {
crypto.RegisterHash(crypto.RIPEMD160, New)
}
// The size of the checksum in bytes.
const Size = 20

View File

@ -6,6 +6,7 @@ package rsa
import (
"big"
"crypto"
"crypto/subtle"
"io"
"os"
@ -139,19 +140,6 @@ func nonZeroRandomBytes(s []byte, rand io.Reader) (err os.Error) {
return
}
// Due to the design of PKCS#1 v1.5, we need to know the exact hash function in
// use. A generic hash.Hash will not do.
type PKCS1v15Hash int
const (
HashMD5 PKCS1v15Hash = iota
HashSHA1
HashSHA256
HashSHA384
HashSHA512
HashMD5SHA1 // combined MD5 and SHA1 hash used for RSA signing in TLS.
)
// These are ASN1 DER structures:
// DigestInfo ::= SEQUENCE {
// digestAlgorithm AlgorithmIdentifier,
@ -160,25 +148,20 @@ const (
// For performance, we don't use the generic ASN1 encoder. Rather, we
// precompute a prefix of the digest value that makes a valid ASN1 DER string
// with the correct contents.
var hashPrefixes = [][]byte{
// HashMD5
{0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10},
// HashSHA1
{0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14},
// HashSHA256
{0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20},
// HashSHA384
{0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30},
// HashSHA512
{0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40},
// HashMD5SHA1
{}, // A special TLS case which doesn't use an ASN1 prefix.
var hashPrefixes = map[crypto.Hash][]byte{
crypto.MD5: []byte{0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10},
crypto.SHA1: []byte{0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14},
crypto.SHA256: []byte{0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20},
crypto.SHA384: []byte{0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30},
crypto.SHA512: {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40},
crypto.MD5SHA1: {}, // A special TLS case which doesn't use an ASN1 prefix.
crypto.RIPEMD160: {0x30, 0x20, 0x30, 0x08, 0x06, 0x06, 0x28, 0xcf, 0x06, 0x03, 0x00, 0x31, 0x04, 0x14},
}
// SignPKCS1v15 calcuates the signature of hashed using RSASSA-PSS-SIGN from RSA PKCS#1 v1.5.
// SignPKCS1v15 calculates the signature of hashed using RSASSA-PKCS1-V1_5-SIGN from RSA PKCS#1 v1.5.
// Note that hashed must be the result of hashing the input message using the
// given hash function.
func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash PKCS1v15Hash, hashed []byte) (s []byte, err os.Error) {
func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) (s []byte, err os.Error) {
hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed))
if err != nil {
return
@ -211,7 +194,7 @@ func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash PKCS1v15Hash, hashed []
// hashed is the result of hashing the input message using the given hash
// function and sig is the signature. A valid signature is indicated by
// returning a nil error.
func VerifyPKCS1v15(pub *PublicKey, hash PKCS1v15Hash, hashed []byte, sig []byte) (err os.Error) {
func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) (err os.Error) {
hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed))
if err != nil {
return
@ -246,28 +229,14 @@ func VerifyPKCS1v15(pub *PublicKey, hash PKCS1v15Hash, hashed []byte, sig []byte
return nil
}
func pkcs1v15HashInfo(hash PKCS1v15Hash, inLen int) (hashLen int, prefix []byte, err os.Error) {
switch hash {
case HashMD5:
hashLen = 16
case HashSHA1:
hashLen = 20
case HashSHA256:
hashLen = 32
case HashSHA384:
hashLen = 48
case HashSHA512:
hashLen = 64
case HashMD5SHA1:
hashLen = 36
default:
return 0, nil, os.ErrorString("unknown hash function")
}
func pkcs1v15HashInfo(hash crypto.Hash, inLen int) (hashLen int, prefix []byte, err os.Error) {
hashLen = hash.Size()
if inLen != hashLen {
return 0, nil, os.ErrorString("input must be hashed message")
}
prefix = hashPrefixes[int(hash)]
prefix, ok := hashPrefixes[hash]
if !ok {
return 0, nil, os.ErrorString("unsupported hash function")
}
return
}

View File

@ -7,6 +7,7 @@ package rsa
import (
"big"
"bytes"
"crypto"
"crypto/rand"
"crypto/sha1"
"encoding/base64"
@ -165,7 +166,7 @@ func TestSignPKCS1v15(t *testing.T) {
h.Write([]byte(test.in))
digest := h.Sum()
s, err := SignPKCS1v15(nil, rsaPrivateKey, HashSHA1, digest)
s, err := SignPKCS1v15(nil, rsaPrivateKey, crypto.SHA1, digest)
if err != nil {
t.Errorf("#%d %s", i, err)
}
@ -185,7 +186,7 @@ func TestVerifyPKCS1v15(t *testing.T) {
sig, _ := hex.DecodeString(test.out)
err := VerifyPKCS1v15(&rsaPrivateKey.PublicKey, HashSHA1, digest, sig)
err := VerifyPKCS1v15(&rsaPrivateKey.PublicKey, crypto.SHA1, digest, sig)
if err != nil {
t.Errorf("#%d %s", i, err)
}

View File

@ -274,6 +274,14 @@ func EncryptOAEP(hash hash.Hash, rand io.Reader, pub *PublicKey, msg []byte, lab
m.SetBytes(em)
c := encrypt(new(big.Int), pub, m)
out = c.Bytes()
if len(out) < k {
// If the output is too small, we need to left-pad with zeros.
t := make([]byte, k)
copy(t[k-len(out):], out)
out = t
}
return
}

View File

@ -66,7 +66,7 @@ func TestEncryptOAEP(t *testing.T) {
t.Errorf("#%d,%d error: %s", i, j, err)
}
if bytes.Compare(out, message.out) != 0 {
t.Errorf("#%d,%d bad result: %s (want %s)", i, j, out, message.out)
t.Errorf("#%d,%d bad result: %x (want %x)", i, j, out, message.out)
}
}
}

View File

@ -6,10 +6,15 @@
package sha1
import (
"crypto"
"hash"
"os"
)
func init() {
crypto.RegisterHash(crypto.SHA1, New)
}
// The size of a SHA1 checksum in bytes.
const Size = 20

View File

@ -6,10 +6,16 @@
package sha256
import (
"crypto"
"hash"
"os"
)
func init() {
crypto.RegisterHash(crypto.SHA224, New224)
crypto.RegisterHash(crypto.SHA256, New)
}
// The size of a SHA256 checksum in bytes.
const Size = 32

View File

@ -6,10 +6,16 @@
package sha512
import (
"crypto"
"hash"
"os"
)
func init() {
crypto.RegisterHash(crypto.SHA384, New384)
crypto.RegisterHash(crypto.SHA512, New)
}
// The size of a SHA512 checksum in bytes.
const Size = 64

View File

@ -5,6 +5,7 @@
package tls
import (
"crypto"
"crypto/rsa"
"crypto/subtle"
"crypto/x509"
@ -56,7 +57,7 @@ func (c *Conn) clientHandshake() os.Error {
vers, ok := mutualVersion(serverHello.vers)
if !ok {
c.sendAlert(alertProtocolVersion)
return c.sendAlert(alertProtocolVersion)
}
c.vers = vers
c.haveVers = true
@ -248,7 +249,7 @@ func (c *Conn) clientHandshake() os.Error {
var digest [36]byte
copy(digest[0:16], finishedHash.serverMD5.Sum())
copy(digest[16:36], finishedHash.serverSHA1.Sum())
signed, err := rsa.SignPKCS1v15(c.config.rand(), c.config.Certificates[0].PrivateKey, rsa.HashMD5SHA1, digest[0:])
signed, err := rsa.SignPKCS1v15(c.config.rand(), c.config.Certificates[0].PrivateKey, crypto.MD5SHA1, digest[0:])
if err != nil {
return c.sendAlert(alertInternalError)
}

View File

@ -61,7 +61,7 @@ func TestRunClient(t *testing.T) {
// Script of interaction with gnutls implementation.
// The values for this test are obtained by building and running in client mode:
// % gotest -match "TestRunClient" -connect
// % gotest -test.run "TestRunClient" -connect
// and then:
// % gnutls-serv -p 10443 --debug 100 --x509keyfile key.pem --x509certfile cert.pem -a > /tmp/log 2>&1
// % python parse-gnutls-cli-debug-log.py < /tmp/log

View File

@ -5,6 +5,7 @@
package tls
import (
"crypto"
"crypto/rsa"
"crypto/subtle"
"crypto/x509"
@ -56,6 +57,7 @@ Curves:
var suite *cipherSuite
var suiteId uint16
FindCipherSuite:
for _, id := range clientHello.cipherSuites {
for _, supported := range config.cipherSuites() {
if id == supported {
@ -66,7 +68,7 @@ Curves:
continue
}
suiteId = id
break
break FindCipherSuite
}
}
}
@ -213,7 +215,7 @@ Curves:
digest := make([]byte, 36)
copy(digest[0:16], finishedHash.serverMD5.Sum())
copy(digest[16:36], finishedHash.serverSHA1.Sum())
err = rsa.VerifyPKCS1v15(pub, rsa.HashMD5SHA1, digest, certVerify.signature)
err = rsa.VerifyPKCS1v15(pub, crypto.MD5SHA1, digest, certVerify.signature)
if err != nil {
c.sendAlert(alertBadCertificate)
return os.ErrorString("could not validate signature of connection nonces: " + err.String())

View File

@ -194,7 +194,7 @@ var testPrivateKey = &rsa.PrivateKey{
// Script of interaction with gnutls implementation.
// The values for this test are obtained by building and running in server mode:
// % gotest -match "TestRunServer" -serve
// % gotest -test.run "TestRunServer" -serve
// and then:
// % gnutls-cli --insecure --debug 100 -p 10443 localhost > /tmp/log 2>&1
// % python parse-gnutls-cli-debug-log.py < /tmp/log

View File

@ -6,6 +6,7 @@ package tls
import (
"big"
"crypto"
"crypto/elliptic"
"crypto/md5"
"crypto/rsa"
@ -143,7 +144,7 @@ Curve:
copy(serverECDHParams[4:], ecdhePublic)
md5sha1 := md5SHA1Hash(clientHello.random, hello.random, serverECDHParams)
sig, err := rsa.SignPKCS1v15(config.rand(), config.Certificates[0].PrivateKey, rsa.HashMD5SHA1, md5sha1)
sig, err := rsa.SignPKCS1v15(config.rand(), config.Certificates[0].PrivateKey, crypto.MD5SHA1, md5sha1)
if err != nil {
return nil, os.ErrorString("failed to sign ECDHE parameters: " + err.String())
}
@ -216,7 +217,7 @@ func (ka *ecdheRSAKeyAgreement) processServerKeyExchange(config *Config, clientH
sig = sig[2:]
md5sha1 := md5SHA1Hash(clientHello.random, serverHello.random, serverECDHParams)
return rsa.VerifyPKCS1v15(cert.PublicKey.(*rsa.PublicKey), rsa.HashMD5SHA1, md5sha1, sig)
return rsa.VerifyPKCS1v15(cert.PublicKey.(*rsa.PublicKey), crypto.MD5SHA1, md5sha1, sig)
Error:
return os.ErrorString("invalid ServerKeyExchange")

View File

@ -124,14 +124,22 @@ func LoadX509KeyPair(certFile string, keyFile string) (cert Certificate, err os.
return
}
certDERBlock, _ := pem.Decode(certPEMBlock)
if certDERBlock == nil {
var certDERBlock *pem.Block
for {
certDERBlock, certPEMBlock = pem.Decode(certPEMBlock)
if certDERBlock == nil {
break
}
if certDERBlock.Type == "CERTIFICATE" {
cert.Certificate = append(cert.Certificate, certDERBlock.Bytes)
}
}
if len(cert.Certificate) == 0 {
err = os.ErrorString("crypto/tls: failed to parse certificate PEM data")
return
}
cert.Certificate = [][]byte{certDERBlock.Bytes}
keyPEMBlock, err := ioutil.ReadFile(keyFile)
if err != nil {
return
@ -153,7 +161,7 @@ func LoadX509KeyPair(certFile string, keyFile string) (cert Certificate, err os.
// We don't need to parse the public key for TLS, but we so do anyway
// to check that it looks sane and matches the private key.
x509Cert, err := x509.ParseCertificate(certDERBlock.Bytes)
x509Cert, err := x509.ParseCertificate(cert.Certificate[0])
if err != nil {
return
}

View File

@ -9,6 +9,7 @@ import (
"asn1"
"big"
"container/vector"
"crypto"
"crypto/rsa"
"crypto/sha1"
"hash"
@ -330,6 +331,10 @@ type Certificate struct {
DNSNames []string
EmailAddresses []string
// Name constraints
PermittedDNSDomainsCritical bool // if true then the name constraints are marked critical.
PermittedDNSDomains []string
PolicyIdentifiers []asn1.ObjectIdentifier
}
@ -374,12 +379,12 @@ func (c *Certificate) CheckSignatureFrom(parent *Certificate) (err os.Error) {
// TODO(agl): don't ignore the path length constraint.
var h hash.Hash
var hashType rsa.PKCS1v15Hash
var hashType crypto.Hash
switch c.SignatureAlgorithm {
case SHA1WithRSA:
h = sha1.New()
hashType = rsa.HashSHA1
hashType = crypto.SHA1
default:
return UnsupportedAlgorithmError{}
}
@ -474,6 +479,18 @@ type policyInformation struct {
// policyQualifiers omitted
}
// RFC 5280, 4.2.1.10
type nameConstraints struct {
Permitted []generalSubtree "optional,tag:0"
Excluded []generalSubtree "optional,tag:1"
}
type generalSubtree struct {
Name string "tag:2,optional,ia5"
Min int "optional,tag:0"
Max int "optional,tag:1"
}
func parsePublicKey(algo PublicKeyAlgorithm, asn1Data []byte) (interface{}, os.Error) {
switch algo {
case RSA:
@ -602,6 +619,43 @@ func parseCertificate(in *certificate) (*Certificate, os.Error) {
// If we didn't parse any of the names then we
// fall through to the critical check below.
case 30:
// RFC 5280, 4.2.1.10
// NameConstraints ::= SEQUENCE {
// permittedSubtrees [0] GeneralSubtrees OPTIONAL,
// excludedSubtrees [1] GeneralSubtrees OPTIONAL }
//
// GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
//
// GeneralSubtree ::= SEQUENCE {
// base GeneralName,
// minimum [0] BaseDistance DEFAULT 0,
// maximum [1] BaseDistance OPTIONAL }
//
// BaseDistance ::= INTEGER (0..MAX)
var constraints nameConstraints
_, err := asn1.Unmarshal(e.Value, &constraints)
if err != nil {
return nil, err
}
if len(constraints.Excluded) > 0 && e.Critical {
return out, UnhandledCriticalExtension{}
}
for _, subtree := range constraints.Permitted {
if subtree.Min > 0 || subtree.Max > 0 || len(subtree.Name) == 0 {
if e.Critical {
return out, UnhandledCriticalExtension{}
}
continue
}
out.PermittedDNSDomains = append(out.PermittedDNSDomains, subtree.Name)
}
continue
case 35:
// RFC 5280, 4.2.1.1
var a authKeyId
@ -698,10 +752,11 @@ var (
oidExtensionBasicConstraints = []int{2, 5, 29, 19}
oidExtensionSubjectAltName = []int{2, 5, 29, 17}
oidExtensionCertificatePolicies = []int{2, 5, 29, 32}
oidExtensionNameConstraints = []int{2, 5, 29, 30}
)
func buildExtensions(template *Certificate) (ret []extension, err os.Error) {
ret = make([]extension, 6 /* maximum number of elements. */ )
ret = make([]extension, 7 /* maximum number of elements. */ )
n := 0
if template.KeyUsage != 0 {
@ -778,6 +833,22 @@ func buildExtensions(template *Certificate) (ret []extension, err os.Error) {
n++
}
if len(template.PermittedDNSDomains) > 0 {
ret[n].Id = oidExtensionNameConstraints
ret[n].Critical = template.PermittedDNSDomainsCritical
var out nameConstraints
out.Permitted = make([]generalSubtree, len(template.PermittedDNSDomains))
for i, permitted := range template.PermittedDNSDomains {
out.Permitted[i] = generalSubtree{Name: permitted}
}
ret[n].Value, err = asn1.Marshal(out)
if err != nil {
return
}
n++
}
// Adding another extension here? Remember to update the maximum number
// of elements in the make() at the top of the function.
@ -792,7 +863,8 @@ var (
// CreateSelfSignedCertificate creates a new certificate based on
// a template. The following members of template are used: SerialNumber,
// Subject, NotBefore, NotAfter, KeyUsage, BasicConstraintsValid, IsCA,
// MaxPathLen, SubjectKeyId, DNSNames.
// MaxPathLen, SubjectKeyId, DNSNames, PermittedDNSDomainsCritical,
// PermittedDNSDomains.
//
// The certificate is signed by parent. If parent is equal to template then the
// certificate is self-signed. The parameter pub is the public key of the
@ -840,7 +912,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub *rsa.P
h.Write(tbsCertContents)
digest := h.Sum()
signature, err := rsa.SignPKCS1v15(rand, priv, rsa.HashSHA1, digest)
signature, err := rsa.SignPKCS1v15(rand, priv, crypto.SHA1, digest)
if err != nil {
return
}

View File

@ -171,7 +171,8 @@ func TestCreateSelfSignedCertificate(t *testing.T) {
IsCA: true,
DNSNames: []string{"test.example.com"},
PolicyIdentifiers: []asn1.ObjectIdentifier{[]int{1, 2, 3}},
PolicyIdentifiers: []asn1.ObjectIdentifier{[]int{1, 2, 3}},
PermittedDNSDomains: []string{".example.com", "example.com"},
}
derBytes, err := CreateCertificate(random, &template, &template, &priv.PublicKey, priv)
@ -190,6 +191,10 @@ func TestCreateSelfSignedCertificate(t *testing.T) {
t.Errorf("Failed to parse policy identifiers: got:%#v want:%#v", cert.PolicyIdentifiers, template.PolicyIdentifiers)
}
if len(cert.PermittedDNSDomains) != 2 || cert.PermittedDNSDomains[0] != ".example.com" || cert.PermittedDNSDomains[1] != "example.com" {
t.Errorf("Failed to parse name constraints: %#v", cert.PermittedDNSDomains)
}
err = cert.CheckSignatureFrom(cert)
if err != nil {
t.Errorf("Signature verification failed: %s", err)

View File

@ -57,7 +57,6 @@ type ImportDirectory struct {
FirstThunk uint32
dll string
rva []uint32
}
// Data reads and returns the contents of the PE section.
@ -267,32 +266,26 @@ func (f *File) ImportedSymbols() ([]string, os.Error) {
}
ida = append(ida, dt)
}
for i, _ := range ida {
for len(d) > 0 {
va := binary.LittleEndian.Uint32(d[0:4])
d = d[4:]
if va == 0 {
break
}
ida[i].rva = append(ida[i].rva, va)
}
}
for _, _ = range ida {
for len(d) > 0 {
va := binary.LittleEndian.Uint32(d[0:4])
d = d[4:]
if va == 0 {
break
}
}
}
names, _ := ds.Data()
var all []string
for _, dt := range ida {
dt.dll, _ = getString(names, int(dt.Name-ds.VirtualAddress))
for _, va := range dt.rva {
fn, _ := getString(names, int(va-ds.VirtualAddress+2))
all = append(all, fn+":"+dt.dll)
d, _ = ds.Data()
// seek to OriginalFirstThunk
d = d[dt.OriginalFirstThunk-ds.VirtualAddress:]
for len(d) > 0 {
va := binary.LittleEndian.Uint32(d[0:4])
d = d[4:]
if va == 0 {
break
}
if va&0x80000000 > 0 { // is Ordinal
// TODO add dynimport ordinal support.
//ord := va&0x0000FFFF
} else {
fn, _ := getString(names, int(va-ds.VirtualAddress+2))
all = append(all, fn+":"+dt.dll)
}
}
}

View File

@ -15,31 +15,31 @@ var fset = token.NewFileSet()
var grammars = []string{
`Program = .
`,
`Program = .
`,
`Program = foo .
foo = "foo" .
`,
`Program = foo .
foo = "foo" .
`,
`Program = "a" | "b" "c" .
`,
`Program = "a" | "b" "c" .
`,
`Program = "a" ... "z" .
`,
`Program = "a" ... "z" .
`,
`Program = Song .
Song = { Note } .
Note = Do | (Re | Mi | Fa | So | La) | Ti .
Do = "c" .
Re = "d" .
Mi = "e" .
Fa = "f" .
So = "g" .
La = "a" .
Ti = ti .
ti = "b" .
`,
`Program = Song .
Song = { Note } .
Note = Do | (Re | Mi | Fa | So | La) | Ti .
Do = "c" .
Re = "d" .
Mi = "e" .
Fa = "f" .
So = "g" .
La = "a" .
Ti = ti .
ti = "b" .
`,
}

View File

@ -2,8 +2,9 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This package implements translation between
// unsigned integer values and byte sequences.
// Package binary implements translation between
// unsigned integer values and byte sequences
// and the reading and writing of fixed-size values.
package binary
import (

View File

@ -2,8 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This package implements a Reader which handles reading \r and \r\n
// deliminated lines.
// The line package implements a Reader that reads lines delimited by '\n' or ' \r\n'.
package line
import (
@ -11,8 +10,7 @@ import (
"os"
)
// Reader reads lines from an io.Reader (which may use either '\n' or
// '\r\n').
// Reader reads lines, delimited by '\n' or \r\n', from an io.Reader.
type Reader struct {
buf []byte
consumed int
@ -20,11 +18,33 @@ type Reader struct {
err os.Error
}
func NewReader(in io.Reader, maxLineLength int) *Reader {
// NewReader returns a new Reader that will read successive
// lines from the input Reader.
func NewReader(input io.Reader, maxLineLength int) *Reader {
return &Reader{
buf: make([]byte, 0, maxLineLength),
consumed: 0,
in: in,
in: input,
}
}
// Read reads from any buffered data past the last line read, or from the underlying
// io.Reader if the buffer is empty.
func (l *Reader) Read(p []byte) (n int, err os.Error) {
l.removeConsumedFromBuffer()
if len(l.buf) > 0 {
n = copy(p, l.buf)
l.consumed += n
return
}
return l.in.Read(p)
}
func (l *Reader) removeConsumedFromBuffer() {
if l.consumed > 0 {
n := copy(l.buf, l.buf[l.consumed:])
l.buf = l.buf[:n]
l.consumed = 0
}
}
@ -36,11 +56,7 @@ func NewReader(in io.Reader, maxLineLength int) *Reader {
// the Reader and is only valid until the next call to ReadLine. ReadLine
// either returns a non-nil line or it returns an error, never both.
func (l *Reader) ReadLine() (line []byte, isPrefix bool, err os.Error) {
if l.consumed > 0 {
n := copy(l.buf, l.buf[l.consumed:])
l.buf = l.buf[:n]
l.consumed = 0
}
l.removeConsumedFromBuffer()
if len(l.buf) == 0 && l.err != nil {
err = l.err
@ -89,6 +105,9 @@ func (l *Reader) ReadLine() (line []byte, isPrefix bool, err os.Error) {
l.buf = l.buf[:oldLen+n]
if readErr != nil {
l.err = readErr
if len(l.buf) == 0 {
return nil, false, readErr
}
}
}
panic("unreachable")

View File

@ -6,6 +6,8 @@ package line
import (
"bytes"
"io"
"io/ioutil"
"os"
"testing"
)
@ -87,3 +89,45 @@ func TestLineTooLong(t *testing.T) {
t.Errorf("bad result for third line: %x", line)
}
}
func TestReadAfterLines(t *testing.T) {
line1 := "line1"
restData := "line2\nline 3\n"
inbuf := bytes.NewBuffer([]byte(line1 + "\n" + restData))
outbuf := new(bytes.Buffer)
maxLineLength := len(line1) + len(restData)/2
l := NewReader(inbuf, maxLineLength)
line, isPrefix, err := l.ReadLine()
if isPrefix || err != nil || string(line) != line1 {
t.Errorf("bad result for first line: isPrefix=%v err=%v line=%q", isPrefix, err, string(line))
}
n, err := io.Copy(outbuf, l)
if int(n) != len(restData) || err != nil {
t.Errorf("bad result for Read: n=%d err=%v", n, err)
}
if outbuf.String() != restData {
t.Errorf("bad result for Read: got %q; expected %q", outbuf.String(), restData)
}
}
func TestReadEmptyBuffer(t *testing.T) {
l := NewReader(bytes.NewBuffer(nil), 10)
line, isPrefix, err := l.ReadLine()
if err != os.EOF {
t.Errorf("expected EOF from ReadLine, got '%s' %t %s", line, isPrefix, err)
}
}
func TestLinesAfterRead(t *testing.T) {
l := NewReader(bytes.NewBuffer([]byte("foo")), 10)
_, err := ioutil.ReadAll(l)
if err != nil {
t.Error(err)
return
}
line, isPrefix, err := l.ReadLine()
if err != os.EOF {
t.Errorf("expected EOF from ReadLine, got '%s' %t %s", line, isPrefix, err)
}
}

View File

@ -7,6 +7,7 @@ package exec
import (
"os"
"strconv"
)
// Arguments to Run.
@ -21,12 +22,22 @@ const (
// Stdin, Stdout, and Stderr are Files representing pipes
// connected to the running command's standard input, output, and error,
// or else nil, depending on the arguments to Run.
// Pid is the running command's operating system process ID.
// Process represents the underlying operating system process.
type Cmd struct {
Stdin *os.File
Stdout *os.File
Stderr *os.File
Pid int
Stdin *os.File
Stdout *os.File
Stderr *os.File
Process *os.Process
}
// PathError records the name of a binary that was not
// found on the current $PATH.
type PathError struct {
Name string
}
func (e *PathError) String() string {
return "command " + strconv.Quote(e.Name) + " not found in $PATH"
}
// Given mode (DevNull, etc), return file for child
@ -77,24 +88,24 @@ func modeToFiles(mode, fd int) (*os.File, *os.File, os.Error) {
// If a parameter is Pipe, then the corresponding field (Stdin, Stdout, Stderr)
// of the returned Cmd is the other end of the pipe.
// Otherwise the field in Cmd is nil.
func Run(name string, argv, envv []string, dir string, stdin, stdout, stderr int) (p *Cmd, err os.Error) {
p = new(Cmd)
func Run(name string, argv, envv []string, dir string, stdin, stdout, stderr int) (c *Cmd, err os.Error) {
c = new(Cmd)
var fd [3]*os.File
if fd[0], p.Stdin, err = modeToFiles(stdin, 0); err != nil {
if fd[0], c.Stdin, err = modeToFiles(stdin, 0); err != nil {
goto Error
}
if fd[1], p.Stdout, err = modeToFiles(stdout, 1); err != nil {
if fd[1], c.Stdout, err = modeToFiles(stdout, 1); err != nil {
goto Error
}
if stderr == MergeWithStdout {
fd[2] = fd[1]
} else if fd[2], p.Stderr, err = modeToFiles(stderr, 2); err != nil {
} else if fd[2], c.Stderr, err = modeToFiles(stderr, 2); err != nil {
goto Error
}
// Run command.
p.Pid, err = os.ForkExec(name, argv, envv, dir, fd[0:])
c.Process, err = os.StartProcess(name, argv, envv, dir, fd[0:])
if err != nil {
goto Error
}
@ -107,7 +118,7 @@ func Run(name string, argv, envv []string, dir string, stdin, stdout, stderr int
if fd[2] != os.Stderr && fd[2] != fd[1] {
fd[2].Close()
}
return p, nil
return c, nil
Error:
if fd[0] != os.Stdin && fd[0] != nil {
@ -119,63 +130,67 @@ Error:
if fd[2] != os.Stderr && fd[2] != nil && fd[2] != fd[1] {
fd[2].Close()
}
if p.Stdin != nil {
p.Stdin.Close()
if c.Stdin != nil {
c.Stdin.Close()
}
if p.Stdout != nil {
p.Stdout.Close()
if c.Stdout != nil {
c.Stdout.Close()
}
if p.Stderr != nil {
p.Stderr.Close()
if c.Stderr != nil {
c.Stderr.Close()
}
if c.Process != nil {
c.Process.Release()
}
return nil, err
}
// Wait waits for the running command p,
// returning the Waitmsg returned by os.Wait and an error.
// The options are passed through to os.Wait.
// Setting options to 0 waits for p to exit;
// Wait waits for the running command c,
// returning the Waitmsg returned when the process exits.
// The options are passed to the process's Wait method.
// Setting options to 0 waits for c to exit;
// other options cause Wait to return for other
// process events; see package os for details.
func (p *Cmd) Wait(options int) (*os.Waitmsg, os.Error) {
if p.Pid <= 0 {
func (c *Cmd) Wait(options int) (*os.Waitmsg, os.Error) {
if c.Process == nil {
return nil, os.ErrorString("exec: invalid use of Cmd.Wait")
}
w, err := os.Wait(p.Pid, options)
w, err := c.Process.Wait(options)
if w != nil && (w.Exited() || w.Signaled()) {
p.Pid = -1
c.Process.Release()
c.Process = nil
}
return w, err
}
// Close waits for the running command p to exit,
// Close waits for the running command c to exit,
// if it hasn't already, and then closes the non-nil file descriptors
// p.Stdin, p.Stdout, and p.Stderr.
func (p *Cmd) Close() os.Error {
if p.Pid > 0 {
// c.Stdin, c.Stdout, and c.Stderr.
func (c *Cmd) Close() os.Error {
if c.Process != nil {
// Loop on interrupt, but
// ignore other errors -- maybe
// caller has already waited for pid.
_, err := p.Wait(0)
_, err := c.Wait(0)
for err == os.EINTR {
_, err = p.Wait(0)
_, err = c.Wait(0)
}
}
// Close the FDs that are still open.
var err os.Error
if p.Stdin != nil && p.Stdin.Fd() >= 0 {
if err1 := p.Stdin.Close(); err1 != nil {
if c.Stdin != nil && c.Stdin.Fd() >= 0 {
if err1 := c.Stdin.Close(); err1 != nil {
err = err1
}
}
if p.Stdout != nil && p.Stdout.Fd() >= 0 {
if err1 := p.Stdout.Close(); err1 != nil && err != nil {
if c.Stdout != nil && c.Stdout.Fd() >= 0 {
if err1 := c.Stdout.Close(); err1 != nil && err != nil {
err = err1
}
}
if p.Stderr != nil && p.Stderr != p.Stdout && p.Stderr.Fd() >= 0 {
if err1 := p.Stderr.Close(); err1 != nil && err != nil {
if c.Stderr != nil && c.Stderr != c.Stdout && c.Stderr.Fd() >= 0 {
if err1 := c.Stderr.Close(); err1 != nil && err != nil {
err = err1
}
}

33
libgo/go/exec/lp_test.go Normal file
View File

@ -0,0 +1,33 @@
// 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 exec
import (
"testing"
)
var nonExistentPaths = []string{
"some-non-existent-path",
"non-existent-path/slashed",
}
func TestLookPathNotFound(t *testing.T) {
for _, name := range nonExistentPaths {
path, err := LookPath(name)
if err == nil {
t.Fatalf("LookPath found %q in $PATH", name)
}
if path != "" {
t.Fatalf("LookPath path == %q when err != nil", path)
}
perr, ok := err.(*PathError)
if !ok {
t.Fatal("LookPath error is not a PathError")
}
if perr.Name != name {
t.Fatalf("want PathError name %q, got %q", name, perr.Name)
}
}
}

View File

@ -29,7 +29,7 @@ func LookPath(file string) (string, os.Error) {
if canExec(file) {
return file, nil
}
return "", &os.PathError{"lookpath", file, os.ENOENT}
return "", &PathError{file}
}
pathenv := os.Getenv("PATH")
for _, dir := range strings.Split(pathenv, ":", -1) {
@ -41,5 +41,5 @@ func LookPath(file string) (string, os.Error) {
return dir + "/" + file, nil
}
}
return "", &os.PathError{"lookpath", file, os.ENOENT}
return "", &PathError{file}
}

View File

@ -49,7 +49,7 @@ func LookPath(file string) (string, os.Error) {
if f, ok := canExec(file, exts); ok {
return f, nil
}
return ``, &os.PathError{"lookpath", file, os.ENOENT}
return ``, &PathError{file}
}
if pathenv := os.Getenv(`PATH`); pathenv == `` {
if f, ok := canExec(`.\`+file, exts); ok {
@ -62,5 +62,5 @@ func LookPath(file string) (string, os.Error) {
}
}
}
return ``, &os.PathError{"lookpath", file, os.ENOENT}
return ``, &PathError{file}
}

View File

@ -122,10 +122,13 @@ func (c *conn) writeSocket() {
func (c *conn) Screen() draw.Image { return c.img }
func (c *conn) FlushImage() {
// We do the send (the <- operator) in an expression context, rather than in
// a statement context, so that it does not block, and fails if the buffered
// channel is full (in which case there already is a flush request pending).
_ = c.flush <- false
select {
case c.flush <- false:
// Flush notification sent.
default:
// Could not send.
// Flush notification must be pending already.
}
}
func (c *conn) Close() os.Error {

View File

@ -908,7 +908,7 @@ func (a *stmtCompiler) compileBranchStmt(s *ast.BranchStmt) {
return
default:
log.Panic("Unexpected branch token %v", s.Tok)
log.Panicf("Unexpected branch token %v", s.Tok)
}
a.flow.put1(false, pc)

View File

@ -217,7 +217,7 @@ var stmtTests = []test{
Val2("if false { i = 2 } else { i = 3 }; i2 = 4", "i", 3, "i2", 4),
Val2("if i == i2 { i = 2 } else { i = 3 }; i2 = 4", "i", 3, "i2", 4),
// Omit optional parts
Val2("if { i = 2 } else { i = 3 }; i2 = 4", "i", 2, "i2", 4),
Val2("if true { i = 2 } else { i = 3 }; i2 = 4", "i", 2, "i2", 4),
Val2("if true { i = 2 }; i2 = 4", "i", 2, "i2", 4),
Val2("if false { i = 2 }; i2 = 4", "i", 1, "i2", 4),
// Init
@ -243,11 +243,11 @@ var stmtTests = []test{
CErr("fn1 := func() int { if true { return 1 } }", "return"),
CErr("fn1 := func() int { if true { } }", "return"),
Run("fn1 := func() int { if true { }; return 1 }"),
CErr("fn1 := func() int { if { } }", "return"),
CErr("fn1 := func() int { if { } else { return 2 } }", "return"),
Run("fn1 := func() int { if { return 1 } }"),
Run("fn1 := func() int { if { return 1 } else { } }"),
Run("fn1 := func() int { if { return 1 } else { } }"),
CErr("fn1 := func() int { if true { } }", "return"),
CErr("fn1 := func() int { if true { } else { return 2 } }", "return"),
Run("fn1 := func() int { if true { return 1 }; return 0 }"),
Run("fn1 := func() int { if true { return 1 } else { }; return 0 }"),
Run("fn1 := func() int { if true { return 1 } else { }; return 0 }"),
// Switch
Val1("switch { case false: i += 2; case true: i += 4; default: i += 8 }", "i", 1+4),

153
libgo/go/exp/wingui/gui.go Normal file
View File

@ -0,0 +1,153 @@
// 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 main
import (
"fmt"
"syscall"
"os"
"unsafe"
)
// some help functions
func abortf(format string, a ...interface{}) {
fmt.Fprintf(os.Stdout, format, a...)
os.Exit(1)
}
func abortErrNo(funcname string, err int) {
abortf("%s failed: %d %s\n", funcname, err, syscall.Errstr(err))
}
// global vars
var (
mh uint32
bh uint32
)
// WinProc called by windows to notify us of all windows events we might be interested in.
func WndProc(hwnd, msg uint32, wparam, lparam int32) uintptr {
var rc int32
switch msg {
case WM_CREATE:
var e int
// CreateWindowEx
bh, e = CreateWindowEx(
0,
syscall.StringToUTF16Ptr("button"),
syscall.StringToUTF16Ptr("Quit"),
WS_CHILD|WS_VISIBLE|BS_DEFPUSHBUTTON,
75, 70, 140, 25,
hwnd, 1, mh, 0)
if e != 0 {
abortErrNo("CreateWindowEx", e)
}
fmt.Printf("button handle is %x\n", bh)
rc = DefWindowProc(hwnd, msg, wparam, lparam)
case WM_COMMAND:
switch uint32(lparam) {
case bh:
e := PostMessage(hwnd, WM_CLOSE, 0, 0)
if e != 0 {
abortErrNo("PostMessage", e)
}
default:
rc = DefWindowProc(hwnd, msg, wparam, lparam)
}
case WM_CLOSE:
DestroyWindow(hwnd)
case WM_DESTROY:
PostQuitMessage(0)
default:
rc = DefWindowProc(hwnd, msg, wparam, lparam)
}
//fmt.Printf("WndProc(0x%08x, %d, 0x%08x, 0x%08x) (%d)\n", hwnd, msg, wparam, lparam, rc)
return uintptr(rc)
}
func rungui() int {
var e int
// GetModuleHandle
mh, e = GetModuleHandle(nil)
if e != 0 {
abortErrNo("GetModuleHandle", e)
}
// Get icon we're going to use.
myicon, e := LoadIcon(0, IDI_APPLICATION)
if e != 0 {
abortErrNo("LoadIcon", e)
}
// Get cursor we're going to use.
mycursor, e := LoadCursor(0, IDC_ARROW)
if e != 0 {
abortErrNo("LoadCursor", e)
}
// Create callback
wproc := syscall.NewCallback(WndProc)
// RegisterClassEx
wcname := syscall.StringToUTF16Ptr("myWindowClass")
var wc Wndclassex
wc.Size = uint32(unsafe.Sizeof(wc))
wc.WndProc = wproc
wc.Instance = mh
wc.Icon = myicon
wc.Cursor = mycursor
wc.Background = COLOR_BTNFACE + 1
wc.MenuName = nil
wc.ClassName = wcname
wc.IconSm = myicon
if _, e := RegisterClassEx(&wc); e != 0 {
abortErrNo("RegisterClassEx", e)
}
// CreateWindowEx
wh, e := CreateWindowEx(
WS_EX_CLIENTEDGE,
wcname,
syscall.StringToUTF16Ptr("My window"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 300, 200,
0, 0, mh, 0)
if e != 0 {
abortErrNo("CreateWindowEx", e)
}
fmt.Printf("main window handle is %x\n", wh)
// ShowWindow
ShowWindow(wh, SW_SHOWDEFAULT)
// UpdateWindow
if e := UpdateWindow(wh); e != 0 {
abortErrNo("UpdateWindow", e)
}
// Process all windows messages until WM_QUIT.
var m Msg
for {
r, e := GetMessage(&m, 0, 0, 0)
if e != 0 {
abortErrNo("GetMessage", e)
}
if r == 0 {
// WM_QUIT received -> get out
break
}
TranslateMessage(&m)
DispatchMessage(&m)
}
return int(m.Wparam)
}
func main() {
rc := rungui()
os.Exit(rc)
}

View File

@ -0,0 +1,148 @@
// 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 main
import (
"syscall"
"unsafe"
)
func loadDll(fname string) uint32 {
h, e := syscall.LoadLibrary(fname)
if e != 0 {
abortf("LoadLibrary(%s) failed with err=%d.\n", fname, e)
}
return h
}
func getSysProcAddr(m uint32, pname string) uintptr {
p, e := syscall.GetProcAddress(m, pname)
if e != 0 {
abortf("GetProcAddress(%s) failed with err=%d.\n", pname, e)
}
return uintptr(p)
}
type Wndclassex struct {
Size uint32
Style uint32
WndProc uintptr
ClsExtra int32
WndExtra int32
Instance uint32
Icon uint32
Cursor uint32
Background uint32
MenuName *uint16
ClassName *uint16
IconSm uint32
}
type Point struct {
X int32
Y int32
}
type Msg struct {
Hwnd uint32
Message uint32
Wparam int32
Lparam int32
Time uint32
Pt Point
}
const (
// Window styles
WS_OVERLAPPED = 0
WS_POPUP = 0x80000000
WS_CHILD = 0x40000000
WS_MINIMIZE = 0x20000000
WS_VISIBLE = 0x10000000
WS_DISABLED = 0x8000000
WS_CLIPSIBLINGS = 0x4000000
WS_CLIPCHILDREN = 0x2000000
WS_MAXIMIZE = 0x1000000
WS_CAPTION = WS_BORDER | WS_DLGFRAME
WS_BORDER = 0x800000
WS_DLGFRAME = 0x400000
WS_VSCROLL = 0x200000
WS_HSCROLL = 0x100000
WS_SYSMENU = 0x80000
WS_THICKFRAME = 0x40000
WS_GROUP = 0x20000
WS_TABSTOP = 0x10000
WS_MINIMIZEBOX = 0x20000
WS_MAXIMIZEBOX = 0x10000
WS_TILED = WS_OVERLAPPED
WS_ICONIC = WS_MINIMIZE
WS_SIZEBOX = WS_THICKFRAME
// Common Window Styles
WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX
WS_TILEDWINDOW = WS_OVERLAPPEDWINDOW
WS_POPUPWINDOW = WS_POPUP | WS_BORDER | WS_SYSMENU
WS_CHILDWINDOW = WS_CHILD
WS_EX_CLIENTEDGE = 0x200
// Some windows messages
WM_CREATE = 1
WM_DESTROY = 2
WM_CLOSE = 16
WM_COMMAND = 273
// Some button control styles
BS_DEFPUSHBUTTON = 1
// Some colour constants
COLOR_WINDOW = 5
COLOR_BTNFACE = 15
// Default window position
CW_USEDEFAULT = 0x80000000 - 0x100000000
// Show window default style
SW_SHOWDEFAULT = 10
)
var (
// Some globaly known cusrors
IDC_ARROW = MakeIntResource(32512)
IDC_IBEAM = MakeIntResource(32513)
IDC_WAIT = MakeIntResource(32514)
IDC_CROSS = MakeIntResource(32515)
// Some globaly known icons
IDI_APPLICATION = MakeIntResource(32512)
IDI_HAND = MakeIntResource(32513)
IDI_QUESTION = MakeIntResource(32514)
IDI_EXCLAMATION = MakeIntResource(32515)
IDI_ASTERISK = MakeIntResource(32516)
IDI_WINLOGO = MakeIntResource(32517)
IDI_WARNING = IDI_EXCLAMATION
IDI_ERROR = IDI_HAND
IDI_INFORMATION = IDI_ASTERISK
)
//sys GetModuleHandle(modname *uint16) (handle uint32, errno int) = GetModuleHandleW
//sys RegisterClassEx(wndclass *Wndclassex) (atom uint16, errno int) = user32.RegisterClassExW
//sys CreateWindowEx(exstyle uint32, classname *uint16, windowname *uint16, style uint32, x int32, y int32, width int32, height int32, wndparent uint32, menu uint32, instance uint32, param uintptr) (hwnd uint32, errno int) = user32.CreateWindowExW
//sys DefWindowProc(hwnd uint32, msg uint32, wparam int32, lparam int32) (lresult int32) = user32.DefWindowProcW
//sys DestroyWindow(hwnd uint32) (errno int) = user32.DestroyWindow
//sys PostQuitMessage(exitcode int32) = user32.PostQuitMessage
//sys ShowWindow(hwnd uint32, cmdshow int32) (wasvisible bool) = user32.ShowWindow
//sys UpdateWindow(hwnd uint32) (errno int) = user32.UpdateWindow
//sys GetMessage(msg *Msg, hwnd uint32, MsgFilterMin uint32, MsgFilterMax uint32) (ret int32, errno int) [failretval==-1] = user32.GetMessageW
//sys TranslateMessage(msg *Msg) (done bool) = user32.TranslateMessage
//sys DispatchMessage(msg *Msg) (ret int32) = user32.DispatchMessageW
//sys LoadIcon(instance uint32, iconname *uint16) (icon uint32, errno int) = user32.LoadIconW
//sys LoadCursor(instance uint32, cursorname *uint16) (cursor uint32, errno int) = user32.LoadCursorW
//sys SetCursor(cursor uint32) (precursor uint32, errno int) = user32.SetCursor
//sys SendMessage(hwnd uint32, msg uint32, wparam int32, lparam int32) (lresult int32) = user32.SendMessageW
//sys PostMessage(hwnd uint32, msg uint32, wparam int32, lparam int32) (errno int) = user32.PostMessageW
func MakeIntResource(id uint16) *uint16 {
return (*uint16)(unsafe.Pointer(uintptr(id)))
}

View File

@ -0,0 +1,211 @@
// mksyscall_windows.sh winapi.go
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
package main
import "unsafe"
import "syscall"
var (
modkernel32 = loadDll("kernel32.dll")
moduser32 = loadDll("user32.dll")
procGetModuleHandleW = getSysProcAddr(modkernel32, "GetModuleHandleW")
procRegisterClassExW = getSysProcAddr(moduser32, "RegisterClassExW")
procCreateWindowExW = getSysProcAddr(moduser32, "CreateWindowExW")
procDefWindowProcW = getSysProcAddr(moduser32, "DefWindowProcW")
procDestroyWindow = getSysProcAddr(moduser32, "DestroyWindow")
procPostQuitMessage = getSysProcAddr(moduser32, "PostQuitMessage")
procShowWindow = getSysProcAddr(moduser32, "ShowWindow")
procUpdateWindow = getSysProcAddr(moduser32, "UpdateWindow")
procGetMessageW = getSysProcAddr(moduser32, "GetMessageW")
procTranslateMessage = getSysProcAddr(moduser32, "TranslateMessage")
procDispatchMessageW = getSysProcAddr(moduser32, "DispatchMessageW")
procLoadIconW = getSysProcAddr(moduser32, "LoadIconW")
procLoadCursorW = getSysProcAddr(moduser32, "LoadCursorW")
procSetCursor = getSysProcAddr(moduser32, "SetCursor")
procSendMessageW = getSysProcAddr(moduser32, "SendMessageW")
procPostMessageW = getSysProcAddr(moduser32, "PostMessageW")
)
func GetModuleHandle(modname *uint16) (handle uint32, errno int) {
r0, _, e1 := syscall.Syscall(procGetModuleHandleW, 1, uintptr(unsafe.Pointer(modname)), 0, 0)
handle = uint32(r0)
if handle == 0 {
if e1 != 0 {
errno = int(e1)
} else {
errno = syscall.EINVAL
}
} else {
errno = 0
}
return
}
func RegisterClassEx(wndclass *Wndclassex) (atom uint16, errno int) {
r0, _, e1 := syscall.Syscall(procRegisterClassExW, 1, uintptr(unsafe.Pointer(wndclass)), 0, 0)
atom = uint16(r0)
if atom == 0 {
if e1 != 0 {
errno = int(e1)
} else {
errno = syscall.EINVAL
}
} else {
errno = 0
}
return
}
func CreateWindowEx(exstyle uint32, classname *uint16, windowname *uint16, style uint32, x int32, y int32, width int32, height int32, wndparent uint32, menu uint32, instance uint32, param uintptr) (hwnd uint32, errno int) {
r0, _, e1 := syscall.Syscall12(procCreateWindowExW, 12, uintptr(exstyle), uintptr(unsafe.Pointer(classname)), uintptr(unsafe.Pointer(windowname)), uintptr(style), uintptr(x), uintptr(y), uintptr(width), uintptr(height), uintptr(wndparent), uintptr(menu), uintptr(instance), uintptr(param))
hwnd = uint32(r0)
if hwnd == 0 {
if e1 != 0 {
errno = int(e1)
} else {
errno = syscall.EINVAL
}
} else {
errno = 0
}
return
}
func DefWindowProc(hwnd uint32, msg uint32, wparam int32, lparam int32) (lresult int32) {
r0, _, _ := syscall.Syscall6(procDefWindowProcW, 4, uintptr(hwnd), uintptr(msg), uintptr(wparam), uintptr(lparam), 0, 0)
lresult = int32(r0)
return
}
func DestroyWindow(hwnd uint32) (errno int) {
r1, _, e1 := syscall.Syscall(procDestroyWindow, 1, uintptr(hwnd), 0, 0)
if int(r1) == 0 {
if e1 != 0 {
errno = int(e1)
} else {
errno = syscall.EINVAL
}
} else {
errno = 0
}
return
}
func PostQuitMessage(exitcode int32) {
syscall.Syscall(procPostQuitMessage, 1, uintptr(exitcode), 0, 0)
return
}
func ShowWindow(hwnd uint32, cmdshow int32) (wasvisible bool) {
r0, _, _ := syscall.Syscall(procShowWindow, 2, uintptr(hwnd), uintptr(cmdshow), 0)
wasvisible = bool(r0 != 0)
return
}
func UpdateWindow(hwnd uint32) (errno int) {
r1, _, e1 := syscall.Syscall(procUpdateWindow, 1, uintptr(hwnd), 0, 0)
if int(r1) == 0 {
if e1 != 0 {
errno = int(e1)
} else {
errno = syscall.EINVAL
}
} else {
errno = 0
}
return
}
func GetMessage(msg *Msg, hwnd uint32, MsgFilterMin uint32, MsgFilterMax uint32) (ret int32, errno int) {
r0, _, e1 := syscall.Syscall6(procGetMessageW, 4, uintptr(unsafe.Pointer(msg)), uintptr(hwnd), uintptr(MsgFilterMin), uintptr(MsgFilterMax), 0, 0)
ret = int32(r0)
if ret == -1 {
if e1 != 0 {
errno = int(e1)
} else {
errno = syscall.EINVAL
}
} else {
errno = 0
}
return
}
func TranslateMessage(msg *Msg) (done bool) {
r0, _, _ := syscall.Syscall(procTranslateMessage, 1, uintptr(unsafe.Pointer(msg)), 0, 0)
done = bool(r0 != 0)
return
}
func DispatchMessage(msg *Msg) (ret int32) {
r0, _, _ := syscall.Syscall(procDispatchMessageW, 1, uintptr(unsafe.Pointer(msg)), 0, 0)
ret = int32(r0)
return
}
func LoadIcon(instance uint32, iconname *uint16) (icon uint32, errno int) {
r0, _, e1 := syscall.Syscall(procLoadIconW, 2, uintptr(instance), uintptr(unsafe.Pointer(iconname)), 0)
icon = uint32(r0)
if icon == 0 {
if e1 != 0 {
errno = int(e1)
} else {
errno = syscall.EINVAL
}
} else {
errno = 0
}
return
}
func LoadCursor(instance uint32, cursorname *uint16) (cursor uint32, errno int) {
r0, _, e1 := syscall.Syscall(procLoadCursorW, 2, uintptr(instance), uintptr(unsafe.Pointer(cursorname)), 0)
cursor = uint32(r0)
if cursor == 0 {
if e1 != 0 {
errno = int(e1)
} else {
errno = syscall.EINVAL
}
} else {
errno = 0
}
return
}
func SetCursor(cursor uint32) (precursor uint32, errno int) {
r0, _, e1 := syscall.Syscall(procSetCursor, 1, uintptr(cursor), 0, 0)
precursor = uint32(r0)
if precursor == 0 {
if e1 != 0 {
errno = int(e1)
} else {
errno = syscall.EINVAL
}
} else {
errno = 0
}
return
}
func SendMessage(hwnd uint32, msg uint32, wparam int32, lparam int32) (lresult int32) {
r0, _, _ := syscall.Syscall6(procSendMessageW, 4, uintptr(hwnd), uintptr(msg), uintptr(wparam), uintptr(lparam), 0, 0)
lresult = int32(r0)
return
}
func PostMessage(hwnd uint32, msg uint32, wparam int32, lparam int32) (errno int) {
r1, _, e1 := syscall.Syscall6(procPostMessageW, 4, uintptr(hwnd), uintptr(msg), uintptr(wparam), uintptr(lparam), 0, 0)
if int(r1) == 0 {
if e1 != 0 {
errno = int(e1)
} else {
errno = syscall.EINVAL
}
} else {
errno = 0
}
return
}

Some files were not shown because too many files have changed in this diff Show More