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); bloc);
Struct_type* type_descriptor_type = Struct_type* type_descriptor_type =
Type::make_builtin_struct_type(9, Type::make_builtin_struct_type(10,
"Kind", uint8_type, "Kind", uint8_type,
"align", uint8_type, "align", uint8_type,
"fieldAlign", uint8_type, "fieldAlign", uint8_type,
@ -1087,7 +1087,9 @@ Type::make_type_descriptor_type()
"hashfn", hashfn_type, "hashfn", hashfn_type,
"equalfn", equalfn_type, "equalfn", equalfn_type,
"string", pointer_string_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", Named_type* named = Type::make_builtin_named_type("commonType",
type_descriptor_type); type_descriptor_type);
@ -1259,6 +1261,16 @@ Type::type_descriptor_constructor(Gogo* gogo, int runtime_type_kind,
only_value_methods)); 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; ++p;
gcc_assert(p == fields->end()); 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 The first line of this file holds the Mercurial revision number of the
last merge done from the master library sources. last merge done from the master library sources.

View file

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

View file

@ -112,6 +112,7 @@ am__installdirs = "$(DESTDIR)$(toolexeclibdir)" \
"$(DESTDIR)$(toolexeclibgoosdir)" \ "$(DESTDIR)$(toolexeclibgoosdir)" \
"$(DESTDIR)$(toolexeclibgorpcdir)" \ "$(DESTDIR)$(toolexeclibgorpcdir)" \
"$(DESTDIR)$(toolexeclibgoruntimedir)" \ "$(DESTDIR)$(toolexeclibgoruntimedir)" \
"$(DESTDIR)$(toolexeclibgosyncdir)" \
"$(DESTDIR)$(toolexeclibgotestingdir)" "$(DESTDIR)$(toolexeclibgotestingdir)"
LIBRARIES = $(toolexeclib_LIBRARIES) LIBRARIES = $(toolexeclib_LIBRARIES)
ARFLAGS = cru ARFLAGS = cru
@ -122,43 +123,45 @@ libgobegin_a_OBJECTS = $(am_libgobegin_a_OBJECTS)
LTLIBRARIES = $(toolexeclib_LTLIBRARIES) LTLIBRARIES = $(toolexeclib_LTLIBRARIES)
am__DEPENDENCIES_1 = am__DEPENDENCIES_1 =
am__DEPENDENCIES_2 = asn1/asn1.lo big/big.lo bufio/bufio.lo \ am__DEPENDENCIES_2 = asn1/asn1.lo big/big.lo bufio/bufio.lo \
bytes/bytes.lo bytes/index.lo cmath/cmath.lo ebnf/ebnf.lo \ bytes/bytes.lo bytes/index.lo cmath/cmath.lo crypto/crypto.lo \
exec/exec.lo expvar/expvar.lo flag/flag.lo fmt/fmt.lo \ ebnf/ebnf.lo exec/exec.lo expvar/expvar.lo flag/flag.lo \
gob/gob.lo hash/hash.lo html/html.lo http/http.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 \ 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 \ mime/mime.lo net/net.lo netchan/netchan.lo os/os.lo \
patch/patch.lo path/path.lo rand/rand.lo reflect/reflect.lo \ patch/patch.lo path/path.lo rand/rand.lo reflect/reflect.lo \
regexp/regexp.lo rpc/rpc.lo runtime/runtime.lo \ regexp/regexp.lo rpc/rpc.lo runtime/runtime.lo \
scanner/scanner.lo smtp/smtp.lo sort/sort.lo \ scanner/scanner.lo smtp/smtp.lo sort/sort.lo \
strconv/strconv.lo strings/strings.lo sync/mutex.lo \ strconv/strconv.lo strings/strings.lo sync/sync.lo \
sync/cas.lo syslog/syslog.lo syslog/syslog_c.lo \ syslog/syslog.lo syslog/syslog_c.lo tabwriter/tabwriter.lo \
tabwriter/tabwriter.lo template/template.lo time/time.lo \ template/template.lo time/time.lo try/try.lo \
try/try.lo unicode/unicode.lo utf16/utf16.lo utf8/utf8.lo \ unicode/unicode.lo utf16/utf16.lo utf8/utf8.lo \
websocket/websocket.lo xml/xml.lo archive/tar.lo \ websocket/websocket.lo xml/xml.lo archive/tar.lo \
archive/zip.lo compress/flate.lo compress/gzip.lo \ archive/zip.lo compress/bzip2.lo compress/flate.lo \
compress/zlib.lo container/heap.lo container/list.lo \ compress/gzip.lo compress/lzw.lo compress/zlib.lo \
container/ring.lo container/vector.lo crypto/aes.lo \ container/heap.lo container/list.lo container/ring.lo \
crypto/block.lo crypto/blowfish.lo crypto/cast5.lo \ container/vector.lo crypto/aes.lo crypto/block.lo \
crypto/cipher.lo crypto/elliptic.lo crypto/hmac.lo \ crypto/blowfish.lo crypto/cast5.lo crypto/cipher.lo \
crypto/md4.lo crypto/md5.lo crypto/ocsp.lo crypto/rand.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/rc4.lo crypto/ripemd160.lo crypto/rsa.lo crypto/sha1.lo \
crypto/sha256.lo crypto/sha512.lo crypto/subtle.lo \ crypto/sha256.lo crypto/sha512.lo crypto/subtle.lo \
crypto/tls.lo crypto/twofish.lo crypto/x509.lo crypto/xtea.lo \ crypto/tls.lo crypto/twofish.lo crypto/x509.lo crypto/xtea.lo \
crypto/openpgp/armor.lo crypto/openpgp/error.lo \ crypto/openpgp/armor.lo crypto/openpgp/error.lo \
crypto/openpgp/s2k.lo debug/dwarf.lo debug/elf.lo \ crypto/openpgp/packet.lo crypto/openpgp/s2k.lo debug/dwarf.lo \
debug/gosym.lo debug/macho.lo debug/pe.lo debug/proc.lo \ debug/elf.lo debug/gosym.lo debug/macho.lo debug/pe.lo \
encoding/ascii85.lo encoding/base32.lo encoding/base64.lo \ debug/proc.lo encoding/ascii85.lo encoding/base32.lo \
encoding/binary.lo encoding/git85.lo encoding/hex.lo \ encoding/base64.lo encoding/binary.lo encoding/git85.lo \
encoding/line.lo encoding/pem.lo exp/datafmt.lo exp/draw.lo \ encoding/hex.lo encoding/line.lo encoding/pem.lo \
exp/eval.lo go/ast.lo go/doc.lo go/parser.lo go/printer.lo \ exp/datafmt.lo exp/draw.lo exp/eval.lo go/ast.lo go/doc.lo \
go/scanner.lo go/token.lo go/typechecker.lo hash/adler32.lo \ go/parser.lo go/printer.lo go/scanner.lo go/token.lo \
hash/crc32.lo hash/crc64.lo http/pprof.lo image/jpeg.lo \ go/typechecker.lo hash/adler32.lo hash/crc32.lo hash/crc64.lo \
image/png.lo index/suffixarray.lo io/ioutil.lo \ http/pprof.lo image/jpeg.lo image/png.lo index/suffixarray.lo \
mime/multipart.lo net/dict.lo net/textproto.lo \ io/ioutil.lo mime/multipart.lo net/dict.lo net/textproto.lo \
$(am__DEPENDENCIES_1) os/signal.lo rpc/jsonrpc.lo \ $(am__DEPENDENCIES_1) os/signal.lo rpc/jsonrpc.lo \
runtime/debug.lo runtime/pprof.lo syscalls/syscall.lo \ runtime/debug.lo runtime/pprof.lo sync/atomic.lo \
syscalls/errno.lo testing/testing.lo testing/iotest.lo \ sync/atomic_c.lo syscalls/syscall.lo syscalls/errno.lo \
testing/quick.lo testing/script.lo testing/testing.lo testing/iotest.lo testing/quick.lo \
testing/script.lo
libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \ libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(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/mcache.c runtime/mcentral.c \
runtime/mem_posix_memalign.c runtime/mem.c runtime/mfinal.c \ runtime/mem_posix_memalign.c runtime/mem.c runtime/mfinal.c \
runtime/mfixalloc.c runtime/mgc0.c runtime/mheap.c \ runtime/mfixalloc.c runtime/mgc0.c runtime/mheap.c \
runtime/mheapmap32.c runtime/mheapmap64.c runtime/msize.c \ runtime/msize.c runtime/proc.c runtime/thread.c \
runtime/proc.c runtime/thread.c \
runtime/rtems-task-variable-add.c chan.c iface.c malloc.c \ runtime/rtems-task-variable-add.c chan.c iface.c malloc.c \
map.c mprof.c reflect.c sigqueue.c string.c map.c mprof.c reflect.c sigqueue.c string.c
@HAVE_SYS_MMAN_H_FALSE@am__objects_1 = mem_posix_memalign.lo @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-unreflect.lo go-unsafe-new.lo go-unsafe-newarray.lo \
go-unsafe-pointer.lo go-unwind.lo mcache.lo mcentral.lo \ go-unsafe-pointer.lo go-unwind.lo mcache.lo mcentral.lo \
$(am__objects_1) mfinal.lo mfixalloc.lo mgc0.lo mheap.lo \ $(am__objects_1) mfinal.lo mfixalloc.lo mgc0.lo mheap.lo \
mheapmap32.lo mheapmap64.lo msize.lo proc.lo thread.lo \ msize.lo proc.lo thread.lo $(am__objects_2) chan.lo iface.lo \
$(am__objects_2) chan.lo iface.lo malloc.lo map.lo mprof.lo \ malloc.lo map.lo mprof.lo reflect.lo sigqueue.lo string.lo
reflect.lo sigqueue.lo string.lo
am_libgo_la_OBJECTS = $(am__objects_3) am_libgo_la_OBJECTS = $(am__objects_3)
libgo_la_OBJECTS = $(am_libgo_la_OBJECTS) libgo_la_OBJECTS = $(am_libgo_la_OBJECTS)
DEFAULT_INCLUDES = -I.@am__isrc@ DEFAULT_INCLUDES = -I.@am__isrc@
@ -280,7 +281,7 @@ DATA = $(toolexeclibgo_DATA) $(toolexeclibgoarchive_DATA) \
$(toolexeclibgoio_DATA) $(toolexeclibgomime_DATA) \ $(toolexeclibgoio_DATA) $(toolexeclibgomime_DATA) \
$(toolexeclibgonet_DATA) $(toolexeclibgoos_DATA) \ $(toolexeclibgonet_DATA) $(toolexeclibgoos_DATA) \
$(toolexeclibgorpc_DATA) $(toolexeclibgoruntime_DATA) \ $(toolexeclibgorpc_DATA) $(toolexeclibgoruntime_DATA) \
$(toolexeclibgotesting_DATA) $(toolexeclibgosync_DATA) $(toolexeclibgotesting_DATA)
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
distclean-recursive maintainer-clean-recursive distclean-recursive maintainer-clean-recursive
AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
@ -546,6 +547,7 @@ toolexeclibgo_DATA = \
bufio.gox \ bufio.gox \
bytes.gox \ bytes.gox \
cmath.gox \ cmath.gox \
crypto.gox \
ebnf.gox \ ebnf.gox \
exec.gox \ exec.gox \
expvar.gox \ expvar.gox \
@ -597,8 +599,10 @@ toolexeclibgoarchive_DATA = \
toolexeclibgocompressdir = $(toolexeclibgodir)/compress toolexeclibgocompressdir = $(toolexeclibgodir)/compress
toolexeclibgocompress_DATA = \ toolexeclibgocompress_DATA = \
compress/bzip2.gox \
compress/flate.gox \ compress/flate.gox \
compress/gzip.gox \ compress/gzip.gox \
compress/lzw.gox \
compress/zlib.gox compress/zlib.gox
toolexeclibgocontainerdir = $(toolexeclibgodir)/container toolexeclibgocontainerdir = $(toolexeclibgodir)/container
@ -615,11 +619,13 @@ toolexeclibgocrypto_DATA = \
crypto/blowfish.gox \ crypto/blowfish.gox \
crypto/cast5.gox \ crypto/cast5.gox \
crypto/cipher.gox \ crypto/cipher.gox \
crypto/dsa.gox \
crypto/elliptic.gox \ crypto/elliptic.gox \
crypto/hmac.gox \ crypto/hmac.gox \
crypto/md4.gox \ crypto/md4.gox \
crypto/md5.gox \ crypto/md5.gox \
crypto/ocsp.gox \ crypto/ocsp.gox \
crypto/openpgp.gox \
crypto/rand.gox \ crypto/rand.gox \
crypto/rc4.gox \ crypto/rc4.gox \
crypto/ripemd160.gox \ crypto/ripemd160.gox \
@ -637,6 +643,7 @@ toolexeclibgocryptoopenpgpdir = $(toolexeclibgocryptodir)/openpgp
toolexeclibgocryptoopenpgp_DATA = \ toolexeclibgocryptoopenpgp_DATA = \
crypto/openpgp/armor.gox \ crypto/openpgp/armor.gox \
crypto/openpgp/error.gox \ crypto/openpgp/error.gox \
crypto/openpgp/packet.gox \
crypto/openpgp/s2k.gox crypto/openpgp/s2k.gox
toolexeclibgodebugdir = $(toolexeclibgodir)/debug toolexeclibgodebugdir = $(toolexeclibgodir)/debug
@ -725,6 +732,10 @@ toolexeclibgoruntime_DATA = \
runtime/debug.gox \ runtime/debug.gox \
runtime/pprof.gox runtime/pprof.gox
toolexeclibgosyncdir = $(toolexeclibgodir)/sync
toolexeclibgosync_DATA = \
sync/atomic.gox
toolexeclibgotestingdir = $(toolexeclibgodir)/testing toolexeclibgotestingdir = $(toolexeclibgodir)/testing
toolexeclibgotesting_DATA = \ toolexeclibgotesting_DATA = \
testing/iotest.gox \ testing/iotest.gox \
@ -821,8 +832,6 @@ runtime_files = \
runtime/mfixalloc.c \ runtime/mfixalloc.c \
runtime/mgc0.c \ runtime/mgc0.c \
runtime/mheap.c \ runtime/mheap.c \
runtime/mheapmap32.c \
runtime/mheapmap64.c \
runtime/msize.c \ runtime/msize.c \
runtime/proc.c \ runtime/proc.c \
runtime/thread.c \ runtime/thread.c \
@ -874,6 +883,9 @@ go_cmath_files = \
go/cmath/sqrt.go \ go/cmath/sqrt.go \
go/cmath/tan.go go/cmath/tan.go
go_crypto_files = \
go/crypto/crypto.go
go_ebnf_files = \ go_ebnf_files = \
go/ebnf/ebnf.go \ go/ebnf/ebnf.go \
go/ebnf/parser.go go/ebnf/parser.go
@ -918,6 +930,7 @@ go_http_files = \
go/http/client.go \ go/http/client.go \
go/http/dump.go \ go/http/dump.go \
go/http/fs.go \ go/http/fs.go \
go/http/header.go \
go/http/lex.go \ go/http/lex.go \
go/http/persist.go \ go/http/persist.go \
go/http/request.go \ go/http/request.go \
@ -925,6 +938,7 @@ go_http_files = \
go/http/server.go \ go/http/server.go \
go/http/status.go \ go/http/status.go \
go/http/transfer.go \ go/http/transfer.go \
go/http/transport.go \
go/http/url.go go/http/url.go
go_image_files = \ go_image_files = \
@ -1051,6 +1065,7 @@ go_os_files = \
go/os/env_unix.go \ go/os/env_unix.go \
go/os/error.go \ go/os/error.go \
go/os/exec.go \ go/os/exec.go \
go/os/exec_unix.go \
go/os/file.go \ go/os/file.go \
go/os/file_unix.go \ go/os/file_unix.go \
go/os/getwd.go \ go/os/getwd.go \
@ -1096,8 +1111,6 @@ go_runtime_files = \
go/runtime/debug.go \ go/runtime/debug.go \
go/runtime/error.go \ go/runtime/error.go \
go/runtime/extern.go \ go/runtime/extern.go \
go/runtime/malloc_defs.go \
go/runtime/runtime_defs.go \
go/runtime/sig.go \ go/runtime/sig.go \
go/runtime/softfloat64.go \ go/runtime/softfloat64.go \
go/runtime/type.go \ go/runtime/type.go \
@ -1128,12 +1141,11 @@ go_strings_files = \
go/strings/strings.go go/strings/strings.go
go_sync_files = \ go_sync_files = \
go/sync/cond.go \
go/sync/mutex.go \ go/sync/mutex.go \
go/sync/once.go \ go/sync/once.go \
go/sync/rwmutex.go go/sync/rwmutex.go \
go/sync/waitgroup.go
go_sync_c_files = \
go/sync/cas.c
@LIBGO_IS_SOLARIS_FALSE@go_syslog_file = go/syslog/syslog_unix.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 @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/reader.go \
go/archive/zip/struct.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_files = \
go/compress/flate/deflate.go \ go/compress/flate/deflate.go \
go/compress/flate/huffman_bit_writer.go \ go/compress/flate/huffman_bit_writer.go \
@ -1209,6 +1227,10 @@ go_compress_gzip_files = \
go/compress/gzip/gzip.go \ go/compress/gzip/gzip.go \
go/compress/gzip/gunzip.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_files = \
go/compress/zlib/reader.go \ go/compress/zlib/reader.go \
go/compress/zlib/writer.go go/compress/zlib/writer.go
@ -1261,6 +1283,9 @@ go_crypto_cipher_files = \
go/crypto/cipher/ocfb.go \ go/crypto/cipher/ocfb.go \
go/crypto/cipher/ofb.go go/crypto/cipher/ofb.go
go_crypto_dsa_files = \
go/crypto/dsa/dsa.go
go_crypto_elliptic_files = \ go_crypto_elliptic_files = \
go/crypto/elliptic/elliptic.go go/crypto/elliptic/elliptic.go
@ -1278,6 +1303,12 @@ go_crypto_md5_files = \
go_crypto_ocsp_files = \ go_crypto_ocsp_files = \
go/crypto/ocsp/ocsp.go 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_files = \
go/crypto/rand/rand.go \ go/crypto/rand/rand.go \
go/crypto/rand/rand_unix.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_files = \
go/crypto/openpgp/error/error.go 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_files = \
go/crypto/openpgp/s2k/s2k.go go/crypto/openpgp/s2k/s2k.go
@ -1484,6 +1529,7 @@ go_net_dict_files = \
go/net/dict/dict.go go/net/dict/dict.go
go_net_textproto_files = \ go_net_textproto_files = \
go/net/textproto/header.go \
go/net/textproto/pipeline.go \ go/net/textproto/pipeline.go \
go/net/textproto/reader.go \ go/net/textproto/reader.go \
go/net/textproto/textproto.go \ go/net/textproto/textproto.go \
@ -1506,6 +1552,12 @@ go_runtime_debug_files = \
go_runtime_pprof_files = \ go_runtime_pprof_files = \
go/runtime/pprof/pprof.go 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_files = \
go/testing/iotest/logger.go \ go/testing/iotest/logger.go \
go/testing/iotest/reader.go \ go/testing/iotest/reader.go \
@ -1606,6 +1658,7 @@ libgo_go_objs = \
bytes/bytes.lo \ bytes/bytes.lo \
bytes/index.lo \ bytes/index.lo \
cmath/cmath.lo \ cmath/cmath.lo \
crypto/crypto.lo \
ebnf/ebnf.lo \ ebnf/ebnf.lo \
exec/exec.lo \ exec/exec.lo \
expvar/expvar.lo \ expvar/expvar.lo \
@ -1636,8 +1689,7 @@ libgo_go_objs = \
sort/sort.lo \ sort/sort.lo \
strconv/strconv.lo \ strconv/strconv.lo \
strings/strings.lo \ strings/strings.lo \
sync/mutex.lo \ sync/sync.lo \
sync/cas.lo \
syslog/syslog.lo \ syslog/syslog.lo \
syslog/syslog_c.lo \ syslog/syslog_c.lo \
tabwriter/tabwriter.lo \ tabwriter/tabwriter.lo \
@ -1651,8 +1703,10 @@ libgo_go_objs = \
xml/xml.lo \ xml/xml.lo \
archive/tar.lo \ archive/tar.lo \
archive/zip.lo \ archive/zip.lo \
compress/bzip2.lo \
compress/flate.lo \ compress/flate.lo \
compress/gzip.lo \ compress/gzip.lo \
compress/lzw.lo \
compress/zlib.lo \ compress/zlib.lo \
container/heap.lo \ container/heap.lo \
container/list.lo \ container/list.lo \
@ -1663,11 +1717,13 @@ libgo_go_objs = \
crypto/blowfish.lo \ crypto/blowfish.lo \
crypto/cast5.lo \ crypto/cast5.lo \
crypto/cipher.lo \ crypto/cipher.lo \
crypto/dsa.lo \
crypto/elliptic.lo \ crypto/elliptic.lo \
crypto/hmac.lo \ crypto/hmac.lo \
crypto/md4.lo \ crypto/md4.lo \
crypto/md5.lo \ crypto/md5.lo \
crypto/ocsp.lo \ crypto/ocsp.lo \
crypto/openpgp.lo \
crypto/rand.lo \ crypto/rand.lo \
crypto/rc4.lo \ crypto/rc4.lo \
crypto/ripemd160.lo \ crypto/ripemd160.lo \
@ -1682,6 +1738,7 @@ libgo_go_objs = \
crypto/xtea.lo \ crypto/xtea.lo \
crypto/openpgp/armor.lo \ crypto/openpgp/armor.lo \
crypto/openpgp/error.lo \ crypto/openpgp/error.lo \
crypto/openpgp/packet.lo \
crypto/openpgp/s2k.lo \ crypto/openpgp/s2k.lo \
debug/dwarf.lo \ debug/dwarf.lo \
debug/elf.lo \ debug/elf.lo \
@ -1723,6 +1780,8 @@ libgo_go_objs = \
rpc/jsonrpc.lo \ rpc/jsonrpc.lo \
runtime/debug.lo \ runtime/debug.lo \
runtime/pprof.lo \ runtime/pprof.lo \
sync/atomic.lo \
sync/atomic_c.lo \
syscalls/syscall.lo \ syscalls/syscall.lo \
syscalls/errno.lo \ syscalls/errno.lo \
testing/testing.lo \ testing/testing.lo \
@ -1857,8 +1916,10 @@ TEST_PACKAGES = \
xml/check \ xml/check \
archive/tar/check \ archive/tar/check \
archive/zip/check \ archive/zip/check \
compress/bzip2/check \
compress/flate/check \ compress/flate/check \
compress/gzip/check \ compress/gzip/check \
compress/lzw/check \
compress/zlib/check \ compress/zlib/check \
container/heap/check \ container/heap/check \
container/list/check \ container/list/check \
@ -1869,11 +1930,13 @@ TEST_PACKAGES = \
crypto/blowfish/check \ crypto/blowfish/check \
crypto/cast5/check \ crypto/cast5/check \
crypto/cipher/check \ crypto/cipher/check \
crypto/dsa/check \
crypto/elliptic/check \ crypto/elliptic/check \
crypto/hmac/check \ crypto/hmac/check \
crypto/md4/check \ crypto/md4/check \
crypto/md5/check \ crypto/md5/check \
crypto/ocsp/check \ crypto/ocsp/check \
crypto/openpgp/check \
crypto/rand/check \ crypto/rand/check \
crypto/rc4/check \ crypto/rc4/check \
crypto/ripemd160/check \ crypto/ripemd160/check \
@ -1887,6 +1950,7 @@ TEST_PACKAGES = \
crypto/x509/check \ crypto/x509/check \
crypto/xtea/check \ crypto/xtea/check \
crypto/openpgp/armor/check \ crypto/openpgp/armor/check \
crypto/openpgp/packet/check \
crypto/openpgp/s2k/check \ crypto/openpgp/s2k/check \
debug/dwarf/check \ debug/dwarf/check \
debug/elf/check \ debug/elf/check \
@ -1919,6 +1983,7 @@ TEST_PACKAGES = \
$(os_inotify_check) \ $(os_inotify_check) \
os/signal/check \ os/signal/check \
rpc/jsonrpc/check \ rpc/jsonrpc/check \
sync/atomic/check \
testing/quick/check \ testing/quick/check \
testing/script/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)/mfixalloc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mgc0.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)/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)/mprof.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msize.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@ @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@ @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 @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 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@ $(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 @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/msize.Tpo $(DEPDIR)/msize.Plo
@ -3261,6 +3310,26 @@ uninstall-toolexeclibgoruntimeDATA:
test -n "$$files" || exit 0; \ test -n "$$files" || exit 0; \
echo " ( cd '$(DESTDIR)$(toolexeclibgoruntimedir)' && rm -f" $$files ")"; \ echo " ( cd '$(DESTDIR)$(toolexeclibgoruntimedir)' && rm -f" $$files ")"; \
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) install-toolexeclibgotestingDATA: $(toolexeclibgotesting_DATA)
@$(NORMAL_INSTALL) @$(NORMAL_INSTALL)
test -z "$(toolexeclibgotestingdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgotestingdir)" test -z "$(toolexeclibgotestingdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgotestingdir)"
@ -3598,7 +3667,7 @@ all-am: Makefile $(LIBRARIES) $(LTLIBRARIES) all-multi $(DATA) \
config.h config.h
installdirs: installdirs-recursive installdirs: installdirs-recursive
installdirs-am: 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"; \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done done
install: install-recursive install: install-recursive
@ -3672,7 +3741,7 @@ install-exec-am: install-multi install-toolexeclibLIBRARIES \
install-toolexeclibgoindexDATA install-toolexeclibgoioDATA \ install-toolexeclibgoindexDATA install-toolexeclibgoioDATA \
install-toolexeclibgomimeDATA install-toolexeclibgonetDATA \ install-toolexeclibgomimeDATA install-toolexeclibgonetDATA \
install-toolexeclibgoosDATA install-toolexeclibgorpcDATA \ install-toolexeclibgoosDATA install-toolexeclibgorpcDATA \
install-toolexeclibgoruntimeDATA \ install-toolexeclibgoruntimeDATA install-toolexeclibgosyncDATA \
install-toolexeclibgotestingDATA install-toolexeclibgotestingDATA
install-html: install-html-recursive install-html: install-html-recursive
@ -3732,6 +3801,7 @@ uninstall-am: uninstall-toolexeclibLIBRARIES \
uninstall-toolexeclibgomimeDATA uninstall-toolexeclibgonetDATA \ uninstall-toolexeclibgomimeDATA uninstall-toolexeclibgonetDATA \
uninstall-toolexeclibgoosDATA uninstall-toolexeclibgorpcDATA \ uninstall-toolexeclibgoosDATA uninstall-toolexeclibgorpcDATA \
uninstall-toolexeclibgoruntimeDATA \ uninstall-toolexeclibgoruntimeDATA \
uninstall-toolexeclibgosyncDATA \
uninstall-toolexeclibgotestingDATA uninstall-toolexeclibgotestingDATA
.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all all-multi \ .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all all-multi \
@ -3766,7 +3836,7 @@ uninstall-am: uninstall-toolexeclibLIBRARIES \
install-toolexeclibgoindexDATA install-toolexeclibgoioDATA \ install-toolexeclibgoindexDATA install-toolexeclibgoioDATA \
install-toolexeclibgomimeDATA install-toolexeclibgonetDATA \ install-toolexeclibgomimeDATA install-toolexeclibgonetDATA \
install-toolexeclibgoosDATA install-toolexeclibgorpcDATA \ install-toolexeclibgoosDATA install-toolexeclibgorpcDATA \
install-toolexeclibgoruntimeDATA \ install-toolexeclibgoruntimeDATA install-toolexeclibgosyncDATA \
install-toolexeclibgotestingDATA installcheck installcheck-am \ install-toolexeclibgotestingDATA installcheck installcheck-am \
installdirs installdirs-am maintainer-clean \ installdirs installdirs-am maintainer-clean \
maintainer-clean-generic maintainer-clean-multi mostlyclean \ maintainer-clean-generic maintainer-clean-multi mostlyclean \
@ -3790,6 +3860,7 @@ uninstall-am: uninstall-toolexeclibLIBRARIES \
uninstall-toolexeclibgomimeDATA uninstall-toolexeclibgonetDATA \ uninstall-toolexeclibgomimeDATA uninstall-toolexeclibgonetDATA \
uninstall-toolexeclibgoosDATA uninstall-toolexeclibgorpcDATA \ uninstall-toolexeclibgoosDATA uninstall-toolexeclibgorpcDATA \
uninstall-toolexeclibgoruntimeDATA \ uninstall-toolexeclibgoruntimeDATA \
uninstall-toolexeclibgosyncDATA \
uninstall-toolexeclibgotestingDATA uninstall-toolexeclibgotestingDATA
@ -3872,6 +3943,12 @@ cmath/check: $(CHECK_DEPS)
$(CHECK) $(CHECK)
.PHONY: cmath/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 \ ebnf/ebnf.lo: $(go_ebnf_files) container/vector.gox go/scanner.gox \
go/token.gox os.gox strconv.gox unicode.gox utf8.gox go/token.gox os.gox strconv.gox unicode.gox utf8.gox
$(BUILDPACKAGE) $(BUILDPACKAGE)
@ -3879,7 +3956,7 @@ ebnf/check: $(CHECK_DEPS)
$(CHECK) $(CHECK)
.PHONY: ebnf/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) $(BUILDPACKAGE)
exec/check: $(CHECK_DEPS) exec/check: $(CHECK_DEPS)
$(CHECK) $(CHECK)
@ -3898,8 +3975,8 @@ flag/check: $(CHECK_DEPS)
$(CHECK) $(CHECK)
.PHONY: flag/check .PHONY: flag/check
fmt/fmt.lo: $(go_fmt_files) bytes.gox io.gox os.gox reflect.gox strconv.gox \ fmt/fmt.lo: $(go_fmt_files) bytes.gox io.gox math.gox os.gox reflect.gox \
strings.gox unicode.gox utf8.gox strconv.gox strings.gox unicode.gox utf8.gox
$(BUILDPACKAGE) $(BUILDPACKAGE)
fmt/check: $(CHECK_DEPS) fmt/check: $(CHECK_DEPS)
$(CHECK) $(CHECK)
@ -3926,10 +4003,10 @@ html/check: $(CHECK_DEPS)
$(CHECK) $(CHECK)
.PHONY: html/check .PHONY: html/check
http/http.lo: $(go_http_files) bufio.gox bytes.gox container/list.gox \ http/http.lo: $(go_http_files) bufio.gox bytes.gox container/vector.gox \
container/vector.gox crypto/rand.gox crypto/tls.gox \ crypto/rand.gox crypto/tls.gox encoding/base64.gox fmt.gox \
encoding/base64.gox fmt.gox io.gox io/ioutil.gox log.gox \ io.gox io/ioutil.gox log.gox mime.gox mime/multipart.gox \
mime.gox mime/multipart.gox net.gox os.gox path.gox sort.gox \ net.gox net/textproto.gox os.gox path.gox sort.gox \
strconv.gox strings.gox sync.gox time.gox utf8.gox strconv.gox strings.gox sync.gox time.gox utf8.gox
$(BUILDPACKAGE) $(BUILDPACKAGE)
http/check: $(CHECK_DEPS) http/check: $(CHECK_DEPS)
@ -3948,9 +4025,10 @@ io/check: $(CHECK_DEPS)
$(CHECK) $(CHECK)
.PHONY: io/check .PHONY: io/check
json/json.lo: $(go_json_files) bytes.gox container/vector.gox fmt.gox io.gox \ json/json.lo: $(go_json_files) bytes.gox container/vector.gox \
math.gox os.gox reflect.gox runtime.gox strconv.gox \ encoding/base64.gox fmt.gox io.gox math.gox os.gox \
strings.gox unicode.gox utf16.gox utf8.gox reflect.gox runtime.gox strconv.gox strings.gox unicode.gox \
utf16.gox utf8.gox
$(BUILDPACKAGE) $(BUILDPACKAGE)
json/check: $(CHECK_DEPS) json/check: $(CHECK_DEPS)
$(CHECK) $(CHECK)
@ -3983,14 +4061,14 @@ net/check: $(CHECK_DEPS)
$(CHECK) $(CHECK)
.PHONY: net/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 reflect.gox strconv.gox sync.gox time.gox
$(BUILDPACKAGE) $(BUILDPACKAGE)
netchan/check: $(CHECK_DEPS) netchan/check: $(CHECK_DEPS)
$(CHECK) $(CHECK)
.PHONY: netchan/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) $(BUILDPACKAGE)
os/check: $(CHECK_DEPS) os/check: $(CHECK_DEPS)
$(CHECK) $(CHECK)
@ -4078,10 +4156,8 @@ strings/check: $(CHECK_DEPS)
$(CHECK) $(CHECK)
.PHONY: strings/check .PHONY: strings/check
sync/mutex.lo: $(go_sync_files) runtime.gox sync/sync.lo: $(go_sync_files) runtime.gox sync/atomic.gox
$(BUILDPACKAGE) $(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) sync/check: $(CHECK_DEPS)
$(CHECK) $(CHECK)
.PHONY: sync/check .PHONY: sync/check
@ -4178,6 +4254,13 @@ archive/zip/check: $(CHECK_DEPS)
$(CHECK) $(CHECK)
.PHONY: archive/zip/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 \ compress/flate.lo: $(go_compress_flate_files) bufio.gox io.gox math.gox \
os.gox sort.gox strconv.gox os.gox sort.gox strconv.gox
$(BUILDPACKAGE) $(BUILDPACKAGE)
@ -4194,6 +4277,13 @@ compress/gzip/check: $(CHECK_DEPS)
$(CHECK) $(CHECK)
.PHONY: compress/gzip/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 \ compress/zlib.lo: $(go_compress_zlib_files) bufio.gox compress/flate.gox \
hash.gox hash/adler32.gox io.gox os.gox hash.gox hash/adler32.gox io.gox os.gox
$(BUILDPACKAGE) $(BUILDPACKAGE)
@ -4265,6 +4355,13 @@ crypto/cipher/check: $(CHECK_DEPS)
$(CHECK) $(CHECK)
.PHONY: crypto/cipher/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 crypto/elliptic.lo: $(go_crypto_elliptic_files) big.gox io.gox os.gox sync.gox
$(BUILDPACKAGE) $(BUILDPACKAGE)
crypto/elliptic/check: $(CHECK_DEPS) crypto/elliptic/check: $(CHECK_DEPS)
@ -4280,21 +4377,21 @@ crypto/hmac/check: $(CHECK_DEPS)
$(CHECK) $(CHECK)
.PHONY: crypto/hmac/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) $(BUILDPACKAGE)
crypto/md4/check: $(CHECK_DEPS) crypto/md4/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/md4 @$(MKDIR_P) crypto/md4
$(CHECK) $(CHECK)
.PHONY: 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) $(BUILDPACKAGE)
crypto/md5/check: $(CHECK_DEPS) crypto/md5/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/md5 @$(MKDIR_P) crypto/md5
$(CHECK) $(CHECK)
.PHONY: 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 crypto/sha1.gox crypto/x509.gox os.gox time.gox
$(BUILDPACKAGE) $(BUILDPACKAGE)
crypto/ocsp/check: $(CHECK_DEPS) crypto/ocsp/check: $(CHECK_DEPS)
@ -4302,8 +4399,18 @@ crypto/ocsp/check: $(CHECK_DEPS)
$(CHECK) $(CHECK)
.PHONY: crypto/ocsp/check .PHONY: crypto/ocsp/check
crypto/rand.lo: $(go_crypto_rand_files) crypto/aes.gox io.gox os.gox sync.gox \ crypto/openpgp.lo: $(go_crypto_openpgp_files) crypto.gox \
time.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) $(BUILDPACKAGE)
crypto/rand/check: $(CHECK_DEPS) crypto/rand/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/rand @$(MKDIR_P) crypto/rand
@ -4317,14 +4424,14 @@ crypto/rc4/check: $(CHECK_DEPS)
$(CHECK) $(CHECK)
.PHONY: crypto/rc4/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) $(BUILDPACKAGE)
crypto/ripemd160/check: $(CHECK_DEPS) crypto/ripemd160/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/ripemd160 @$(MKDIR_P) crypto/ripemd160
$(CHECK) $(CHECK)
.PHONY: 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 crypto/subtle.gox encoding/hex.gox hash.gox io.gox os.gox
$(BUILDPACKAGE) $(BUILDPACKAGE)
crypto/rsa/check: $(CHECK_DEPS) crypto/rsa/check: $(CHECK_DEPS)
@ -4332,21 +4439,21 @@ crypto/rsa/check: $(CHECK_DEPS)
$(CHECK) $(CHECK)
.PHONY: crypto/rsa/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) $(BUILDPACKAGE)
crypto/sha1/check: $(CHECK_DEPS) crypto/sha1/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/sha1 @$(MKDIR_P) crypto/sha1
$(CHECK) $(CHECK)
.PHONY: 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) $(BUILDPACKAGE)
crypto/sha256/check: $(CHECK_DEPS) crypto/sha256/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/sha256 @$(MKDIR_P) crypto/sha256
$(CHECK) $(CHECK)
.PHONY: 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) $(BUILDPACKAGE)
crypto/sha512/check: $(CHECK_DEPS) crypto/sha512/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/sha512 @$(MKDIR_P) crypto/sha512
@ -4361,7 +4468,7 @@ crypto/subtle/check: $(CHECK_DEPS)
.PHONY: crypto/subtle/check .PHONY: crypto/subtle/check
crypto/tls.lo: $(go_crypto_tls_files) big.gox bufio.gox bytes.gox \ 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/elliptic.gox crypto/hmac.gox crypto/md5.gox \
crypto/rc4.gox crypto/rand.gox crypto/rsa.gox crypto/sha1.gox \ crypto/rc4.gox crypto/rand.gox crypto/rsa.gox crypto/sha1.gox \
crypto/subtle.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 .PHONY: crypto/twofish/check
crypto/x509.lo: $(go_crypto_x509_files) asn1.gox big.gox container/vector.gox \ 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 \ crypto.gox crypto/rsa.gox crypto/sha1.gox hash.gox os.gox \
time.gox strings.gox time.gox
$(BUILDPACKAGE) $(BUILDPACKAGE)
crypto/x509/check: $(CHECK_DEPS) crypto/x509/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/x509 @$(MKDIR_P) crypto/x509
@ -4405,16 +4512,30 @@ crypto/openpgp/armor/check: $(CHECK_DEPS)
$(CHECK) $(CHECK)
.PHONY: crypto/openpgp/armor/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) $(BUILDPACKAGE)
crypto/openpgp/error/check: $(CHECK_DEPS) crypto/openpgp/error/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/openpgp/error @$(MKDIR_P) crypto/openpgp/error
$(CHECK) $(CHECK)
.PHONY: crypto/openpgp/error/check .PHONY: crypto/openpgp/error/check
crypto/openpgp/s2k.lo: $(go_crypto_openpgp_s2k_files) crypto/md5.gox \ crypto/openpgp/packet.lo: $(go_crypto_openpgp_packet_files) big.gox bytes.gox \
crypto/openpgp/error.gox crypto/ripemd160.gox crypto/sha1.gox \ compress/flate.gox compress/zlib.gox crypto.gox \
crypto/sha256.gox crypto/sha512.gox hash.gox io.gox os.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) $(BUILDPACKAGE)
crypto/openpgp/s2k/check: $(CHECK_DEPS) crypto/openpgp/s2k/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/openpgp/s2k @$(MKDIR_P) crypto/openpgp/s2k
@ -4733,6 +4854,15 @@ runtime/pprof/check: $(CHECK_DEPS)
$(CHECK) $(CHECK)
.PHONY: runtime/pprof/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 testing/iotest.lo: $(go_testing_iotest_files) io.gox log.gox os.gox
$(BUILDPACKAGE) $(BUILDPACKAGE)
testing/iotest/check: $(CHECK_DEPS) testing/iotest/check: $(CHECK_DEPS)
@ -4777,6 +4907,8 @@ bytes.gox: bytes/bytes.lo
$(BUILDGOX) $(BUILDGOX)
cmath.gox: cmath/cmath.lo cmath.gox: cmath/cmath.lo
$(BUILDGOX) $(BUILDGOX)
crypto.gox: crypto/crypto.lo
$(BUILDGOX)
ebnf.gox: ebnf/ebnf.lo ebnf.gox: ebnf/ebnf.lo
$(BUILDGOX) $(BUILDGOX)
exec.gox: exec/exec.lo exec.gox: exec/exec.lo
@ -4837,7 +4969,7 @@ strconv.gox: strconv/strconv.lo
$(BUILDGOX) $(BUILDGOX)
strings.gox: strings/strings.lo strings.gox: strings/strings.lo
$(BUILDGOX) $(BUILDGOX)
sync.gox: sync/mutex.lo sync.gox: sync/sync.lo
$(BUILDGOX) $(BUILDGOX)
syslog.gox: syslog/syslog.lo syslog.gox: syslog/syslog.lo
$(BUILDGOX) $(BUILDGOX)
@ -4869,10 +5001,14 @@ archive/tar.gox: archive/tar.lo
archive/zip.gox: archive/zip.lo archive/zip.gox: archive/zip.lo
$(BUILDGOX) $(BUILDGOX)
compress/bzip2.gox: compress/bzip2.lo
$(BUILDGOX)
compress/flate.gox: compress/flate.lo compress/flate.gox: compress/flate.lo
$(BUILDGOX) $(BUILDGOX)
compress/gzip.gox: compress/gzip.lo compress/gzip.gox: compress/gzip.lo
$(BUILDGOX) $(BUILDGOX)
compress/lzw.gox: compress/lzw.lo
$(BUILDGOX)
compress/zlib.gox: compress/zlib.lo compress/zlib.gox: compress/zlib.lo
$(BUILDGOX) $(BUILDGOX)
@ -4895,6 +5031,8 @@ crypto/cast5.gox: crypto/cast5.lo
$(BUILDGOX) $(BUILDGOX)
crypto/cipher.gox: crypto/cipher.lo crypto/cipher.gox: crypto/cipher.lo
$(BUILDGOX) $(BUILDGOX)
crypto/dsa.gox: crypto/dsa.lo
$(BUILDGOX)
crypto/elliptic.gox: crypto/elliptic.lo crypto/elliptic.gox: crypto/elliptic.lo
$(BUILDGOX) $(BUILDGOX)
crypto/hmac.gox: crypto/hmac.lo crypto/hmac.gox: crypto/hmac.lo
@ -4905,6 +5043,8 @@ crypto/md5.gox: crypto/md5.lo
$(BUILDGOX) $(BUILDGOX)
crypto/ocsp.gox: crypto/ocsp.lo crypto/ocsp.gox: crypto/ocsp.lo
$(BUILDGOX) $(BUILDGOX)
crypto/openpgp.gox: crypto/openpgp.lo
$(BUILDGOX)
crypto/rand.gox: crypto/rand.lo crypto/rand.gox: crypto/rand.lo
$(BUILDGOX) $(BUILDGOX)
crypto/rc4.gox: crypto/rc4.lo crypto/rc4.gox: crypto/rc4.lo
@ -4934,6 +5074,8 @@ crypto/openpgp/armor.gox: crypto/openpgp/armor.lo
$(BUILDGOX) $(BUILDGOX)
crypto/openpgp/error.gox: crypto/openpgp/error.lo crypto/openpgp/error.gox: crypto/openpgp/error.lo
$(BUILDGOX) $(BUILDGOX)
crypto/openpgp/packet.gox: crypto/openpgp/packet.lo
$(BUILDGOX)
crypto/openpgp/s2k.gox: crypto/openpgp/s2k.lo crypto/openpgp/s2k.gox: crypto/openpgp/s2k.lo
$(BUILDGOX) $(BUILDGOX)
@ -5031,6 +5173,9 @@ runtime/debug.gox: runtime/debug.lo
runtime/pprof.gox: runtime/pprof.lo runtime/pprof.gox: runtime/pprof.lo
$(BUILDGOX) $(BUILDGOX)
sync/atomic.gox: sync/atomic.lo
$(BUILDGOX)
testing/iotest.gox: testing/iotest.lo testing/iotest.gox: testing/iotest.lo
$(BUILDGOX) $(BUILDGOX)
testing/quick.gox: testing/quick.lo testing/quick.gox: testing/quick.lo

View file

@ -42,6 +42,10 @@ type File struct {
bodyOffset int64 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. // OpenReader will open the Zip file specified by name and return a Reader.
func OpenReader(name string) (*Reader, os.Error) { func OpenReader(name string) (*Reader, os.Error) {
f, err := os.Open(name, os.O_RDONLY, 0644) f, err := os.Open(name, os.O_RDONLY, 0644)
@ -93,7 +97,16 @@ func (f *File) Open() (rc io.ReadCloser, err os.Error) {
return 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 { switch f.Method {
case 0: // store (no compression) case 0: // store (no compression)
rc = nopCloser{r} rc = nopCloser{r}
@ -103,7 +116,7 @@ func (f *File) Open() (rc io.ReadCloser, err os.Error) {
err = UnsupportedMethod err = UnsupportedMethod
} }
if rc != nil { if rc != nil {
rc = &checksumReader{rc, crc32.NewIEEE(), f.CRC32} rc = &checksumReader{rc, crc32.NewIEEE(), f, r}
} }
return return
} }
@ -111,7 +124,8 @@ func (f *File) Open() (rc io.ReadCloser, err os.Error) {
type checksumReader struct { type checksumReader struct {
rc io.ReadCloser rc io.ReadCloser
hash hash.Hash32 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) { 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 { if err != os.EOF {
return 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 err = ChecksumError
} }
return return
@ -205,6 +224,18 @@ func readDirectoryHeader(f *File, r io.Reader) (err os.Error) {
return 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) { func readDirectoryEnd(r io.ReaderAt, size int64) (d *directoryEnd, err os.Error) {
// look for directoryEndSignature in the last 1k, then in the last 65k // look for directoryEndSignature in the last 1k, then in the last 65k
var b []byte var b []byte

View file

@ -52,6 +52,15 @@ var tests = []ZipTest{
}, },
{Name: "readme.zip"}, {Name: "readme.zip"},
{Name: "readme.notzip", Error: FormatError}, {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) { func TestReader(t *testing.T) {
@ -102,6 +111,7 @@ func readTestZip(t *testing.T, zt ZipTest) {
} }
// test invalid checksum // test invalid checksum
if !z.File[0].hasDataDescriptor() { // skip test when crc32 in dd
z.File[0].CRC32++ // invalidate z.File[0].CRC32++ // invalidate
r, err := z.File[0].Open() r, err := z.File[0].Open()
if err != nil { if err != nil {
@ -114,6 +124,7 @@ func readTestZip(t *testing.T, zt ZipTest) {
t.Errorf("%s: copy error=%v, want %v", z.File[0].Name, err, ChecksumError) t.Errorf("%s: copy error=%v, want %v", z.File[0].Name, err, ChecksumError)
} }
} }
}
func readTestFile(t *testing.T, ft ZipTestFile, f *File) { func readTestFile(t *testing.T, ft ZipTestFile, f *File) {
if f.Name != ft.Name { if f.Name != ft.Name {

View file

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

View file

@ -317,7 +317,7 @@ func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameter
switch v := value.(type) { switch v := value.(type) {
case *reflect.BoolValue: case *reflect.BoolValue:
if v.Get() { if v.Get() {
return out.WriteByte(1) return out.WriteByte(255)
} else { } else {
return out.WriteByte(0) 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. // returning a slice containing the data up to and including the delimiter.
// If ReadBytes encounters an error before finding a 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). // 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) { func (b *Reader) ReadBytes(delim byte) (line []byte, err os.Error) {
// Use ReadSlice to look for array, // Use ReadSlice to look for array,
// accumulating full buffers. // 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. // returning a string containing the data up to and including the delimiter.
// If ReadString encounters an error before finding a 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). // 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) { func (b *Reader) ReadString(delim byte) (line string, err os.Error) {
bytes, e := b.ReadBytes(delim) bytes, e := b.ReadBytes(delim)
return string(bytes), e return string(bytes), e
@ -383,6 +385,9 @@ func (b *Writer) Flush() os.Error {
if b.err != nil { if b.err != nil {
return b.err return b.err
} }
if b.n == 0 {
return nil
}
n, e := b.wr.Write(b.buf[0:b.n]) n, e := b.wr.Write(b.buf[0:b.n])
if n < b.n && e == nil { if n < b.n && e == nil {
e = io.ErrShortWrite 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 // 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. // Any error encountered during the write is also returned.
func (b *Buffer) WriteTo(w io.Writer) (n int64, err os.Error) { func (b *Buffer) WriteTo(w io.Writer) (n int64, err os.Error) {
b.lastRead = opInvalid b.lastRead = opInvalid
for b.off < len(b.buf) { if b.off < len(b.buf) {
m, e := w.Write(b.buf[b.off:]) m, e := w.Write(b.buf[b.off:])
n += int64(m)
b.off += m b.off += m
n = int64(m)
if e != nil { if e != nil {
return n, e return n, e
} }
// otherwise all bytes were written, by definition of
// Write method in io.Writer
} }
// Buffer is now empty; reset. // Buffer is now empty; reset.
b.Truncate(0) b.Truncate(0)
@ -301,6 +304,36 @@ func (b *Buffer) UnreadByte() os.Error {
return nil 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 // 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 // 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, // can also be used to size the internal buffer for writing. To do that,

View file

@ -6,6 +6,7 @@ package bytes_test
import ( import (
. "bytes" . "bytes"
"os"
"rand" "rand"
"testing" "testing"
"utf8" "utf8"
@ -238,7 +239,7 @@ func TestMixedReadsAndWrites(t *testing.T) {
func TestNil(t *testing.T) { func TestNil(t *testing.T) {
var b *Buffer var b *Buffer
if b.String() != "<nil>" { 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") panic("unreachable")
} }
func (b *syncBuffer) signal() {
select {
case b.ready <- true:
default:
}
}
func (b *syncBuffer) Write(p []byte) (n int, err os.Error) { func (b *syncBuffer) Write(p []byte) (n int, err os.Error) {
n, err = b.buf.Write(p) n, err = b.buf.Write(p)
_ = b.ready <- true b.signal()
return return
} }
@ -128,12 +135,12 @@ func (b *syncBuffer) WriteMode() {
func (b *syncBuffer) ReadMode() { func (b *syncBuffer) ReadMode() {
b.mu.Unlock() b.mu.Unlock()
_ = b.ready <- true b.signal()
} }
func (b *syncBuffer) Close() os.Error { func (b *syncBuffer) Close() os.Error {
b.closed = true b.closed = true
_ = b.ready <- true b.signal()
return nil return nil
} }
@ -255,135 +262,9 @@ func TestReverseBits(t *testing.T) {
} }
func TestDeflateInflateString(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...") 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{ var filenames = []string{
"testdata/e.txt", "../testdata/e.txt",
"testdata/pi.txt", "../testdata/pi.txt",
} }
// Tests that compressing and then decompressing the given file at the given compression level // 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{} { // Do calls function f on each element of the ring, in forward order.
c := make(chan interface{}) // The behavior of Do is undefined if f changes *r.
go func() { func (r *Ring) Do(f func(interface{})) {
if r != nil { if r != nil {
c <- r.Value f(r.Value)
for p := r.Next(); p != r; p = p.next { for p := r.Next(); p != r; p = p.next {
c <- p.Value 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 // iteration
n = 0 n = 0
s := 0 s := 0
for p := range r.Iter() { r.Do(func(p interface{}) {
n++ n++
if p != nil { if p != nil {
s += p.(int) s += p.(int)
} }
} })
if n != N { if n != N {
t.Errorf("number of forward iterations == %d; expected %d", n, N) t.Errorf("number of forward iterations == %d; expected %d", n, N)
} }
@ -128,16 +128,6 @@ func makeN(n int) *Ring {
return r 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 } func sumN(n int) int { return (n*n + n) / 2 }

View file

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

View file

@ -11,29 +11,34 @@ import (
"testing" "testing"
) )
func TestOCFB(t *testing.T) { func testOCFB(t *testing.T, resync OCFBResyncOption) {
block, err := aes.NewCipher(commonKey128) block, err := aes.NewCipher(commonKey128)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
return 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()) randData := make([]byte, block.BlockSize())
rand.Reader.Read(randData) rand.Reader.Read(randData)
ocfb, prefix := NewOCFBEncrypter(block, randData) ocfb, prefix := NewOCFBEncrypter(block, randData, resync)
ciphertext := make([]byte, len(plaintext)) ciphertext := make([]byte, len(plaintext))
ocfb.XORKeyStream(ciphertext, plaintext) ocfb.XORKeyStream(ciphertext, plaintext)
ocfbdec := NewOCFBDecrypter(block, prefix) ocfbdec := NewOCFBDecrypter(block, prefix, resync)
if ocfbdec == nil { if ocfbdec == nil {
t.Error("NewOCFBDecrypter failed") t.Errorf("NewOCFBDecrypter failed (resync: %t)", resync)
return return
} }
plaintextCopy := make([]byte, len(plaintext)) plaintextCopy := make([]byte, len(plaintext))
ocfbdec.XORKeyStream(plaintextCopy, ciphertext) ocfbdec.XORKeyStream(plaintextCopy, ciphertext)
if !bytes.Equal(plaintextCopy, plaintext) { 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 package md4
import ( import (
"crypto"
"hash" "hash"
"os" "os"
) )
func init() {
crypto.RegisterHash(crypto.MD4, New)
}
// The size of an MD4 checksum in bytes. // The size of an MD4 checksum in bytes.
const Size = 16 const Size = 16

View file

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

View file

@ -9,8 +9,9 @@ package ocsp
import ( import (
"asn1" "asn1"
"crypto"
"crypto/rsa" "crypto/rsa"
"crypto/sha1" _ "crypto/sha1"
"crypto/x509" "crypto/x509"
"os" "os"
"time" "time"
@ -168,8 +169,8 @@ func ParseResponse(bytes []byte) (*Response, os.Error) {
return nil, x509.UnsupportedAlgorithmError{} return nil, x509.UnsupportedAlgorithmError{}
} }
h := sha1.New() hashType := crypto.SHA1
hashType := rsa.HashSHA1 h := hashType.New()
pub := ret.Certificate.PublicKey.(*rsa.PublicKey) pub := ret.Certificate.PublicKey.(*rsa.PublicKey)
h.Write(basicResp.TBSResponseData.Raw) 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 return 0, os.EOF
} }
if len(line) != 64 { if len(line) > 64 {
return 0, ArmorCorrupt return 0, ArmorCorrupt
} }

View file

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

View file

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

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. // This package contains common error types for the OpenPGP packages.
package error package error
import (
"strconv"
)
// A StructuralError is returned when OpenPGP data is found to be syntactically // A StructuralError is returned when OpenPGP data is found to be syntactically
// invalid. // invalid.
type StructuralError string type StructuralError string
@ -44,3 +48,17 @@ func (ki keyIncorrect) String() string {
} }
var KeyIncorrectError = keyIncorrect(0) 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 package s2k
import ( import (
"crypto/md5" "crypto"
"crypto/openpgp/error" "crypto/openpgp/error"
"crypto/ripemd160"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"hash" "hash"
"io" "io"
"os" "os"
"strconv"
) )
// Simple writes to out the result of computing the Simple S2K function (RFC // 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 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 { 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] { 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") return nil, error.UnsupportedError("S2K function")
} }
// hashFuncFromType returns a hash.Hash which corresponds to the given hash // hashToHashIdMapping contains pairs relating OpenPGP's hash identifier with
// type byte. See RFC 4880, section 9.4. // Go's crypto.Hash type. See RFC 4880, section 9.4.
func hashFuncFromType(hashType byte) hash.Hash { var hashToHashIdMapping = []struct {
switch hashType { id byte
case 1: hash crypto.Hash
return md5.New() }{
case 2: {1, crypto.MD5},
return sha1.New() {2, crypto.SHA1},
case 3: {3, crypto.RIPEMD160},
return ripemd160.New() {8, crypto.SHA256},
case 8: {9, crypto.SHA384},
return sha256.New() {10, crypto.SHA512},
case 9: {11, crypto.SHA224},
return sha512.New384()
case 10:
return sha512.New()
case 11:
return sha256.New224()
} }
return nil // 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 package rand
import ( import (
"bufio"
"crypto/aes" "crypto/aes"
"io" "io"
"os" "os"
@ -23,21 +24,20 @@ func init() { Reader = &devReader{name: "/dev/urandom"} }
// A devReader satisfies reads by reading the file named name. // A devReader satisfies reads by reading the file named name.
type devReader struct { type devReader struct {
name string name string
f *os.File f io.Reader
mu sync.Mutex mu sync.Mutex
} }
func (r *devReader) Read(b []byte) (n int, err os.Error) { func (r *devReader) Read(b []byte) (n int, err os.Error) {
r.mu.Lock() r.mu.Lock()
defer r.mu.Unlock()
if r.f == nil { if r.f == nil {
f, err := os.Open(r.name, os.O_RDONLY, 0) f, err := os.Open(r.name, os.O_RDONLY, 0)
if f == nil { if f == nil {
r.mu.Unlock()
return 0, err return 0, err
} }
r.f = f r.f = bufio.NewReader(f)
} }
r.mu.Unlock()
return r.f.Read(b) 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 { if r.prov == 0 {
const provType = syscall.PROV_RSA_FULL const provType = syscall.PROV_RSA_FULL
const flags = syscall.CRYPT_VERIFYCONTEXT | syscall.CRYPT_SILENT const flags = syscall.CRYPT_VERIFYCONTEXT | syscall.CRYPT_SILENT
ok, errno := syscall.CryptAcquireContext(&r.prov, nil, nil, provType, flags) errno := syscall.CryptAcquireContext(&r.prov, nil, nil, provType, flags)
if !ok { if errno != 0 {
r.mu.Unlock() r.mu.Unlock()
return 0, os.NewSyscallError("CryptAcquireContext", errno) return 0, os.NewSyscallError("CryptAcquireContext", errno)
} }
} }
r.mu.Unlock() r.mu.Unlock()
ok, errno := syscall.CryptGenRandom(r.prov, uint32(len(b)), &b[0]) errno := syscall.CryptGenRandom(r.prov, uint32(len(b)), &b[0])
if !ok { if errno != 0 {
return 0, os.NewSyscallError("CryptGenRandom", errno) return 0, os.NewSyscallError("CryptGenRandom", errno)
} }
return len(b), nil return len(b), nil

View file

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

View file

@ -6,6 +6,7 @@ package rsa
import ( import (
"big" "big"
"crypto"
"crypto/subtle" "crypto/subtle"
"io" "io"
"os" "os"
@ -139,19 +140,6 @@ func nonZeroRandomBytes(s []byte, rand io.Reader) (err os.Error) {
return 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: // These are ASN1 DER structures:
// DigestInfo ::= SEQUENCE { // DigestInfo ::= SEQUENCE {
// digestAlgorithm AlgorithmIdentifier, // digestAlgorithm AlgorithmIdentifier,
@ -160,25 +148,20 @@ const (
// For performance, we don't use the generic ASN1 encoder. Rather, we // 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 // precompute a prefix of the digest value that makes a valid ASN1 DER string
// with the correct contents. // with the correct contents.
var hashPrefixes = [][]byte{ var hashPrefixes = map[crypto.Hash][]byte{
// HashMD5 crypto.MD5: []byte{0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10},
{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},
// HashSHA1 crypto.SHA256: []byte{0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20},
{0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14}, crypto.SHA384: []byte{0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30},
// HashSHA256 crypto.SHA512: {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40},
{0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20}, crypto.MD5SHA1: {}, // A special TLS case which doesn't use an ASN1 prefix.
// HashSHA384 crypto.RIPEMD160: {0x30, 0x20, 0x30, 0x08, 0x06, 0x06, 0x28, 0xcf, 0x06, 0x03, 0x00, 0x31, 0x04, 0x14},
{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.
} }
// 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 // Note that hashed must be the result of hashing the input message using the
// given hash function. // 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)) hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed))
if err != nil { if err != nil {
return 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 // 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 // function and sig is the signature. A valid signature is indicated by
// returning a nil error. // 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)) hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed))
if err != nil { if err != nil {
return return
@ -246,28 +229,14 @@ func VerifyPKCS1v15(pub *PublicKey, hash PKCS1v15Hash, hashed []byte, sig []byte
return nil return nil
} }
func pkcs1v15HashInfo(hash PKCS1v15Hash, inLen int) (hashLen int, prefix []byte, err os.Error) { func pkcs1v15HashInfo(hash crypto.Hash, inLen int) (hashLen int, prefix []byte, err os.Error) {
switch hash { hashLen = hash.Size()
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")
}
if inLen != hashLen { if inLen != hashLen {
return 0, nil, os.ErrorString("input must be hashed message") return 0, nil, os.ErrorString("input must be hashed message")
} }
prefix, ok := hashPrefixes[hash]
prefix = hashPrefixes[int(hash)] if !ok {
return 0, nil, os.ErrorString("unsupported hash function")
}
return return
} }

View file

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

View file

@ -66,7 +66,7 @@ func TestEncryptOAEP(t *testing.T) {
t.Errorf("#%d,%d error: %s", i, j, err) t.Errorf("#%d,%d error: %s", i, j, err)
} }
if bytes.Compare(out, message.out) != 0 { 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 package sha1
import ( import (
"crypto"
"hash" "hash"
"os" "os"
) )
func init() {
crypto.RegisterHash(crypto.SHA1, New)
}
// The size of a SHA1 checksum in bytes. // The size of a SHA1 checksum in bytes.
const Size = 20 const Size = 20

View file

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

View file

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

View file

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

View file

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

View file

@ -5,6 +5,7 @@
package tls package tls
import ( import (
"crypto"
"crypto/rsa" "crypto/rsa"
"crypto/subtle" "crypto/subtle"
"crypto/x509" "crypto/x509"
@ -56,6 +57,7 @@ Curves:
var suite *cipherSuite var suite *cipherSuite
var suiteId uint16 var suiteId uint16
FindCipherSuite:
for _, id := range clientHello.cipherSuites { for _, id := range clientHello.cipherSuites {
for _, supported := range config.cipherSuites() { for _, supported := range config.cipherSuites() {
if id == supported { if id == supported {
@ -66,7 +68,7 @@ Curves:
continue continue
} }
suiteId = id suiteId = id
break break FindCipherSuite
} }
} }
} }
@ -213,7 +215,7 @@ Curves:
digest := make([]byte, 36) digest := make([]byte, 36)
copy(digest[0:16], finishedHash.serverMD5.Sum()) copy(digest[0:16], finishedHash.serverMD5.Sum())
copy(digest[16:36], finishedHash.serverSHA1.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 { if err != nil {
c.sendAlert(alertBadCertificate) c.sendAlert(alertBadCertificate)
return os.ErrorString("could not validate signature of connection nonces: " + err.String()) 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. // Script of interaction with gnutls implementation.
// The values for this test are obtained by building and running in server mode: // 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: // and then:
// % gnutls-cli --insecure --debug 100 -p 10443 localhost > /tmp/log 2>&1 // % gnutls-cli --insecure --debug 100 -p 10443 localhost > /tmp/log 2>&1
// % python parse-gnutls-cli-debug-log.py < /tmp/log // % python parse-gnutls-cli-debug-log.py < /tmp/log

View file

@ -6,6 +6,7 @@ package tls
import ( import (
"big" "big"
"crypto"
"crypto/elliptic" "crypto/elliptic"
"crypto/md5" "crypto/md5"
"crypto/rsa" "crypto/rsa"
@ -143,7 +144,7 @@ Curve:
copy(serverECDHParams[4:], ecdhePublic) copy(serverECDHParams[4:], ecdhePublic)
md5sha1 := md5SHA1Hash(clientHello.random, hello.random, serverECDHParams) 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 { if err != nil {
return nil, os.ErrorString("failed to sign ECDHE parameters: " + err.String()) 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:] sig = sig[2:]
md5sha1 := md5SHA1Hash(clientHello.random, serverHello.random, serverECDHParams) 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: Error:
return os.ErrorString("invalid ServerKeyExchange") return os.ErrorString("invalid ServerKeyExchange")

View file

@ -124,14 +124,22 @@ func LoadX509KeyPair(certFile string, keyFile string) (cert Certificate, err os.
return return
} }
certDERBlock, _ := pem.Decode(certPEMBlock) var certDERBlock *pem.Block
for {
certDERBlock, certPEMBlock = pem.Decode(certPEMBlock)
if certDERBlock == nil { 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") err = os.ErrorString("crypto/tls: failed to parse certificate PEM data")
return return
} }
cert.Certificate = [][]byte{certDERBlock.Bytes}
keyPEMBlock, err := ioutil.ReadFile(keyFile) keyPEMBlock, err := ioutil.ReadFile(keyFile)
if err != nil { if err != nil {
return 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 // 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. // 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 { if err != nil {
return return
} }

View file

@ -9,6 +9,7 @@ import (
"asn1" "asn1"
"big" "big"
"container/vector" "container/vector"
"crypto"
"crypto/rsa" "crypto/rsa"
"crypto/sha1" "crypto/sha1"
"hash" "hash"
@ -330,6 +331,10 @@ type Certificate struct {
DNSNames []string DNSNames []string
EmailAddresses []string EmailAddresses []string
// Name constraints
PermittedDNSDomainsCritical bool // if true then the name constraints are marked critical.
PermittedDNSDomains []string
PolicyIdentifiers []asn1.ObjectIdentifier 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. // TODO(agl): don't ignore the path length constraint.
var h hash.Hash var h hash.Hash
var hashType rsa.PKCS1v15Hash var hashType crypto.Hash
switch c.SignatureAlgorithm { switch c.SignatureAlgorithm {
case SHA1WithRSA: case SHA1WithRSA:
h = sha1.New() h = sha1.New()
hashType = rsa.HashSHA1 hashType = crypto.SHA1
default: default:
return UnsupportedAlgorithmError{} return UnsupportedAlgorithmError{}
} }
@ -474,6 +479,18 @@ type policyInformation struct {
// policyQualifiers omitted // 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) { func parsePublicKey(algo PublicKeyAlgorithm, asn1Data []byte) (interface{}, os.Error) {
switch algo { switch algo {
case RSA: case RSA:
@ -602,6 +619,43 @@ func parseCertificate(in *certificate) (*Certificate, os.Error) {
// If we didn't parse any of the names then we // If we didn't parse any of the names then we
// fall through to the critical check below. // 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: case 35:
// RFC 5280, 4.2.1.1 // RFC 5280, 4.2.1.1
var a authKeyId var a authKeyId
@ -698,10 +752,11 @@ var (
oidExtensionBasicConstraints = []int{2, 5, 29, 19} oidExtensionBasicConstraints = []int{2, 5, 29, 19}
oidExtensionSubjectAltName = []int{2, 5, 29, 17} oidExtensionSubjectAltName = []int{2, 5, 29, 17}
oidExtensionCertificatePolicies = []int{2, 5, 29, 32} oidExtensionCertificatePolicies = []int{2, 5, 29, 32}
oidExtensionNameConstraints = []int{2, 5, 29, 30}
) )
func buildExtensions(template *Certificate) (ret []extension, err os.Error) { 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 n := 0
if template.KeyUsage != 0 { if template.KeyUsage != 0 {
@ -778,6 +833,22 @@ func buildExtensions(template *Certificate) (ret []extension, err os.Error) {
n++ 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 // Adding another extension here? Remember to update the maximum number
// of elements in the make() at the top of the function. // of elements in the make() at the top of the function.
@ -792,7 +863,8 @@ var (
// CreateSelfSignedCertificate creates a new certificate based on // CreateSelfSignedCertificate creates a new certificate based on
// a template. The following members of template are used: SerialNumber, // a template. The following members of template are used: SerialNumber,
// Subject, NotBefore, NotAfter, KeyUsage, BasicConstraintsValid, IsCA, // 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 // 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 // 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) h.Write(tbsCertContents)
digest := h.Sum() digest := h.Sum()
signature, err := rsa.SignPKCS1v15(rand, priv, rsa.HashSHA1, digest) signature, err := rsa.SignPKCS1v15(rand, priv, crypto.SHA1, digest)
if err != nil { if err != nil {
return return
} }

View file

@ -172,6 +172,7 @@ func TestCreateSelfSignedCertificate(t *testing.T) {
DNSNames: []string{"test.example.com"}, 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) 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) 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) err = cert.CheckSignatureFrom(cert)
if err != nil { if err != nil {
t.Errorf("Signature verification failed: %s", err) t.Errorf("Signature verification failed: %s", err)

View file

@ -57,7 +57,6 @@ type ImportDirectory struct {
FirstThunk uint32 FirstThunk uint32
dll string dll string
rva []uint32
} }
// Data reads and returns the contents of the PE section. // Data reads and returns the contents of the PE section.
@ -267,34 +266,28 @@ func (f *File) ImportedSymbols() ([]string, os.Error) {
} }
ida = append(ida, dt) 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() names, _ := ds.Data()
var all []string var all []string
for _, dt := range ida { for _, dt := range ida {
dt.dll, _ = getString(names, int(dt.Name-ds.VirtualAddress)) dt.dll, _ = getString(names, int(dt.Name-ds.VirtualAddress))
for _, va := range dt.rva { 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)) fn, _ := getString(names, int(va-ds.VirtualAddress+2))
all = append(all, fn+":"+dt.dll) all = append(all, fn+":"+dt.dll)
} }
} }
}
return all, nil return all, nil
} }

View file

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

View file

@ -2,8 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// This package implements a Reader which handles reading \r and \r\n // The line package implements a Reader that reads lines delimited by '\n' or ' \r\n'.
// deliminated lines.
package line package line
import ( import (
@ -11,8 +10,7 @@ import (
"os" "os"
) )
// Reader reads lines from an io.Reader (which may use either '\n' or // Reader reads lines, delimited by '\n' or \r\n', from an io.Reader.
// '\r\n').
type Reader struct { type Reader struct {
buf []byte buf []byte
consumed int consumed int
@ -20,11 +18,33 @@ type Reader struct {
err os.Error 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{ return &Reader{
buf: make([]byte, 0, maxLineLength), buf: make([]byte, 0, maxLineLength),
consumed: 0, 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 // 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. // either returns a non-nil line or it returns an error, never both.
func (l *Reader) ReadLine() (line []byte, isPrefix bool, err os.Error) { func (l *Reader) ReadLine() (line []byte, isPrefix bool, err os.Error) {
if l.consumed > 0 { l.removeConsumedFromBuffer()
n := copy(l.buf, l.buf[l.consumed:])
l.buf = l.buf[:n]
l.consumed = 0
}
if len(l.buf) == 0 && l.err != nil { if len(l.buf) == 0 && l.err != nil {
err = l.err err = l.err
@ -89,6 +105,9 @@ func (l *Reader) ReadLine() (line []byte, isPrefix bool, err os.Error) {
l.buf = l.buf[:oldLen+n] l.buf = l.buf[:oldLen+n]
if readErr != nil { if readErr != nil {
l.err = readErr l.err = readErr
if len(l.buf) == 0 {
return nil, false, readErr
}
} }
} }
panic("unreachable") panic("unreachable")

View file

@ -6,6 +6,8 @@ package line
import ( import (
"bytes" "bytes"
"io"
"io/ioutil"
"os" "os"
"testing" "testing"
) )
@ -87,3 +89,45 @@ func TestLineTooLong(t *testing.T) {
t.Errorf("bad result for third line: %x", line) 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 ( import (
"os" "os"
"strconv"
) )
// Arguments to Run. // Arguments to Run.
@ -21,12 +22,22 @@ const (
// Stdin, Stdout, and Stderr are Files representing pipes // Stdin, Stdout, and Stderr are Files representing pipes
// connected to the running command's standard input, output, and error, // connected to the running command's standard input, output, and error,
// or else nil, depending on the arguments to Run. // 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 { type Cmd struct {
Stdin *os.File Stdin *os.File
Stdout *os.File Stdout *os.File
Stderr *os.File Stderr *os.File
Pid int 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 // 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) // If a parameter is Pipe, then the corresponding field (Stdin, Stdout, Stderr)
// of the returned Cmd is the other end of the pipe. // of the returned Cmd is the other end of the pipe.
// Otherwise the field in Cmd is nil. // 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) { func Run(name string, argv, envv []string, dir string, stdin, stdout, stderr int) (c *Cmd, err os.Error) {
p = new(Cmd) c = new(Cmd)
var fd [3]*os.File 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 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 goto Error
} }
if stderr == MergeWithStdout { if stderr == MergeWithStdout {
fd[2] = fd[1] 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 goto Error
} }
// Run command. // 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 { if err != nil {
goto Error 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] { if fd[2] != os.Stderr && fd[2] != fd[1] {
fd[2].Close() fd[2].Close()
} }
return p, nil return c, nil
Error: Error:
if fd[0] != os.Stdin && fd[0] != nil { 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] { if fd[2] != os.Stderr && fd[2] != nil && fd[2] != fd[1] {
fd[2].Close() fd[2].Close()
} }
if p.Stdin != nil { if c.Stdin != nil {
p.Stdin.Close() c.Stdin.Close()
} }
if p.Stdout != nil { if c.Stdout != nil {
p.Stdout.Close() c.Stdout.Close()
} }
if p.Stderr != nil { if c.Stderr != nil {
p.Stderr.Close() c.Stderr.Close()
}
if c.Process != nil {
c.Process.Release()
} }
return nil, err return nil, err
} }
// Wait waits for the running command p, // Wait waits for the running command c,
// returning the Waitmsg returned by os.Wait and an error. // returning the Waitmsg returned when the process exits.
// The options are passed through to os.Wait. // The options are passed to the process's Wait method.
// Setting options to 0 waits for p to exit; // Setting options to 0 waits for c to exit;
// other options cause Wait to return for other // other options cause Wait to return for other
// process events; see package os for details. // process events; see package os for details.
func (p *Cmd) Wait(options int) (*os.Waitmsg, os.Error) { func (c *Cmd) Wait(options int) (*os.Waitmsg, os.Error) {
if p.Pid <= 0 { if c.Process == nil {
return nil, os.ErrorString("exec: invalid use of Cmd.Wait") 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()) { if w != nil && (w.Exited() || w.Signaled()) {
p.Pid = -1 c.Process.Release()
c.Process = nil
} }
return w, err 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 // if it hasn't already, and then closes the non-nil file descriptors
// p.Stdin, p.Stdout, and p.Stderr. // c.Stdin, c.Stdout, and c.Stderr.
func (p *Cmd) Close() os.Error { func (c *Cmd) Close() os.Error {
if p.Pid > 0 { if c.Process != nil {
// Loop on interrupt, but // Loop on interrupt, but
// ignore other errors -- maybe // ignore other errors -- maybe
// caller has already waited for pid. // caller has already waited for pid.
_, err := p.Wait(0) _, err := c.Wait(0)
for err == os.EINTR { for err == os.EINTR {
_, err = p.Wait(0) _, err = c.Wait(0)
} }
} }
// Close the FDs that are still open. // Close the FDs that are still open.
var err os.Error var err os.Error
if p.Stdin != nil && p.Stdin.Fd() >= 0 { if c.Stdin != nil && c.Stdin.Fd() >= 0 {
if err1 := p.Stdin.Close(); err1 != nil { if err1 := c.Stdin.Close(); err1 != nil {
err = err1 err = err1
} }
} }
if p.Stdout != nil && p.Stdout.Fd() >= 0 { if c.Stdout != nil && c.Stdout.Fd() >= 0 {
if err1 := p.Stdout.Close(); err1 != nil && err != nil { if err1 := c.Stdout.Close(); err1 != nil && err != nil {
err = err1 err = err1
} }
} }
if p.Stderr != nil && p.Stderr != p.Stdout && p.Stderr.Fd() >= 0 { if c.Stderr != nil && c.Stderr != c.Stdout && c.Stderr.Fd() >= 0 {
if err1 := p.Stderr.Close(); err1 != nil && err != nil { if err1 := c.Stderr.Close(); err1 != nil && err != nil {
err = err1 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) { if canExec(file) {
return file, nil return file, nil
} }
return "", &os.PathError{"lookpath", file, os.ENOENT} return "", &PathError{file}
} }
pathenv := os.Getenv("PATH") pathenv := os.Getenv("PATH")
for _, dir := range strings.Split(pathenv, ":", -1) { for _, dir := range strings.Split(pathenv, ":", -1) {
@ -41,5 +41,5 @@ func LookPath(file string) (string, os.Error) {
return dir + "/" + file, nil 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 { if f, ok := canExec(file, exts); ok {
return f, nil return f, nil
} }
return ``, &os.PathError{"lookpath", file, os.ENOENT} return ``, &PathError{file}
} }
if pathenv := os.Getenv(`PATH`); pathenv == `` { if pathenv := os.Getenv(`PATH`); pathenv == `` {
if f, ok := canExec(`.\`+file, exts); ok { 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) Screen() draw.Image { return c.img }
func (c *conn) FlushImage() { func (c *conn) FlushImage() {
// We do the send (the <- operator) in an expression context, rather than in select {
// a statement context, so that it does not block, and fails if the buffered case c.flush <- false:
// channel is full (in which case there already is a flush request pending). // Flush notification sent.
_ = c.flush <- false default:
// Could not send.
// Flush notification must be pending already.
}
} }
func (c *conn) Close() os.Error { func (c *conn) Close() os.Error {

View file

@ -908,7 +908,7 @@ func (a *stmtCompiler) compileBranchStmt(s *ast.BranchStmt) {
return return
default: default:
log.Panic("Unexpected branch token %v", s.Tok) log.Panicf("Unexpected branch token %v", s.Tok)
} }
a.flow.put1(false, pc) 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 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), Val2("if i == i2 { i = 2 } else { i = 3 }; i2 = 4", "i", 3, "i2", 4),
// Omit optional parts // 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 true { i = 2 }; i2 = 4", "i", 2, "i2", 4),
Val2("if false { i = 2 }; i2 = 4", "i", 1, "i2", 4), Val2("if false { i = 2 }; i2 = 4", "i", 1, "i2", 4),
// Init // Init
@ -243,11 +243,11 @@ var stmtTests = []test{
CErr("fn1 := func() int { if true { return 1 } }", "return"), CErr("fn1 := func() int { if true { return 1 } }", "return"),
CErr("fn1 := func() int { if true { } }", "return"), CErr("fn1 := func() int { if true { } }", "return"),
Run("fn1 := func() int { if true { }; return 1 }"), Run("fn1 := func() int { if true { }; return 1 }"),
CErr("fn1 := func() int { if { } }", "return"), CErr("fn1 := func() int { if true { } }", "return"),
CErr("fn1 := func() int { if { } else { return 2 } }", "return"), CErr("fn1 := func() int { if true { } else { return 2 } }", "return"),
Run("fn1 := func() int { if { return 1 } }"), Run("fn1 := func() int { if true { return 1 }; return 0 }"),
Run("fn1 := func() int { if { return 1 } else { } }"), Run("fn1 := func() int { if true { return 1 } else { }; return 0 }"),
Run("fn1 := func() int { if { return 1 } else { } }"), Run("fn1 := func() int { if true { return 1 } else { }; return 0 }"),
// Switch // Switch
Val1("switch { case false: i += 2; case true: i += 4; default: i += 8 }", "i", 1+4), 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
}

View file

@ -96,7 +96,7 @@ func newIntValue(val int, p *int) *intValue {
} }
func (i *intValue) Set(s string) bool { func (i *intValue) Set(s string) bool {
v, err := strconv.Atoi(s) v, err := strconv.Btoi64(s, 0)
*i = intValue(v) *i = intValue(v)
return err == nil return err == nil
} }
@ -112,7 +112,7 @@ func newInt64Value(val int64, p *int64) *int64Value {
} }
func (i *int64Value) Set(s string) bool { func (i *int64Value) Set(s string) bool {
v, err := strconv.Atoi64(s) v, err := strconv.Btoi64(s, 0)
*i = int64Value(v) *i = int64Value(v)
return err == nil return err == nil
} }
@ -128,7 +128,7 @@ func newUintValue(val uint, p *uint) *uintValue {
} }
func (i *uintValue) Set(s string) bool { func (i *uintValue) Set(s string) bool {
v, err := strconv.Atoui(s) v, err := strconv.Btoui64(s, 0)
*i = uintValue(v) *i = uintValue(v)
return err == nil return err == nil
} }
@ -144,7 +144,7 @@ func newUint64Value(val uint64, p *uint64) *uint64Value {
} }
func (i *uint64Value) Set(s string) bool { func (i *uint64Value) Set(s string) bool {
v, err := strconv.Atoui64(s) v, err := strconv.Btoui64(s, 0)
*i = uint64Value(v) *i = uint64Value(v)
return err == nil return err == nil
} }

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